home *** CD-ROM | disk | FTP | other *** search
- /* CROSSFADE.C Cross fade loop generator for the
- SoundScape sampler.
-
- (c) 1987 Todor Fay
- */
-
- #include "exec/exec.h"
- #include "exec/types.h"
- #include "intuition/intuition.h"
- #include "soundscape.h"
- #include "sampler.h"
-
- /* Cross Fade Icon for Patch Panel: */
-
- UWORD crossfadedata[] = { /* 36 x 11 */
- 0, 0, 0,
- 16383, 65535, 49152,
- 511, 65528, 0,
- 15887, 65287, 49152,
- 16368, 24831, 49152,
- 16383, 40959, 49152,
- 16368, 24831, 49152,
- 15887, 65287, 49152,
- 511, 65528, 0,
- 16383, 65535, 49152,
- 0, 0, 0,
- 65535, 65535, 61440,
- 49152, 4, 12288,
- 49152, 57544, 12288,
- 49153, 61700, 28672,
- 55792, 24812, 61440,
- 65535, 40959, 61440,
- 55792, 24812, 61440,
- 49153, 61444, 28672,
- 49152, 57544, 12288,
- 49152, 4, 12288,
- 65535, 65535, 61440,
- };
-
- struct Image crossfadeimage =
- { 0,0,36,11,2,crossfadedata,3,0,0 };
-
- /* Edit window. This has the gadgets for selecting
- sampler channel and octave, and Doing and Undoing
- the cross fade. These intuition data structures
- were generated with Power Windows.
- */
-
- USHORT BorderVectors1[] = {0,0,107,0,107,10,0,10,0,0};
- struct Border Border1 = {
- -2,-1,
- 3,0,JAM1,
- 5,
- BorderVectors1,
- NULL
- };
-
- struct IntuiText IText1 = {
- 1,0,JAM2,
- 33,1,
- NULL,
- "Undo",
- NULL
- };
-
- struct Gadget UndoGadget = {
- NULL,
- 23,55,
- 104,9,
- GADGHCOMP,
- RELVERIFY,
- BOOLGADGET,
- (APTR)&Border1,
- NULL,
- &IText1,
- 0,
- NULL,
- 8,
- NULL
- };
-
- UBYTE SIBuffer7[4] =
- "5";
- struct StringInfo GadgetSI7 = {
- SIBuffer7,
- NULL,
- 0,
- 4,
- 0,
- 0,0,0,0,0,
- 0,
- 5,
- NULL
- };
-
- USHORT BorderVectors2[] = {0,0,35,0,35,9,0,9,0,0};
- struct Border Border2 = {
- -2,-1,
- 1,0,JAM1,
- 5,
- BorderVectors2,
- NULL
- };
-
- struct IntuiText IText2 = {
- 2,0,JAM2,
- -60,0,
- NULL,
- "Octave",
- NULL
- };
-
- struct Gadget OctaveGadget = {
- &UndoGadget,
- 95,28,
- 32,8,
- GADGHCOMP,
- LONGINT+RELVERIFY+STRINGCENTER,
- STRGADGET,
- (APTR)&Border2,
- NULL,
- &IText2,
- 0,
- (APTR)&GadgetSI7,
- 7,
- NULL
- };
-
- UBYTE SIBuffer6[4] =
- "1";
- struct StringInfo GadgetSI6 = {
- SIBuffer6,
- NULL,
- 0,
- 4,
- 0,
- 0,0,0,0,0,
- 0,
- 1,
- NULL
- };
-
- USHORT BorderVectors3[] = {0,0,35,0,35,9,0,9,0,0};
- struct Border Border3 = {
- -2,-1,
- 1,0,JAM1,
- 5,
- BorderVectors3,
- NULL
- };
-
- struct IntuiText IText3 = {
- 2,0,JAM2,
- -67,0,
- NULL,
- "Channel",
- NULL
- };
-
- struct Gadget ChannelGadget = {
- &OctaveGadget,
- 95,15,
- 32,8,
- GADGHCOMP,
- LONGINT+RELVERIFY+STRINGCENTER,
- STRGADGET,
- (APTR)&Border3,
- NULL,
- &IText3,
- 0,
- (APTR)&GadgetSI6,
- 6,
- NULL
- };
-
- USHORT BorderVectors4[] = {0,0,107,0,107,10,0,10,0,0};
- struct Border Border4 = {
- -2,-1,
- 3,0,JAM1,
- 5,
- BorderVectors4,
- NULL
- };
-
- struct IntuiText IText4 = {
- 1,0,JAM2,
- 12,1,
- NULL,
- "Cross Fade",
- NULL
- };
-
- struct Gadget CrossFadeGadget = {
- &ChannelGadget,
- 23,41,
- 104,9,
- GADGHCOMP,
- RELVERIFY,
- BOOLGADGET,
- (APTR)&Border4,
- NULL,
- &IText4,
- 0,
- NULL,
- 5,
- NULL
- };
-
- /* Gadget list */
-
- struct NewWindow NewWindowStructure = {
- 0,0,
- 152,72,
- 0,1,
- GADGETUP+CLOSEWINDOW+RAWKEY,
- WINDOWSIZING+WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE
- +ACTIVATE,
- &CrossFadeGadget,
- NULL,
- " X Fade ",
- NULL,
- NULL,
- 30,20,
- 152,72,
- WBENCHSCREEN
- };
-
- unsigned short thisport;
- opencode(direction)
-
- /* There is nothing to be initialised. However,
- it would be nice to connect the console
- keyboard to the sampler so the user can test
- the cross fade loops, so make an OpenLink call.
- FindMidiPort returns the port id, given the
- name of the port. Actually, these two ports
- have ids that are hard coded into SoundScape.
- This is an example what you should do with
- modules that are independantly loaded into
- the system.
- */
-
- unsigned char direction;
-
- {
- OpenLink(FindMidiPort("console keyboard"),
- FindMidiPort("sampler"));
- return(1);
- }
-
- closecode(direction)
-
- unsigned char direction;
-
- {
- return(1);
- }
-
- clearsounddata(sounddata)
-
- /* This routine frees up the sample buffer belonging
- to the SoundData structure 'sounddata'.
- */
-
- struct SoundData *sounddata;
-
- {
- if (sounddata->data)
- FreeMem(sounddata->data,sounddata->length);
- sounddata->data = 0;
- sounddata->length = 0;
- sounddata->loopstart = 0;
- sounddata->loopend = 0;
- sounddata->start = 0;
- }
-
- crossfade(sounddata)
-
- /* This, the cross fade routine, operates on a
- SoundData structure.
-
- The cross fade is done on the region of the
- sample between the two loop points. The
- sample prior to the loop start is gradually
- mixed in until it is in full force by the
- end of the loop.
-
- This is very straight forward, the only problem
- encountered is a sample with a loop that
- is longer than the part leading into the
- loop. This is solved by having the cross fade
- section be shorter - the length of the lead
- in section.
- */
-
- struct SoundData *sounddata;
-
- {
- char *sample; /* Points to sample */
- unsigned short loop; /* Length of loop. */
- unsigned short crosslength; /* Length of cross fade. */
- unsigned short start; /* Start point. */
- long result; /* Intermediate result. */
- unsigned short a,b; /* Indexes into sample. */
- unsigned short j; /* Loop index. */
-
- loop = sounddata->loopend - sounddata->loopstart;
- sample = &sounddata->data[sounddata->start];
- start = sounddata->loopstart - sounddata->start;
-
- /* If the loop is greater than the start segment, set
- the crossfade to cover the last part of the loop,
- equal to the starting segment.
- */
-
- if (loop > start) {
- crosslength = start;
- a = 0;
- b = loop;
- }
-
- /* Otherwise, set the crossfade to cover the entire
- loop.
- */
-
- else {
- crosslength = loop;
- a = start - loop;
- b = start;
- }
- for (j = 0; j < crosslength; j++ ) {
- result = (j * sample[a]);
- result += (crosslength - j) * sample[b];
- result = result / crosslength;
- sample[b] = result;
- a++;
- b++;
- }
- }
-
- void useredit()
-
- /* This routine is called whenever the user clicks
- twice on the cross fade icon. A window is opened
- and four gadgets are presented. Two string
- gadgets allow the user to select the octave and
- channel of the sample they'd like to work on.
- Two boolean gadgets are used to command the
- cross fade and undo operations.
-
- There are two SoundData structures. OldSound
- is used to keep an old copy of the sample
- around for undoing. CFSound is used to hold
- the sample that gets cross faded.
-
- RAWKEY events are passed on to the console
- keyboard with the OutConsole command.
- This is so the user can test the changed sound
- without having to click on another window to
- enable the Console Keyboard.
- */
-
- {
- struct IntuiMessage *message;
- struct SoundData *oldsound, *cfsound;
- short code, class;
- struct Gadget *gadget;
- struct Window *window;
- short octave = 5;
- short channel = 0;
- oldsound = (struct SoundData *)
- AllocMem(sizeof(*oldsound),MEMF_CLEAR);
- if (!oldsound) return;
- cfsound = (struct SoundData *)
- AllocMem(sizeof(*cfsound),MEMF_CLEAR);
- if (!cfsound) {
- FreeMem(oldsound,sizeof(*oldsound));
- return;
- }
- window = (struct Window *)
- OpenWindow(&NewWindowStructure);
- while (window) {
- while (!(message = (struct IntuiMessage *)
- GetMsg(window->UserPort)))
- WaitPort(window->UserPort);
- class = message->Class;
- code = message->Code;
- gadget = (struct Gadget *) message->IAddress;
- ReplyMsg(message);
- if (class == CLOSEWINDOW) break;
- if (class == RAWKEY) OutConsole(code);
- if (class == GADGETUP) {
- switch (gadget->GadgetID) {
- case 5 :
-
- /* The crossfade gadget. Get the sample, using
- GetSoundData, and put it in cfsound. Clear
- the undo buffer (oldsound) and get the same
- sample loaded into it. Call crossfade to alter
- cfsound, then install it in the sampler with
- a call to SetSoundData.
- Then, clear out cfsound.
- */
-
- if (!(GetSoundData(channel,
- octave,cfsound))) {
- clearsounddata(oldsound);
- if (GetSoundData(channel,
- octave,oldsound)) {
- oldsound->data = 0;
- }
- crossfade(cfsound);
- SetSoundData(channel,octave,cfsound);
- clearsounddata(cfsound);
- }
- break;
- case 6 :
-
- /* This gadget simply sets the channel of the sampler
- that we are looking at. Also, clear the undo buffer.
- */
-
- channel = (GadgetSI6.LongInt - 1) & 0x0F;
- clearsounddata(oldsound);
- break;
- case 7 :
-
- /* This gadget sets the octave of the sample we are
- looking at. Clear the undo buffer.
- */
-
- octave = GadgetSI7.LongInt;
- if (octave < 0) octave = 0;
- if (octave > 9) octave = 9;
- clearsounddata(oldsound);
- break;
- case 8 :
-
- /* This is the undo command. Simply give the undo
- buffer to the sampler, then clear the undo buffer.
- */
-
- if (oldsound->data) {
- SetSoundData(channel,octave,oldsound);
- clearsounddata(oldsound);
- }
- break;
- }
- }
- }
- CloseWindow(window);
- clearsounddata(oldsound);
- clearsounddata(cfsound);
- FreeMem(oldsound,sizeof(*oldsound));
- FreeMem(cfsound,sizeof(*cfsound));
- }
-
- editcode(direction,command,buffer)
-
- /* This is the edit routine provided to SoundScape
- in the AddMidiPort call.
-
- There is nothing in the way of data structures
- that we would like any other modules to access,
- nor is there anything to save or load with
- environment loads and save. So, the GETSTATE,
- SETSTATE, SAVESTATE, and LOADSTATE commands are
- all ignored and the sample's length is set to
- 0.
-
- However, USEREDIT indicates the user has clicked
- twice on the cross fade icon and would like to
- work with it. In that case, call the routine
- 'useredit' which puts up a window and lets the
- user do that wild cross fade thing.
-
- */
-
- char direction, command;
- long *buffer;
-
- {
- static char not_editing = 1;
- *buffer = 0;
- switch (command) {
- case USEREDIT :
- if (not_editing) {
- not_editing = 0;
- useredit();
- not_editing = 1;
- }
- break;
- }
- }
-
- /* The main program is simple. Just open SoundScape to
- get the address of the library vector, then close
- the library (since this is a module and usually is
- invoked by SoundScape when the first program opens
- SoundScape, if it keeps the library count up, there
- will be no way to close SoundScape.)
- Check the version number. If it's below 2, this
- SoundScape Sampler module doesn't support having
- samples changed, so quit.
- Else, add the module's port and wait for SoundScape
- to shut it down.
- */
-
- long SoundScapeBase;
- long IntuitionBase;
-
- main() {
- SoundScapeBase = OpenLibrary("soundscape.library",0);
- if (SoundScapeBase) {
- IntuitionBase = OpenLibrary("intuition.library",0);
- CloseLibrary(SoundScapeBase);
- if (Version() > 1) {
- thisport = AddMidiPort(opencode,closecode,
- editcode,0,&crossfadeimage,0,-1,"cross fade");
- SetTaskPri(FindTask(0),-20);
- while (MidiPort(thisport)) Delay(100);
- }
- CloseLibrary(IntuitionBase);
- }
- }
-