0

since there is no easy way in java to access the systems microphones and speakers I tried to implement something like that my self. For this I have a class AudioDevice representing any device.

It is a abstract class defining all method a audiodevice needs and is based on a javax.sound.sampled.Mixer. Then I have the classes Microphone and Speaker which are extending from AudioDevice and are implementing the abstract methods of AudioDevice. Such as transferData(byte[]), open(AudioFormat), isOpen() and close().

When i run my testcode it seems to work since no error are occuring. But for some reason the transferData(byte[]) of my microphone isn't writing any data to the array. If I use a prefilled byte[] and i use it as a parameter for the transferData(byte[]) of my speaker, the speaker isn't playing any sound either.

I've spend multiple hours on searching the error causing this problem and I've also tried to capture/play sound like it is discribed here and it didn't work on my computer either.

Capturing Playing

I have got a Windows Professional N 64-Bit OS if that could be a reason why it isnt working. The Programm is running with Java 8.

This is the code i've come up with

AudioDevice:

public abstract class AudioDevice<E> {

private final static Set<AudioFormat> AUDIO_FORMATS = new HashSet<>();
static {
    final float[] sampleRates = new float[] { 8000.0F, 11025.0F, 16000.0F, 22050.0F, 44100.0F };
    final int[] sampleSizes = new int[] { 8, 16 };
    final int[] channels = new int[] { 1, 2 };

    for (final float sampleRate : sampleRates) {
        for (final int sampleSize : sampleSizes) {
            for (final int channel : channels) {
                final AudioFormat bigEndian_signed = new AudioFormat(sampleRate, sampleSize, channel, true, true);
                final AudioFormat bigEndian_unsigned = new AudioFormat(sampleRate, sampleSize, channel, false,
                        true);
                final AudioFormat littleEndian_signed = new AudioFormat(sampleRate, sampleSize, channel, true,
                        false);
                final AudioFormat littleEndian_unsigned = new AudioFormat(sampleRate, sampleSize, channel, false,
                        false);
                AUDIO_FORMATS.add(littleEndian_unsigned);
                AUDIO_FORMATS.add(bigEndian_unsigned);
                AUDIO_FORMATS.add(bigEndian_signed);
                AUDIO_FORMATS.add(littleEndian_signed);
            }
        }

    }
}

protected final Mixer mixer;
private final Mixer.Info mixerInfo;
private final Class<E> lineType;
private final Set<AudioFormat> supportedFormats = new HashSet<>();

protected AudioFormat currentFormat;
protected E currentDataLine;

public AudioDevice(final Mixer pMixer, final Class<E> pLineType) {
    if (pMixer == null) {
        throw new IllegalArgumentException();
    }
    this.mixer = pMixer;
    this.mixerInfo = pMixer.getMixerInfo();
    this.lineType = pLineType;
    loadSupportedFormats(pLineType);
    if (this.supportedFormats.isEmpty()) {
        throw new IllegalArgumentException();
    }
}

public abstract boolean transferData(final byte[] pBuffer);

public abstract boolean open(final AudioFormat pFormat);

public abstract boolean isOpen();

public abstract boolean close();

public final boolean isUsingFormat(final AudioFormat pFormat) {
    if (isOpen() && this.currentFormat != null) {
        return this.currentFormat.equals(pFormat);
    }
    return false;
}

public final Set<AudioFormat> getSupportedFormats() {
    return this.supportedFormats;
}

public final AudioFormat getCurrentFormat() {
    return this.currentFormat;
}

public final boolean isFormatSupported(final AudioFormat pFormat) {
    if (pFormat != null) {
        final Set<AudioFormat> supportedFormats = getSupportedFormats();
        if (supportedFormats != null) {
            final DataLine.Info info = new Info(this.lineType, pFormat);
            return this.mixer.isLineSupported(info);
        }
    }
    return false;
}

public final String getName() {
    return this.mixerInfo.getName();
}

public final String getDescription() {
    return this.mixerInfo.getDescription();
}

public final String getVendor() {
    return this.mixerInfo.getVendor();
}

public final String getVersion() {
    return this.mixerInfo.getVersion();
}

private final void loadSupportedFormats(final Class<E> pLineType) {
    for (final AudioFormat format : AUDIO_FORMATS) {
        final DataLine.Info info = new Info(pLineType, format);
        if (this.mixer.isLineSupported(info)) {
            this.supportedFormats.add(format);
        }
    }
}
}

