2 AHI - Hardware independent audio subsystem
3 Copyright (C) 1996-2005 Martin Blom <martin@blom.org>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
23 #include <exec/memory.h>
24 #include <exec/alerts.h>
25 #include <utility/utility.h>
26 #include <utility/tagitem.h>
28 #include <proto/exec.h>
29 #include <proto/utility.h>
30 #include <proto/dos.h>
32 #define __NOGLOBALIFACE__
33 #include <proto/ahi.h>
35 #undef __NOGLOBALIFACE__
36 #include <proto/ahi_sub.h>
37 #include <clib/alib_protos.h>
42 #include "audioctrl.h"
51 // Makes 'in' fit the given bounds.
53 #define inbounds(in,min,max) \
54 ( (in > max) ? max : ( (in < min) ? min : in ) )
57 /******************************************************************************
58 ** RecalcBuff *****************************************************************
59 ******************************************************************************/
61 // Calculates how many samples to mix each mixer pass. The result it
62 // both returned and stored in ahiac_BuffSamples.
63 // ahiac_BuffSizeNow will also be updated (For mixing routine)
66 RecalcBuff ( Fixed freq
, struct AHIPrivAudioCtrl
*audioctrl
)
70 // If ULONG, convert to Fixed
71 // if(freq < 65536) freq <<= 16;
74 if(freq
== 0) return 0;
76 audioctrl
->ac
.ahiac_BuffSamples
= (audioctrl
->ac
.ahiac_MixFreq
<< 8) /
79 // ahiac_BuffSamples *must* fit a WORD according to the driver autodocs!
80 if(audioctrl
->ac
.ahiac_BuffSamples
> 65535)
82 audioctrl
->ac
.ahiac_BuffSamples
= 65535;
85 // Now, calculate the required mixing buffer size.
87 length
= audioctrl
->ac
.ahiac_BuffSamples
*
88 AHI_SampleFrameSize(audioctrl
->ac
.ahiac_BuffType
);
90 if(audioctrl
->ac
.ahiac_Flags
& AHIACF_POSTPROC
)
92 length
<<= 1; // 2 buffers
95 // Pad to even 8 and add some more (because of an old Mungwall hit, but I
96 // think that bug was fixed a long, long time ago..?)
98 length
= ((length
+ 7) & (~7) ) + 80;
100 audioctrl
->ahiac_BuffSizeNow
= length
;
102 return audioctrl
->ac
.ahiac_BuffSamples
;
107 /******************************************************************************
108 ** CreateAudioCtrl & UpdateAudioCtrl ******************************************
109 ******************************************************************************/
111 #define DEFPLAYERFREQ (50<<16)
120 static const struct Hook DefPlayerHook
=
123 (HOOKFUNC
) HookEntry
,
124 (HOOKFUNC
) DummyHook
,
129 static const struct TagItem boolmap
[] =
131 { AHIDB_Volume
, AHIACF_VOL
},
132 { AHIDB_Panning
, AHIACF_PAN
},
133 { AHIDB_Stereo
, AHIACF_STEREO
},
134 { AHIDB_HiFi
, AHIACF_HIFI
},
135 { AHIDB_PingPong
, AHIACF_PINGPONG
},
136 { AHIDB_Record
, AHIACF_RECORD
},
137 { AHIDB_MultTable
, AHIACF_MULTTAB
},
138 { AHIDB_MultiChannel
, AHIACF_MULTICHANNEL
},
143 struct AHIPrivAudioCtrl
*
144 CreateAudioCtrl(struct TagItem
*tags
)
146 struct AHIPrivAudioCtrl
*audioctrl
;
147 struct AHI_AudioDatabase
*audiodb
;
148 struct TagItem
*dbtags
;
151 ULONG data_flags
= MEMF_ANY
;
156 data_flags
= MEMF_PUBLIC
| MEMF_CLEAR
;
159 #if defined( ENABLE_WARPUP )
161 // Non-cached from both the PPC and m68k side
162 data_flags
= MEMF_PUBLIC
| MEMF_CLEAR
| MEMF_CHIP
;
167 audioctrl
= AHIAllocVec( sizeof( struct AHIPrivAudioCtrl
),
170 if( audioctrl
!= NULL
)
172 audioctrl
->ac
.ahiac_AudioCtrl
.ahiac_UserData
=
173 (APTR
)GetTagData(AHIA_UserData
,0,tags
);
174 audioctrl
->ahiac_AudioID
=
175 GetTagData(AHIA_AudioID
,AHI_DEFAULT_ID
,tags
);
176 audioctrl
->ac
.ahiac_MixFreq
=
177 GetTagData(AHIA_MixFreq
,AHI_DEFAULT_FREQ
,tags
);
178 audioctrl
->ac
.ahiac_Channels
=
179 GetTagData(AHIA_Channels
,0,tags
);
180 audioctrl
->ac
.ahiac_Sounds
=
181 GetTagData(AHIA_Sounds
,0,tags
);
182 audioctrl
->ac
.ahiac_SoundFunc
=
183 (struct Hook
*)GetTagData(AHIA_SoundFunc
,0,tags
);
184 audioctrl
->ahiac_RecordFunc
=
185 (struct Hook
*)GetTagData(AHIA_RecordFunc
,0,tags
);
186 audioctrl
->ac
.ahiac_PlayerFunc
=
187 (struct Hook
*)GetTagData(AHIA_PlayerFunc
,0,tags
);
188 audioctrl
->ac
.ahiac_PlayerFreq
=
189 GetTagData(AHIA_PlayerFreq
,0,tags
);
190 audioctrl
->ac
.ahiac_MinPlayerFreq
=
191 GetTagData(AHIA_MinPlayerFreq
,0,tags
);
192 audioctrl
->ac
.ahiac_MaxPlayerFreq
=
193 GetTagData(AHIA_MaxPlayerFreq
,0,tags
);
194 audioctrl
->ac
.ahiac_AntiClickSamples
=
195 GetTagData(AHIA_AntiClickSamples
,~0,tags
);
197 audioctrl
->ahiac_MasterVolume
=0x00010000;
198 audioctrl
->ahiac_SetMasterVolume
=0x00010000;
199 audioctrl
->ahiac_EchoMasterVolume
=0x00010000;
201 if(audioctrl
->ahiac_AudioID
== AHI_DEFAULT_ID
)
202 audioctrl
->ahiac_AudioID
= AHIBase
->ahib_AudioMode
;
204 if(audioctrl
->ac
.ahiac_MixFreq
== AHI_DEFAULT_FREQ
)
205 audioctrl
->ac
.ahiac_MixFreq
= AHIBase
->ahib_Frequency
;
207 if(audioctrl
->ac
.ahiac_PlayerFunc
== NULL
)
208 audioctrl
->ac
.ahiac_PlayerFunc
=(struct Hook
*)&DefPlayerHook
;
210 if(audioctrl
->ac
.ahiac_PlayerFreq
== 0)
211 audioctrl
->ac
.ahiac_PlayerFreq
= DEFPLAYERFREQ
;
212 if(audioctrl
->ac
.ahiac_MinPlayerFreq
== 0)
213 audioctrl
->ac
.ahiac_MinPlayerFreq
= DEFPLAYERFREQ
;
214 if(audioctrl
->ac
.ahiac_MaxPlayerFreq
== 0)
215 audioctrl
->ac
.ahiac_MaxPlayerFreq
= DEFPLAYERFREQ
;
217 if(audioctrl
->ac
.ahiac_PlayerFreq
< 65536)
218 audioctrl
->ac
.ahiac_PlayerFreq
<<= 16;
219 if(audioctrl
->ac
.ahiac_MinPlayerFreq
< 65536)
220 audioctrl
->ac
.ahiac_MinPlayerFreq
<<= 16;
221 if(audioctrl
->ac
.ahiac_MaxPlayerFreq
< 65536)
222 audioctrl
->ac
.ahiac_MaxPlayerFreq
<<= 16;
224 if(audioctrl
->ac
.ahiac_AntiClickSamples
== ~0)
225 audioctrl
->ac
.ahiac_AntiClickSamples
=
226 ( AHIBase
->ahib_AntiClickTime
* audioctrl
->ac
.ahiac_MixFreq
) >> 16;
228 if((audiodb
=LockDatabase()))
230 if((dbtags
=GetDBTagList(audiodb
,audioctrl
->ahiac_AudioID
)))
232 char driver_name
[128];
234 audioctrl
->ac
.ahiac_Flags
=PackBoolTags(GetTagData(AHIDB_Flags
,0,
235 dbtags
),dbtags
,(struct TagItem
*)boolmap
);
237 if(AHIBase
->ahib_Flags
& AHIBF_CLIPPING
)
239 audioctrl
->ac
.ahiac_Flags
|= AHIACF_CLIPPING
;
242 strcpy( audioctrl
->ahiac_DriverName
,
243 (char *) GetTagData( AHIDB_DriverBaseName
, (ULONG
) "DEVS:AHI", dbtags
) );
246 (char *) GetTagData( AHIDB_Driver
, (ULONG
) "", dbtags
) );
247 strcat( driver_name
, ".audio" );
249 AddPart(audioctrl
->ahiac_DriverName
, driver_name
, sizeof(audioctrl
->ahiac_DriverName
));
253 UnlockDatabase(audiodb
);
259 AHIFreeVec(audioctrl
);
267 UpdateAudioCtrl(struct AHIPrivAudioCtrl
*audioctrl
)
271 temp
=audioctrl
->ac
.ahiac_MinPlayerFreq
;
275 audioctrl
->ac
.ahiac_MaxBuffSamples
=audioctrl
->ac
.ahiac_MixFreq
/temp
;
277 audioctrl
->ac
.ahiac_MaxBuffSamples
=AHIBase
->ahib_Frequency
/audioctrl
->ac
.ahiac_PlayerFreq
;
279 temp
=audioctrl
->ac
.ahiac_MaxPlayerFreq
;
281 temp
= (temp
+ 65535) >> 16;
283 audioctrl
->ac
.ahiac_MinBuffSamples
=audioctrl
->ac
.ahiac_MixFreq
/temp
;
285 audioctrl
->ac
.ahiac_MinBuffSamples
=AHIBase
->ahib_Frequency
/audioctrl
->ac
.ahiac_PlayerFreq
;
290 /******************************************************************************
291 ** SamplerFunc ****************************************************************
292 ******************************************************************************/
296 SamplerFunc( struct Hook
* hook
,
297 struct AHIPrivAudioCtrl
* actrl
,
298 struct AHIRecordMessage
* recmsg
)
300 if(actrl
->ahiac_RecordFunc
)
302 CallHookPkt(actrl
->ahiac_RecordFunc
, actrl
, recmsg
);
306 /******************************************************************************
307 ** AHI_AllocAudioA ************************************************************
308 ******************************************************************************/
310 /****** ahi.device/AHI_AllocAudioA ******************************************
313 * AHI_AllocAudioA -- allocates and initializes the audio hardware
314 * AHI_AllocAudio -- varargs stub for AHI_AllocAudioA()
317 * audioctrl = AHI_AllocAudioA( tags );
320 * struct AHIAudioCtrl *AHI_AllocAudioA( struct TagItem * );
322 * audioctrl = AHI_AllocAudio( tag1, ... );
324 * struct AHIAudioCtrl *AHI_AllocAudio( Tag, ... );
327 * Allocates and initializes the audio hardware, selects the best
328 * mixing routine (if necessary) according to the supplied tags.
329 * To start playing you first need to call AHI_ControlAudioA().
332 * tags - A pointer to a tag list.
336 * AHIA_AudioID (ULONG) - The audio mode to use. Default is
337 * AHI_DEFAULT_ID. (AHI_DEFAULT_ID is the ID the user has selected
338 * in the preferences program. It's a good value to use the first
339 * time she starts your application.)
341 * AHIA_MixFreq (ULONG) - Desired mixing frequency. The actual
342 * mixing rate may or may not be exactly what you asked for.
343 * Default is AHI_DEFAULT_FREQ. (AHI_DEFAULT_FREQ is the user's
344 * prefered frequency.)
346 * AHIA_Channels (UWORD) - Number of channel to use. The actual
347 * number of channels used will be equal or grater than the
348 * requested. If too many channels were requested, this function
349 * will fail. This tag must be supplied.
351 * AHIA_Sounds (UWORD) - Number of sounds to use. This tag must be
354 * AHIA_SoundFunc (struct Hook *) - A function to call each time
355 * when a sound has been started. The function receives the
356 * following parameters:
357 * A0 - (struct Hook *)
358 * A2 - (struct AHIAudioCtrl *)
359 * A1 - (struct AHISoundMessage *)
360 * The hook may be called from an interrupt, so normal interrupt
361 * restrictions apply.
363 * The called function should follow normal register conventions,
364 * which means that d2-d7 and a2-a6 must be preserved.
368 * AHIA_PlayerFunc (struct Hook *) - A function to be called at regular
369 * intervals. By using this hook there is no need for music players
370 * to use other timing, such as VBLANK or CIA timers. But the real
371 * reason it's present is that it makes it possible to do non-
372 * realtime mixing to disk.
374 * Using this interrupt source is currently the only supported way
375 * to ensure that no mixing occurs between calls to AHI_SetVol(),
376 * AHI_SetFreq() or AHI_SetSound().
378 * If the sound playback is done without mixing, 'realtime.library'
379 * is used to provide timing. The function receives the following
381 * A0 - (struct Hook *)
382 * A2 - (struct AHIAudioCtrl *)
384 * Do not assume A1 contains any particular value!
385 * The hook may be called from an interrupt, so normal interrupt
386 * restrictions apply.
388 * The called function should follow normal register conventions,
389 * which means that d2-d7 and a2-a6 must be preserved.
393 * AHIA_PlayerFreq (Fixed) - If non-zero, enables timing and specifies
394 * how many times per second PlayerFunc will be called. This must
395 * be specified if AHIA_PlayerFunc is! Do not use any extreme
396 * frequencies. The result of MixFreq/PlayerFreq must fit an UWORD,
397 * ie it must be less or equal to 65535. It is also suggested that
398 * you keep the result over 80. For normal use this should not be a
399 * problem. Note that the data type is Fixed, not integer (see BUGS
400 * below). 50 Hz is 50<<16, which is a reasonable lower limit.
402 * Default is a reasonable value. Don't depend on it.
404 * AHIA_MinPlayerFreq (Fixed) - The minimum frequency (AHIA_PlayerFreq)
405 * you will use. You MUST supply this if you are using the device's
408 * AHIA_MaxPlayerFreq (Fixed) - The maximum frequency (AHIA_PlayerFreq)
409 * you will use. You MUST supply this if you are using the device's
412 * AHIA_RecordFunc (struct Hook *) - This function will be called
413 * regularly when sampling is turned on (see AHI_ControlAudioA())
414 * with the following parameters:
415 * A0 - (struct Hook *)
416 * A2 - (struct AHIAudioCtrl *)
417 * A1 - (struct AHIRecordMessage *)
418 * The message (AHIRecordMessage) is filled as follows:
419 * ahirm_Buffer - Pointer to the samples. The buffer is valid
420 * until next time the Hook is called.
421 * ahirm_Length - Number of sample FRAMES in buffer.
422 * To get the size in bytes, multiply by 4 if ahiim_Type is
424 * ahirm_Type - Always AHIST_S16S at the moment, but you *must*
425 * check this, since it may change in the future!
426 * The hook may be called from an interrupt, so normal interrupt
427 * restrictions apply. Signal a process if you wish to save the
428 * buffer to disk. The called function should follow normal register
429 * conventions, which means that d2-d7 and a2-a6 must be preserved.
431 * NOTE: The function MUST return NULL (in d0). This was previously
432 * not documented. Now you know.
436 * AHIA_UserData (APTR) - Can be used to initialize the ahiac_UserData
437 * field. Default is 0.
440 * A pointer to an AHIAudioCtrl structure or NULL if an error occured.
445 * SoundFunc will be called in the same manner as Paula interrupts
446 * occur; when the device has updated its internal variables and can
447 * accept new commands.
450 * For compability reasons with some really old applications,
451 * AHIA_PlayerFreq, AHIA_MinPlayerFreq and AHIA_MaxPlayerFreq
452 * interpret values lower than 0x10000 as integers, not Fixed.
453 * This means that the lowest frequency possible is 1 Hz. However,
454 * you should *never* use a value than say 10-20 Hz anyway, because
455 * of the high latency and the impact on multitasking.
457 * This kludge will be removed some day. Always use Fixed!
461 * AHI_FreeAudio(), AHI_ControlAudioA()
463 ****************************************************************************
468 _AHI_AllocAudioA( struct TagItem
* tags
,
469 struct AHIBase
* AHIBase
)
471 struct AHIPrivAudioCtrl
* audioctrl
;
472 struct Library
*AHIsubBase
;
473 struct AHI_AudioDatabase
*audiodb
;
474 struct TagItem
*dbtags
;
476 struct AHIsubIFace
* IAHIsub
;
479 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
481 Debug_AllocAudioA(tags
);
484 audioctrl
= CreateAudioCtrl( tags
);
488 AHIBase
->ahib_AudioCtrl
=audioctrl
; // Save latest (for KillAudio)
490 if(!audioctrl
->ac
.ahiac_Channels
|| !audioctrl
->ac
.ahiac_Sounds
)
493 audioctrl
->ahiac_SubAllocRC
= AHISF_ERROR
;
494 audioctrl
->ahiac_SubLib
=
495 AHIsubBase
= OpenLibrary(audioctrl
->ahiac_DriverName
,DriverVersion
);
496 //KPrintF("Opened AHIsubBase()\n");
499 audioctrl
->ahiac_IAHIsub
= NULL
;
506 if ((audioctrl
->ahiac_IAHIsub
= (struct AHIsubIFace
*) GetInterface((struct Library
*) AHIsubBase
, "main", 1, NULL
)) == NULL
)
510 IAHIsub
= audioctrl
->ahiac_IAHIsub
;
513 // Never allow drivers that are newer than ahi.device.
514 if(AHIsubBase
->lib_Version
> AHIBase
->ahib_Library
.lib_Version
)
517 audiodb
=LockDatabase();
521 dbtags
=GetDBTagList(audiodb
,audioctrl
->ahiac_AudioID
);
523 audioctrl
->ahiac_SubAllocRC
=AHIsub_AllocAudio(dbtags
,(struct AHIAudioCtrlDrv
*)audioctrl
);
524 //KPrintF("Called AHIsub_AllocAudio()\n");
525 UnlockDatabase(audiodb
);
530 UpdateAudioCtrl(audioctrl
);
532 if(audioctrl
->ahiac_SubAllocRC
& AHISF_ERROR
)
536 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_MIXING
))
537 audioctrl
->ac
.ahiac_Flags
|= AHIACF_NOMIXING
;
540 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_TIMING
))
541 audioctrl
->ac
.ahiac_Flags
|= AHIACF_NOTIMING
;
544 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_KNOWSTEREO
))
545 audioctrl
->ac
.ahiac_Flags
&= ~AHIACF_STEREO
;
548 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_KNOWMULTICHANNEL
))
549 audioctrl
->ac
.ahiac_Flags
&= ~AHIACF_MULTICHANNEL
;
553 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_KNOWHIFI
))
554 audioctrl
->ac
.ahiac_Flags
&= ~AHIACF_HIFI
;
557 if(audioctrl
->ahiac_SubAllocRC
& AHISF_CANPOSTPROCESS
)
558 audioctrl
->ac
.ahiac_Flags
|= AHIACF_POSTPROC
;
560 if(!(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOMIXING
))
562 switch(audioctrl
->ac
.ahiac_Flags
& (AHIACF_STEREO
| AHIACF_HIFI
| AHIACF_MULTICHANNEL
))
565 audioctrl
->ac
.ahiac_BuffType
=AHIST_M16S
;
568 audioctrl
->ac
.ahiac_BuffType
=AHIST_S16S
;
571 audioctrl
->ac
.ahiac_Flags
|= AHIACF_CLIPPING
;
572 audioctrl
->ac
.ahiac_BuffType
=AHIST_M32S
;
574 case (AHIACF_STEREO
| AHIACF_HIFI
):
575 audioctrl
->ac
.ahiac_Flags
|= AHIACF_CLIPPING
;
576 audioctrl
->ac
.ahiac_BuffType
=AHIST_S32S
;
578 case (AHIACF_STEREO
| AHIACF_HIFI
| AHIACF_MULTICHANNEL
):
579 audioctrl
->ac
.ahiac_Flags
|= AHIACF_CLIPPING
;
580 audioctrl
->ac
.ahiac_BuffType
=AHIST_L7_1
;
583 Alert(AT_Recovery
|AG_BadParm
);
587 /* Max channels/2 channels per hardware channel if stereo w/o pan */
588 if((audioctrl
->ac
.ahiac_Flags
& (AHIACF_STEREO
| AHIACF_PAN
)) == AHIACF_STEREO
)
589 audioctrl
->ahiac_Channels2
=(audioctrl
->ac
.ahiac_Channels
+1)/2;
591 audioctrl
->ahiac_Channels2
=audioctrl
->ac
.ahiac_Channels
;
593 if(!(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOTIMING
))
595 RecalcBuff(audioctrl
->ac
.ahiac_MinPlayerFreq
,audioctrl
);
596 audioctrl
->ac
.ahiac_BuffSize
=audioctrl
->ahiac_BuffSizeNow
;
597 RecalcBuff(audioctrl
->ac
.ahiac_PlayerFreq
,audioctrl
);
603 size
=audioctrl
->ac
.ahiac_BuffSamples
*\
604 AHI_SampleFrameSize(audioctrl
->ac
.ahiac_BuffType
)*\
605 (audioctrl
->ac
.ahiac_Flags
& AHIACF_POSTPROC
? 2 : 1);
608 size
&= ~7; // byte align
610 audioctrl
->ahiac_BuffSizeNow
=size
;
613 audioctrl
->ac
.ahiac_MixerFunc
=AllocVec(sizeof(struct Hook
),MEMF_PUBLIC
|MEMF_CLEAR
);
614 if(!audioctrl
->ac
.ahiac_MixerFunc
)
618 audioctrl
->ac
.ahiac_MixerFunc
->h_Entry
= (HOOKFUNC
) HookEntryPreserveAllRegs
;
619 audioctrl
->ac
.ahiac_MixerFunc
->h_SubEntry
= (HOOKFUNC
) MixerFunc
;
621 if((AHIBase
->ahib_MaxCPU
>= 0x10000) || (AHIBase
->ahib_MaxCPU
<= 0x0))
623 audioctrl
->ahiac_MaxCPU
= 0x100;
627 audioctrl
->ahiac_MaxCPU
= AHIBase
->ahib_MaxCPU
>> 8;
630 audioctrl
->ac
.ahiac_PreTimer
= (BOOL (*)(void)) PreTimerPreserveAllRegs
;
631 audioctrl
->ac
.ahiac_PostTimer
= (void (*)(void)) PostTimerPreserveAllRegs
;
633 audioctrl
->ac
.ahiac_PreTimerFunc
=AllocVec(sizeof(struct Hook
),MEMF_PUBLIC
|MEMF_CLEAR
);
634 if(!audioctrl
->ac
.ahiac_PreTimerFunc
)
637 audioctrl
->ac
.ahiac_PostTimerFunc
=AllocVec(sizeof(struct Hook
),MEMF_PUBLIC
|MEMF_CLEAR
);
638 if(!audioctrl
->ac
.ahiac_PostTimerFunc
)
641 audioctrl
->ac
.ahiac_PreTimerFunc
->h_Entry
= (HOOKFUNC
) HookEntry
;
642 audioctrl
->ac
.ahiac_PreTimerFunc
->h_SubEntry
= (HOOKFUNC
) PreTimerFunc
;
644 audioctrl
->ac
.ahiac_PostTimerFunc
->h_Entry
= (HOOKFUNC
) HookEntry
;
645 audioctrl
->ac
.ahiac_PostTimerFunc
->h_SubEntry
= (HOOKFUNC
) PostTimerFunc
;
647 if( !InitMixroutine( audioctrl
) ) goto error
;
650 audioctrl
->ac
.ahiac_SamplerFunc
= AllocVec(sizeof(struct Hook
),
651 MEMF_PUBLIC
|MEMF_CLEAR
);
652 if(!audioctrl
->ac
.ahiac_SamplerFunc
)
655 audioctrl
->ac
.ahiac_SamplerFunc
->h_Entry
= (HOOKFUNC
) HookEntry
;
656 audioctrl
->ac
.ahiac_SamplerFunc
->h_SubEntry
= (HOOKFUNC
) SamplerFunc
;
658 /* Set default hardware properties, only if AHI_DEFAULT_ID was used!*/
659 if(GetTagData(AHIA_AudioID
, AHI_DEFAULT_ID
, tags
) == AHI_DEFAULT_ID
)
661 AHI_ControlAudio((struct AHIAudioCtrl
*)audioctrl
,
662 AHIC_MonitorVolume
, AHIBase
->ahib_MonitorVolume
,
663 AHIC_InputGain
, AHIBase
->ahib_InputGain
,
664 AHIC_OutputVolume
, AHIBase
->ahib_OutputVolume
,
665 AHIC_Input
, AHIBase
->ahib_Input
,
666 AHIC_Output
, AHIBase
->ahib_Output
,
671 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
673 KPrintF("=>0x%08lx\n", (ULONG
) audioctrl
);
675 return (struct AHIAudioCtrl
*) audioctrl
;
679 AHI_FreeAudio((struct AHIAudioCtrl
*)audioctrl
);
685 /******************************************************************************
686 ** AHI_FreeAudio **************************************************************
687 ******************************************************************************/
689 /****** ahi.device/AHI_FreeAudio *******************************************
692 * AHI_FreeAudio -- deallocates the audio hardware
695 * AHI_FreeAudio( audioctrl );
698 * void AHI_FreeAudio( struct AHIAudioCtrl * );
701 * Deallocates the AHIAudioCtrl structure and any other resources
702 * allocated by AHI_AllocAudioA(). After this call it must not be used
703 * by any other functions anymore. AHI_UnloadSound() is automatically
704 * called for every sound.
707 * audioctrl - A pointer to an AHIAudioCtrl structure obtained from
708 * AHI_AllocAudioA(). If NULL, this function does nothing.
717 * AHI_AllocAudioA(), AHI_UnloadSound()
719 ****************************************************************************
724 _AHI_FreeAudio( struct AHIPrivAudioCtrl
* audioctrl
,
725 struct AHIBase
* AHIBase
)
727 struct Library
*AHIsubBase
;
730 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
732 Debug_FreeAudio(audioctrl
);
737 if((AHIsubBase
=audioctrl
->ahiac_SubLib
))
740 struct AHIsubIFace
* IAHIsub
= audioctrl
->ahiac_IAHIsub
;
743 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_ERROR
))
745 //KPrintF("Called AHIsub_Stop(play|record)\n");
746 AHIsub_Stop(AHISF_PLAY
|AHISF_RECORD
,(struct AHIAudioCtrlDrv
*)audioctrl
);
748 for(i
=audioctrl
->ac
.ahiac_Sounds
-1;i
>=0;i
--)
750 AHI_UnloadSound(i
,(struct AHIAudioCtrl
*)audioctrl
);
753 //KPrintF("Called AHIsub_FreeAudio()\n");
754 AHIsub_FreeAudio((struct AHIAudioCtrlDrv
*) audioctrl
);
755 //KPrintF("Closed AHIsubbase\n");
757 DropInterface((struct Interface
*) IAHIsub
);
761 CloseLibrary(AHIsubBase
);
764 if(!(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOMIXING
))
766 CleanUpMixroutine( audioctrl
);
769 FreeVec( audioctrl
->ac
.ahiac_SamplerFunc
);
770 FreeVec( audioctrl
->ac
.ahiac_MixerFunc
);
771 FreeVec( audioctrl
->ac
.ahiac_PreTimerFunc
);
772 FreeVec( audioctrl
->ac
.ahiac_PostTimerFunc
);
774 AHIFreeVec( audioctrl
);
780 /******************************************************************************
781 ** AHI_KillAudio **************************************************************
782 ******************************************************************************/
784 /****i* ahi.device/AHI_KillAudio *******************************************
787 * AHI_KillAudio -- clean up
792 * void AHI_KillAudio( void );
795 * 'ahi.device' keeps track of most of what the user does. This call is
796 * used to clean up as much as possible. It must never, ever, be used
797 * in an application. It is included for development use only, and can
798 * be used to avoid rebooting the computer if your program has allocated
799 * the audio hardware and crashed. This call can lead to a system crash,
800 * so don't use it if you don't have to.
805 * This function returns nothing. In fact, it may never return.
816 ****************************************************************************
821 _AHI_KillAudio( struct AHIBase
* AHIBase
)
825 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
830 for(i
=0xffff;i
!= 0; i
--)
832 *((UWORD
*) 0xdff102)=i
;
835 AHI_FreeAudio(AHIBase
->ahib_AudioCtrl
);
836 AHIBase
->ahib_AudioCtrl
=NULL
;
841 /******************************************************************************
842 ** AHI_ControlAudioA **********************************************************
843 ******************************************************************************/
845 /****** ahi.device/AHI_ControlAudioA ***************************************
848 * AHI_ControlAudioA -- change audio attributes
849 * AHI_ControlAudio -- varargs stub for AHI_ControlAudioA()
852 * error = AHI_ControlAudioA( audioctrl, tags );
855 * ULONG AHI_ControlAudioA( struct AHIAudioCtrl *, struct TagItem * );
857 * error = AHI_ControlAudio( AudioCtrl, tag1, ...);
859 * ULONG AHI_ControlAudio( struct AHIAudioCtrl *, Tag, ... );
862 * This function should be used to change attributes for a given
863 * AHIAudioCtrl structure. It is also used to start and stop playback,
864 * and to control special hardware found on some sound cards.
867 * audioctrl - A pointer to an AHIAudioCtrl structure.
868 * tags - A pointer to a tag list.
871 * AHIC_Play (BOOL) - Starts (TRUE) and stops (FALSE) playback and
872 * PlayerFunc. NOTE: If the audio hardware cannot play at the same
873 * time as recording samples, the recording will be stopped.
875 * AHIC_Record (BOOL) - Starts (TRUE) and stops (FALSE) sampling and
876 * RecordFunc. NOTE: If the audio hardware cannot record at the same
877 * time as playing samples, the playback will be stopped.
879 * AHIC_MonitorVolume (Fixed) - Sets the input monitor volume, i.e. how
880 * much of the input signal is mixed with the output signal while
881 * recording. Use AHI_GetAudioAttrsA() to find the available range.
883 * AHIC_MonitorVolume_Query (Fixed *) - Get the current input monitor
884 * volume. ti_Data is a pointer to a Fixed variable, where the result
887 * AHIC_MixFreq_Query (ULONG *) - Get the current mixing frequency.
888 * ti_Data is a pointer to an ULONG variable, where the result will
891 * AHIC_InputGain (Fixed) - Set the input gain. Use AHI_GetAudioAttrsA()
892 * to find the available range. (V2)
894 * AHIC_InputGain_Query (Fixed *) - Get current input gain. (V2)
896 * AHIC_OutputVolume (Fixed) - Set the output volume. Use
897 * AHI_GetAudioAttrsA() to find the available range. (V2)
899 * AHIC_OutputVolume_Query (Fixed *) - Get current output volume. (V2)
901 * AHIC_Input (ULONG) - Select input source. See AHI_GetAudioAttrsA().
904 * AHIC_Input_Query (ULONG *) - Get current input source. (V2)
906 * AHIC_Output (ULONG) - Select destination for output. See
907 * AHI_GetAudioAttrsA(). (V2)
909 * AHIC_Output_Query (ULONG *) - Get destination for output. (V2)
911 * The following tags are also recognized by AHI_ControlAudioA(). See
912 * AHI_AllocAudioA() for what they do. They may be used from interrupts.
914 * AHIA_SoundFunc (struct Hook *)
915 * AHIA_PlayerFunc (struct Hook *)
916 * AHIA_PlayerFreq (Fixed)
917 * AHIA_RecordFunc (struct Hook *)
918 * AHIA_UserData (APTR)
920 * Note that AHIA_PlayerFreq must never be outside the limits specified
921 * with AHIA_MinPlayerFreq and AHIA_MaxPlayerFreq! Also note that the
922 * timing feature is designed to be used for music. When you change the
923 * frequency, be reasonable. Using 50 Hz one moment and 5 the other is
924 * to ask for trouble.
927 * An error code, defined in <devices/ahi.h>.
932 * The AHIC_Play and AHIC_Record tags *must not* be used from
938 * AHI_AllocAudioA(), AHI_GetAudioAttrsA(), <devices/ahi.h>
940 ****************************************************************************
945 _AHI_ControlAudioA( struct AHIPrivAudioCtrl
* audioctrl
,
946 struct TagItem
* tags
,
947 struct AHIBase
* AHIBase
)
949 ULONG
*ptr
, playflags
=0, stopflags
=0, rc
=AHIE_OK
;
951 struct TagItem
*tag
,*tstate
=tags
;
952 struct Library
*AHIsubBase
=audioctrl
->ahiac_SubLib
;
954 struct AHIsubIFace
* IAHIsub
= audioctrl
->ahiac_IAHIsub
;
957 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
959 Debug_ControlAudioA(audioctrl
,tags
);
962 while((tag
=NextTagItem(&tstate
)))
964 ptr
=(ULONG
*)tag
->ti_Data
; // For ..._Query tags
968 audioctrl
->ac
.ahiac_SoundFunc
=(struct Hook
*) tag
->ti_Data
;
971 case AHIA_RecordFunc
:
972 audioctrl
->ahiac_RecordFunc
=(struct Hook
*) tag
->ti_Data
;
975 case AHIA_PlayerFunc
:
976 audioctrl
->ac
.ahiac_PlayerFunc
=(struct Hook
*) tag
->ti_Data
;
979 case AHIA_PlayerFreq
:
980 audioctrl
->ac
.ahiac_PlayerFreq
=tag
->ti_Data
;
982 if(audioctrl
->ac
.ahiac_PlayerFreq
< 65536)
983 audioctrl
->ac
.ahiac_PlayerFreq
<<= 16;
985 if(!(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOTIMING
)) // Dont call unless timing is used.
986 RecalcBuff(audioctrl
->ac
.ahiac_PlayerFreq
,audioctrl
);
990 audioctrl
->ac
.ahiac_AudioCtrl
.ahiac_UserData
=(void *)tag
->ti_Data
;
995 playflags
|= AHISF_PLAY
;
996 stopflags
&= ~AHISF_PLAY
;
1000 playflags
&= ~AHISF_PLAY
;
1001 stopflags
|= AHISF_PLAY
;
1008 playflags
|= AHISF_RECORD
;
1009 stopflags
&= ~AHISF_RECORD
;
1013 playflags
&= ~AHISF_RECORD
;
1014 stopflags
|= AHISF_RECORD
;
1018 case AHIC_MixFreq_Query
:
1019 *ptr
=audioctrl
->ac
.ahiac_MixFreq
;
1021 case AHIC_MonitorVolume
:
1022 case AHIC_InputGain
:
1023 case AHIC_OutputVolume
:
1026 AHIsub_HardwareControl(tag
->ti_Tag
, tag
->ti_Data
, (struct AHIAudioCtrlDrv
*)audioctrl
);
1027 //KPrintF("Called AHIsub_HardwareControl(%08lx:%08lx)\n",tag->ti_Tag, tag->ti_Data);
1029 case AHIC_MonitorVolume_Query
:
1030 case AHIC_InputGain_Query
:
1031 case AHIC_OutputVolume_Query
:
1032 case AHIC_Input_Query
:
1033 case AHIC_Output_Query
:
1034 *ptr
=AHIsub_HardwareControl(tag
->ti_Tag
, 0, (struct AHIAudioCtrlDrv
*)audioctrl
);
1035 //KPrintF("Called AHIsub_HardwareControl(%08lx:NULL)\n",tag->ti_Tag);
1043 AHIsub_Update(0,(struct AHIAudioCtrlDrv
*)audioctrl
);
1044 //KPrintF("Called AHIsub_Update()\n");
1049 rc
=AHIsub_Start(playflags
,(struct AHIAudioCtrlDrv
*)audioctrl
);
1050 //KPrintF("Called AHIsub_Start(%08lx)=>%ld\n",playflags,rc);
1055 AHIsub_Stop(stopflags
,(struct AHIAudioCtrlDrv
*)audioctrl
);
1056 //KPrintF("Called AHIsub_Stop(%08lx)\n",stopflags);
1059 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
1061 KPrintF("=>%ld\n",rc
);