Intereting Posts
Как получить расположение файла конфигурации Wi-Fi в android Добавление новых маркеров на карту с помощью ящика кластера не отражает изменений до тех пор, пока я не увеличу масштаб и не уменьшу карту Установка PhoneGap, ошибка выполнения команды 'ant' Загрузка локального файла html в webView android Android SDK – не масштабирование в центре прикосновения Как остановить выполнение Javascript в Android Webview Как я могу программно установить для параметра adjustViewBounds значение true в Android? Поиск и устранение причины большого размера кучи Firebase 2.0 – как бороться с несколькими вкусами (средами) приложения Android? В чем разница между windowBackground и фоном для стиля деятельности? OnRestart () вызывается, когда нажата кнопка «Назад», каким-либо образом предотвратить это? Android Volley дает мне исключение outOfMemory Эспрессо, как подождать некоторое время (1 час)? JQuery Мобильные иконки белые, а не черные на Android Кинжал не создает компоненты для / тестового класса

Как преобразовать образцы pcm в массив байтов как числа с плавающей запятой в диапазоне от -1.0 до 1.0 и обратно?

Алгоритм передискретизации, который я использую, ожидает массив float, содержащий входные образцы в диапазоне от -1,0 до 1,0 . Аудиоданные – 16 бит PCM с частотой 22 кГц .

Я хочу уменьшить размер звука с 22 кГц до 8 кГц, как представить образцы в массиве байтов как числа с плавающей запятой > = -1 и <= 1 и обратно в байтовый массив?

Solutions Collecting From Web of "Как преобразовать образцы pcm в массив байтов как числа с плавающей запятой в диапазоне от -1.0 до 1.0 и обратно?"

Вы задаете два вопроса:

  1. Как снизить производительность с 22 кГц до 8 кГц?

  2. Как конвертировать из float [-1,1] в 16-бит int и обратно?

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

1. Как снизить производительность с 22 кГц до 8 кГц?

Комментирующий намекнул, что это можно решить с помощью FFT. Это неверно (один шаг в повторной выборке – фильтрация. Я упоминаю, почему бы не использовать FFT для фильтрации здесь, если вы заинтересованы: http://blog.bjornroche.com/2012/08/when-to-not-use -fft.html ).

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

  • Используйте библиотеку, которая реализует повторную выборку высокого качества, например libsamplerate
  • Делать что-то быстрое и грязное

Похоже, вы уже пошли с первым подходом, и это здорово.

Быстрое и грязное решение не будет звучать так же хорошо, но, поскольку вы снижаетесь до 8 кГц, я предполагаю, что качество звука не является вашим первоочередным приоритетом. Один быстрый и грязный вариант:

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

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

Если вы действительно хотите реализовать собственное преобразование частоты дискретизации высокого качества, например, полифазный фильтр, вам следует его изучить, а затем задайте любые вопросы, которые у вас есть на https://dsp.stackexchange.com/ , а не здесь.

2. Как конвертировать из float [-1,1] в 16-битный int и обратно?

Это началось c.fogelklou уже, но позвольте мне украсить.

Для начала, диапазон 16-битных целых чисел составляет от -32768 до 32767 (обычно 16-битный звук подписывается). Для преобразования из int в float вы делаете это:

float f; int16 i = ...; f = ((float) i) / (float) 32768 if( f > 1 ) f = 1; if( f < -1 ) f = -1; 

Обычно вам не нужно делать лишние «ограничивающие» (на самом деле это не так, если вы действительно используете 16-битное целое число), но оно есть, если по какой-то причине у вас есть> 16-битные целые числа.

Чтобы преобразовать назад, вы делаете это:

 float f = ...; int16 i; f = f * 32768 ; if( f > 32767 ) f = 32767; if( f < -32768 ) f = -32768; i = (int16) f; 

В этом случае обычно необходимо следить за значениями вне диапазона, особенно значениями, превышающими 32767. Вы можете пожаловаться, что это приводит к некоторым искажениям для f = 1. Этот вопрос горячо обсуждается. Для некоторого (неполного) обсуждения этого, см. Это сообщение в блоге .

Это больше, чем «достаточно хорошо для работы правительства». Другими словами, он будет работать нормально, за исключением случаев, когда вы обеспокоены качеством звука. Поскольку вы собираетесь на 8 кГц, я думаю, что мы установили, что это не так, так что этот ответ в порядке.

Однако, для полноты, я должен добавить это: если вы пытаетесь сохранить вещи абсолютно нетронутыми, имейте в виду, что это преобразование приводит к искажениям. Зачем? Поскольку ошибка при преобразовании из float в int коррелирует с сигналом. Оказывается, корреляция этой ошибки ужасна, и вы действительно можете ее услышать, хотя она очень маленькая. (К счастью, он достаточно мал, что для таких вещей, как речь и низкодинамичная музыка диапазона, это не имеет большого значения). Чтобы устранить эту ошибку, вы должны использовать что-то называемое сглаживание при преобразовании из float в int. Опять же, если это то, о чем вы заботитесь, изучите его и задайте соответствующие конкретные вопросы на https://dsp.stackexchange.com/ , а не здесь.

Вы также можете быть заинтересованы в слайдах из моего рассказа об основах цифрового аудиопрограммирования, в котором есть слайд на эту тему, хотя в основном он говорит то же самое (может быть, даже меньше, чем я только что сказал): http: // blog .bjornroche.com / 2011/11 / горок-от-основ-оф-audio.html

16-битный PCM имеет диапазон от 32768 до 32767. Итак, умножьте каждый из ваших образцов PCM на (1.0f / 32768.0f) в новый массив поплавков и передайте это вашему повторному набору.

Возвращаясь к поплавке после повторной дискретизации, умножьте на 32768.0, насытите (закрепите что-нибудь вне диапазона – 32768 до 32767), округлите (или смените, как упомянул Бьорн), а затем отбросьте его на короткий.

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

 // PcmConvertTest.cpp : Defines the entry point for the console application. // #include <assert.h> #include <string.h> #include <stdint.h> #define SZ 65536 #define MAX(x,y) ((x)>(y)) ? (x) : (y) #define MIN(x,y) ((x)<(y)) ? (x) : (y) int main(int argc, char* argv[]) { int16_t *pIntBuf1 = new int16_t[SZ]; int16_t *pIntBuf2 = new int16_t[SZ]; float *pFloatBuf = new float[SZ]; // Create an initial short buffer for testing for( int i = 0; i < SZ; i++) { pIntBuf1[i] = (int16_t)(-32768 + i); } // Convert the buffer to floats. (before resampling) const float div = (1.0f/32768.0f); for( int i = 0; i < SZ; i++) { pFloatBuf[i] = div * (float)pIntBuf1[i]; } // Convert back to shorts const float mul = (32768.0f); for( int i = 0; i < SZ; i++) { int32_t tmp = (int32_t)(mul * pFloatBuf[i]); tmp = MAX( tmp, -32768 ); // CLIP < 32768 tmp = MIN( tmp, 32767 ); // CLIP > 32767 pIntBuf2[i] = tmp; } // Check that the conversion went int16_t to float and back to int for every PCM value without any errors. assert( 0 == memcmp( pIntBuf1, pIntBuf2, sizeof(int16_t) * SZ) ); delete pIntBuf1; delete pIntBuf2; delete pFloatBuf; return 0; }