我使用Android AudioTrack对象来传输16位单声道PCM文件。我的代码从DataInputStream中读取一个double,将其转换为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
}
}
答案 0 :(得分:2)
如果您使用Android AudioRecord和AudioTrack类进行录制和播放,请记住16位单声道音频样本默认为小端。如果您正在使用DataInputStream类的readDouble()方法读取字节,则它会在Big endian中不加区分地读取64位,因此正在以错误的顺序读取字节。但请记住,即使readDouble将读取小端的字节,或者如果您的音频是Big endian,它也会读取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