[audio] Remove 'clac' noise when playing wave (javasound) (#2670)
* [audio] Remove 'clac' noise when playing wav (javasound) A 'clac' can be heard at the beginning of a wav file when playing on the javasound sink. Close #2669 Signed-off-by: Gwendal Roulleau <gwendal.roulleau@gmail.com>pull/2680/head
parent
0a778df0ad
commit
fa029b265c
bundles/org.openhab.core.audio/src/main/java/org/openhab/core/audio
internal/javasound
utils
|
@ -25,6 +25,7 @@ import javax.sound.sampled.SourceDataLine;
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.core.audio.AudioStream;
|
import org.openhab.core.audio.AudioStream;
|
||||||
|
import org.openhab.core.audio.utils.AudioWaveUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -60,7 +61,10 @@ public class AudioPlayer extends Thread {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
SourceDataLine line;
|
SourceDataLine line;
|
||||||
AudioFormat audioFormat = convertAudioFormat(this.audioStream.getFormat());
|
|
||||||
|
org.openhab.core.audio.AudioFormat openhabAudioFormat = audioStream.getFormat();
|
||||||
|
|
||||||
|
AudioFormat audioFormat = convertAudioFormat(openhabAudioFormat);
|
||||||
if (audioFormat == null) {
|
if (audioFormat == null) {
|
||||||
logger.warn("Audio format is unsupported or does not have enough details in order to be played");
|
logger.warn("Audio format is unsupported or does not have enough details in order to be played");
|
||||||
return;
|
return;
|
||||||
|
@ -87,6 +91,11 @@ public class AudioPlayer extends Thread {
|
||||||
int nRead = 0;
|
int nRead = 0;
|
||||||
byte[] abData = new byte[65532]; // needs to be a multiple of 4 and 6, to support both 16 and 24 bit stereo
|
byte[] abData = new byte[65532]; // needs to be a multiple of 4 and 6, to support both 16 and 24 bit stereo
|
||||||
try {
|
try {
|
||||||
|
// If this is a wav container, we should remove the header from the stream
|
||||||
|
// to avoid a "clack" noise at the beginning
|
||||||
|
if (org.openhab.core.audio.AudioFormat.CONTAINER_WAVE.equals(openhabAudioFormat.getContainer())) {
|
||||||
|
AudioWaveUtils.removeFMT(audioStream);
|
||||||
|
}
|
||||||
while (-1 != nRead) {
|
while (-1 != nRead) {
|
||||||
nRead = audioStream.read(abData, 0, abData.length);
|
nRead = audioStream.read(abData, 0, abData.length);
|
||||||
if (nRead >= 0) {
|
if (nRead >= 0) {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.core.audio.utils;
|
package org.openhab.core.audio.utils;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
@ -31,6 +32,11 @@ import org.openhab.core.audio.AudioFormat;
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class AudioWaveUtils {
|
public class AudioWaveUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This "magic" packet marks the beginning of the read data
|
||||||
|
*/
|
||||||
|
private final static int DATA_MAGIC = 0x64617461;
|
||||||
|
|
||||||
private static final AudioFormat DEFAULT_WAVE_AUDIO_FORMAT = new AudioFormat(AudioFormat.CONTAINER_WAVE,
|
private static final AudioFormat DEFAULT_WAVE_AUDIO_FORMAT = new AudioFormat(AudioFormat.CONTAINER_WAVE,
|
||||||
AudioFormat.CODEC_PCM_SIGNED, false, 16, 705600, 44100L, 1);
|
AudioFormat.CODEC_PCM_SIGNED, false, 16, 705600, 44100L, 1);
|
||||||
|
|
||||||
|
@ -69,4 +75,26 @@ public class AudioWaveUtils {
|
||||||
inputStream.reset();
|
inputStream.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove FMT block (WAV header) from a stream by consuming it until
|
||||||
|
* the magic packet signaling data. Limit to 200 readInt() (arbitrary value
|
||||||
|
* used in sun audio package).
|
||||||
|
* If you don't remove/consume the FMT and pass the data to a player
|
||||||
|
* as if it is a pure PCM stream, it could try to play it and will
|
||||||
|
* do a "click" noise at the beginning.
|
||||||
|
*
|
||||||
|
* @param audio A wav container in an InputStream
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static void removeFMT(InputStream data) throws IOException {
|
||||||
|
DataInputStream dataInputStream = new DataInputStream(data);
|
||||||
|
Integer nextInt = dataInputStream.readInt();
|
||||||
|
int i = 0;
|
||||||
|
while (nextInt != DATA_MAGIC && i < 200) {
|
||||||
|
nextInt = dataInputStream.readInt();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
dataInputStream.readInt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue