我无法编写从 USB 麦克风录音的代码;仅记录笔记本电脑内部麦克风

问题描述 投票:0回答:1

我用 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
    }
}
java audio
1个回答
0
投票

我认为您的系统只是使用系统上第一个可用的麦克风 - 而这恰好是您笔记本电脑中的麦克风。您需要扩展代码才能使用您认为正确的麦克风。此代码列出了可用的麦克风。

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
                }
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.