2010-09-30 3 views
10

У меня возникли трудности с извлечением данных амплитуды из линейного PCM на iPhone, хранящемся в файле audio.caf.Извлечение данных амплитуды из линейного PCM на iPhone

Мои вопросы:

  1. хранит Linear PCM амплитуды выборок, как 16-битовых значений. Это верно?
  2. Как амплитуда хранится в пакетах, возвращаемых AudioFileReadPacketData()? При записи моно линейного PCM не каждый образец (в одном кадре, в одном пакете) просто массив для SInt16? Что такое порядок байтов (большой энтиан против маленького конца)?
  3. Что означает каждый шаг в линейной амплитуде PCM физически?
  4. Когда линейный PCM записан на iPhone, является центральной точкой 0 (SInt16) или 32768 (UInt16)? Что означают значения max min в физической форме волны/давлении воздуха?

и вопрос с бонусом: существуют ли формы звукового/воздушного давления, которые микрофон iPhone не может измерить?

Мой код следующим образом:

// get the audio file proxy object for the audio 
AudioFileID fileID; 
AudioFileOpenURL((CFURLRef)audioURL, kAudioFileReadPermission, kAudioFileCAFType, &fileID); 

// get the number of packets of audio data contained in the file 
UInt64 totalPacketCount = [self packetCountForAudioFile:fileID]; 

// get the size of each packet for this audio file 
UInt32 maxPacketSizeInBytes = [self packetSizeForAudioFile:fileID]; 

// setup to extract the audio data 
Boolean inUseCache = false; 
UInt32 numberOfPacketsToRead = 4410; // 0.1 seconds of data 
UInt32 ioNumPackets = numberOfPacketsToRead; 
UInt32 ioNumBytes = maxPacketSizeInBytes * ioNumPackets; 
char *outBuffer = malloc(ioNumBytes); 
memset(outBuffer, 0, ioNumBytes); 

SInt16 signedMinAmplitude = -32768; 
SInt16 signedCenterpoint = 0; 
SInt16 signedMaxAmplitude = 32767; 

SInt16 minAmplitude = signedMaxAmplitude; 
SInt16 maxAmplitude = signedMinAmplitude; 

// process each and every packet 
for (UInt64 packetIndex = 0; packetIndex < totalPacketCount; packetIndex = packetIndex + ioNumPackets) 
{ 
    // reset the number of packets to get 
    ioNumPackets = numberOfPacketsToRead; 

    AudioFileReadPacketData(fileID, inUseCache, &ioNumBytes, NULL, packetIndex, &ioNumPackets, outBuffer); 

    for (UInt32 batchPacketIndex = 0; batchPacketIndex < ioNumPackets; batchPacketIndex++) 
    { 
     SInt16 packetData = outBuffer[batchPacketIndex * maxPacketSizeInBytes]; 
     SInt16 absoluteValue = abs(packetData); 

     if (absoluteValue < minAmplitude) { minAmplitude = absoluteValue; } 
     if (absoluteValue > maxAmplitude) { maxAmplitude = absoluteValue; } 
    } 
} 

NSLog(@"minAmplitude: %hi", minAmplitude); 
NSLog(@"maxAmplitude: %hi", maxAmplitude); 

С помощью этого кода я почти всегда получаю мин 0 и макс 128! Это не значит для меня смысл .

Я запись звука с помощью AVAudioRecorder следующим образом:

// specify mono, 44.1 kHz, Linear PCM with Max Quality as recording format 
NSDictionary *recordSettings = [[NSDictionary alloc] initWithObjectsAndKeys: 
    [NSNumber numberWithFloat: 44100.0], AVSampleRateKey, 
    [NSNumber numberWithInt: kAudioFormatLinearPCM], AVFormatIDKey, 
    [NSNumber numberWithInt: 1], AVNumberOfChannelsKey, 
    [NSNumber numberWithInt: AVAudioQualityMax], AVEncoderAudioQualityKey, 
    nil]; 

// store the sound file in the app doc folder as calibration.caf 
NSString *documentsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; 
NSURL *audioFileURL = [NSURL fileURLWithPath:[documentsDir stringByAppendingPathComponent: @"audio.caf"]]; 

