Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
QTSound.c
/* |
File: QTSound.c |
Contains: Sound code for QuickTime CreateMovie sample |
Written by: Scott Kuechle |
(based heavily on QuickTime sample code in Inside Macintosh: QuickTime) |
Copyright: © 1998 by Apple Computer, Inc. All rights reserved |
Change History (most recent first) |
<2> 9/28/98 rtm changes for Metrowerks compiler |
<1> 6/26/98 srk first file |
*/ |
/************************************************************ |
* * |
* INCLUDE FILES * |
* * |
*************************************************************/ |
#if !defined(_MSC_VER) && _WIN32 |
#include <Win32Headers.mch> |
#define TARGET_OS_WIN32 1 |
#else |
#include <ConditionalMacros.h> |
#endif |
#if TARGET_OS_WIN32 |
#include <QTML.h> |
#define STRICT |
#include <windows.h> |
#endif |
#include <Resources.h> |
#include <FixMath.h> |
#include <Sound.h> |
#include "CreateMovie.h" |
#include "QTSound.h" |
/************************************************************ |
* * |
* TYPE DEFINITIONS * |
* * |
*************************************************************/ |
typedef SndCommand *SndCmdPtr; |
#if PRAGMA_STRUCT_ALIGN |
#pragma options align=mac68k |
#elif PRAGMA_STRUCT_PACKPUSH |
#pragma pack(push, 2) |
#elif PRAGMA_STRUCT_PACK |
#pragma pack(2) |
#endif |
/* 'snd ' resource format 1 - see the Sound Manager chapter of Inside Macintosh: Sound |
for the details */ |
typedef struct |
{ |
short format; |
short numSynths; |
} Snd1Header, *Snd1HdrPtr, **Snd1HdrHndl; |
/* 'snd ' resource format 2 - see the Sound Manager chapter of Inside Macintosh: Sound |
for the details */ |
typedef struct |
{ |
short format; |
short refCount; |
} Snd2Header, *Snd2HdrPtr, **Snd2HdrHndl; |
#if PRAGMA_STRUCT_ALIGN |
#pragma options align=reset |
#elif PRAGMA_STRUCT_PACKPUSH |
#pragma pack(pop) |
#elif PRAGMA_STRUCT_PACK |
#pragma pack() |
#endif |
/************************************************************ |
* * |
* FUNCTION PROTOTYPES * |
* * |
*************************************************************/ |
static void QTSound_CreateSoundDescription (Handle sndHandle, |
SoundDescriptionHandle sndDesc, |
long *sndDataOffset, |
long *numSamples, |
long *sndDataSize ); |
static long QTSound_GetSndHdrOffset (Handle sndHandle); |
/************************************************************ |
* * |
* CONSTANTS * |
* * |
*************************************************************/ |
#define kOurSoundResourceID 128 |
#define kSoundSampleDuration 1 |
#define kSyncSample 0 |
#define kTrackStart 0 |
#define kMediaStart 0 |
/* |
for the following constants, please consult the Macintosh |
Audio Compression and Expansion Toolkit |
*/ |
#define kMACEBeginningNumberOfBytes 6 |
#define kMACE31MonoPacketSize 2 |
#define kMACE31StereoPacketSize 4 |
#define kMACE61MonoPacketSize 1 |
#define kMACE61StereoPacketSize 2 |
/************************************************************ |
* * |
* QTSound_CreateMySoundTrack() * |
* * |
* Creates a QuickTime movie sound track & media data * |
* * |
*************************************************************/ |
void QTSound_CreateMySoundTrack (Movie theMovie) |
{ |
Track theTrack; |
Media theMedia; |
Handle sndHandle = nil; |
SoundDescriptionHandle sndDesc = nil; |
long sndDataOffset; |
long sndDataSize; |
long numSamples; |
OSErr err = noErr; |
#if TARGET_OS_WIN32 |
char path[MAX_PATH+1]; |
short resID; |
FSSpec fsspec; |
fsspec.vRefNum = 0; |
fsspec.parID = 0; |
GetModuleFileName( NULL, path, MAX_PATH+1); |
NativePathNameToFSSpec((char *)&path, &fsspec, 0); |
/* open our application resource file so we |
can access the Macintosh 'snd ' resource */ |
resID = FSpOpenResFile(&fsspec, fsRdPerm); |
CheckError (ResError(), "FSpOpenResFile error" ); |
#endif |
sndHandle = GetResource ('snd ', kOurSoundResourceID); |
CheckError (ResError(), "GetResource error" ); |
if (sndHandle == nil) |
{ |
return; |
} |
sndDesc = (SoundDescriptionHandle) NewHandle(4); |
CheckError (MemError(), "NewHandle error" ); |
QTSound_CreateSoundDescription (sndHandle, |
sndDesc, |
&sndDataOffset, |
&numSamples, |
&sndDataSize ); |
theTrack = NewMovieTrack (theMovie, 0, 0, kFullVolume); |
CheckError (GetMoviesError(), "NewMovieTrack error" ); |
theMedia = NewTrackMedia (theTrack, SoundMediaType, |
FixRound ((**sndDesc).sampleRate), |
nil, 0); |
CheckError (GetMoviesError(), "NewTrackMedia error" ); |
err = BeginMediaEdits (theMedia); |
CheckError( err, "BeginMediaEdits error" ); |
err = AddMediaSample(theMedia, |
sndHandle, |
sndDataOffset,/* offset in data */ |
sndDataSize, |
kSoundSampleDuration,/* duration of each sound sample */ |
(SampleDescriptionHandle) sndDesc, |
numSamples, |
kSyncSample,/* self-contained samples */ |
nil); |
CheckError( err, "AddMediaSample error" ); |
err = EndMediaEdits (theMedia); |
CheckError( err, "EndMediaEdits error" ); |
err = InsertMediaIntoTrack (theTrack, |
kTrackStart,/* track start time */ |
kMediaStart,/* media start time */ |
GetMediaDuration (theMedia), |
fixed1); |
CheckError( err, "InsertMediaIntoTrack error" ); |
if (sndDesc != nil) |
{ |
DisposeHandle( (Handle)sndDesc); |
} |
} |
/************************************************************ |
* * |
* QTSound_CreateSoundDescription() * |
* * |
* Creates a SoundDescription structure for a given sound * |
* sample * |
* * |
*************************************************************/ |
static void QTSound_CreateSoundDescription (Handle sndHandle, |
SoundDescriptionHandle sndDesc, |
long *sndDataOffset, |
long *numSamples, |
long *sndDataSize ) |
{ |
long sndHdrOffset = 0; |
long sampleDataOffset; |
SoundHeaderPtr sndHdrPtr = nil; |
long numFrames; |
long samplesPerFrame; |
long bytesPerFrame; |
SoundDescriptionPtr sndDescPtr; |
*sndDataOffset = 0; |
*numSamples = 0; |
*sndDataSize = 0; |
SetHandleSize( (Handle)sndDesc, sizeof(SoundDescription) ); |
CheckError(MemError(),"SetHandleSize error"); |
sndHdrOffset = QTSound_GetSndHdrOffset (sndHandle); |
if (sndHdrOffset == 0) |
{ |
CheckError(-1, "QTSound_GetSndHdrOffset error"); |
} |
/* we can use pointers since we don't move memory */ |
sndHdrPtr = (SoundHeaderPtr) (*sndHandle + sndHdrOffset); |
sndDescPtr = *sndDesc; |
sndDescPtr->descSize = sizeof (SoundDescription); |
/* total size of sound description structure */ |
sndDescPtr->resvd1 = 0; |
sndDescPtr->resvd2 = 0; |
sndDescPtr->dataRefIndex = 1; |
sndDescPtr->compressionID = 0; |
sndDescPtr->packetSize = 0; |
sndDescPtr->version = 0; |
sndDescPtr->revlevel = 0; |
sndDescPtr->vendor = 0; |
switch (sndHdrPtr->encode) |
{ |
case stdSH: |
sndDescPtr->dataFormat = kRawCodecType; |
/* uncompressed offset-binary data */ |
sndDescPtr->numChannels = 1; |
/* number of channels of sound */ |
sndDescPtr->sampleSize = 8; |
/* number of bits per sample */ |
sndDescPtr->sampleRate = sndHdrPtr->sampleRate; |
/* sample rate */ |
*numSamples = sndHdrPtr->length; |
*sndDataSize = *numSamples; |
bytesPerFrame = 1; |
samplesPerFrame = 1; |
sampleDataOffset = (Ptr)&sndHdrPtr->sampleArea - (Ptr)sndHdrPtr; |
break; |
case extSH: |
{ |
ExtSoundHeaderPtr extSndHdrP; |
extSndHdrP = (ExtSoundHeaderPtr)sndHdrPtr; |
sndDescPtr->dataFormat = kRawCodecType; |
/* uncompressed offset-binary data */ |
/* we typecast a long to a short here, and it should really be fixed */ |
sndDescPtr->numChannels = (short)extSndHdrP->numChannels; |
/* number of channels of sound */ |
sndDescPtr->sampleSize = extSndHdrP->sampleSize; |
/* number of bits per sample */ |
sndDescPtr->sampleRate = extSndHdrP->sampleRate; |
/* sample rate */ |
numFrames = extSndHdrP->numFrames; |
*numSamples = numFrames; |
bytesPerFrame = extSndHdrP->numChannels * ( extSndHdrP->sampleSize / 8); |
samplesPerFrame = 1; |
*sndDataSize = numFrames * bytesPerFrame; |
sampleDataOffset = (Ptr)(&extSndHdrP->sampleArea) - (Ptr)extSndHdrP; |
} |
break; |
case cmpSH: |
{ |
CmpSoundHeaderPtr cmpSndHdrP; |
cmpSndHdrP = (CmpSoundHeaderPtr)sndHdrPtr; |
/* we typecast a long to a short here, and it should really be fixed */ |
sndDescPtr->numChannels = (short)cmpSndHdrP->numChannels; |
/* number of channels of sound */ |
sndDescPtr->sampleSize = cmpSndHdrP->sampleSize; |
/* number of bits per sample before compression */ |
sndDescPtr->sampleRate = cmpSndHdrP->sampleRate; |
/* sample rate */ |
numFrames = cmpSndHdrP->numFrames; |
sampleDataOffset =(Ptr)(&cmpSndHdrP->sampleArea) - (Ptr)cmpSndHdrP; |
switch (cmpSndHdrP->compressionID) |
{ |
case threeToOne: |
sndDescPtr->dataFormat = kMACE3Compression; |
/* compressed 3:1 data */ |
samplesPerFrame = kMACEBeginningNumberOfBytes; |
*numSamples = numFrames * samplesPerFrame; |
switch (cmpSndHdrP->numChannels) |
{ |
case 1: |
bytesPerFrame = cmpSndHdrP->numChannels |
* kMACE31MonoPacketSize; |
break; |
case 2: |
bytesPerFrame = cmpSndHdrP->numChannels |
* kMACE31StereoPacketSize; |
break; |
default: |
CheckError(-1, "Corrupt sound data" ); |
break; |
} |
*sndDataSize = numFrames * bytesPerFrame; |
break; |
case sixToOne: |
sndDescPtr->dataFormat = kMACE6Compression; |
/* compressed 6:1 data */ |
samplesPerFrame = kMACEBeginningNumberOfBytes; |
*numSamples = numFrames * samplesPerFrame; |
switch (cmpSndHdrP->numChannels) |
{ |
case 1: |
bytesPerFrame = cmpSndHdrP->numChannels |
* kMACE61MonoPacketSize; |
break; |
case 2: |
bytesPerFrame = cmpSndHdrP->numChannels |
* kMACE61StereoPacketSize; |
break; |
default: |
CheckError(-1, "Corrupt sound data" ); |
break; |
} |
*sndDataSize = (*numSamples) * bytesPerFrame; |
break; |
default: |
CheckError(-1, "Corrupt sound data" ); |
break; |
} |
} /* switch cmpSndHdrP->compressionID:*/ |
break; /* of cmpSH: */ |
default: |
CheckError(-1, "Corrupt sound data" ); |
break; |
} /* switch sndHdrPtr->encode */ |
*sndDataOffset = sndHdrOffset + sampleDataOffset; |
} |
/************************************************************ |
* * |
* QTSound_GetSndHdrOffset() * |
* * |
* Returns an pointer to the first sound command in the * |
* sound resource * |
* * |
*************************************************************/ |
static long QTSound_GetSndHdrOffset (Handle sndHandle) |
{ |
short howManyCmds; |
long sndOffset = 0; |
Ptr sndPtr; |
if (sndHandle == nil) |
{ |
return 0; |
} |
sndPtr = *sndHandle; |
if (sndPtr == nil) |
{ |
return 0; |
} |
if ((*(SndListPtr)sndPtr).format == firstSoundFormat) |
{ |
short synths = ((SndListPtr)sndPtr)->numModifiers; |
sndPtr += ( sizeof(Snd1Header) + (sizeof(ModRef) * synths) ); |
} |
else |
{ |
sndPtr += sizeof(Snd2Header); |
} |
howManyCmds = *(short *)sndPtr; |
sndPtr += sizeof(howManyCmds); |
/* |
sndPtr is now at the first sound command--cruise all |
commands and find the first soundCmd or bufferCmd |
*/ |
while (howManyCmds > 0) |
{ |
switch (((SndCmdPtr)sndPtr)->cmd) |
{ |
case (soundCmd + dataOffsetFlag): |
case (bufferCmd + dataOffsetFlag): |
sndOffset = ((SndCmdPtr)sndPtr)->param2; |
howManyCmds = 0; /* done, get out of loop */ |
break; |
default:/* catch any other type of commands */ |
sndPtr += sizeof(SndCommand); |
howManyCmds--; |
break; |
} |
}/* done with all commands */ |
return sndOffset; |
}/* of GetSndHdrOffset */ |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14