AudioRecord PCM数据没用?

时间:2011-02-10 16:53:34

标签: java android pcm

我已经在我的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)};
    }

2 个答案:

答案 0 :(得分:1)

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

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

如果您已创建标题并附加原始数据,并且生成的文件播放没有错误但听起来像噪音,那么最可能的原因是原始音频每个样本使用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)};
    }

?我不确定>>>在比特转换的世界中意味着什么。

答案 1 :(得分:0)

查看用于编写wav标头here

的排演助手代码