// create the audio recorder 
NSError *createAudioRecorderError = nil; 
AVAudioRecorder *newAudioRecorder = [[AVAudioRecorder alloc] initWithURL:audioFileURL settings:recordSettings error:&createAudioRecorderError]; 
[recordSettings release]; 

if (newAudioRecorder) 
{ 
    // record the audio 
    self.recorder = newAudioRecorder; 
    [newAudioRecorder release]; 

    self.recorder.delegate = self; 
    [self.recorder prepareToRecord]; 
    [self.recorder record]; 
} 
else 
{ 
    NSLog(@"%@", [createAudioRecorderError localizedDescription]); 
} 

Спасибо за любую проницательность вы можете предложить. Это мой первый проект с использованием Core Audio, поэтому не стесняйтесь оторвать мой подход!

P.S. Я попытался выполнить поиск архивов списка Core Audio, но запрос продолжает давать ошибку: (http://search.lists.apple.com/?q=linear+pcm+amplitude&cmd=Search%21&ul=coreaudio-api)

P.P.S. Я посмотрел на:

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

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

http://wiki.multimedia.cx/index.php?title=PCM

Get the amplitude at a given time within a sound file?

http://music.columbia.edu/pipermail/music-dsp/2002-April/048341.html

Я также прочитал полноту Core Audio Обзор и большинство аудио Программирование сессий Руководство, но мои вопросы остаются.

ответ

7

1) ОС х/iphone чтение файла процедура позволяет определить формат образец, как правило, один из SInt8, SInt16, SInt32, float32, Float64 или смежного 24 разрядного Int для LPCM

2) для int-форматов MIN_FOR_TYPE представляет максимальную амплитуду в отрицательной фазе, а MAX_FOR_TYPE представляет максимальную амплитуду в положительном. 0 равносильно молчанию. форматы с плавающей запятой модулируются между [-1 ... 1], с нулем, как и с поплавком. при чтении, записи, записи или работе с конкретным форматом будет иметь значение конечность - для файла может потребоваться определенный формат, и вы, как правило, хотите манипулировать данными в исходной форме. некоторые подпрограммы в файлах аудиофайлов Apple позволяют передавать флаг, обозначающий исходную сущность, а не его ручное преобразование. CAF немного сложнее - он действует как мета-обертка для одного или нескольких аудиофайлов и поддерживает множество типов.

3) представление амплитуды для lpcm представляет собой просто представление линейной амплитуды грубой силы (для воспроизведения не требуется преобразование/декодирование, а шаги амплитуды равны).

4) см. # 2. значения не связаны с давлением воздуха, они связаны с 0 dBFS; например если вы передаете поток прямо на ЦАП, тогда int max (или -1/1, если с плавающей запятой) представляет уровень, на котором будет зажиматься отдельный образец.

Бонус), так как каждый АЦП и составная цепь имеют ограничения на то, что он может обрабатывать при вводе с точки зрения напряжения. кроме того, частота дискретизации определяет наивысшую частоту, которая может быть захвачена (самая высокая из которых составляет половину частоты дискретизации). adc может использовать фиксированную или выбираемую битовую глубину, но максимальное входное напряжение обычно не изменяется при выборе другой битовой глубины.

одна ошибка, которую вы делаете на уровне кода: вы управляете `outBuffer 'как символы - не SInt16

2
  1. Если вы запрашиваете 16-битные образцы в своем формате записи, вы получаете 16-битные образцы. Но другие форматы существуют во многих API-интерфейсах Core Audio для записи/воспроизведения и в возможных форматах файлов в формате.

  2. В моно вы получите массив подписанных 16-битных ints. Вы можете запросить большой или маленький endian в некоторых API-интерфейсах записи Core Audio.

  3. Если вы не хотите откалибровать микрофон вашего устройства или внешний микрофон (и убедитесь, что обработка звука/AGC выключена), вы можете захотеть, чтобы уровни звука были произвольно масштабированы. Плюс ответ зависит также от направленности микрофона и частоты звука.

  4. Центральная точка для 16-битных звуковых образцов обычно 0 (диапазон от -32 до 32 тыс.). Нет предубеждений.

Смежные вопросы