-
Notifications
You must be signed in to change notification settings - Fork 127
/
music.c
428 lines (364 loc) · 11 KB
/
music.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
#include "Burger.h"
#include <Portfolio.h>
#include <SoundFile.h>
#include <TimerUtils.h>
extern uint32 MainTask; /* My own task item */
/**********************************
This big chunk of code handles all 3DO music and sound
for generic drivers
**********************************/
#define NUMBLOCKS 6 /* Size of memory needed for player */
#define BLOCKSIZE 2048
#define BUFSIZE (NUMBLOCKS*BLOCKSIZE)
static Item MusicIns; /* Instrument for music so I can pause it */
static char *MusicName;
static Item MixerIns; /* Main Mixer */
static Item SamplerIns[VOICECOUNT]; /* 3DO Instruments for sound voices */
static Item SamplerRateKnob[VOICECOUNT]; /* 3DO Sample rate knob */
static Item SampleAtt[VOICECOUNT]; /* 3DO Attachment items */
static Boolean LockHit;
Word SampleSound[VOICECOUNT]; /* Sound number being playing in this channel */
Word SamplePriority[VOICECOUNT] = {0,1,2,3}; /* Priority chain */
Item LeftKnobs[VOICECOUNT]; /* Left and right output volumes */
Item RightKnobs[VOICECOUNT];
Word LeftVolume;
Word RightVolume;
static volatile Word SongPtr; /* Current song script */
static Item iSoundHandler; /* Item for music thread */
static uint32 SongIsDeadSignal; /* Signals for the music driver */
static uint32 NewSongIsLoaded; /* A new song is present */
static uint32 AbortSongSignal; /* Stop a song */
static Item DiskLocker; /* So I can lock the multitasking */
static volatile Word OhShit; /* Flag for aborting the tool */
static char SongFileName[40]; /* Filename of the song */
static char SongNum[10]; /* Number for song name */
Word MusicVolume = 15; /* Maximum volume */
Word SfxVolume = 15;
Word LoopSong;
Word SongNumber;
/**********************************
This thread will play the music
**********************************/
static void MusicPlayer(void)
{
SoundFilePlayer *SongItem; /* Pointer to data */
int32 Result;
int32 SignalIn;
int32 SignalsNeeded;
NewSongIsLoaded = AllocSignal(0);
AbortSongSignal = AllocSignal(0);
OpenAudioFolio(); /* Start up the sound tools */
SongItem = CreateSoundFilePlayer(8,BUFSIZE,0); /* Create my song thread */
SongItem->sfp_Flags |= (SFP_NO_SAMPLER);
SongItem->sfp_SamplerIns = LoadInstrument(MusicName,0,100);
MusicIns = SongItem->sfp_SamplerIns;
/* Wait until a song is ready! */
Again:
while (!SongPtr) { /* No song to play? */
WaitSignal(NewSongIsLoaded|AbortSongSignal); /* Go to sleep */
}
strcpy(SongFileName,"Music/Song"); /* Open the sound file */
LongWordToAscii(SongNumber,(Byte *)SongNum);
strcat(SongFileName,SongNum);
LockItem(DiskLocker,SEM_WAIT); /* Wait for the lock to happen */
Result = LoadSoundFile(SongItem,SongFileName); /* Open up the sound stream */
UnlockItem(DiskLocker);
if (Result < 0) { /* Open up the sound stream */
goto Abort; /* Fatal!! */
}
Repeat:
StartSoundFile(SongItem,MusicVolume*0x888); /* Play the music */
SignalIn = 0; /* No signals pending */
SignalsNeeded = 0;
do {
if (!SignalIn || (SignalIn & SignalsNeeded)) {
LockItem(DiskLocker,SEM_WAIT); /* Wait for the lock to happen */
if (LockHit) { /* Was a disk load started? */
LongWord TimeMark;
TimeMark = ReadTick(); /* Log the time */
do {
LockHit = FALSE; /* Ack the disk load */
UnlockItem(DiskLocker); /* Release the disk */
SleepMSec(0,80); /* Sleep a little */
LockItem(DiskLocker,SEM_WAIT); /* Try again... */
if ((ReadTick()-TimeMark)>=40) { /* Am I getting hungry? */
LockHit = FALSE; /* Forget it!! */
break;
}
} while (LockHit); /* Still hitting the CD ROM? */
}
Result = ServiceSoundFile(SongItem,SignalIn, &SignalsNeeded);
UnlockItem(DiskLocker);
}
if (Result<0 || OhShit) { /* Sound error?!? */
goto BadNews; /* Forget it! */
}
if (SignalsNeeded) { /* Do I need to wait? */
SignalIn = WaitSignal(SignalsNeeded | AbortSongSignal);
}
if (OhShit) { /* Time to abort? */
BadNews:
StopSoundFile(SongItem); /* Stop the current song */
UnloadSoundFile(SongItem); /* Release the memory!! IMPORTANT! */
Result = GetCurrentSignals() & SignalsNeeded;
if (Result) {
WaitSignal(Result);
}
goto Abort;
}
} while (SignalsNeeded); /* Do I still have data pending? */
StopSoundFile(SongItem); /* Stop the current song */
if (LoopSong) { /* End of list? */
RewindSoundFile(SongItem); /* Rewind the song */
goto Repeat; /* Repeat the song */
}
SongPtr = 0; /* Index to the next song */
UnloadSoundFile(SongItem); /* Release the memory!! IMPORTANT! */
Result = GetCurrentSignals() & SignalsNeeded;
if (Result) {
WaitSignal(Result);
}
if (SongPtr) { /* Are there any more songs? */
goto Again;
}
Abort:;
SongPtr = 0;
SendSignal(MainTask,SongIsDeadSignal); /* Tell the main task that I am dead */
goto Again;
} /* Exit the task */
/**********************************
Allocate resources for the music player for 3DO
**********************************/
void InitMusicPlayer(char *MusicDSP)
{
MusicName = MusicDSP;
DiskLocker = CreateSemaphore("DiskLocker",KernelBase->kb_CurrentTask->t.n_Priority);
SongIsDeadSignal = AllocSignal(0);
NewSongIsLoaded = AllocSignal(0);
AbortSongSignal = AllocSignal(0);
iSoundHandler = CreateThread("MusicPlayer",KernelBase->kb_CurrentTask->t.n_Priority+1,MusicPlayer,4000);
SetMusicVolume(15);
}
/**********************************
Play a song
**********************************/
void PlaySong(Word NewSong)
{
LoopSong = NewSong;
if (NewSong==SongNumber) { /* Same as before? */
return; /* Bye */
}
if (SongPtr && NewSong==SongPtr) {
return;
}
if (SongNumber) { /* Was a song playing? */
OhShit = 1;
SendSignal(iSoundHandler,AbortSongSignal);
/* Wait until song is aborted */
while (SongPtr) { /* No result */
WaitSignal(SongIsDeadSignal);
}
SongNumber = 0; /* No song anymore */
OhShit = 0;
ScavengeMem(); /* Release memory */
}
if (NewSong) { /* Shall I play a song? */
SongNumber = NewSong; /* Set the song */
if (!(SystemState&MusicActive)) {
return;
}
SongPtr = NewSong; /* Get the real song file # */
if (iSoundHandler) {
SendSignal(iSoundHandler,NewSongIsLoaded);
}
}
}
/**********************************
Prepare the sound player for the threedo
Audio requirements
Total memory (512 words)
Total clocks (565 ticks)
Head.dsp 29/32
Tail.dsp 16/16
Adpcm 91/51 (364/204)
dcsqxstereo.dsp 66/64
mixer4x2.dsp 32/32
directout.dsp 8/8
**********************************/
static char LeftG[] = "LeftGain0";
static char RightG[] = "RightGain0";
static char Inp[] = "Input0";
void InitSoundPlayer(char *SoundDSP,Word Rate)
{
Word i;
MixerIns = LoadInstrument("system/audio/dsp/mixer4x2.dsp",0,0);
i = 0;
do {
LeftG[8] = i+'0'; /* Set the left gain text */
RightG[9] = i+'0'; /* Set the right gain text */
LeftKnobs[i] = GrabKnob(MixerIns,LeftG); /* Grab the knobs */
RightKnobs[i] = GrabKnob(MixerIns,RightG);
} while (++i<VOICECOUNT); /* All 4 channels */
StartInstrument(MixerIns,0); /* Begin execution of the mixer */
i = 0;
do {
SamplerIns[i] = LoadInstrument(SoundDSP,0,100);
SamplerRateKnob[i] = GrabKnob(SamplerIns[i],"Frequency");
Inp[5] = i+'0';
ConnectInstruments(SamplerIns[i],"Output",MixerIns,Inp); /* Allow mono out on both speakers */
} while (++i<VOICECOUNT);
SetSfxVolume(15);
LeftVolume = 255;
RightVolume = 255;
}
/**********************************
Play a sound effect
**********************************/
void PlaySound(Word SoundNum)
{
Word Number;
Word i;
Word OldPrior;
if (SoundNum&0x8000) { /* Stop previous sound */
SoundNum&=(~0x8000); /* Clear the flag */
StopSound(SoundNum); /* Stop the sound */
}
if (!SoundNum || /* No sound at all? */
!AllSamples[SoundNum-1] || /* Valid sound loaded? */
!(SystemState&SfxActive)) { /* Sound enabled? */
goto WrapUp;
}
Number = 0;
do {
if (!SampleSound[Number]) { /* Find an empty sound channel */
goto Begin; /* Found it! */
}
} while (++Number<VOICECOUNT);
Number = 0; /* Get the lowest priority sound */
do {
if (!SamplePriority[Number]) { /* Get the priority */
break; /* Priority zero? */
}
} while (++Number<(VOICECOUNT-1)); /* Drop out on the last channel */
StopInstrument(SamplerIns[Number],0); /* Stop the sound */
if (SampleAtt[Number]) { /* Delete the attachment */
DetachSample(SampleAtt[Number]);
}
Begin:
SampleSound[Number] = SoundNum; /* Attach the sound number to this channel */
SampleAtt[Number] = AttachSample(SamplerIns[Number],AllSamples[SoundNum-1],0);
TweakKnob(SamplerRateKnob[Number],AllRates[SoundNum-1]); /* Set to 11 Khz fixed */
TweakKnob(LeftKnobs[Number],LeftVolume<<6); /* Set the volume setting */
TweakKnob(RightKnobs[Number],RightVolume<<6);
StartInstrument(SamplerIns[Number],0); /* Begin playing... */
i = 0;
OldPrior = SamplePriority[Number]; /* Get the old priority */
do {
if (SamplePriority[i]>=OldPrior) {
--SamplePriority[i]; /* Reduce the priority */
}
} while (++i<VOICECOUNT);
SamplePriority[Number] = (VOICECOUNT-1); /* Set the higher priority */
WrapUp:
LeftVolume = 255; /* Reset the volume */
RightVolume = 255;
}
/**********************************
Stop a sound effect (If playing)
**********************************/
void StopSound(Word SoundNum)
{
Word i;
if (SoundNum) {
i = 0;
do {
if (SampleSound[i] == SoundNum) { /* Match? */
StopInstrument(SamplerIns[i],0); /* Stop the sound */
if (SampleAtt[i]) {
DetachSample(SampleAtt[i]); /* Remove the attachment */
SampleAtt[i] = 0;
}
SampleSound[i] = 0; /* No sound active */
}
} while (++i<VOICECOUNT); /* All channels checked? */
}
}
/**********************************
Pause the sound effects
**********************************/
static Boolean Paused;
void PauseSound(void)
{
Word i;
if (Paused) {
return;
}
Paused = TRUE;
i = 0;
do {
PauseInstrument(SamplerIns[i]);
} while (++i<VOICECOUNT);
}
/**********************************
Resume paused sound
**********************************/
void ResumeSound(void)
{
Word i;
if (Paused) {
Paused = FALSE;
i = 0;
do {
ResumeInstrument(SamplerIns[i]);
} while (++i<VOICECOUNT);
}
}
void PauseMusic(void)
{
PauseInstrument(MusicIns);
}
void ResumeMusic(void)
{
ResumeInstrument(MusicIns);
}
void SetSfxVolume(Word NewVolume)
{
Word i;
Item MyKnob;
if (NewVolume>=16) {
NewVolume=15;
}
SfxVolume=NewVolume;
NewVolume = NewVolume*0x888; /* Convert 0-15 -> 0-0x7FF8 */
i = 0;
do {
MyKnob = GrabKnob(SamplerIns[i],"Amplitude");
TweakKnob(MyKnob,NewVolume); /* Set to 11 Khz fixed */
ReleaseKnob(MyKnob);
} while (++i<VOICECOUNT);
}
void SetMusicVolume(Word NewVolume)
{
Item MyKnob;
if (NewVolume>=16) {
NewVolume=15;
}
MusicVolume=NewVolume;
NewVolume = NewVolume*0x888; /* Convert 0-15 -> 0-0x7FF8 */
MyKnob = GrabKnob(MusicIns,"Amplitude");
TweakKnob(MyKnob,NewVolume); /* Set to 11 Khz fixed */
ReleaseKnob(MyKnob);
}
void LockMusic(void)
{
if (DiskLocker) {
LockItem(DiskLocker,SEM_WAIT); /* Lock me down */
}
}
void UnlockMusic(void)
{
if (DiskLocker) {
LockHit = TRUE;
UnlockItem(DiskLocker); /* Release the disk */
}
}