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();
    }