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.
MusicHelper.c
#include <types.h> |
#include <QuickTimeComponents.h> |
#define _MusicHelperC_ |
#define kFullVolume 256 |
typedef struct |
{ |
short partCount; |
ToneDescription **toneDescriptions; |
FlatInstrument ***flatInstruments; |
long tuneSize; |
long tuneHandleSize; |
unsigned long **tune; |
} MusicScoreRecord, **MusicScore; |
typedef struct |
{ |
Movie mo; |
Track tr; |
Media me; |
MusicDescriptionHandle mdH; |
TimeValue duration; |
short refNum; |
} MusicMovieRecord, **MusicMovie; |
#include "MusicHelper.h" |
#define kTuneHandleBump 1024 |
static void StuffToneDescription(short gmNumber,ToneDescription *td); |
static void BumpTuneHandleSize(MusicScoreRecord *msr); |
static short InternalAddPart(MusicScore ms,ToneDescription *td,FlatInstrument *flat); |
#define hLock(x) HLock((Handle)(x)) |
#define hUnlock(x) HUnlock((Handle)(x)) |
MusicScore NewMusicScore(void) |
{ |
MusicScoreRecord *msr; |
MusicScore ms; |
ms = (MusicScore)NewHandle(sizeof(MusicScoreRecord)); |
hLock(ms); |
msr = *ms; |
msr->partCount= 0; |
msr->toneDescriptions = (ToneDescription **)NewHandle(0); |
msr->flatInstruments = (FlatInstrument ***)NewHandle(0); |
msr->tuneSize = 0; |
msr->tuneHandleSize = kTuneHandleBump; |
msr->tune = (unsigned long**)NewHandle(kTuneHandleBump * sizeof(long)); |
hUnlock(ms); |
return ms; |
} |
void DisposeMusicScore(MusicScore *ms) |
{ |
MusicScoreRecord *msr; |
hLock(*ms); |
msr = **ms; |
DisposeHandle((Handle)msr->toneDescriptions); |
DisposeHandle((Handle)msr->tune); |
*ms = nil; |
} |
short AddMusicScoreGMInstrument(MusicScore ms,short gmInstrument) |
{ |
ToneDescription td; |
StuffToneDescription(gmInstrument,&td); |
return AddMusicScoreInstrument(ms,&td); |
} |
short AddMusicScoreInstrument(MusicScore ms,ToneDescription *td) |
{ |
return InternalAddPart(ms,td,nil); |
} |
short AddMusicScoreFlatInstrument(MusicScore ms,FlatInstrument *flat) |
{ |
return InternalAddPart(ms,&flat->tone,flat); |
} |
short InternalAddPart(MusicScore ms,ToneDescription *td,FlatInstrument *flat) |
{ |
MusicScoreRecord *msr; |
hLock(ms); |
msr = *ms; |
msr->partCount++; |
SetHandleSize((Handle)msr->toneDescriptions,msr->partCount * sizeof(ToneDescription)); |
SetHandleSize((Handle)msr->flatInstruments,msr->partCount * sizeof(FlatInstrument *)); |
(*msr->toneDescriptions)[msr->partCount-1] = *td; |
(*msr->flatInstruments)[msr->partCount-1] = flat; |
hUnlock(ms); |
return msr->partCount; |
} |
void AddMusicScoreNote(MusicScore ms,short part,Fixed pitch,long velocity,TimeValue noteDuration) |
{ |
MusicScoreRecord *msr; |
unsigned long *w; |
hLock(ms); |
msr = *ms; |
part--; |
BumpTuneHandleSize(msr); |
HLock((Handle)msr->tune); |
w = *(msr->tune) + msr->tuneSize; |
if(pitch >= 32 && pitch <= 95 && part < 32 |
&& noteDuration < 2048) |
{ |
_StuffNoteEvent(*w,part,pitch,velocity,noteDuration); |
msr->tuneSize ++; |
} |
else |
{ |
_StuffXNoteEvent(*w,*(w+1),part,pitch,velocity,noteDuration); |
msr->tuneSize += 2; |
} |
hUnlock(msr->tune); |
hUnlock(ms); |
} |
void AddMusicScoreRest(MusicScore ms,TimeValue restDuration) |
{ |
MusicScoreRecord *msr; |
unsigned long *w; |
hLock(ms); |
msr = *ms; |
BumpTuneHandleSize(msr); |
HLock((Handle)msr->tune); |
w = *(msr->tune) + msr->tuneSize; |
_StuffRestEvent(*w,restDuration); |
msr->tuneSize ++; |
hUnlock(msr->tune); |
hUnlock(ms); |
} |
#define kNoteRequestMessageSize sizeof(NoteRequest)/4 + 2 |
Handle GetMusicScoreHeader(MusicScore ms) |
{ |
Handle h; |
unsigned long *w; |
long size; |
NoteRequest *nr; |
FlatInstrument *flat; |
MusicScoreRecord *msr; |
int i; |
hLock(ms); |
msr = *ms; |
size = msr->partCount*(8 + sizeof(NoteRequest)) |
+ 4; /* 8 bytes for general music message, |
+ 4 for end marker */ |
for(i = 0; i < msr->partCount; i++) |
{ |
flat = (*msr->flatInstruments)[i]; |
if(flat) |
size += flat->size; |
} |
h = NewHandleClear(size); |
w = (unsigned long *)*h; |
for(i = 0; i < msr->partCount; i++) |
{ |
flat = (*msr->flatInstruments)[i]; |
if(flat) |
{ |
size = kNoteRequestMessageSize + (flat->size + 3)/4; |
_StuffGeneralEvent(*w,*(w + size - 1), |
i,kGeneralEventFlatInstrument,size); |
nr = (NoteRequest *)(w + 1); |
nr->polyphony = 1; |
nr->typicalPolyphony = 0x10000; |
nr->tone = (*msr->toneDescriptions)[i]; |
BlockMove(&flat->size,((char *)&nr->tone) + sizeof(ToneDescription),flat->size); |
w += size; |
} |
else |
{ |
_StuffGeneralEvent(*w,*(w + kNoteRequestMessageSize - 1), |
i,kGeneralEventNoteRequest,kNoteRequestMessageSize); |
nr = (NoteRequest *)(w + 1); |
nr->polyphony = 1; |
nr->typicalPolyphony = 0x10000; |
nr->tone = (*msr->toneDescriptions)[i]; |
w += kNoteRequestMessageSize; |
} |
} |
*w++ = 0x60000000; /* end marker */ |
hUnlock(ms); |
return h; |
} |
Handle GetMusicScoreScore(MusicScore ms) |
{ |
Handle h; |
MusicScoreRecord *msr; |
unsigned long *w; |
long size; |
hLock(ms); |
msr = *ms; |
size = msr->tuneSize * sizeof(unsigned long) + 4; |
msr = *ms; |
h = NewHandle(size); |
BlockMove(*msr->tune, *h, size); |
(*(unsigned long **)h)[msr->tuneSize] = 0x60000000; |
hUnlock(ms); |
return h; |
} |
void StuffToneDescription(short gmNumber,ToneDescription *td) |
{ |
ComponentResult result; |
NoteAllocator na; |
na = OpenDefaultComponent('nota',0); |
if(na) |
{ |
NAStuffToneDescription(na,gmNumber,td); |
CloseComponent(na); |
} |
else |
{ |
td->synthesizerType = 0; |
td->synthesizerName[0] = 0; |
td->instrumentName[0] = 0; |
td->instrumentNumber = 0; |
td->gmNumber = gmNumber; |
} |
} |
#define kTuneSizeMargin 16 |
void BumpTuneHandleSize(MusicScoreRecord *msr) |
{ |
if(msr->tuneHandleSize - msr->tuneSize < kTuneSizeMargin) |
{ |
msr->tuneHandleSize += kTuneHandleBump; |
SetHandleSize((Handle)msr->tune,msr->tuneHandleSize * sizeof(unsigned long)); |
} |
} |
MusicMovie StartMusicMovie(FSSpec *movieSpec,Handle header) |
{ |
MusicMovie mm; |
MusicMovieRecord *mmr; |
ComponentResult thisError; |
unsigned long size; |
EnterMovies(); |
mm = (MusicMovie)NewHandle(sizeof(MusicMovieRecord)); |
hLock(mm); |
mmr = *mm; |
thisError = CreateMovieFile(movieSpec,'TVOD',0, |
createMovieFileDeleteCurFile, |
&mmr->refNum, |
&mmr->mo); |
SetMoviePreferredVolume(mmr->mo,kFullVolume); |
SetMovieVolume(mmr->mo,kFullVolume); |
mmr->tr = NewMovieTrack(mmr->mo,0,0,kFullVolume); |
mmr->me = NewTrackMedia(mmr->tr,kMusicComponentType,600,0,0); |
thisError = GetMoviesError(); |
size = sizeof(MusicDescription) + GetHandleSize(header); |
mmr->mdH = (void *)NewHandleClear(size); |
// ¥¥¥ ??? (**mmr->mdH).size = size; |
// ¥¥¥ ??? (**mmr->mdH).type = 'musi'; |
BlockMove(*header,&(**mmr->mdH).headerData,GetHandleSize(header)); |
mmr->duration = 0; |
thisError = BeginMediaEdits(mmr->me); |
hUnlock(mm); |
return mm; |
} |
void AddMusicMovieSample(MusicMovie mm,Handle score) |
{ |
MusicMovieRecord *mmr; |
ComponentResult thisError; |
TimeValue sampleDuration; |
unsigned long sampleLength; |
hLock(mm); |
mmr = *mm; |
// ¥ Compute duration of tune |
{ |
unsigned long *start,*w,*end; |
unsigned long eventType,eventLength; |
unsigned long x; |
start = (unsigned long *)*score; |
end = (unsigned long *)( ((char *)*score) + GetHandleSize(score)); |
w = start; |
sampleDuration = 0; |
while(w < end) |
{ |
x = *w; |
eventLength = _EventLength(x); |
eventType = _EventType(x); |
if(eventType == kRestEventType) |
sampleDuration += _RestDuration(x); |
if(eventLength < 1 || eventLength > 1000) |
goto done; |
w += eventLength; |
} |
done: |
sampleLength = (w - start) * sizeof(unsigned long); |
} |
thisError = AddMediaSample(mmr->me,score,0,sampleLength, |
sampleDuration,(void *)mmr->mdH, |
1,0,0); |
mmr->duration += sampleDuration; |
hUnlock(mm); |
} |
void FinishMusicMovie(MusicMovie *mm) |
{ |
MusicMovieRecord *mmr; |
ComponentResult thisError; |
hLock(*mm); |
mmr = **mm; |
thisError = InsertMediaIntoTrack(mmr->tr,0,0,mmr->duration,(1L<<16)); |
thisError = EndMediaEdits(mmr->me); |
thisError = AddMovieResource(mmr->mo,mmr->refNum,nil,nil); |
thisError = CloseMovieFile(mmr->refNum); |
DisposeHandle((Handle)*mm); |
*mm = 0; |
ExitMovies(); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14