Microphone:

public final class Microphone extends AudioDevice<TargetDataLine> {

public Microphone(final Mixer pMixer) {
    super(pMixer, TargetDataLine.class);
}

@Override
public final boolean transferData(final byte[] pBuffer) {
    if (isOpen()) {
        this.currentDataLine.read(pBuffer, 0, pBuffer.length);
        return true;
    }
    return false;
}

@Override
public final boolean open(final AudioFormat pFormat) {
    if (!isOpen() && isFormatSupported(pFormat)) {
        try {
            this.mixer.open();
            final DataLine.Info info = new Info(TargetDataLine.class, pFormat);
            this.currentDataLine = (TargetDataLine) this.mixer.getLine(info);
            this.currentFormat = pFormat;
            return true;
        } catch (final LineUnavailableException e) {
            close();
            return false;
        }
    }
    return false;

}

@Override
public final boolean isOpen() {
    return this.mixer.isOpen() && this.currentDataLine != null;
}

@Override
public final boolean close() {
    if (isOpen()) {
        this.currentDataLine.close();
        this.mixer.close();
        this.currentDataLine = null;
        this.currentFormat = null;
        return true;
    }
    this.currentDataLine = null;
    this.currentFormat = null;
    return false;
}
}

Speaker:

public final class Speaker extends AudioDevice<SourceDataLine> {

public Speaker(final Mixer pMixer) {
    super(pMixer, SourceDataLine.class);
}

@Override
public final boolean transferData(final byte[] pBuffer) {
    if (isOpen()) {
        this.currentDataLine.write(pBuffer, 0, pBuffer.length);
        return true;
    }
    return false;
}

@Override
public final boolean open(final AudioFormat pFormat) {
    if (!isOpen() && isFormatSupported(pFormat)) {
        try {
            this.mixer.open();
            final DataLine.Info info = new Info(SourceDataLine.class, pFormat);
            this.currentDataLine = (SourceDataLine) this.mixer.getLine(info);
            this.currentFormat = pFormat;
            return true;
        } catch (final LineUnavailableException e) {
            close();
            return false;
        }
    }
    return false;

}

@Override
public final boolean isOpen() {
    return this.mixer.isOpen() && this.currentDataLine != null;
}

@Override
public final boolean close() {
    if (isOpen()) {
        this.currentDataLine.close();
        this.mixer.close();
        this.currentDataLine = null;
        this.currentFormat = null;
        return true;
    }
    this.currentDataLine = null;
    this.currentFormat = null;
    return false;
}
}
Tom11
  • 2,419
  • 8
  • 30
  • 56
Basti
  • 1,117
  • 12
  • 32
  • despite the fact that I cannot debug your code because its gonna throw all kinds of fancy errors - have you checked that at least one format is supported? the testcode might be revealing – gpasch May 10 '16 at 16:35
  • @gpasch if the format i try to open the mic/speaker with is not supported, the method open returns false. i only test my stuff if open of the speaker and mic returned true. so yes i am sure that the audioformat i am using for testing is working – Basti May 10 '16 at 18:43
  • you may want to throw in the whole program there – gpasch May 10 '16 at 19:04
  • @gpasch There is no programm to it yet. The only thing i have done so far besides what you see up there is a testclass with a main-method which picks a mic and a speaker, opens both with the same audioformat and then reads data from the mic and writes it to the speaker in a permanent while-loop – Basti May 11 '16 at 09:37

0 Answers0