revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / AHI / Examples / Low-level / SimplePlay / SimplePlay.c
blob3bfb67cf841e0439083c5a7947b866ac3c989ef3
1 /* Simple sample player for AHI using the low-level API.
2 Hardcoded sample names.
4 This software is Public Domain. */
6 #include <devices/ahi.h>
7 #include <exec/exec.h>
8 #include <proto/ahi.h>
9 #include <proto/dos.h>
10 #include <proto/exec.h>
12 #define USE_AHI_V4 TRUE
14 #define CHANNELS 2
15 #define MAXSAMPLES 16
17 #define INT_FREQ 50
19 char *ID = "$VER: SimplePlay 1.3 (23.4.97)\r\n";
21 APTR samples[MAXSAMPLES] = { 0 };
23 struct {
24 BOOL FadeVolume;
25 Fixed Volume;
26 sposition Position;
27 } channelstate[CHANNELS];
29 struct {
30 struct AHIEffDSPMask mask;
31 UBYTE mode[CHANNELS];
32 } maskeffect = {0};
33 struct AHIEffDSPEcho echoeffect = {0};
35 struct Library *AHIBase;
36 struct MsgPort *AHImp = NULL;
37 struct AHIRequest *AHIio = NULL;
38 BYTE AHIDevice = -1;
39 struct AHIAudioCtrl *actrl = NULL;
41 LONG mixfreq = 0;
43 /* Prototypes */
45 BOOL OpenAHI(void);
46 void CloseAHI(void);
47 BOOL AllocAudio(void);
48 void FreeAudio(void);
49 UWORD LoadSample(unsigned char * , ULONG );
50 void UnloadSample(UWORD );
51 int main(void);
53 /******************************************************************************
54 ** PlayerFunc *****************************************************************
55 ******************************************************************************/
57 __asm __interrupt __saveds static void PlayerFunc(
58 register __a0 struct Hook *hook,
59 register __a2 struct AHIAudioCtrl *actrl,
60 register __a1 APTR ignored) {
62 int i;
64 for(i = 0; i < CHANNELS; i++) {
66 if(channelstate[i].FadeVolume) {
68 channelstate[i].Volume = (channelstate[i].Volume * 90) / 100; // Fade volume
70 if(channelstate[i].Volume == 0) {
71 channelstate[i].FadeVolume = FALSE;
74 AHI_SetVol(i, channelstate[i].Volume, channelstate[i].Position,
75 actrl, AHISF_IMM);
78 return;
81 struct Hook PlayerHook = {
82 0,0,
83 (ULONG (* )()) PlayerFunc,
84 NULL,
85 NULL,
88 /******************************************************************************
89 **** OpenAHI ******************************************************************
90 ******************************************************************************/
92 /* Open the device for low-level usage */
94 BOOL OpenAHI(void) {
96 if(AHImp = CreateMsgPort()) {
97 if(AHIio = (struct AHIRequest *)CreateIORequest(
98 AHImp,sizeof(struct AHIRequest))) {
100 #if USE_AHI_V4
101 AHIio->ahir_Version = 4;
102 #else
103 AHIio->ahir_Version = 2;
104 #endif
106 if(!(AHIDevice = OpenDevice(AHINAME, AHI_NO_UNIT,
107 (struct IORequest *) AHIio,NULL))) {
108 AHIBase = (struct Library *) AHIio->ahir_Std.io_Device;
109 return TRUE;
113 FreeAudio();
114 return FALSE;
118 /******************************************************************************
119 **** CloseAHI *****************************************************************
120 ******************************************************************************/
122 /* Close the device */
124 void CloseAHI(void) {
126 if(! AHIDevice)
127 CloseDevice((struct IORequest *)AHIio);
128 AHIDevice=-1;
129 DeleteIORequest((struct IORequest *)AHIio);
130 AHIio=NULL;
131 DeleteMsgPort(AHImp);
132 AHImp=NULL;
136 /******************************************************************************
137 **** AllocAudio ***************************************************************
138 ******************************************************************************/
140 /* Ask user for an audio mode and allocate it */
142 BOOL AllocAudio(void) {
143 struct AHIAudioModeRequester *req;
144 BOOL rc = FALSE;
146 req = AHI_AllocAudioRequest(
147 AHIR_PubScreenName, NULL,
148 AHIR_TitleText, "Select a mode and rate",
149 AHIR_DoMixFreq, TRUE,
150 TAG_DONE);
152 if(req) {
153 if(AHI_AudioRequest(req, TAG_DONE)) {
154 actrl = AHI_AllocAudio(
155 AHIA_AudioID, req->ahiam_AudioID,
156 AHIA_MixFreq, req->ahiam_MixFreq,
157 AHIA_Channels, CHANNELS,
158 AHIA_Sounds, MAXSAMPLES,
159 AHIA_PlayerFunc, &PlayerHook,
160 AHIA_PlayerFreq, INT_FREQ<<16,
161 AHIA_MinPlayerFreq, INT_FREQ<<16,
162 AHIA_MaxPlayerFreq, INT_FREQ<<16,
163 TAG_DONE);
164 if(actrl) {
165 // Get real mixing frequency
166 AHI_ControlAudio(actrl, AHIC_MixFreq_Query, &mixfreq, TAG_DONE);
167 rc = TRUE;
170 AHI_FreeAudioRequest(req);
172 return rc;
176 /******************************************************************************
177 **** FreeAudio ****************************************************************
178 ******************************************************************************/
180 /* Release the audio hardware */
182 void FreeAudio() {
184 AHI_FreeAudio(actrl);
185 actrl = NULL;
188 /******************************************************************************
189 **** LoadSample ***************************************************************
190 ******************************************************************************/
192 /* Load a (raw) 8 or 16 bit sample from disk. The sample ID is returned
193 (or AHI_NOSOUND on error). */
195 UWORD LoadSample(char *filename, ULONG type) {
196 struct AHISampleInfo sample;
197 APTR *samplearray = samples;
198 UWORD id = 0, rc = AHI_NOSOUND;
199 BPTR file;
201 // Find a free sample slot
203 while(*samplearray) {
204 id++;
205 samplearray++;
206 if(id >= MAXSAMPLES) {
207 return AHI_NOSOUND;
211 file = Open(filename, MODE_OLDFILE);
213 if(file) {
214 int length;
216 Seek(file, 0, OFFSET_END);
217 length = Seek(file, 0, OFFSET_BEGINNING);
218 *samplearray = AllocVec(length, MEMF_PUBLIC);
219 if(*samplearray) {
220 Read(file, *samplearray, length);
222 sample.ahisi_Type = type;
223 sample.ahisi_Address = *samplearray;
224 #if USE_AHI_V4
225 sample.ahisi_Length = length / AHI_SampleFrameSize(type);
226 #else
227 sample.ahisi_Length = length / (type == AHIST_M16S ? 2 : 1);
228 #endif
229 if(! AHI_LoadSound(id, AHIST_SAMPLE, &sample, actrl)) {
230 rc = id;
233 Close(file);
235 return rc;
239 /******************************************************************************
240 **** UnloadSample *************************************************************
241 ******************************************************************************/
243 void UnloadSample(UWORD id) {
245 AHI_UnloadSound(id, actrl);
246 FreeVec(samples[id]);
247 samples[id] = NULL;
250 /******************************************************************************
251 **** main *********************************************************************
252 ******************************************************************************/
254 int main() {
255 UWORD sample, ahem, louise;
256 int i;
258 for(i = 0; i < CHANNELS; i++) {
259 channelstate[i].FadeVolume = FALSE;
262 if(OpenAHI()) {
263 if(AllocAudio()) {
264 ahem = LoadSample("Projekt:ahi/samples/ASS-14.sb", AHIST_M8S);
265 louise = LoadSample("Projekt:ahi/samples/LouiseR.sw", AHIST_M16S);
266 if((ahem != AHI_NOSOUND) && (louise != AHI_NOSOUND)) {
268 // Start feeding samples to sound hardware
269 if(!(AHI_ControlAudio(actrl,
270 AHIC_Play, TRUE,
271 TAG_DONE)))
274 #if USE_AHI_V4
275 Printf("Playing two samples, one with echo and one without.\n");
277 // Turn on echo on channel 1
278 // No error checking here, but you should do that.
279 maskeffect.mask.ahie_Effect = AHIET_DSPMASK;
280 maskeffect.mask.ahiedm_Channels = CHANNELS;
281 maskeffect.mode[0] = AHIEDM_DRY;
282 maskeffect.mode[1] = AHIEDM_WET;
283 AHI_SetEffect( &maskeffect, actrl );
285 echoeffect.ahie_Effect = AHIET_DSPECHO;
286 echoeffect.ahiede_Delay = mixfreq / 4; // 250 ms
287 echoeffect.ahiede_Feedback = 0x8000; // 50 %
288 echoeffect.ahiede_Mix = 0x10000; // 100% and...
289 echoeffect.ahiede_Cross = 0; // ...0% gives faster echo code.
290 AHI_SetEffect( &echoeffect, actrl );
292 AHI_Play(actrl,
293 // A forever-looping sample on channel 0
294 AHIP_BeginChannel, 0,
295 AHIP_Freq, 17640,
296 AHIP_Vol, 0x10000,
297 AHIP_Pan, 0xc000,
298 AHIP_Sound, louise,
299 AHIP_EndChannel, NULL,
301 // A oneshot sample on channel 1
302 AHIP_BeginChannel, 1,
303 AHIP_Freq, 22254,
304 AHIP_Vol, 0x10000,
305 AHIP_Pan, 0x4000,
306 AHIP_Sound, ahem,
307 AHIP_LoopSound, AHI_NOSOUND,
308 AHIP_EndChannel, NULL,
310 TAG_DONE);
311 #else
312 Printf("Playing two samples.\n");
314 // A forever-looping sample on channel 0
315 AHI_SetFreq(0, 17640, actrl, AHISF_IMM);
316 AHI_SetVol(0, 0x10000, 0xc000, actrl, AHISF_IMM);
317 AHI_SetSound(0, louise, 0, 0, actrl, AHISF_IMM);
319 // A oneshot sample on channel 1
320 AHI_SetFreq(1, 22254, actrl, AHISF_IMM);
321 AHI_SetVol(1, 0x10000, 0x4000, actrl, AHISF_IMM);
322 AHI_SetSound(1, ahem, 0, 0, actrl, AHISF_IMM);
323 AHI_SetSound(1, AHI_NOSOUND, 0, 0, actrl, 0);
324 #endif
325 channelstate[0].Volume = 0x10000;
326 channelstate[0].Position = 0xc000;
327 channelstate[1].Volume = 0x10000;
328 channelstate[1].Position = 0x4000;
330 // Wait 5 seconds
332 Delay(5 * TICKS_PER_SECOND);
334 #if USE_AHI_V4
335 Printf("Turning on echo on channel 0.\n");
337 // Turn on echo on channel 0, turn off channel 1
338 // No error checking here, but you should do that.
339 maskeffect.mode[0] = AHIEDM_WET;
340 maskeffect.mode[1] = AHIEDM_DRY;
341 AHI_SetEffect( &maskeffect, actrl );
342 #endif
344 // Wait 5 seconds
346 Delay(5 * TICKS_PER_SECOND);
348 Printf("Fading away the sound on channel 0... ");
349 Flush(Output());
351 // Fade away channel 0
353 channelstate[0].FadeVolume = TRUE;
355 while(channelstate[0].FadeVolume) {
356 Delay(1);
359 Printf("Done!\n");
361 // Wait a sec...
363 Delay(TICKS_PER_SECOND);
365 // Stop sounds
366 AHI_ControlAudio(actrl,
367 AHIC_Play, FALSE,
368 TAG_DONE);
371 #if USE_AHI_V4
372 // Cancel effects
374 maskeffect.mask.ahie_Effect = AHIET_DSPMASK | AHIET_CANCEL;
375 AHI_SetEffect( &maskeffect, actrl );
377 echoeffect.ahie_Effect = AHIET_DSPECHO | AHIET_CANCEL;
378 AHI_SetEffect( &echoeffect, actrl );
379 #endif
384 // Ask AHI to unload all loaded samples and free the memory for them
385 for(sample = 0; sample < MAXSAMPLES; sample++) {
386 UnloadSample(sample);
390 FreeAudio();
392 CloseAHI();
394 return 0;