我正在使用 Android AudioTrack 对象来传输 16 位单声道 PCM 文件。我的代码从 DataInputStream 读取双精度值,将其转换为 8 字节,然后将该 8 字节保存到缓冲区以写入 AudioTrack。这很好用。但现在,我尝试通过将双精度乘以标量(例如 0.5)来调整增益。当我这样做时,它会使我的音频严重失真。我尝试使用浮点数而不是双精度数,得到了相同的结果。有没有更好的方法来改变流的增益?我的最终目标是创建一个简单的回声效果,这就是我这样做的原因。
ByteBuffer bb = ByteBuffer.allocate(8);
while(isPlaying){
try {
//fill buffer with bytes from file reader
for(int i=0; i < BUFFSIZE/8; i++){
//read double from DataInputStream
double temp = dis.readDouble();
//save double to ByteBuffer
bb.putDouble(0, temp * .5);
// save 8 bytes to array of bytes
bb.rewind();
bb.get(buff,i*8,8);
}
//write buffer to track to play
track.write(buff, 0, BUFFSIZE);
} catch (IOException e) {
break; //when eof is reached
}
}
如果您使用 Android AudioRecord 和 AudioTrack 类进行录制和播放,请记住,16 位单声道音频样本默认为小端字节序。如果您使用 DataInputStream 类的 readDouble() 方法读取字节,则会不加区别地读取 Big endian 中的 64 位,因此会以错误的顺序读取字节。但请记住,即使 readDouble 会以小端方式读取字节,或者如果您的音频采用大端方式,它也会读取 64 位并将它们视为一个大双值,而实际上每个样本都代表一个带符号短值,其值范围为从 -32768 到 +32767(假设它已签名)。如果出于数字信号处理的目的将其转换为双精度型,最好通过除以 32767.0f 将其标准化为 -1.0 到 +1.0 范围(否则,不必费心将其转换为双精度型)第一名)。当您完成 DSP 的双精度运算后,将其乘以 32767 并将其转换回小端。这是一个快速但肮脏的方法:
try{
for(int offset=0; offset < buff_size; offset+= 2) //increment index by two because 16bit mono sample is 2 bytes long
{
//reads 2 bytes from stream and stores them in buff at offset. returns number of bytes read.
if (dis.read(buff,offset, 2) > 0){
//where buff is an array of bytes
// Low Byte High Byte Left Shift
double sample= ((buff[offset + 0]) | (buff[offset + 1] << 8) );
/*Explanation: First We take the High Byte and shift it 8 Bytes to the left. In Java, this promotes it to an integer(32 bits).
* Next we merge the int representing High Byte and the Low Byte byte with a bitwise OR operator
* 00000000 0000000 10101111 00000000
* OR 10110000 =
* 00000000 0000000 10101111 10110000 Now our bytes are in the Big Endian order required for primitive types */
//since 2 bytes is a short which has range -32768 to +32767, we divide by 32768 to normalize to -1.0 to +1.0 range for DSP
sample = sample /32768.0;
sample = sample * .5;
//convert it back to small endian
int nsample = (int) Math.round(sample * 32767.0);//expands it to the range of -32768 to 32767 range of short, round, & truncate
buff[offset + 1] = (byte) ((nsample >> 8) & 0xFF); //isolate and extract the high byte
buff[offset + 0] = (byte) (nsample & 0xFF); //isolate the low byte with MASK
}
}
track.write(buff, 0, buff_size);
}catch(Exception e){
//
}
来源:http://www.jsresources.org/faq_audio.html#samples_organized http://www.jsresources.org/faq%5faudio.html#samples%5forganized
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)