Re: Getting raw audio data from an AIFF file
Re: Getting raw audio data from an AIFF file
- Subject: Re: Getting raw audio data from an AIFF file
- From: john <email@hidden>
- Date: Mon, 17 Feb 2003 17:02:08 -0500
Hi Peter,
Too add to this discussion if you're interested, here is some ObjC code
for reading an AIFF file modified from SOX I think and just has basic
support. Supporting the sowt type (for the audio CD) would be a quick
check, but it's not in the code now. There may very well be
problems/mistakes with this, but it does work.
-- John
- (BOOL)examineFile: (NSFileHandle*)theFileHandle
{
char chunkHeader[4];
unsigned long totalFileSize = 0;
unsigned long chunkSize = 0;
unsigned short channels = 0;
unsigned long frames = 0;
unsigned short bits = 0;
UInt8 theRate[10];
BOOL foundCOMM = NO;
BOOL foundSSND = NO;
unsigned long offset = 0;
unsigned long blockSize = 0;
unsigned long audioDataSize = 0;
unsigned long audioOffset = 0;
// seek to the first bit
[theFileHandle seekToFileOffset: 0];
// get the bytes we need
[[theFileHandle readDataOfLength: 4] getBytes: &chunkHeader];
// make sure it is the FORM chunk
if (strncmp(chunkHeader, "FORM", 4) != 0)
{ // return out of here
return NO;
}
// get the reported file size
[[theFileHandle readDataOfLength: 4] getBytes: &totalFileSize];
// get the bytes we need
[[theFileHandle readDataOfLength: 4] getBytes: &chunkHeader];
// make sure this is the AIFF chunk
if ((strncmp(chunkHeader, "AIFF", 4) != 0) && (strncmp(chunkHeader,
"AIFC", 4) != 0))
{ // return out of here
return NO;
}
// we just skip everything but the COMM chunk and the SSND chunk
while (!(foundCOMM) || !(foundSSND))
{
// break if we've hit the end of the file
if (totalFileSize == [theFileHandle offsetInFile])
{ // post to the log
break;
}
// read some bytes
[[theFileHandle readDataOfLength: 4] getBytes: &chunkHeader];
// see if we are at the COMM chunk
if (strncmp(chunkHeader, "COMM", 4) == 0)
{ // read the bits we need
[[theFileHandle readDataOfLength: 4] getBytes: &chunkSize];
[[theFileHandle readDataOfLength: 2] getBytes: &channels];
[[theFileHandle readDataOfLength: 4] getBytes: &frames];
[[theFileHandle readDataOfLength: 2] getBytes: &bits];
// read the rate
[[theFileHandle readDataOfLength: 10] getBytes: &theRate];
// do this so we know how much there is left to read
chunkSize -= 18;
// if there is still some size left?
if (chunkSize > 0)
{
char miscHeader[4];
// read the next 4 bytes
[[theFileHandle readDataOfLength: 4] getBytes:
&miscHeader];
// decrement this too
chunkSize -= 4;
// see if we have compressed data
if (strncmp(miscHeader, "NONE", 4) != 0)
{ // break out of here
break;
}
}
// if we have bytes left
if (chunkSize > 0)
{ // make a variable using the chunk size
unsigned theData[chunkSize];
// just read to increment the file position
[[theFileHandle readDataOfLength: chunkSize] getBytes:
&theData];
}
// update so we know we found this
foundCOMM = YES;
}
// else if we're at the SSND chunk
else if (strncmp(chunkHeader, "SSND", 4) == 0)
{ // read in the bits we need
[[theFileHandle readDataOfLength: 4] getBytes: &chunkSize];
[[theFileHandle readDataOfLength: 4] getBytes: &offset];
[[theFileHandle readDataOfLength: 4] getBytes: &blockSize];
// subtract this
chunkSize -= 8;
// save these
audioDataSize = chunkSize;
// must calculate this based on where we are
audioOffset = offset + 12 + [theFileHandle offsetInFile];
// update this so we know
foundSSND = YES;
}
// else we're at another chunk type we don't care about
else
{ // is this a bogus file, probably from the Mac?
if ((chunkHeader[0] < 'A' || chunkHeader[0] > 'Z') ||
(chunkHeader[1] < 'A' || chunkHeader[1] > 'Z')
||
(chunkHeader[2] < 'A' || chunkHeader[2] > 'Z')
||
(chunkHeader[3] < 'A' || chunkHeader[3] > 'Z'))
break;
// get our chunk size
[[theFileHandle readDataOfLength: 4] getBytes: &chunkSize];
// if we have bytes
if (chunkSize > 0)
{ // make this just read the data
UInt8 theData[chunkSize];
// just read in the data to increment the file position
[[theFileHandle readDataOfLength: chunkSize] getBytes:
&theData];
}
}
}
// if we found the COMM and SSND chunks
if (foundCOMM && foundSSND)
{
// decide if we support this file
}
// else if we didn't find it
else
{ // just return that we can't support this file
return NO;
}
// return YES
return YES;
}
>
Hello everyone,
>
>
I'm about to check out the AudioFile API but would like clarification
>
before I abandon where I am. I've been working on using file calls
>
and wanted to ask about reading in the headers. I'm just beginning so
>
robustness and coolness are not adjectives that apply to this code.
>
>
I'm using an AIFC copied straight from a CD to the Finder. No
>
importing has been done.
>
OS 10.2.4 and Project Builder Version 2.1 (December 2002 Developer
>
Tools)
>
Newest Core
>
>
I want to skip all headers after the FORM chunk is read and go to the
>
SSND chunk so I can start playing the audio. While my chunkID is
>
'SSND' (a four char array), I print it out and get 'SSND\277\260'
>
instead. Why would there be more than the four chars printing out?
>
This is a problem because my chunk skipping routine doesn't know when
>
to stop. You can see that I stop now by doing four char comparisons.
>
Ugh.
>
>
Here's some _optional_ weirdness that I have; it involves the
>
debugger. See that AIFC type check? When I run my program, strcmp
>
evaluate to true but when I debug, that if statement evaluates to
>
true, and the program returns an error. It's commented out here so I
>
can get down to the other code while I debug. It's weird that two
>
different actions occur when running or debugging without a code
>
modification. Since I have no idea what to do, I tried swapping
>
"#import <Foundation/Foundation.h>" with "#include <string.h>" and had
>
nothing change.
>
>
I've been looking at The Omni Group's SoundExample for reference and
>
changing things to chars and ints instead of everything being unsigned
>
ints. I can understand my code better. No bit-shifting or "and-ing"
>
is involved. Any other raw code examples pop into your mind?
>
>
I appreciate any help. It would be great if it was a "Wow, I made a
>
stupid-newbie mistake." type of problem.
>
>
Peter
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.