问题
I'm trying to get raw audio data from a file (i'm used to seeing floating point values between -1 and 1).
I'm trying to pull this data out of the buffers in real time so that I can provide some type of metering for the app.
I'm basically reading the whole file into memory using AudioFileReadPackets. I've create a RemoteIO audio unit to do playback and inside of the playbackCallback, i'm supplying the mData to the AudioBuffer so that it can be sent to hardware.
The big problem I'm having is that the data being sent to the buffers from my array of data (from AudioFileReadPackets) is UInt32... I'm really confused. It looks like it's 32-bits and I've set the packets/frames to be 4bytes each. How the heck to I get my raw audio data (from -1 to 1) out of this?
This is my Format description
// Describe format
audioFormat.mSampleRate = 44100.00;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioFormat.mFramesPerPacket = 1;
audioFormat.mChannelsPerFrame = 2;
audioFormat.mBitsPerChannel = 16;
audioFormat.mBytesPerPacket = 4;
audioFormat.mBytesPerFrame = 4;
I am reading a wave file currently.
Thanks!
回答1:
I'm not sure exactly why you are getting UInt32 data back from this callback, though I suspect that it is actually two interlaced UInt16 packets, one per each channel. Anyways, if you want floating point data from the file, it needs to be converted, and I'm not convinced that the way @John Ballinger recommends is the correct way. My suggestion would be:
// Get buffer in render/read callback
SInt16 *frames = inBuffer->mAudioData;
for(int i = 0; i < inNumPackets; i++) {
Float32 currentFrame = frames[i] / 32768.0f;
// Do stuff with currentFrame (add it to your buffer, etc.)
}
You can't simply cast the frames to the format you want. If you need floating point data, you will need to divide by 32768, which is the maximum possible value for 16-bit samples. This will yield correct floating point data in the {-1.0 .. 1.0} range.
回答2:
Have a look at this function... The data is SInt16.
static void recordingCallback (
void *inUserData,
AudioQueueRef inAudioQueue,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime,
UInt32 inNumPackets,
const AudioStreamPacketDescription *inPacketDesc
) {
// This callback, being outside the implementation block, needs a reference to the AudioRecorder object
AudioRecorder *recorder = (AudioRecorder *) inUserData;
// if there is audio data, write it to the file
if (inNumPackets > 0) {
SInt16 *frameBuffer = inBuffer->mAudioData;
//NSLog(@"byte size %i, number of packets %i, starging packetnumber %i", inBuffer->mAudioDataByteSize, inNumPackets,recorder.startingPacketNumber);
//int totalSlices = 1;
//int framesPerSlice = inNumPackets/totalSlices;
float total = 0;
for (UInt32 frame=0; frame<inNumPackets; frame+=20) {
total += (float)abs((SInt16)frameBuffer[frame]) ;
}
来源:https://stackoverflow.com/questions/3740499/core-audio-audiofilereadpackets-looking-for-raw-audio