• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Getting raw audio data from an AIFF file
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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.

References: 
 >Re: Getting raw audio data from an AIFF file (From: Peter <email@hidden>)

  • Prev by Date: Re: Getting raw audio data from an AIFF file
  • Next by Date: Re: Start of Distributed MIDI Standard [...]
  • Previous by thread: Re: Getting raw audio data from an AIFF file
  • Next by thread: Re: Getting raw audio data from an AIFF file
  • Index(es):
    • Date
    • Thread