Кодирование 32-битных стерео семплов AudioUnitCanonical PCM в mp3 с помощью lame

Я напрямую конвертирую 32-битные стереосэмплы из цифровой линии на устройствах iOS, используя добавку для микрофона Mickey Blue, в mp3 с хромой.

Проблема в том, что он принимает только 16-битные образцы. Попытка напрямую конвертировать сэмплы оставляет меня с большим количеством шума и без узнаваемого звука. Настройки, которые я использую для записи звука на iOS, следующие:

AudioStreamBasicDescription stereoStreamFormat;
stereoStreamFormat.mSampleRate          = 44100.00;
stereoStreamFormat.mFormatID            = kAudioFormatLinearPCM;
stereoStreamFormat.mFormatFlags         = kAudioFormatFlagsAudioUnitCanonical;
stereoStreamFormat.mBytesPerPacket      = 4;
stereoStreamFormat.mBytesPerFrame       = 4;
stereoStreamFormat.mFramesPerPacket     = 1;
stereoStreamFormat.mChannelsPerFrame    = 2;
stereoStreamFormat.mBitsPerChannel      = 32;//changing this to 16bit does not work

Затем я конвертирую сэмплы из двух отдельных буферов с помощью lame:

-(void) encodeMicrophoneWithLeft :(NSData*) left andRight : (NSData *) right
{
    void *mp3 = malloc(MP3_SIZE_MIC);
    int write = lame_encode_buffer(microphoneLame, left.bytes, right.bytes, left.length/2, mp3, MP3_SIZE_MIC);
    [self.microphoneBuffer appendBytes:mp3 length:write];
}

С этими настройками:

lame_set_brate(microphoneLame, 128);// current streaming speed kbps
lame_set_in_samplerate(microphoneLame, 44100);
lame_set_VBR(microphoneLame, vbr_off);//set variable bitrate off
lame_set_num_channels(microphoneLame,2);

Можно ли как-нибудь преобразовать 32-битные сэмплы в 16-битные или заставить работать с 32-битными семплами? Рекордер почему-то не работает с настройками, отличными от 32-битных для стерео, но если есть другой способ инициализации с 16-битными, это тоже было бы решением для меня.


person Dirk de Boer    schedule 23.05.2014    source источник
comment
Вы можете просто отрезать младшие 16 бит от образцов PCM.   -  person jaket    schedule 24.05.2014
comment
Спасибо, я пробовал это раньше, но, похоже, это не сработало. Возможно, я допустил некоторые ошибки, поэтому попытаюсь снова пойти по этому пути.   -  person Dirk de Boer    schedule 27.05.2014
comment
Это не сработало, это не математически правильный ответ.   -  person jaket    schedule 27.05.2014
comment
IOW, если у вас есть 32-битный сигнал и вы отбрасываете младшие 16 бит, чтобы получить 16-битный сигнал, то вы мало что сделали, но выбросили незначительную часть сигнала.   -  person jaket    schedule 27.05.2014
comment
Что ж, в предыдущих попытках я получал кучу искажений, обрезав нижние 16 бит, а в других попытках получить действительные сэмплы для хромоты. Искажение казалось совершенно случайным, ничего не слышно. У меня больше нет установки, поэтому я не могу опубликовать более подробное описание банкомата. Я также нашел это, которое кажется, что формат требует немного больше работы. Я опубликую результаты, как только получу их.   -  person Dirk de Boer    schedule 27.05.2014


Ответы (2)


Отбрасывание 16 битов не сработает, потому что kAudioFormatFlagsAudioUnitCanonical делает ваш поток с плавающей запятой :) AudioUnit потоки являются 32-битными с плавающей запятой.

Не используйте kAudioFormatFlagsAudioUnitCanonical для флагов формата. Прочтите шапку и посмотрите, что нужно LAME. kAudioFormatFlagsAreAllClear и mBitsPerChannel из 16 должны работать (также с соответствующими изменениями все поля байтов на кадр и т. д.). Это даст вам 16-битные целые выборки с прямым порядком байтов.

person iluvcapra    schedule 29.05.2014
comment
Спасибо, но, похоже, он принимает только этот конкретный формат со стереозаписью с использованием надстройки Mickey Blue. Он записывает в моно с 16 битами, но мне нужны стереосэмплы. - person Dirk de Boer; 05.06.2014

Похоже, что kAudioFormatFlagsAudioUnitCanonical действительно не просто 32-битный, а 24-битный образец с фиксированной запятой, хранящийся в нотации с плавающей запятой. Старшие 7 битов могут быть отброшены, только младший бит из первых 8 старших битов используется для подписи значения.

       sign    actual sample data
      /       /
|--8--|------24------|
     |----16----| <- part you need

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

Нравится:

NSData *left =[[NSData alloc]initWithBytes:tempBufferLeft.mData length:tempBufferLeft.mDataByteSize ];
NSData *right =[[NSData alloc]initWithBytes:tempBufferRight.mData length:tempBufferRight.mDataByteSize ];

convertedArrayLeft = [[NSMutableData alloc]init];
convertedArrayRight = [[NSMutableData alloc]init];
for (int i = 0; i < left.length; i+=4)//steps of 4 bytes
{
    int tmpValueL, tmpValueR;
    [left getBytes:&tmpValueL range:NSMakeRange(i, 4)];//extract float samples into int for easier manipulation
    [right getBytes:&tmpValueR range:NSMakeRange(i, 4)];

    short endValueL = tmpValueL>>9, endValueR = tmpValueR>>9;//bitshift 9 to the right and save as short to lose most significant 16 bits that are now useless

    [convertedArrayLeft appendBytes:&endValueL length:sizeof(short)];
    [convertedArrayRight appendBytes:&endValueR length:sizeof(short)];
}

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

person Dirk de Boer    schedule 13.06.2014