我用 Java 编写了以下脚本,该脚本旨在从麦克风录制几秒钟的音频。 问题是它只想录制内部笔记本电脑麦克风,而不是外部 USB 麦克风。
USB 麦克风使用类似的 Python 脚本正确录制,这意味着它可以被检测到并且完全正常工作。
import javax.sound.sampled.*;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import java.util.Timer;
import java.util.TimerTask;
public class SimpleAudioRecorder {
private static final float SAMPLE_RATE = 44100; // Audio sample rate
private static final int BUFFER_SIZE = 4096; // Buffer size for audio recording
private static final float GAIN_FACTOR = 1.0f; // Amplification factor for microphone input (adjusted)
private static final File OUTPUT_FILE = new File("recording.wav"); // Output file path
private static final int RECORD_DURATION_MS = 5000; // Record duration in milliseconds (5 seconds)
private static TargetDataLine microphone;
private static volatile boolean recordingStopped = false; // Flag to indicate if recording is stopped
public static void main(String[] args) {
try {
// Initialize audio components
AudioFormat format = new AudioFormat(SAMPLE_RATE, 16, 2, true, true);
initializeMicrophone(format);
startRecording();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void initializeMicrophone(AudioFormat format) {
try {
// Get and open the microphone
DataLine.Info micInfo = new DataLine.Info(TargetDataLine.class, format);
if (!AudioSystem.isLineSupported(micInfo)) {
System.err.println("Microphone not supported");
System.exit(0);
}
microphone = (TargetDataLine) AudioSystem.getLine(micInfo);
microphone.open(format);
System.out.println("Microphone initialized and opened.");
} catch (LineUnavailableException e) {
e.printStackTrace();
System.exit(0);
}
}
private static void startRecording() {
System.out.println("Recording started!");
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// Set up a timer to stop recording after 5 seconds
Timer stopTimer = new Timer();
stopTimer.schedule(new TimerTask() {
@Override
public void run() {
stopRecording(); // Stop the recording after 5 seconds
saveRecording(outputStream); // Save the recording
}
}, RECORD_DURATION_MS);
microphone.start();
System.out.println("Microphone started.");
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
// Record audio
while (!recordingStopped) {
bytesRead = microphone.read(buffer, 0, buffer.length);
if (bytesRead > 0) {
// Amplify the audio data correctly by scaling up each sample
for (int i = 0; i < bytesRead - 1; i += 2) {
// Convert byte pair (little-endian) into a 16-bit signed sample
short sample = (short) ((buffer[i + 1] << 8) | (buffer[i] & 0xff));
// Apply gain factor to amplify the sample
sample = (short) Math.min(Math.max(sample * GAIN_FACTOR, Short.MIN_VALUE), Short.MAX_VALUE);
// Break the 16-bit sample back into two bytes (little-endian)
buffer[i] = (byte) sample;
buffer[i + 1] = (byte) (sample >> 8);
}
outputStream.write(buffer, 0, bytesRead);
}
}
// Stop and close the microphone
microphone.stop();
microphone.close();
System.out.println("Microphone stopped and closed.");
}
private static void saveRecording(ByteArrayOutputStream outputStream) {
try {
// Save the recorded audio to a file
byte[] audioData = outputStream.toByteArray();
saveAudioToFile(audioData, new AudioFormat(SAMPLE_RATE, 16, 2, true, true));
System.out.println("Recording saved to " + OUTPUT_FILE.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
}
private static void saveAudioToFile(byte[] audioData, AudioFormat format) throws IOException {
byte[] normalizedAudioData = normalizeVolume(audioData);
try (FileOutputStream fos = new FileOutputStream(OUTPUT_FILE);
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
AudioInputStream audioInputStream = new AudioInputStream(
new ByteArrayInputStream(normalizedAudioData), format, normalizedAudioData.length / format.getFrameSize());
AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, bos);
}
}
private static byte[] normalizeVolume(byte[] audioData) {
short[] audioDataShort = new short[audioData.length / 2];
ByteBuffer.wrap(audioData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(audioDataShort);
// Find the maximum absolute value
int max = 0; // Change type to int
for (short sample : audioDataShort) {
int absSample = Math.abs(sample); // Convert to int for abs calculation
if (absSample > max) {
max = absSample;
}
}
// Calculate normalization factor
float normalizationFactor = 32767.0f / max;
// Apply normalization
for (int i = 0; i < audioDataShort.length; i++) {
audioDataShort[i] = (short) Math.min(Math.max(audioDataShort[i] * normalizationFactor, Short.MIN_VALUE), Short.MAX_VALUE);
}
ByteBuffer byteBuffer = ByteBuffer.allocate(audioDataShort.length * 2).order(ByteOrder.LITTLE_ENDIAN);
ShortBuffer shortBuffer = byteBuffer.asShortBuffer();
shortBuffer.put(audioDataShort);
return byteBuffer.array();
}
private static void stopRecording() {
System.out.println("Stopping recording...");
recordingStopped = true; // Set flag to true to stop recording
}
}
我认为您的系统只是使用系统上第一个可用的麦克风 - 而这恰好是您笔记本电脑中的麦克风。您需要扩展代码才能使用您认为正确的麦克风。此代码列出了可用的麦克风。
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;
public class ListMicrophones {
public static void main(String[] args) {
Mixer.Info[] mixers = AudioSystem.getMixerInfo(); // Get all available mixers
System.out.println("Available microphones:");
for (Mixer.Info mixerInfo : mixers) {
Mixer mixer = AudioSystem.getMixer(mixerInfo);
Line.Info[] targetLines = mixer.getTargetLineInfo(); // Get lines for target (input) audio
for (Line.Info lineInfo : targetLines) {
if (TargetDataLine.class.isAssignableFrom(lineInfo.getLineClass())) {
System.out.println("Microphone: " + mixerInfo.getName());
break; // Found a microphone, move to next mixer
}
}
}
}
}