Регулировка скорости воспроизведения Android AudioTrack

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

if (deviceIsIOS &&
    targetElement.setSelectionRange &&
    (
        targetElement.type === 'text' ||
        targetElement.type === 'search' ||
        targetElement.type === 'password' ||
        targetElement.type === 'url' ||
        targetElement.type === 'tel'
    )
) {

вместо этого:

if (deviceIsIOS && 
    targetElement.setSelectionRange && 
    targetElement.type.indexOf('date') !== 0 && 
    targetElement.type !== 'time' && 
    targetElement.type !== 'month'
) {
0
задан Jason Nanay 13 July 2018 в 07:48
поделиться

2 ответа

Первый вопрос, который я вижу, это произвольная частота дискретизации.

AudioTrack.getNativeOutputSampleRate вернет частоту дискретизации, используемую звуковой системой. Это может быть 44100, 48000, 96000, 192000 или что угодно. Но похоже, что у вас есть аудиоданные из какого-то независимого источника, который производит данные по очень точной частоте дискретизации.

Предположим, что аудиоданные из источника выбраны с частотой 44100 выборок в секунду. Если вы начнете воспроизводить его на 96000, он будет ускорен и выше.

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

Второе: вы уверены, что процедура readData всегда будет достаточно быстрой, чтобы успешно заполнить буфер, каков бы ни был небольшой буфер, и вернуться назад быстрее, чем буфер воспроизводится?

Вы создали AudioTrack с AudioTrack.getMinBufferSize , переданным как параметр bufferSizeInBytes.

Функция getMinBufferSize возвращает минимальный возможный размер буфера, который можно использовать при этом параметре. Предположим, что он возвращает размер, соответствующий буфере длиной 10 мс. Это означает, что новые данные должны быть подготовлены в течение этого временного интервала. То есть Временной интервал между предыдущим write возвратом элемента управления и новым write будет меньше, чем размер времени буфера.

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

Причины, по которым readData могут задерживаться, могут быть различными: если он считывает данные из файла, то это может задержать ожидание операций ввода-вывода; если он выделяет java-объекты, он может быть наложен на задержку сборщика мусора; если он использует какой-то декодер другого типа источника звука, который использует собственную буферизацию, он может периодически задерживать перезарядку буфера.

Но в любом случае, если вы не создаете синтезатор реального времени который должен как можно скорее реагировать на ввод пользователя, всегда используйте размер буфера, достаточно высокий, но не менее getMinBufferSize. I.e.:

sampleRate = 44100;// sampling rate of the source

int bufSize = sampleRate * 4; // 1 second length; 4 - is the frame size: 2 chanels * 2 bytes per each sample
bufSize = max(bufSize, AudioTrack.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT)); // Not less than getMinBufferSize returns
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
                AudioFormat.CHANNEL_OUT_STEREO,
                AudioFormat.ENCODING_PCM_16BIT,
                bufSize,
                AudioTrack.MODE_STREAM);
0
ответ дан AterLux 17 August 2018 в 13:31
поделиться
  • 1
    Большое спасибо AterLux. Да, вы правы, данные отправляются потоковым устройством через RTP с постоянной частотой дискретизации. Однако у меня нет деталей его конфигурации. Во-вторых, readData возвращает данные из буфера данных, и данные добавляются в буфер по мере поступления в мобильное приложение. Только в маленьком временном окне, которое считывает и записывает блокировку. Кроме того, как чтение, так и отпирание из / в буфер происходит параллельно. – Jason Nanay 13 July 2018 в 12:10
  • 2
    Глядя на настройки кодировщика потокового устройства, я вижу, что он использует частоту дискретизации 16000. Каков метод вычисления необходимого размера буфера для данных, отобранных на 16000? Если недостаточно данных для заполнения всей длины буфера, я должен заполнить оставшуюся длину тишиной (ноль)? – Jason Nanay 13 July 2018 в 12:10
  • 3
    Нет, вы должны заполнить столько данных, сколько у вас есть, но в третьем параметре «write» вместо shortBuffer.length вы должны указать точное количество данных, возвращаемых функцией readData. Поэтому, если readData заполняет только часть буфера, тогда он должен каким-то образом вернуть количество фактических данных. – AterLux 13 July 2018 в 15:47
  • 4
    readData использует длину shortBuffer как минимальную длину. Если недостаточно данных, он возвращает ноль, не указывает никаких данных. Если возвращается нулевая длина, я нажимаю пустой массив с минимальной длиной до AudioTrack.write. – Jason Nanay 13 July 2018 в 22:36
  • 5
    Затем вы должны пересмотреть, как readData заполняет массив. И определенно не передавать пустые массивы методу write. – AterLux 13 July 2018 в 23:10

Как и пользователь @pskink,

Скорее всего, ваш sampleRate (или любой другой параметр, переданный конструктору AudioTrack) недействителен.

Итак, я начните с проверки того, какое значение вы фактически устанавливаете для частоты дискретизации.

Для справки вы также можете установить скорость AudioTrack, вызвав метод setPlayBackParams:

public void setPlaybackParams (PlaybackParams params)

Если вы проверите документы AudioTrack docs , вы увидите документы PlaybackParams и можете установить скорость и pitch выходного аудио. Затем этот объект можно передать, чтобы установить параметры воспроизведения в вашем объекте AudioTrack.

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

0
ответ дан WoodyDev 17 August 2018 в 13:31
поделиться
  • 1
    Частота выборки извлекается из метода AudioTrack.getNativeOutputSampleRate () (добавляется к исходному вопросу). Я попытался установить частоту дискретизации на разные значения, но ничего из этого не получилось. – Jason Nanay 13 July 2018 в 07:50
Другие вопросы по тегам:

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