音频采集转wav文件

1:short[]数组的帧:

音频返回的short[]代表一个音频信号的波形数据。在数字音频处理中,波形数据通常以数字形式表示,而short[]是一种常见的表示方法。

short[]中,每个元素都是一个16位的有符号整数,通常表示一个音频样本的振幅。每个样本对应音频波形中的一个时间点。振幅的值范围在-32768到32767之间,其中0表示无振幅,正数表示正相位振幅,负数表示负相位振幅。

对于音频处理来说,采样率(sampling rate)也是一个关键的参数,它表示每秒从模拟音频信号中获取的样本数。例如,如果采样率为44100 Hz,那么每秒就会有44100个short类型的值表示音频波形。采样率与波形数据的长度之间存在直接的关系,可以通过以下公式计算:

音频数据长度=总时间采样率音频数据长度=采样率总时间

总时间是指音频信号的持续时间,单位是秒。这样,通过short[]的长度和采样率,你可以了解到音频数据所覆盖的时间范围。

在音频处理中,还有其他一些重要的概念,如声道数(单声道、立体声等)、位深度(采样位数,表示每个样本的比特数)等,这些参数也会影响音频数据的解释和处理方式。

 

2:

如果采集工具的采样率和转成WAV文件的采样率不一致,可能会导致音频变速或者音调发生变化,这是因为不同的采样率会导致音频播放速度的改变。具体的后果取决于两个采样率之间的差异以及音频数据的内容。

  1. 变速效果: 如果转换后的WAV文件的采样率高于采集工具的采样率,音频将被加速播放;反之,如果采样率低于原始采样率,音频将被减速播放。这可能会导致声音的变化,使得音频听起来较快或较慢。

  2. 音调变化: 不同的采样率会导致音频频率的变化,从而影响音调。如果采样率增加,音频会变高调;如果采样率降低,音频会变低调。这可能导致原始声音与转换后的声音之间存在明显的音调差异。

为了避免这些问题,确保在转换过程中采用与采集工具相同的采样率。如果无法获取采集工具的准确采样率,可以尝试多个常见的采样率,然后观察转换后的音频是否听起来正常。理想情况下,你应该以原始采样率进行转换,以保持音频的原始特性。

这种差异主要是因为采样率影响了音频的时间表达和频率解析度。采样率表示每秒从模拟音频信号中取样的次数。如果两个系统(例如采集工具和WAV文件转换工具)的采样率不一致,就会导致两个关键方面的变化:

  1. 时间尺度: 不同的采样率意味着相同时间内的样本数量不同。当你改变采样率时,实际上是在改变音频的时间尺度。更高的采样率会导致更多的样本在相同的时间内,从而加快音频的播放速度;更低的采样率则会减慢播放速度。

  2. 频率解析度: 采样率还影响了对音频频率的解析度。根据奈奎斯特定理,一个信号的最高频率不能超过其采样率的一半。因此,如果你将采样率减小,可能会导致高频信息的丢失,从而影响音频的高频部分。

这两个因素的变化可能导致音频听起来变速或变调。为了保持音频的原始特性,通常应确保在处理或转换音频时使用相同的采样率。如果不同系统之间的采样率不同,可能需要进行采样率转换,以使它们保持一致。采样率转换过程中会使用插值等技术来调整音频的时间尺度和频率解析度,以尽可能地保留原始音频的特性。

 

3:采集到的帧short[]类型转为wav文件:

 public void convertToWav(short[] audioData, String filePath) {

        byte[] byteData = new byte[audioData.length * 2]; // 一个short类型占两个字节
        ByteBuffer.wrap(byteData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(audioData);
        // 创建临时 byte 数组

        try {
            // 设置音频参数
            int sampleRate = 17000;
            int numChannels = 1;
            int bitsPerSample = 16;

            // 写入WAV文件头
            long byteRate = sampleRate * numChannels * bitsPerSample / 8;
            long totalDataLen = byteData.length + 36;
            long totalAudioLen = byteData.length;
            byte[] header = new byte[44];
            header[0] = 'R';  // RIFF/WAVE header
            header[1] = 'I';
            header[2] = 'F';
            header[3] = 'F';
            header[4] = (byte) (totalDataLen & 0xff);
            header[5] = (byte) ((totalDataLen >> 8) & 0xff);
            header[6] = (byte) ((totalDataLen >> 16) & 0xff);
            header[7] = (byte) ((totalDataLen >> 24) & 0xff);
            header[8] = 'W';
            header[9] = 'A';
            header[10] = 'V';
            header[11] = 'E';
            header[12] = 'f';  // 'fmt ' chunk
            header[13] = 'm';
            header[14] = 't';
            header[15] = ' ';
            header[16] = 16;  // 4 bytes: size of 'fmt ' chunk
            header[17] = 0;
            header[18] = 0;
            header[19] = 0;
            header[20] = 1;  // format = 1 for PCM
            header[21] = 0;
            header[22] = (byte) numChannels;
            header[23] = 0;
            header[24] = (byte) (sampleRate & 0xff);
            header[25] = (byte) ((sampleRate >> 8) & 0xff);
            header[26] = (byte) ((sampleRate >> 16) & 0xff);
            header[27] = (byte) ((sampleRate >> 24) & 0xff);
            header[28] = (byte) (byteRate & 0xff);
            header[29] = (byte) ((byteRate >> 8) & 0xff);
            header[30] = (byte) ((byteRate >> 16) & 0xff);
            header[31] = (byte) ((byteRate >> 24) & 0xff);
            header[32] = (byte) (numChannels * bitsPerSample / 8);  // block align
            header[33] = 0;
            header[34] = (byte) bitsPerSample;
            header[35] = 0;
            header[36] = 'd';
            header[37] = 'a';
            header[38] = 't';
            header[39] = 'a';
            header[40] = (byte) (totalAudioLen & 0xff);
            header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
            header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
            header[43] = (byte) ((totalAudioLen >> 24) & 0xff);

            // 写入WAV文件
            FileOutputStream os = new FileOutputStream(filePath);
            os.write(header, 0, 44);
            os.write(byteData, 0, byteData.length);
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 

 

posted @ 2024-01-17 09:47  蜗牛攀爬  阅读(21)  评论(0编辑  收藏  举报