Любые поддерживаемые форматы звука для Java в Windows 7?

мы будем, я бил головой о стену, пытаясь заставить Java играть в простые wav-файлы без каких-либо успехов. Я пробовал этот код:

Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(new ByteArrayInputStream(soundBytes));
clip.open(inputStream);
clip.start();

это не на "клип.открытый.(..)" за исключением:

javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian not supported.

и я пробовал более сложную (потоковую версию):

int BUFFER_SIZE = 128000;
AudioInputStream audioStream = null;
AudioFormat audioFormat;
SourceDataLine sourceLine = null;

try {
    audioStream = AudioSystem.getAudioInputStream(new ByteArrayInputStream(soundBytes));
} catch (Exception e){
    e.printStackTrace();
}

audioFormat = audioStream.getFormat();

DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
try {
    sourceLine = (SourceDataLine) AudioSystem.getLine(info);
    sourceLine.open(audioFormat);
} catch (LineUnavailableException e) {
    e.printStackTrace();
} catch (Exception e) {
    e.printStackTrace();
}

sourceLine.start();

int nBytesRead = 0;
byte[] abData = new byte[BUFFER_SIZE];
while (nBytesRead != -1) {
    try {
        nBytesRead = audioStream.read(abData, 0, abData.length);
    } catch (IOException e) {
        e.printStackTrace();
    }
    if (nBytesRead >= 0) {
       @SuppressWarnings("unused")
       int nBytesWritten = sourceLine.write(abData, 0, nBytesRead);
    }
}

sourceLine.drain();
sourceLine.close();

это также не удается на " sourceLine.открытый.(..)" за исключением:

javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian not supported.

Я пробовал два разных файла wav, включая почтенный " tada.в формате WAV" это входит C:WindowsMedia - ...

Я также использовал GoldWave для изменения одного из файлов на unsigned 8 bit mono, но это только изменило сообщение об ошибке на:

javax.sound.sampled.LineUnavailableException: line with format PCM_UNSIGNED 44100.0 Hz, 8 bit, mono, 1 bytes/frame,  not supported.

есть мысли о том, где я могу ошибаться? Похоже, играть в простой волновой файл должно быть просто, поэтому я предполагаю, что я где-то вышел в сорняках.

спасибо заранее.

обновление

так, сюжет закручивается. Код работает нормально, если мы переместите его в отдельную автономную java-программу. Что-то в нашем приложении должно готовить способность Java играть звуки.

вот трассировка стека для вышеуказанных ошибок:

javax.sound.sampled.LineUnavailableException: line with format PCM_UNSIGNED 44100.0 Hz, 8 bit, mono, 1 bytes/frame,  not supported.
at com.sun.media.sound.DirectAudioDevice$DirectDL.implOpen(DirectAudioDevice.java:492)
at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:107)
at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:139)
at com.hcs.orc.detail.SoundAddEdit.playButtonActionPerformed(SoundAddEdit.java:315)
at com.hcs.orc.detail.SoundAddEdit.access0(SoundAddEdit.java:40)
at com.hcs.orc.detail.SoundAddEdit.actionPerformed(SoundAddEdit.java:225)

обновление 2

более интересные находки. Кажется, что у нас есть конфликт при загрузке DLL. У нас есть наша собственная DLL, чтобы помочь нам сделать вещи (например, найти надежный и полезный MAC-адрес). Если вы воспроизводите звук (который загружает связанные со звуком библиотеки DLL) перед вы загружаете нашу DLL, затем оба работают. Однако, если вы наша DLL, а затем попытаться воспроизвести звук, звук дает вам ошибки, указанные выше.

у кого-нибудь есть представление о том, почему, казалось бы, несвязанная DLL приведет к неправильной загрузке другой DLL позже?

как запись для действительно хромых и плохих обходных путей, мы можем играть долю секунды тишины при запуске, прежде чем искать MAC-адрес. Это дурной тон по нескольким причинам, включая то, что многие из наших клиентов не используйте звук вообще.

обновление 3

копаясь в нашей библиотеке, кажется, проблема вызвана вызовом RegisterClassEx(...). Мы делаем это, чтобы мы могли отобразить встроенное окно IE с нашим файлом справки HTML.

2 ответов


я столкнулся с подобной проблемой раньше (хотя и не в отношении загрузки DLL.) Javasound работает снизу, используя 1 или более смесителей, каждый с 1 или более линиями. Каждая из этих строк имеет ряд форматов, которые она поддерживает, но это не означает, что он не будет самопроизвольно гореть, когда данный формат для воспроизведения (по сути, ничто не мешает ему хвастаться форматами воспроизведения, которые он не может.)

при использовании AudioSystem.getLine(), он будет перебирать все эти строки из всех этих микшеров и по существу возвращают первый, который встречается, который говорит, что он может обрабатывать этот формат. Если эта линия-большой жирный лжец, тогда она не будет искать других - она просто пойдет с ней и произведет ошибку, которую вы видите.

теперь важно помнить, что порядок, который он повторяет по этим строкам, является обыкновенный произвольных. Таким образом, все может привести к его изменению, включая то, что кажется неуместным, например загрузке DLL. Я вижу одну из двух возможностей здесь, DLL каким-то образом предоставляет другую звуковую линию, которая вызывает проблему, или загрузка DLL просто приводит к изменению произвольного порядка, и когда вы это делаете, по какой-то причине он сталкивается с подозрительной линией.

обходной путь не очень хороший, но это лучше, чем играть звук и ждать немного, вы по существу должны проверить линию, чтобы увидеть, говорит ли она правду:

SourceDataLine dataline = null;
for (Mixer.Info mixerInfo : AudioSystem.getMixerInfo()) {
    try {
        Mixer mixer = AudioSystem.getMixer(mixerInfo);
        dataline = (SourceDataLine)mixer.getLine(info);
        if(dataline==null) {
            continue; //Doesn't support this format
        }
        dataline.open(audioFormat);
        dataline.start();
    }
    catch (Exception ex) {
        //If we get here it's a buggered line, so loop round again
        continue;
    }
    try {
        dataline.close();
    }
    catch (Exception ex) {
        ex.printStackTrace(); //Shouldn't get here
    }
}


if(dataline==null) {
    //No dataline capable of *really* playing the stream
}
else {
    //We have a non-lying dataline!
}

этот способ занимает немного больше времени, но это, по сути, двойная проверка-мы проходим через каждую строку данных, и если это говорит он может воспроизводить формат, мы проверяем, действительно ли он может - и только в этом случае мы определяем, безопасно ли его использовать.


после выяснения, что это была проблема с нашим кодом JNI, делая это:

rc=CoInitialize(NULL);
rc=OleInitialize(NULL);
{
     WNDCLASSEX     wc; 
     // Register the class of our window to host the browser. 'WindowProc' is our message handler
 // and 'ClassName' is the class name. You can choose any class name you want.
 ZeroMemory(&wc, sizeof(WNDCLASSEX));
 wc.cbSize = sizeof(WNDCLASSEX);
 wc.hInstance = hinstance;
 wc.lpfnWndProc = WindowProc;
 wc.lpszClassName = &ClassName[0];
 rc=RegisterClassEx(&wc);
}

Это была проблема, потому что мы вызывали ее в неправильном месте в dllMain(...). Вместо этого мы переместили его в место, где он вызывается только один раз, прямо перед тем, как он действительно нужен для открытия встроенного браузера.

это решило нашу проблему.