Re: Save PCM Stream to AIFF File (was How to play RAW PCM data using CA?)
Re: Save PCM Stream to AIFF File (was How to play RAW PCM data using CA?)
- Subject: Re: Save PCM Stream to AIFF File (was How to play RAW PCM data using CA?)
- From: Doug Wyatt <email@hidden>
- Date: Mon, 27 Apr 2009 08:31:52 -0700
You're making a single AudioStreamPacketDescription to pass to
AudioFileWritePackets, but that's unnecessary with PCM (and apparently
the implementation is declining to generate an error and ignoring it).
Just pass NULL.
The next problem is that you're generating native-endian "ints" (which
are 32-bit on MacOSX) and then writing them to an AIFF, having
declared that you will supply big-endian 16-bit integers.
You have two choices:
[1] do your own byte-swapping (on little-endian machines only) to
generate the big-endian integers the file format expects. And make
sure to generate 16-bit integers.
[2] use ExtendedAudioFile to insulate you from that level of detail.
If you choose to use ExtendedAudioFile, the outline of the recipe is
to create the file specifying the same file data format you currently
are specifying (16-bit big endian integers), and then set the file's
_client_ data format to whatever format you are planning to generate,
32-bit native endian integers in your current implementation, though
it would be best to use a type with an explicit size, like int32_t,
SInt16 or Float32.
Doug
On Apr 27, 2009, at 8:05 AM, malcom wrote:
On Mon, Apr 27, 2009 at 4:45 PM, Doug Wyatt <email@hidden> wrote:
If you call AudioFileWritePackets instead of AudioFileSetUserData,
you will
be storing your audio data where other applications expect to read
it.
Well thank you, a big step forward. Now the file can be read by any
player but the results is a background noise. Now if I try to import
this file (as raw file in Audacity and set Byte Order: No Endianness,
look here http://yfrog.com/4cimmagine1cgrp) i can listen the correct
sound - the chirp. So probability I need to set the byte order in my
AIFF file but I don't know where is the costant for it.
I've tried with kLinearPCMFormatFlagIsNonInterleaved and
kAudioFormatFlagsAreAllClear but nothing.
(This is the fixed code for archives purpose):
#import "MainController.h"
#import <AudioToolbox/AudioToolbox.h>
void WriteChirpAIFFFile(FSRef fsRef, CFStringRef newFile);
int* generateChirpSignalBuffer(double freq_start,double freq_end,int
duration_secs,long sample_rate, int bits_persample, int
*ret_totalSamples);
#define kFileName @"testme.aiff"
#define kDefaultLocation @"~/Desktop/"
- (void) writeAIFF {
NSLog(@"%d",sizeof(int));
FSRef fsRef;
// try to make an AIFF file in desktop (this call fails if the file
exists yet)
NSString *fPath = [[NSString
stringWithFormat:@"%@%@",kDefaultLocation,kFileName]
stringByStandardizingPath];
if ([[NSFileManager defaultManager] fileExistsAtPath:fPath] == YES)
[[NSFileManager defaultManager] removeFileAtPath: fPath
handler:nil]; // remove old file if it exists
// make our aiff file
CFURLGetFSRef((CFURLRef)[NSURL fileURLWithPath:[kDefaultLocation
stringByStandardizingPath]], &fsRef);
WriteChirpAIFFFile(fsRef, (CFStringRef)kFileName);
}
void WriteChirpAIFFFile(FSRef fsRef, CFStringRef newFile) {
// setup the format
Float64 sampleRate = 44100; // 44100 sample rate frequency
UInt32 bitsPerChannel = 16; // 16 bits of data
double start_freq = 1000; // starting frequency is 1000Hz
double end_freq = 10000; // end frequency is 10000Hz
int duration = 10; // duration of chirp is 10 seconds
// setup audio stream description
AudioStreamBasicDescription aiffFormat;
aiffFormat.mSampleRate = sampleRate; // sample rate data
aiffFormat.mFormatID = kAudioFormatLinearPCM; // linear pulse-code
modulation data
// importing my stream data in Audacity I need to set the endianess
parameter (not big endian or little endian)
// so... the error could be in here, but I don't know how to solve
it.
aiffFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger |
kLinearPCMFormatFlagIsPacked |
kLinearPCMFormatFlagIsBigEndian;
aiffFormat.mBytesPerPacket = 4; // The number of bytes in a
packet of data.
aiffFormat.mFramesPerPacket = 1; // In uncompressed audio, a
Packet is one frame, (mFramesPerPacket == 1)
aiffFormat.mBytesPerFrame = 4; // The number of bytes in a
packet of data.
aiffFormat.mChannelsPerFrame = 1;
aiffFormat.mBitsPerChannel = bitsPerChannel;
FSRef outRef;
AudioFileID audioFileID;
// create our AIFF audio file structure (headers only)
OSStatus status = AudioFileCreate(&fsRef, newFile,
kAudioFileAIFFType, &aiffFormat, 0, &outRef, &audioFileID);
if (status == kAudioFormatUnsupportedDataFormatError)
NSLog(@"error: audio format is not supported"); // ops something
wrong in audio format params...
else if (status == noErr) NSLog(@"all done, file was created"); //
okay
else NSLog(@"Other error occurred: %d",status); // something else
goes wrong
int total_fileSize = 0;
// generate chirp signal from 1000Hz to 10000Hz of 10 secs at
16bit/44100 sample rate
int *arr = generateChirpSignalBuffer(start_freq, end_freq, duration,
(long)sampleRate, bitsPerChannel,&total_fileSize);
// copy buffer data to file
//status = AudioFileSetUserData(audioFileID, kAudioFileAIFFType, 0,
total_fileSize, arr);
//if (status == noErr)
// NSLog(@"%d bytes of data, our chirp stream of shorts, was copied
successfully to aiff file",total_fileSize);
AudioStreamPacketDescription asbd;
asbd.mDataByteSize = total_fileSize;
asbd.mStartOffset = 0;
asbd.mVariableFramesInPacket = 0; // not variable
UInt32 pullPackets = total_fileSize;
status = AudioFileWritePackets(audioFileID, NO, total_fileSize*4,
&asbd, 0, &pullPackets, arr);
if (status == noErr)
NSLog(@"%d bytes of data, our chirp stream of shorts, was copied
successfully to aiff file",total_fileSize);
// close and free memory
// AT THIS TIME THE FILE IS CORRECTLY FILLED WITH OUR STREAM DATA BUT
// BOTH THE FINDER AND AUDIO APPS SAYS "FILE FORMAT ERROR".
// IF I TRY TO IMPORT IT AS RAW DATA (or import the raw buffer data
without the aiff headers)
// IT WORKS FINE!
// JUST A NOTE: in Audacity i need to import is as endianess format
AudioFileClose(audioFileID);
free(arr);
}
#define MIN_INT -32768
#define MAX_INT 32767
#define PI 3.141592653
int* generateChirpSignalBuffer(double freq_start,double freq_end,int
duration_secs,long sample_rate, int bits_persample, int
*ret_totalSamples) {
long len_array = (long)duration_secs*sample_rate; // this is the
number of samples to generate
*ret_totalSamples = len_array; // store the total sample we will make
// short *wavesamples = malloc(len_array*sizeof(short));
int *wavesamples = malloc(len_array*sizeof(int));
int i; for (i=0; i < len_array; i++) // some funky initializations...
wavesamples[i] = 0;
double k = (freq_end-freq_start)/len_array;
double freq = freq_start; // this is our time-to-time frequency value
double omega = (double)(PI / sample_rate);
long t;
for (t=0; t < len_array; t++) {
freq += k; // increase frequency over the time with the omega value
double c_sample = sin(omega*freq*t)*MAX_INT;
// wavesamples[t] = (short)c_sample; // okay we have our sample at
time t
wavesamples[t] = (int)c_sample; // okay we have our sample at time t
}
return wavesamples; // okay, our array now contains a sequence of
mono short signed pcm data
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden