AudioRecord PCM数据没有用吗?

发布于 2024-10-16 13:58:17 字数 4781 浏览 5 评论 0原文

我已经在我的 Android 应用程序中使用麦克风进行了录制,并且在使用已将数据流式传输的 AudioPlayer 类时播放效果非常好。我的问题是我想向此数据附加一个 wav 标头,以便可以在应用程序外部播放它。我非常确定在十六进制编辑器中与其他音频文件一起使用后创建标头的方法会起作用,这会导致记录的 pcm 数据不能作为 wav 文件中的原始数据使用?

有人能解释一下吗?我可以将 pcm/wav 文件作为原始文件导入到 audacity 中,并且播放完美,但是当我尝试打开 wav 时,我只是听到噪音,再次暗示 pcm 数据有问题。

录音设置:

int frequency = 22050;
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;

标头变量:

byte[] clipData = data;
long myDataSize = clipData.length;
long mySubChunk1Size = 16;
int myBitsPerSample= 16;
int myFormat = 1;
long myChannels = 1;
long mySampleRate = 22050;
long myByteRate = mySampleRate * myChannels * myBitsPerSample/8;
int myBlockAlign = (int) (myChannels * myBitsPerSample/8);
long myChunk2Size =  myDataSize * myChannels * myBitsPerSample/8;
long myChunkSize = 36 + myChunk2Size;

try
        {
            File audioDirectory = new File(Environment
                    .getExternalStorageDirectory().getAbsolutePath()
                    + "/Directory/");
            audioDirectory.mkdir();
            File file = new File(audioDirectory, "test.wav");
            if (file.exists())
                file.delete();

            // Create the new file.
            try {
                file.createNewFile();
            } catch (IOException e) {
                throw new IllegalStateException("Failed to create "
                        + file.toString());
            }
            OutputStream os = new FileOutputStream(file);
            BufferedOutputStream bos = new BufferedOutputStream(os);
            DataOutputStream outFile = new DataOutputStream(bos);

            // write the wav file per the wav file format
            outFile.writeBytes("RIFF");                 // 00 - RIFF
            outFile.write(intToByteArray((int)myChunkSize), 0, 4);      // 04 - how big is the rest of this file?
            outFile.writeBytes("WAVE");                 // 08 - WAVE
            outFile.writeBytes("fmt ");                 // 12 - fmt 
            outFile.write(intToByteArray((int)mySubChunk1Size), 0, 4);  // 16 - size of this chunk
            outFile.write(shortToByteArray((short)myFormat), 0, 2);     // 20 - what is the audio format? 1 for PCM = Pulse Code Modulation
            outFile.write(shortToByteArray((short)myChannels), 0, 2);   // 22 - mono or stereo? 1 or 2?  (or 5 or ???)
            outFile.write(intToByteArray((int)mySampleRate), 0, 4);     // 24 - samples per second (numbers per second)
            outFile.write(intToByteArray((int)myByteRate), 0, 4);       // 28 - bytes per second
            outFile.write(shortToByteArray((short)myBlockAlign), 0, 2); // 32 - # of bytes in one sample, for all channels
            outFile.write(shortToByteArray((short)myBitsPerSample), 0, 2);  // 34 - how many bits in a sample(number)?  usually 16 or 24
            outFile.writeBytes("data");                 // 36 - data
            outFile.write(intToByteArray((int)myDataSize), 0, 4);       // 40 - how big is this data chunk
            outFile.write(clipData);                        // 44 - the actual data itself - just a long string of numbers
        }

转换器

public static int byteArrayToInt(byte[] b)
    {
        int start = 0;
        int low = b[start] & 0xff;
        int high = b[start+1] & 0xff;
        return (int)( high << 8 | low );
    }


    // these two routines convert a byte array to an unsigned integer
    public static long byteArrayToLong(byte[] b)
    {
        int start = 0;
        int i = 0;
        int len = 4;
        int cnt = 0;
        byte[] tmp = new byte[len];
        for (i = start; i < (start + len); i++)
        {
            tmp[cnt] = b[i];
            cnt++;
        }
        long accum = 0;
        i = 0;
        for ( int shiftBy = 0; shiftBy < 32; shiftBy += 8 )
        {
            accum |= ( (long)( tmp[i] & 0xff ) ) << shiftBy;
            i++;
        }
        return accum;
    }


// ===========================
// CONVERT JAVA TYPES TO BYTES
// ===========================
    // returns a byte array of length 4
    private static byte[] intToByteArray(int i)
    {
        byte[] b = new byte[4];
        b[0] = (byte) (i & 0x00FF);
        b[1] = (byte) ((i >> 8) & 0x000000FF);
        b[2] = (byte) ((i >> 16) & 0x000000FF);
        b[3] = (byte) ((i >> 24) & 0x000000FF);
        return b;
    }

    // convert a short to a byte array
    public static byte[] shortToByteArray(short data)
    {
        return new byte[]{(byte)(data & 0xff),(byte)((data >>> 8) & 0xff)};
    }

I have recorded using the Mic in my android app and this plays perfectly well when using the AudioPlayer class having streamed the data in. My problem is I want to append a wav header to this data so it can be played outside of the application. I am pretty sure the methods to create the header work after playing around in a hex editor with other audio files, which leads to the pcm data recorded to not being useful as raw data in a wav file?

Can anybody shed any light on this? I can import the pcm/wav file into audacity as a raw file and it plays perfectly but when I try it as just opening the wav I just get noise, again hinting the pcm data is at fault.

Recording Settings:

int frequency = 22050;
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;

Header Variables:

