Android: Audio Track (Stream-Mode) перерывает запись

Эта ошибка может быть вызвана неконтролируемыми требованиями к Java-версии.

В моем случае я смог разрешить эту ошибку, создав высокопрофильный проект с открытым исходным кодом, переключившись с Java 9 на Java 8 используя SDKMAN! .

sdk list java
sdk install java 8u152-zulu
sdk use java 8u152-zulu

Затем выполните чистую установку, как описано ниже.


При использовании Maven в качестве инструмента построения иногда полезно - и, как правило, приятно, сделать clean сборку установки с отключенным тестированием.

mvn clean install -DskipTests

Теперь, когда все построенный и установленный, вы можете продолжить и запустить тесты.

mvn test

0
задан BlockLab 17 January 2019 в 19:43
поделиться

1 ответ

Основная причина этого оказалась: вы использовали функцию decode() таким образом, для которого она не была специально разработана. Даже если кажется, что decode() позволит вам декодировать любую часть потока .mp3 способом произвольного доступа, на практике первые несколько мс возвращенного аудио всегда всегда молчат , независимо от того, начинаете ли вы в начале песни или в середине. Это молчание вызывало «пробелы». По-видимому, функция decode() была больше предназначена для повторного запуска воспроизведения в случайном месте, например, из-за пользовательского «поиска».

decode() ведет себя таким образом, потому что для декодирования N-го блока сжатых данных декодеру требуется как блок N-1 , так и блок N. Декомпрессированные данные, которые соответствуют блоку N, будут хорошо, но данные для блока N-1 будут иметь этот звук "постепенного появления". Это общая особенность декодеров .mp3, и я знаю, что это происходит и с AAC. Между тем, декодирование блоков N + 1, N + 2, N + 3 и т. Д. Не представляет проблем, поскольку в каждом случае декодер уже имеет предыдущий блок.

Одним из решений является изменение функции decode():

private Decoder decoder;
private float totalMs;
private Bitstream bitstream;
private InputStream inputStream;

//call this once, when it is time to start a new song:
private void startNewSong(String path) throws IOException
{
    decoder = new Decoder();
    totalMs = 0;
    File file = new File(path);
    inputStream = new BufferedInputStream(new FileInputStream(file), 8 * 1024);
    bitstream = new Bitstream(inputStream);
}

private byte[] decode(String path, int startMs, int maxMs)
        throws IOException {
    ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024);


    try {
        boolean done = false;
        while (! done) {
            Header frameHeader = bitstream.readFrame();
            if (frameHeader == null) {
                done = true;
                inputStream.close();   //Note this change. Now, the song is done. You can also clean up the decoder here.
            } else {
                totalMs += frameHeader.ms_per_frame();

                SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);

                if (output.getSampleFrequency() != 44100
                        || output.getChannelCount() != 2) {
                    Log.w("ERROR", "mono or non-44100 MP3 not supported");
                }

                short[] pcm = output.getBuffer();
                for (short s : pcm) {
                    outStream.write(s & 0xff);
                    outStream.write((s >> 8) & 0xff);
                }

                if (totalMs >= (startMs + maxMs)) {
                    done = true;
                }
            }
            bitstream.closeFrame();
        }
    } catch (BitstreamException e) {
        throw new IOException("Bitstream error: " + e);
    } catch (DecoderException e) {
        Log.w("ERROR", "Decoder error", e);
    }
    return outStream.toByteArray();
}

Этот код немного грубоват. готов, и это может использовать некоторые улучшения. Но общий подход, вместо произвольного доступа, decode() использует FSM , чтобы каждый раз декодировать немного больше песни; прочитайте немного больше файла и отправьте еще несколько кусков в декодер. Поскольку состояние декодера (и bitstream) сохраняется между каждым вызовом decode(), нет необходимости искать блок N-1.

UDP и потоковая передача

Достоверность вашего подхода UDP зависит от многих вещей. Вы можете искать другие вопросы, которые касаются именно этого. UDP удобен для широковещательной рассылки на несколько устройств в данной подсети, но он не поможет вам гарантировать, что пакеты получены в порядке или вообще. Вы можете хотеть TCP вместо этого. Также подумайте, хотите ли вы передать закодированные блоки .mp3 (возвращенные bitstream.readFrame()) или блоки распакованного звука. Также подумайте о том, как вы будете справляться с задержкой в ​​сети, разрывом соединений и буферизацией. Здесь есть много сложных дизайнерских решений, и у каждого выбора есть свои плюсы и минусы. Удачи.

0
ответ дан greeble31 17 January 2019 в 19:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: