Запись, изменение и воспроизведение звука на iOS - PullRequest
0 голосов
/ 28 февраля 2011

РЕДАКТИРОВАТЬ: В конце я использовал точно так, как я объяснил ниже, AVRecorder для записи речи и openAL для сдвига высоты и воспроизведения. Это сработало довольно хорошо.

У меня есть вопрос относительно записи, изменения и воспроизведения аудио. Я задавал подобный вопрос раньше ( Записывайте, изменяйте высоту звука и воспроизводите звук в режиме реального времени на iOS ), но теперь у меня есть больше информации, и я мог бы обратиться к некоторым дополнительным советам, пожалуйста.

Итак, во-первых, это то, что я пытаюсь сделать (в отдельном потоке к основному потоку):

  1. монитор микрофона iphone
  2. проверка звука больше определенной громкости
  3. если выше порогового значения, начать запись, например человек начинает говорить
  4. продолжать запись, пока громкость не упадет ниже порогового значения, например, человек перестает говорить
  5. изменить высоту записанного звука.
  6. Воспроизведение звука

Я думал об использовании AVRecorder для мониторинга и записи звука, хороший урок здесь: http://mobileorchard.com/tutorial-detecting-when-a-user-blows-into-the-mic/

и я думал об использовании openAL для изменения высоты записанного звука.

Итак, мой вопрос: правильно ли я думаю в списке пунктов выше, я что-то упустил или есть лучший / более простой способ сделать это? Могу ли я избежать микширования аудиотек и просто использовать AVFoundation, чтобы изменить высоту тона?

Ответы [ 2 ]

2 голосов
/ 28 февраля 2011

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

Понятие «громкость» довольно расплывчато.Возможно, вы захотите взглянуть на разницу между вычислением пиковых и среднеквадратичных значений и понять, как интегрировать среднеквадратичное значение за определенный промежуток времени (скажем, 300 мс, который использует измеритель VU).

По сути, вы суммируете всеквадраты значений.Вы бы взяли квадратный корень и преобразовали бы в dBFS с 10 * log10f (sqrt (sum / num_samples)), но вы можете сделать это без sqrt за один шаг с 20 * log10f (sum / num_samples).

Вам нужно будет много отрегулировать время интеграции и пороги, чтобы заставить его вести себя так, как вы хотите.

Для смещения высоты тона, я думаю, OpenAL с этим справится, техника, стоящая за ним, называется bandограниченная интерполяция - https://ccrma.stanford.edu/~jos/resample/Theory_Ideal_Bandlimited_Interpolation.html

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

Пример:

class VUMeter
{

protected:

    // samples per second
    float _sampleRate;

    // the integration time in seconds (vu meter is 300ms)
    float _integrationTime;

    // these maintain a circular buffer which contains
    // the 'squares' of the audio samples

    int _integrationBufferLength;
    float *_integrationBuffer;
    float *_integrationBufferEnd;
    float *_cursor;

    // this is a sort of accumulator to make a running
    // average more efficient

    float _sum;

public:

    VUMeter()
    : _sampleRate(48000.0f)
    , _integrationTime(0.3f)
    , _sum(0.)
    {
        // create a buffer of values to be integrated
        // e.g 300ms @ 48khz is 14400 samples

        _integrationBufferLength = (int) (_integrationTime * _sampleRate);

        _integrationBuffer = new float[_integrationBufferLength + 1];
        bzero(_integrationBuffer, _integrationBufferLength);

        // set the pointers for our ciruclar buffer

        _integrationBufferEnd = _integrationBuffer + _integrationBufferLength;
        _cursor = _integrationBuffer;

    }

    ~VUMeter()
    {
        delete _integrationBuffer;
    }

    float getRms(float *audio, int samples)
    {
        // process the samples
        // this part accumulates the 'squares'

        for (int i = 0; i < samples; ++i)
        {
            // get the input sample

            float s = audio[i];

            // remove the oldest value from the sum

            _sum -= *_cursor;

            // calculate the square and write it into the buffer

            double square = s * s;
            *_cursor = square;

            // add it to the sum

            _sum += square;

            // increment the buffer cursor and wrap

            ++_cursor;

            if (_cursor == _integrationBufferEnd)
                _cursor = _integrationBuffer;
        }

        // now calculate the 'root mean' value in db

        return 20 * log10f(_sum / _integrationBufferLength);
    }
};
1 голос
/ 28 февраля 2011

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

...