byte[] clipData = data;
long myDataSize = clipData.length;
long mySubChunk1Size = 16;
int myBitsPerSample= 16;
int myFormat = 1;
long myChannels = 1;
long mySampleRate = 22050;
long myByteRate = mySampleRate * myChannels * myBitsPerSample/8;
int myBlockAlign = (int) (myChannels * myBitsPerSample/8);
long myChunk2Size =  myDataSize * myChannels * myBitsPerSample/8;
long myChunkSize = 36 + myChunk2Size;

try
        {
            File audioDirectory = new File(Environment
                    .getExternalStorageDirectory().getAbsolutePath()
                    + "/Directory/");
            audioDirectory.mkdir();
            File file = new File(audioDirectory, "test.wav");
            if (file.exists())
                file.delete();

            // Create the new file.
            try {
                file.createNewFile();
            } catch (IOException e) {
                throw new IllegalStateException("Failed to create "
                        + file.toString());
            }
            OutputStream os = new FileOutputStream(file);
            BufferedOutputStream bos = new BufferedOutputStream(os);
            DataOutputStream outFile = new DataOutputStream(bos);

            // write the wav file per the wav file format
            outFile.writeBytes("RIFF");                 // 00 - RIFF
            outFile.write(intToByteArray((int)myChunkSize), 0, 4);      // 04 - how big is the rest of this file?
            outFile.writeBytes("WAVE");                 // 08 - WAVE
            outFile.writeBytes("fmt ");                 // 12 - fmt 
            outFile.write(intToByteArray((int)mySubChunk1Size), 0, 4);  // 16 - size of this chunk
            outFile.write(shortToByteArray((short)myFormat), 0, 2);     // 20 - what is the audio format? 1 for PCM = Pulse Code Modulation
            outFile.write(shortToByteArray((short)myChannels), 0, 2);   // 22 - mono or stereo? 1 or 2?  (or 5 or ???)
            outFile.write(intToByteArray((int)mySampleRate), 0, 4);     // 24 - samples per second (numbers per second)
            outFile.write(intToByteArray((int)myByteRate), 0, 4);       // 28 - bytes per second
            outFile.write(shortToByteArray((short)myBlockAlign), 0, 2); // 32 - # of bytes in one sample, for all channels
            outFile.write(shortToByteArray((short)myBitsPerSample), 0, 2);  // 34 - how many bits in a sample(number)?  usually 16 or 24
            outFile.writeBytes("data");                 // 36 - data
            outFile.write(intToByteArray((int)myDataSize), 0, 4);       // 40 - how big is this data chunk
            outFile.write(clipData);                        // 44 - the actual data itself - just a long string of numbers
        }

Convertors

public static int byteArrayToInt(byte[] b)
    {
        int start = 0;
        int low = b[start] & 0xff;
        int high = b[start+1] & 0xff;
        return (int)( high << 8 | low );
    }


    // these two routines convert a byte array to an unsigned integer
    public static long byteArrayToLong(byte[] b)
    {
        int start = 0;
        int i = 0;
        int len = 4;
        int cnt = 0;
        byte[] tmp = new byte[len];
        for (i = start; i < (start + len); i++)
        {
            tmp[cnt] = b[i];
            cnt++;
        }
        long accum = 0;
        i = 0;
        for ( int shiftBy = 0; shiftBy < 32; shiftBy += 8 )
        {
            accum |= ( (long)( tmp[i] & 0xff ) ) << shiftBy;
            i++;
        }
        return accum;
    }


// ===========================
// CONVERT JAVA TYPES TO BYTES
// ===========================
    // returns a byte array of length 4
    private static byte[] intToByteArray(int i)
    {
        byte[] b = new byte[4];
        b[0] = (byte) (i & 0x00FF);
        b[1] = (byte) ((i >> 8) & 0x000000FF);
        b[2] = (byte) ((i >> 16) & 0x000000FF);
        b[3] = (byte) ((i >> 24) & 0x000000FF);
        return b;
    }

    // convert a short to a byte array
    public static byte[] shortToByteArray(short data)
    {
        return new byte[]{(byte)(data & 0xff),(byte)((data >>> 8) & 0xff)};
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情场扛把子 2024-10-23 13:58:18

您可能只是将标头属性设置错误。 WAV 格式标头应为 44 字节,后面是原始音频数据。以下是 WAV 格式的说明:

http://www.sonicspot.com/guide/wavefiles。 如果您

创建了标头并附加了原始数据,并且生成的文件播放时没有错误,但听起来像噪音,那么最可能的罪魁祸首是原始音频每个样本使用 2 个字节,但您设置了 BitsPerSample将标头中的属性更改为 8。

您使用的方法(在原始音频中添加 WAV 标头)完全有效并且应该可以正常工作。

更新:嘿,你的转换方法不应该是吗

    // convert a short to a byte array
    public static byte[] shortToByteArray(short data)
    {
        return new byte[]{(byte)(data & 0xff),(byte)((data >> 8) & 0xff)};
    }

?我不确定 >>> 在位移世界中意味着什么。

You're probably just setting the header properties wrong. The WAV format header should be 44 bytes, followed by the raw audio data. Here is a description of the WAV format:

http://www.sonicspot.com/guide/wavefiles.html

If you've created a header and appended the raw data, and the resulting file plays without error but sounds like noise, then the most likely culprit is that the raw audio uses 2 bytes per sample but you set the BitsPerSample property in the header to 8.

The approach that you're using (prepending a WAV header to raw audio) is perfectly valid and should work fine.

Update: Hey, shouldn't your conversion method be

    // convert a short to a byte array
    public static byte[] shortToByteArray(short data)
    {
        return new byte[]{(byte)(data & 0xff),(byte)((data >> 8) & 0xff)};
    }

? I'm not sure what >>> means in the bit-shifting world.

人疚 2024-10-23 13:58:18

看一下用于编写 wav 标头的排练助手代码 此处

Take a look at the rehearshal assistant code for writing the wav header here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文