Hi ich schon wieder,
Jetzt versuche ich mehrere byte arrays zu mischen um sie über eine SourceDataLine abspielen zu können!
Es funktioniert auch einigermaßen mit folgendem Code:
public static void playByteArrays(AudioFormat format, byte[]... byteArrays) throws Exception {
AudioInputStream[] streams = new AudioInputStream[byteArrays.length];
for(int i=0;i<byteArrays.length;i++)
streams** = new AudioInputStream(new ByteArrayInputStream(byteArrays**),format,byteArrays**.length/format.getFrameSize());
playStreams(format, streams);
}
public static void playStreams(AudioFormat format, AudioInputStream... streams) throws Exception {
SourceDataLine sourceDataLine = (SourceDataLine)AudioSystem.getLine(new DataLine.Info(SourceDataLine.class,format));
sourceDataLine.open(format);
sourceDataLine.start();
boolean allStreamsFinished = false;
int bufferSize = 4444;
byte[][] buffers = new byte[streams.length][bufferSize];
short[][] sampleBuffers = new short[streams.length][bufferSize/2];
byte[] outBuffer = new byte[bufferSize];
short[] sampleOutBuffer = new short[bufferSize/2];
while(!allStreamsFinished) {
//fill buffers and check if there are streams left running
allStreamsFinished=true;
for (int i=0;i<buffers.length;i++)
if(streams**.read(buffers**,0,buffers**.length) > 0)
allStreamsFinished = false;
if (allStreamsFinished) break;
//fill sample buffers
for (int i=0;i<buffers.length;i++)
ByteBuffer.wrap(buffers**).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(sampleBuffers**);
//mix samples
sampleOutBuffer = getMixedSamples(bufferSize/2, sampleBuffers);
//fill outBuffer
ByteBuffer.wrap(outBuffer).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(sampleOutBuffer);
sourceDataLine.write(outBuffer, 0, bufferSize);
}
sourceDataLine.drain();
sourceDataLine.stop();
sourceDataLine.close();
}
Sowie der folgenden Funktion für das Mixen:
public static short[] getMixedSamples(int sampleSize, short[]... sampleBuffers) {
short[] outSamples = new short[sampleSize];
for (int s = 0; s < outSamples.length; s++) {
short computedVal = 0;
for (short[] sampleBuffer:sampleBuffers)
if (sampleBuffer.length>0)
computedVal+=sampleBuffer[s];
//reduziert die Lautstärke um die Anzahl der Channels ändert aber nichts an der Welle
// outSamples[s] = (short) (computedVal/sampleBuffers.length);
outSamples[s] = computedVal;
}
return outSamples;
}```
Das Problem sind gelegentliche Klick, Klack und andere Störgeräusche!
Ich hab sehr viel rumgegoogelt und folgende sehr spannende Website gefunden:
[Mixing and normalizing digital audio](http://www.voegler.eu/pub/audio/digital-audio-mixing-and-normalization.html)
Dort steht etwas von einem Logarithmus und auch genau wie der aussieht, aber ich habe keine Ahnung wie ich den jetzt in Java Code konvertieren kann!
Wäre nett wenn mir jemand dabei oder mit einem Anstoß helfen könnte =)
Danke
EDIT:
Ausprobieren könnt ihr die Funktion einfach so:
public static void main(final String[] args) {
File f1 = …
File f2 = …
AudioInputStream sourceAIS_1 = AudioSystem.getAudioInputStream(f1 );
AudioFormat sourceFormat_1 = sourceAIS_1.getFormat();
AudioInputStream convert1AIS_1 = AudioSystem.getAudioInputStream(SOUND_UTIL.getConvertFormat(sourceFormat_1), sourceAIS_1);
AudioInputStream audioInputStream_1 = new AudioInputStream(convert1AIS_1, convert1AIS_1.getFormat(), convert1AIS_1.getFrameLength());
byte[] sound1 = UTIL.toByteArray(audioInputStream_1);
AudioInputStream sourceAIS_2 = AudioSystem.getAudioInputStream(f2);
AudioFormat sourceFormat_2 = sourceAIS_2.getFormat();
AudioInputStream convert1AIS_2 = AudioSystem.getAudioInputStream(SOUND_UTIL.getConvertFormat(sourceFormat_2), sourceAIS_2);
AudioInputStream audioInputStream_2 = new AudioInputStream(convert1AIS_2, convert1AIS_2.getFormat(), convert1AIS_2.getFrameLength());
byte[] sound2 = UTIL.toByteArray(audioInputStream_2);
playByteArrays(convert1AIS_1.getFormat(), sound1, sound2);
}
public static AudioFormat getConvertFormat(AudioFormat sourceFormat) {
return new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, sourceFormat.getSampleRate(), 16, sourceFormat.getChannels(), sourceFormat.getChannels()*2, sourceFormat.getSampleRate(), false);
}