简体   繁体   中英

How do I combine two AudioInputStream?

The file format is "PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian", and I want to add them together while amplifying one of the two files. I plan to read the two wav get put them into two audioinputstream instances, then store the instances into two byte[] array, manipulate in the arrays, and get return as another audioinputstream instance.

I have done a lot of research but I have got no good results. I know that is a class from www.jsresources.org mixing two audioinputstream, but it doesn't allow me to modify either of the two streams before mixing while I want to decrease one of the streams before mixing them. What do you think I should do?

To do this, you can convert the streams to PCM data, multiply the channel whose volume you wish to change by the desired factor, add the PCM data from the results together, then convert back to bytes.

To access the AudioStreams on a per-byte basis, check out the first extended code fragment at the Java Tutorials section on Using Files and Format Converters . This shows how to get an array of sound byte data. There is a comment that reads:

  // Here, do something useful with the audio data that's 
  // now in the audioBytes array...

At this point, iterate through the bytes, converting to PCM. A set of commands based on the following should work:

for (int i = 0; i < numBytes; i += 2)
{
    pcmA[i/2] = audioBytesA[i] & 0xff ) | ( audioBytesA[i + 1] << 8 );
    pcmB[i/2] = audioBytesB[i] & 0xff ) | ( audioBytesB[i + 1] << 8 );
}

In the above, audioBytesA and audioBytesB are two input streams (names based on the code from the example), and pcmA and pcmB could be either int arrays or short arrays, holding values that fit within the range of a short . It might be best to make pcm arrays floats since you will be doing some math that will result in fractions. Using floats as in the example below only adds one place worth of accuracy (better rounding than when using int ), and int would perform faster. I think using floats is more often done if the audio data gets normalized for use with additional processing.

From there, the best way to change volume is to multiply every PCM value by the same amount. For example, to increase volume by 25%,

pcmA[i] = pcmA[i] * 1.25f; 

Then, add pcmA and pcmB, and convert back to bytes. You might also want to put in min or max functions to ensure that the volume & merging do not exceed values that can fit in the format's 16 bits.

I use the following to convert back to bytes:

for (int i = 0; i < numBytes; i++)
{
   outBuffer[i*2] = (byte) pcmCombined[i];
   outBuffer[(i*2) + 1] = (byte)((int)pcmCombined[i] >> 8 );            
}

Above assumes pcmCombined[] is a float array. The conversion code can be a bit simpler if it is a short[] or int[] array.

I cut and pasted the above from dev work I did for programs posted at my website , and edited it for your scenario, so if there is a typo or bug crept in, please let me know in the comments and I will fix it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM