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>
10 #include <proto/exec.h>
12 #define USE_AHI_V4 TRUE
19 char *ID
= "$VER: SimplePlay 1.3 (23.4.97)\r\n";
21 APTR samples
[MAXSAMPLES
] = { 0 };
27 } channelstate
[CHANNELS
];
30 struct AHIEffDSPMask mask
;
33 struct AHIEffDSPEcho echoeffect
= {0};
35 struct Library
*AHIBase
;
36 struct MsgPort
*AHImp
= NULL
;
37 struct AHIRequest
*AHIio
= NULL
;
39 struct AHIAudioCtrl
*actrl
= NULL
;
47 BOOL
AllocAudio(void);
49 UWORD
LoadSample(unsigned char * , ULONG
);
50 void UnloadSample(UWORD
);
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
) {
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
,
81 struct Hook PlayerHook
= {
83 (ULONG (* )()) PlayerFunc
,
88 /******************************************************************************
89 **** OpenAHI ******************************************************************
90 ******************************************************************************/
92 /* Open the device for low-level usage */
96 if(AHImp
= CreateMsgPort()) {
97 if(AHIio
= (struct AHIRequest
*)CreateIORequest(
98 AHImp
,sizeof(struct AHIRequest
))) {
101 AHIio
->ahir_Version
= 4;
103 AHIio
->ahir_Version
= 2;
106 if(!(AHIDevice
= OpenDevice(AHINAME
, AHI_NO_UNIT
,
107 (struct IORequest
*) AHIio
,NULL
))) {
108 AHIBase
= (struct Library
*) AHIio
->ahir_Std
.io_Device
;
118 /******************************************************************************
119 **** CloseAHI *****************************************************************
120 ******************************************************************************/
122 /* Close the device */
124 void CloseAHI(void) {
127 CloseDevice((struct IORequest
*)AHIio
);
129 DeleteIORequest((struct IORequest
*)AHIio
);
131 DeleteMsgPort(AHImp
);
136 /******************************************************************************
137 **** AllocAudio ***************************************************************
138 ******************************************************************************/
140 /* Ask user for an audio mode and allocate it */
142 BOOL
AllocAudio(void) {
143 struct AHIAudioModeRequester
*req
;
146 req
= AHI_AllocAudioRequest(
147 AHIR_PubScreenName
, NULL
,
148 AHIR_TitleText
, "Select a mode and rate",
149 AHIR_DoMixFreq
, TRUE
,
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,
165 // Get real mixing frequency
166 AHI_ControlAudio(actrl
, AHIC_MixFreq_Query
, &mixfreq
, TAG_DONE
);
170 AHI_FreeAudioRequest(req
);
176 /******************************************************************************
177 **** FreeAudio ****************************************************************
178 ******************************************************************************/
180 /* Release the audio hardware */
184 AHI_FreeAudio(actrl
);
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
;
201 // Find a free sample slot
203 while(*samplearray
) {
206 if(id
>= MAXSAMPLES
) {
211 file
= Open(filename
, MODE_OLDFILE
);
216 Seek(file
, 0, OFFSET_END
);
217 length
= Seek(file
, 0, OFFSET_BEGINNING
);
218 *samplearray
= AllocVec(length
, MEMF_PUBLIC
);
220 Read(file
, *samplearray
, length
);
222 sample
.ahisi_Type
= type
;
223 sample
.ahisi_Address
= *samplearray
;
225 sample
.ahisi_Length
= length
/ AHI_SampleFrameSize(type
);
227 sample
.ahisi_Length
= length
/ (type
== AHIST_M16S
? 2 : 1);
229 if(! AHI_LoadSound(id
, AHIST_SAMPLE
, &sample
, actrl
)) {
239 /******************************************************************************
240 **** UnloadSample *************************************************************
241 ******************************************************************************/
243 void UnloadSample(UWORD id
) {
245 AHI_UnloadSound(id
, actrl
);
246 FreeVec(samples
[id
]);
250 /******************************************************************************
251 **** main *********************************************************************
252 ******************************************************************************/
255 UWORD sample
, ahem
, louise
;
258 for(i
= 0; i
< CHANNELS
; i
++) {
259 channelstate
[i
].FadeVolume
= FALSE
;
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
,
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
);
293 // A forever-looping sample on channel 0
294 AHIP_BeginChannel
, 0,
299 AHIP_EndChannel
, NULL
,
301 // A oneshot sample on channel 1
302 AHIP_BeginChannel
, 1,
307 AHIP_LoopSound
, AHI_NOSOUND
,
308 AHIP_EndChannel
, NULL
,
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);
325 channelstate
[0].Volume
= 0x10000;
326 channelstate
[0].Position
= 0xc000;
327 channelstate
[1].Volume
= 0x10000;
328 channelstate
[1].Position
= 0x4000;
332 Delay(5 * TICKS_PER_SECOND
);
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
);
346 Delay(5 * TICKS_PER_SECOND
);
348 Printf("Fading away the sound on channel 0... ");
351 // Fade away channel 0
353 channelstate
[0].FadeVolume
= TRUE
;
355 while(channelstate
[0].FadeVolume
) {
363 Delay(TICKS_PER_SECOND
);
366 AHI_ControlAudio(actrl
,
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
);
384 // Ask AHI to unload all loaded samples and free the memory for them
385 for(sample
= 0; sample
< MAXSAMPLES
; sample
++) {
386 UnloadSample(sample
);