Вопрос

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

Я сделал копию и писательную часть. Полученный файл идентичен входному файлу. Я использую функции audioFileDbytes () и AudioFileWriteBytes () AudioFile Services в Audiotoolbox Framework для этого.

Таким образом, у меня есть байты входного файла, а также его аудиоданный формат (с помощью использования audiofilegetproperty () с Kaudiofieplepropertydataformat), но я не могу найти в них переменную, чтобы играть с максимальным уровнем громкости исходного файла.

Чтобы прояснить мою цель, я пытаюсь создать еще один звуковой файл, какой уровень объема увеличивается или уменьшается по сравнению с исходным, поэтому мне не волнует уровень громкости системы, который установлен пользователем или iOS.

Можно ли это делать с упомянутой я рамкой? Если нет, есть ли альтернативные предложения?

Спасибо


РЕДАКТИРОВАТЬ: Прогулка по ответу Сэма в отношении некоторых оснований аудио, я решил расширить вопрос с другой альтернативой.

Могу ли я использовать AudioQueue Services для записи существующего звукового файла (который находится в пакете) в другой файл и воспроизводить уровень громкости (с помощью структуры) на этапе записи?


Обновление: вот как я читаю входной файл и пишу вывод. Ниже код снижает уровень звука для «некоторых» значений амплитуды, но с большим количеством шума. Интересно, что если я выберу 0,5 в качестве значения амплитуды, он увеличивает уровень звука вместо его снижения, но когда я использую 0,1 в качестве значения амплитуды, он снижает звук. Оба случая связаны с тревожным шумом. Я думаю, именно поэтому искусство говорит о нормализации, но я понятия не имею о нормализации.

AudioFileID inFileID;

CFURLRef inURL = [self inSoundURL];

AudioFileOpenURL(inURL, kAudioFileReadPermission, kAudioFileWAVEType, &inFileID)

UInt32 fileSize = [self audioFileSize:inFileID];
Float32 *inData = malloc(fileSize * sizeof(Float32)); //I used Float32 type with jv42's suggestion
AudioFileReadBytes(inFileID, false, 0, &fileSize, inData);

Float32 *outData = malloc(fileSize * sizeof(Float32));

//Art's suggestion, if I've correctly understood him

float ampScale = 0.5f; //this will reduce the 'volume' by -6db
for (int i = 0; i < fileSize; i++) {
    outData[i] = (Float32)(inData[i] * ampScale);
}

AudioStreamBasicDescription outDataFormat = {0};
[self audioDataFormat:inFileID];

AudioFileID outFileID;

CFURLRef outURL = [self outSoundURL];
AudioFileCreateWithURL(outURL, kAudioFileWAVEType, &outDataFormat, kAudioFileFlags_EraseFile, &outFileID)

AudioFileWriteBytes(outFileID, false, 0, &fileSize, outData);

AudioFileClose(outFileID);
AudioFileClose(inFileID);
Это было полезно?

Решение

Вы не найдете операции масштабирования амплитуды в (EXT) AudioFile, потому что речь идет о самых простых DSP, которые вы можете сделать.

Давайте предположим, что вы используете Extaudiofile для преобразования того, что вы читаете, в 32-разрядные поплавки. Чтобы изменить амплитуду, вы просто размножаетесь:

float ampScale = 0.5f; //this will reduce the 'volume' by -6db
for (int ii=0; ii<numSamples; ++ii) {
    *sampOut = *sampIn * ampScale;
    sampOut++; sampIn++;
}

Чтобы увеличить усиление, вы просто используете шкалу> 1.f. Например, Ampscale of 2.f даст вам +6 дБ от усиления.

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

Использование AudioQueue Services только для получения доступа к собственности на объем является серьезным, серьезным излишним.

ОБНОВИТЬ:

В вашем обновленном коде вы умножаете каждый байт на 0,5 вместо каждого образца. Вот быстрое исправление для вашего кода, Но см. Мои заметки ниже. Анкет Я бы не стал делать то, что ты делаешь.

...

// create short pointers to our byte data
int16_t *inDataShort = (int16_t *)inData;
int16_t *outDataShort = (int16_t *)inData;

int16_t ampScale = 2;
for (int i = 0; i < fileSize; i++) {
    outDataShort[i] = inDataShort[i] / ampScale;
}

...

Конечно, это не лучший способ сделать что-то: он предполагает, что ваш файл-16-битный линейный PCM с малой эндэндин. (Большинство файлов WAV - это, но не AIFF, M4A, MP3 и т. Д.) Я бы использовал API ExtaudiOfile вместо AUDIOFILE API, поскольку это будет преобразовать любой формат, который вы читаете в любой формат, с которым вы хотите работать в коде. Обычно самое простое, что нужно сделать, это прочитать ваши образцы в 32-разрядном плавании. Вот пример вашего кода с использованием ExtaudioApi для обработки любого входного формата файла, включая Stereo v. Mono

