Сложность переноса исходного кода вывода PCM с Java на Android AudioTrack API - PullRequest
8 голосов
/ 25 апреля 2010

Я пытаюсь портировать приложение, которое воспроизводит музыкальные файлы с микросхемами (NSF, SPC и т. Д.) С Java SE на Android. В Android API, похоже, отсутствуют мультимедийные классы javax, которые это приложение использует для вывода необработанного звука PCM. Ближайший аналог, который я нашел в API, это AudioTrack, и я боролся с этим.

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

Настройка DataLine в исходном коде выглядит примерно так:

AudioFormat audioFormat = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
                44100, 16, 2, 4, 44100, true );
DataLine.Info lineInfo = new DataLine.Info( SourceDataLine.class, audioFormat );
DataLine line = (SourceDataLine)AudioSystem.getLine( lineInfo );

Конструктор, который я сейчас использую:

AudioTrack = new AudioTrack( AudioManager.STREAM_MUSIC,
        44100,
        AudioFormat.CHANNEL_CONFIGURATION_STEREO,
        AudioFormat.ENCODING_PCM_16BIT,
        AudioTrack.getMinBufferSize( 44100,
                AudioFormat.CHANNEL_CONFIGURATION_STEREO,
                AudioFormat.ENCODING_PCM_16BIT ),
        AudioTrack.MODE_STREAM );

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

1 Ответ

7 голосов
/ 28 апреля 2010

Итак, у меня было немного времени, чтобы посмотреть на это сегодня, и я думаю, что прибил это. В объявлении AudioFormat в первом примере кода выше для параметра с прямым порядком байтов установлено значение «true», но Android AudioTrack ожидает, что данные PCM будут иметь формат с прямым порядком байтов.

Итак, я написал небольшую небольшую петлю, чтобы проверить мою догадку так:

 for( int i = 0; i + LEN_PCM_SAMPLE_BYTES < LEN_PCM_BUFFER; i += LEN_PCM_SAMPLE_BYTES ) {
    // Really rude endian conversion.
    byte bytTemp = a_bytBuffer[i];
    a_bytBuffer[i] = a_bytBuffer[i + 1];
    a_bytBuffer[i + 1] = bytTemp;
 }

По сути, этот цикл переворачивает байты каждой (16-битной) выборки в буфере. Это прекрасно работает, за исключением того, что это немного изменчиво, потому что это ужасно неэффективно. Я попытался использовать ByteBuffer, но, похоже, это не переворачивает байты в отдельных сэмплах.

Я придумаю что-то еще лучше, но основная проблема здесь решена. Надеюсь, кто-то еще найдет это полезным!

...