从iPhone上的线性PCM中提取幅度数据 [英] Extracting Amplitude Data from Linear PCM on the iPhone

查看:197
本文介绍了从iPhone上的线性PCM中提取幅度数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难从存储在audio.caf中的iPhone上的线性PCM中提取幅度数据。

I'm having difficulty extracting amplitude data from linear PCM on the iPhone stored in a audio.caf.

我的问题是:


  1. 线性PCM将幅度采样存储为16位值。这是正确的吗?

  2. 振幅如何存储在AudioFileReadPacketData()返回的数据包中?录制单声道线性PCM时,不是每个样本(在一个帧中,在一个数据包中)只是一个SInt16阵列?什么是字节顺序(大端与小端)?

  3. 线性PCM幅度的每一步在物理上是什么意思?

  4. 线性PCM时记录在iPhone上,是中心点0(SInt16)还是32768(UInt16)?物理波形/气压的最大最小值是什么意思?

  1. Linear PCM stores amplitude samples as 16-bit values. Is this correct?
  2. How is amplitude stored in packets returned by AudioFileReadPacketData()? When recording mono linear PCM, isn't each sample, (in one frame, in one packet) just an array for SInt16? What is the byte order (big endian vs. little endian)?
  3. What does each step in linear PCM amplitude mean physically?
  4. When linear PCM is recorded on the iPhone, is the center point 0 (SInt16) or 32768 (UInt16)? What do the max min values mean in the physical wave form/air pressure?

和一个奖励问题:是否有声音/气压iPhone麦克风无法测量的波形?

and a bonus question: Are there sound/air pressure wave forms that the iPhone mic can't measure?

我的代码如下:

// 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!这对我没有任何意义。

With this code I almost always get a min of 0 and a max of 128! That makes no sense to me.

我正在使用AVAudioRecorder录制音频,如下所示:

I'm recording the audio using the AVAudioRecorder as follows:

// 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的第一个项目,所以请随意撕开我的方法!

Thanks for any insight you can offer. This is my first project using Core Audio, so feel free to tear apart my approach!

P.S。我试图搜索Core Audio列表存档,但请求一直出错:( http://search.lists.apple.com/?q=linear+pcm+amplitude&cmd=Search%21&ul=coreaudio-api

P.S. I have tried to searched the Core Audio list archives, but the request keeps giving an error: ( http://search.lists.apple.com/?q=linear+pcm+amplitude&cmd=Search%21&ul=coreaudio-api )

PPS我看过:

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

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

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

获取给定时间内的振幅声音文件?

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

我还阅读了整个Core Audio Overview和大部分音频会话编程指南,但我的问题仍然存在。

I have also read the entirety of the Core Audio Overview and most of the Audio Session Programming Guide, but my questions remain.

推荐答案

1)os x / iphone文件读取例程允许您确定样本格式,通常是SInt8,SInt16,SInt32,Float32,Float64或连续的24位签名之一对于LPCM

1) the os x/iphone file read routines allow you to determine the sample format, typically one of SInt8, SInt16, SInt32, Float32, Float64, or contiguous 24 bit signed int for LPCM

2)对于int格式,MIN_FOR_TYPE表示负相位的最大幅度,MAX_FOR_TYPE表示正的最大幅度。 0等于沉默。浮点格式在[-1 ... 1]之间调制,与浮点数一样为零。在读取,写入,记录或使用特定格式时,字节顺序很重要 - 文件可能需要特定格式,并且您通常希望以本机字节顺序操作数据。 apple audio file libs中的一些例程允许您传递表示源字节序的标志,而不是手动转换它。 CAF有点复杂 - 它就像一个或多个音频文件的元包装器,支持多种类型。

2) for int formats, MIN_FOR_TYPE represents the max amplitude in the negative phase, and MAX_FOR_TYPE represents the maximum amplitude in the positive. 0 equals silence. floating point formats modulate between [-1...1], with zero as with float. when reading, writing, recording, or working with a specific format, endianness will matter - a file may require a specific format, and you typically want to manipulate the data in the native endianness. some routines in the apple audio file libs allow you to pass a flag denoting source endianness, rather than you manually converting it. CAF is a bit more complicated - it acts like a meta wrapper for one or more audio files, and supports many types.

3)lpcm的幅度表示只是一个蛮力线性幅度表示(播放时不需要转换/解码,幅度步长相等)。

3) the amplitude representation for lpcm is just a brute-force linear amplitude representation (no conversion/decoding is required to playback, and the amplitude steps are equal).

4)见#2。这些值与气压无关,它们与0 dBFS有关;例如如果您将流直接输出到DAC,那么int max(如果浮点数为-1/1,则表示单个样本将剪切的级别)。

4) see #2. the values are not related to air pressure, they are related to 0 dBFS; e.g. if you're outputting the stream straight to a DAC, then the int max (or -1/1 if floating point) represents the level at which an individual sample will clip.

Bonus)它像每个ADC和组件链一样,在电压方面对输入的处理能力有限制。此外,采样率定义了可捕获的最高频率(最高为采样率的一半)。 adc可以使用固定或可选择的位深度,但选择另一位深度时,最大输入电压通常不会改变。

Bonus) it, like every ADC and component chain has limits to what it can handle on input in terms of voltage. additionally, the sampling rate defines the highest frequency that may be captured (the highest being half of the sampling rate). the adc may use a fixed or selectable bit depth, but the max input voltage does not generally change when choosing another bit depth.

您在代码中犯了一个错误level:你正在操纵`outBuffer'作为字符 - 而不是SInt16

one mistake you're making at the code level: you're manipulating `outBuffer' as chars - not SInt16

这篇关于从iPhone上的线性PCM中提取幅度数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