void ScaleAudioFileAmplitude(NSURL *theURL, float ampScale) {
    OSStatus err = noErr;

    ExtAudioFileRef audiofile;
    ExtAudioFileOpenURL((CFURLRef)theURL, &audiofile);
    assert(audiofile);

    // get some info about the file's format.
    AudioStreamBasicDescription fileFormat;
    UInt32 size = sizeof(fileFormat);
    err = ExtAudioFileGetProperty(audiofile, kExtAudioFileProperty_FileDataFormat, &size, &fileFormat);

    // we'll need to know what type of file it is later when we write 
    AudioFileID aFile;
    size = sizeof(aFile);
    err = ExtAudioFileGetProperty(audiofile, kExtAudioFileProperty_AudioFile, &size, &aFile);
    AudioFileTypeID fileType;
    size = sizeof(fileType);
    err = AudioFileGetProperty(aFile, kAudioFilePropertyFileFormat, &size, &fileType);


    // tell the ExtAudioFile API what format we want samples back in
    AudioStreamBasicDescription clientFormat;
    bzero(&clientFormat, sizeof(clientFormat));
    clientFormat.mChannelsPerFrame = fileFormat.mChannelsPerFrame;
    clientFormat.mBytesPerFrame = 4;
    clientFormat.mBytesPerPacket = clientFormat.mBytesPerFrame;
    clientFormat.mFramesPerPacket = 1;
    clientFormat.mBitsPerChannel = 32;
    clientFormat.mFormatID = kAudioFormatLinearPCM;
    clientFormat.mSampleRate = fileFormat.mSampleRate;
    clientFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat | kAudioFormatFlagIsNonInterleaved;
    err = ExtAudioFileSetProperty(audiofile, kExtAudioFileProperty_ClientDataFormat, sizeof(clientFormat), &clientFormat);

    // find out how many frames we need to read
    SInt64 numFrames = 0;
    size = sizeof(numFrames);
    err = ExtAudioFileGetProperty(audiofile, kExtAudioFileProperty_FileLengthFrames, &size, &numFrames);

    // create the buffers for reading in data
    AudioBufferList *bufferList = malloc(sizeof(AudioBufferList) + sizeof(AudioBuffer) * (clientFormat.mChannelsPerFrame - 1));
    bufferList->mNumberBuffers = clientFormat.mChannelsPerFrame;
    for (int ii=0; ii < bufferList->mNumberBuffers; ++ii) {
        bufferList->mBuffers[ii].mDataByteSize = sizeof(float) * numFrames;
        bufferList->mBuffers[ii].mNumberChannels = 1;
        bufferList->mBuffers[ii].mData = malloc(bufferList->mBuffers[ii].mDataByteSize);
    }

    // read in the data
    UInt32 rFrames = (UInt32)numFrames;
    err = ExtAudioFileRead(audiofile, &rFrames, bufferList);

    // close the file
    err = ExtAudioFileDispose(audiofile);

    // process the audio
    for (int ii=0; ii < bufferList->mNumberBuffers; ++ii) {
        float *fBuf = (float *)bufferList->mBuffers[ii].mData;
        for (int jj=0; jj < rFrames; ++jj) {
            *fBuf = *fBuf * ampScale;
            fBuf++;
        }
    }

    // open the file for writing
    err = ExtAudioFileCreateWithURL((CFURLRef)theURL, fileType, &fileFormat, NULL, kAudioFileFlags_EraseFile, &audiofile);

    // tell the ExtAudioFile API what format we'll be sending samples in
    err = ExtAudioFileSetProperty(audiofile, kExtAudioFileProperty_ClientDataFormat, sizeof(clientFormat), &clientFormat);

    // write the data
    err = ExtAudioFileWrite(audiofile, rFrames, bufferList);

    // close the file
    ExtAudioFileDispose(audiofile);

    // destroy the buffers
    for (int ii=0; ii < bufferList->mNumberBuffers; ++ii) {
        free(bufferList->mBuffers[ii].mData);
    }
    free(bufferList);
    bufferList = NULL;

}

Другие советы

Я думаю, что вам следует избегать работы с 8 битами без знака для аудио, если можете. Постарайтесь получить данные как 16 бит или 32 бита, что позволит избежать некоторых проблем с шумом/плохим качеством.

Для большинства распространенных аудио -файлов нет ни одной переменной мастер -тома. Вместо этого вам нужно будет взять (или преобразовать) образцы звука PCM и выполнить хотя бы некоторую минимальную обработку цифровых сигналов (умножьте, насыщенные/предел/AGC, формирование шума квантования и т. Д.) На каждом образце.

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

http://en.wikipedia.org/wiki/audio_bit_depth

Правильно сохраненные аудиофайлы будут иметь максимальный объем на или около максимального значения, доступного для глубины бита файла. Если вы попытаетесь «уменьшить громкость» звукового файла, вы, по сути, просто разбавляете качество звука.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top