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
=&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,dbtags
),dbtags
,boolmap
);
236 if(AHIBase
->ahib_Flags
& AHIBF_CLIPPING
)
238 audioctrl
->ac
.ahiac_Flags
|= AHIACF_CLIPPING
;
241 strcpy( audioctrl
->ahiac_DriverName
,
242 (char *) GetTagData( AHIDB_DriverBaseName
, (ULONG
) "DEVS:AHI", dbtags
) );
245 (char *) GetTagData( AHIDB_Driver
, (ULONG
) "", dbtags
) );
246 strcat( driver_name
, ".audio" );
248 AddPart(audioctrl
->ahiac_DriverName
, driver_name
, sizeof(audioctrl
->ahiac_DriverName
));
252 UnlockDatabase(audiodb
);
258 AHIFreeVec(audioctrl
);
266 UpdateAudioCtrl(struct AHIPrivAudioCtrl
*audioctrl
)
270 temp
=audioctrl
->ac
.ahiac_MinPlayerFreq
;
274 audioctrl
->ac
.ahiac_MaxBuffSamples
=audioctrl
->ac
.ahiac_MixFreq
/temp
;
276 audioctrl
->ac
.ahiac_MaxBuffSamples
=AHIBase
->ahib_Frequency
/audioctrl
->ac
.ahiac_PlayerFreq
;
278 temp
=audioctrl
->ac
.ahiac_MaxPlayerFreq
;
280 temp
= (temp
+ 65535) >> 16;
282 audioctrl
->ac
.ahiac_MinBuffSamples
=audioctrl
->ac
.ahiac_MixFreq
/temp
;
284 audioctrl
->ac
.ahiac_MinBuffSamples
=AHIBase
->ahib_Frequency
/audioctrl
->ac
.ahiac_PlayerFreq
;
289 /******************************************************************************
290 ** SamplerFunc ****************************************************************
291 ******************************************************************************/
295 SamplerFunc( struct Hook
* hook
,
296 struct AHIPrivAudioCtrl
* actrl
,
297 struct AHIRecordMessage
* recmsg
)
299 if(actrl
->ahiac_RecordFunc
)
301 CallHookPkt(actrl
->ahiac_RecordFunc
, actrl
, recmsg
);
305 /******************************************************************************
306 ** AHI_AllocAudioA ************************************************************
307 ******************************************************************************/
309 /****** ahi.device/AHI_AllocAudioA ******************************************
312 * AHI_AllocAudioA -- allocates and initializes the audio hardware
313 * AHI_AllocAudio -- varargs stub for AHI_AllocAudioA()
316 * audioctrl = AHI_AllocAudioA( tags );
319 * struct AHIAudioCtrl *AHI_AllocAudioA( struct TagItem * );
321 * audioctrl = AHI_AllocAudio( tag1, ... );
323 * struct AHIAudioCtrl *AHI_AllocAudio( Tag, ... );
326 * Allocates and initializes the audio hardware, selects the best
327 * mixing routine (if necessary) according to the supplied tags.
328 * To start playing you first need to call AHI_ControlAudioA().
331 * tags - A pointer to a tag list.
335 * AHIA_AudioID (ULONG) - The audio mode to use. Default is
336 * AHI_DEFAULT_ID. (AHI_DEFAULT_ID is the ID the user has selected
337 * in the preferences program. It's a good value to use the first
338 * time she starts your application.)
340 * AHIA_MixFreq (ULONG) - Desired mixing frequency. The actual
341 * mixing rate may or may not be exactly what you asked for.
342 * Default is AHI_DEFAULT_FREQ. (AHI_DEFAULT_FREQ is the user's
343 * prefered frequency.)
345 * AHIA_Channels (UWORD) - Number of channel to use. The actual
346 * number of channels used will be equal or grater than the
347 * requested. If too many channels were requested, this function
348 * will fail. This tag must be supplied.
350 * AHIA_Sounds (UWORD) - Number of sounds to use. This tag must be
353 * AHIA_SoundFunc (struct Hook *) - A function to call each time
354 * when a sound has been started. The function receives the
355 * following parameters:
356 * A0 - (struct Hook *)
357 * A2 - (struct AHIAudioCtrl *)
358 * A1 - (struct AHISoundMessage *)
359 * The hook may be called from an interrupt, so normal interrupt
360 * restrictions apply.
362 * The called function should follow normal register conventions,
363 * which means that d2-d7 and a2-a6 must be preserved.
367 * AHIA_PlayerFunc (struct Hook *) - A function to be called at regular
368 * intervals. By using this hook there is no need for music players
369 * to use other timing, such as VBLANK or CIA timers. But the real
370 * reason it's present is that it makes it possible to do non-
371 * realtime mixing to disk.
373 * Using this interrupt source is currently the only supported way
374 * to ensure that no mixing occurs between calls to AHI_SetVol(),
375 * AHI_SetFreq() or AHI_SetSound().
377 * If the sound playback is done without mixing, 'realtime.library'
378 * is used to provide timing. The function receives the following
380 * A0 - (struct Hook *)
381 * A2 - (struct AHIAudioCtrl *)
383 * Do not assume A1 contains any particular value!
384 * The hook may be called from an interrupt, so normal interrupt
385 * restrictions apply.
387 * The called function should follow normal register conventions,
388 * which means that d2-d7 and a2-a6 must be preserved.
392 * AHIA_PlayerFreq (Fixed) - If non-zero, enables timing and specifies
393 * how many times per second PlayerFunc will be called. This must
394 * be specified if AHIA_PlayerFunc is! Do not use any extreme
395 * frequencies. The result of MixFreq/PlayerFreq must fit an UWORD,
396 * ie it must be less or equal to 65535. It is also suggested that
397 * you keep the result over 80. For normal use this should not be a
398 * problem. Note that the data type is Fixed, not integer (see BUGS
399 * below). 50 Hz is 50<<16, which is a reasonable lower limit.
401 * Default is a reasonable value. Don't depend on it.
403 * AHIA_MinPlayerFreq (Fixed) - The minimum frequency (AHIA_PlayerFreq)
404 * you will use. You MUST supply this if you are using the device's
407 * AHIA_MaxPlayerFreq (Fixed) - The maximum frequency (AHIA_PlayerFreq)
408 * you will use. You MUST supply this if you are using the device's
411 * AHIA_RecordFunc (struct Hook *) - This function will be called
412 * regularly when sampling is turned on (see AHI_ControlAudioA())
413 * with the following parameters:
414 * A0 - (struct Hook *)
415 * A2 - (struct AHIAudioCtrl *)
416 * A1 - (struct AHIRecordMessage *)
417 * The message (AHIRecordMessage) is filled as follows:
418 * ahirm_Buffer - Pointer to the samples. The buffer is valid
419 * until next time the Hook is called.
420 * ahirm_Length - Number of sample FRAMES in buffer.
421 * To get the size in bytes, multiply by 4 if ahiim_Type is
423 * ahirm_Type - Always AHIST_S16S at the moment, but you *must*
424 * check this, since it may change in the future!
425 * The hook may be called from an interrupt, so normal interrupt
426 * restrictions apply. Signal a process if you wish to save the
427 * buffer to disk. The called function should follow normal register
428 * conventions, which means that d2-d7 and a2-a6 must be preserved.
430 * NOTE: The function MUST return NULL (in d0). This was previously
431 * not documented. Now you know.
435 * AHIA_UserData (APTR) - Can be used to initialize the ahiac_UserData
436 * field. Default is 0.
439 * A pointer to an AHIAudioCtrl structure or NULL if an error occured.
444 * SoundFunc will be called in the same manner as Paula interrupts
445 * occur; when the device has updated its internal variables and can
446 * accept new commands.
449 * For compability reasons with some really old applications,
450 * AHIA_PlayerFreq, AHIA_MinPlayerFreq and AHIA_MaxPlayerFreq
451 * interpret values lower than 0x10000 as integers, not Fixed.
452 * This means that the lowest frequency possible is 1 Hz. However,
453 * you should *never* use a value than say 10-20 Hz anyway, because
454 * of the high latency and the impact on multitasking.
456 * This kludge will be removed some day. Always use Fixed!
460 * AHI_FreeAudio(), AHI_ControlAudioA()
462 ****************************************************************************
467 _AHI_AllocAudioA( struct TagItem
* tags
,
468 struct AHIBase
* AHIBase
)
470 struct AHIPrivAudioCtrl
* audioctrl
;
471 struct Library
*AHIsubBase
;
472 struct AHI_AudioDatabase
*audiodb
;
473 struct TagItem
*dbtags
;
475 struct AHIsubIFace
* IAHIsub
;
478 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
480 Debug_AllocAudioA(tags
);
483 audioctrl
= CreateAudioCtrl( tags
);
487 AHIBase
->ahib_AudioCtrl
=audioctrl
; // Save latest (for KillAudio)
489 if(!audioctrl
->ac
.ahiac_Channels
|| !audioctrl
->ac
.ahiac_Sounds
)
492 audioctrl
->ahiac_SubAllocRC
= AHISF_ERROR
;
493 audioctrl
->ahiac_SubLib
=
494 AHIsubBase
= OpenLibrary(audioctrl
->ahiac_DriverName
,DriverVersion
);
495 //KPrintF("Opened AHIsubBase()\n");
498 audioctrl
->ahiac_IAHIsub
= NULL
;
505 if ((audioctrl
->ahiac_IAHIsub
= (struct AHIsubIFace
*) GetInterface((struct Library
*) AHIsubBase
, "main", 1, NULL
)) == NULL
)
509 IAHIsub
= audioctrl
->ahiac_IAHIsub
;
512 // Never allow drivers that are newer than ahi.device.
513 if(AHIsubBase
->lib_Version
> AHIBase
->ahib_Library
.lib_Version
)
516 audiodb
=LockDatabase();
520 dbtags
=GetDBTagList(audiodb
,audioctrl
->ahiac_AudioID
);
522 audioctrl
->ahiac_SubAllocRC
=AHIsub_AllocAudio(dbtags
,(struct AHIAudioCtrlDrv
*)audioctrl
);
523 //KPrintF("Called AHIsub_AllocAudio()\n");
524 UnlockDatabase(audiodb
);
529 UpdateAudioCtrl(audioctrl
);
531 if(audioctrl
->ahiac_SubAllocRC
& AHISF_ERROR
)
535 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_MIXING
))
536 audioctrl
->ac
.ahiac_Flags
|= AHIACF_NOMIXING
;
539 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_TIMING
))
540 audioctrl
->ac
.ahiac_Flags
|= AHIACF_NOTIMING
;
543 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_KNOWSTEREO
))
544 audioctrl
->ac
.ahiac_Flags
&= ~AHIACF_STEREO
;
547 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_KNOWMULTICHANNEL
))
548 audioctrl
->ac
.ahiac_Flags
&= ~AHIACF_MULTICHANNEL
;
552 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_KNOWHIFI
))
553 audioctrl
->ac
.ahiac_Flags
&= ~AHIACF_HIFI
;
556 if(audioctrl
->ahiac_SubAllocRC
& AHISF_CANPOSTPROCESS
)
557 audioctrl
->ac
.ahiac_Flags
|= AHIACF_POSTPROC
;
559 if(!(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOMIXING
))
561 switch(audioctrl
->ac
.ahiac_Flags
& (AHIACF_STEREO
| AHIACF_HIFI
| AHIACF_MULTICHANNEL
))
564 audioctrl
->ac
.ahiac_BuffType
=AHIST_M16S
;
567 audioctrl
->ac
.ahiac_BuffType
=AHIST_S16S
;
570 audioctrl
->ac
.ahiac_Flags
|= AHIACF_CLIPPING
;
571 audioctrl
->ac
.ahiac_BuffType
=AHIST_M32S
;
573 case (AHIACF_STEREO
| AHIACF_HIFI
):
574 audioctrl
->ac
.ahiac_Flags
|= AHIACF_CLIPPING
;
575 audioctrl
->ac
.ahiac_BuffType
=AHIST_S32S
;
577 case (AHIACF_STEREO
| AHIACF_HIFI
| AHIACF_MULTICHANNEL
):
578 audioctrl
->ac
.ahiac_Flags
|= AHIACF_CLIPPING
;
579 audioctrl
->ac
.ahiac_BuffType
=AHIST_L7_1
;
582 Alert(AT_Recovery
|AG_BadParm
);
586 /* Max channels/2 channels per hardware channel if stereo w/o pan */
587 if((audioctrl
->ac
.ahiac_Flags
& (AHIACF_STEREO
| AHIACF_PAN
)) == AHIACF_STEREO
)
588 audioctrl
->ahiac_Channels2
=(audioctrl
->ac
.ahiac_Channels
+1)/2;
590 audioctrl
->ahiac_Channels2
=audioctrl
->ac
.ahiac_Channels
;
592 if(!(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOTIMING
))
594 RecalcBuff(audioctrl
->ac
.ahiac_MinPlayerFreq
,audioctrl
);
595 audioctrl
->ac
.ahiac_BuffSize
=audioctrl
->ahiac_BuffSizeNow
;
596 RecalcBuff(audioctrl
->ac
.ahiac_PlayerFreq
,audioctrl
);
602 size
=audioctrl
->ac
.ahiac_BuffSamples
*\
603 AHI_SampleFrameSize(audioctrl
->ac
.ahiac_BuffType
)*\
604 (audioctrl
->ac
.ahiac_Flags
& AHIACF_POSTPROC
? 2 : 1);
607 size
&= ~7; // byte align
609 audioctrl
->ahiac_BuffSizeNow
=size
;
612 audioctrl
->ac
.ahiac_MixerFunc
=AllocVec(sizeof(struct Hook
),MEMF_PUBLIC
|MEMF_CLEAR
);
613 if(!audioctrl
->ac
.ahiac_MixerFunc
)
617 audioctrl
->ac
.ahiac_MixerFunc
->h_Entry
= (HOOKFUNC
) HookEntryPreserveAllRegs
;
618 audioctrl
->ac
.ahiac_MixerFunc
->h_SubEntry
= (HOOKFUNC
) MixerFunc
;
620 if((AHIBase
->ahib_MaxCPU
>= 0x10000) || (AHIBase
->ahib_MaxCPU
<= 0x0))
622 audioctrl
->ahiac_MaxCPU
= 0x100;
626 audioctrl
->ahiac_MaxCPU
= AHIBase
->ahib_MaxCPU
>> 8;
629 audioctrl
->ac
.ahiac_PreTimer
= (BOOL (*)(void)) PreTimerPreserveAllRegs
;
630 audioctrl
->ac
.ahiac_PostTimer
= (void (*)(void)) PostTimerPreserveAllRegs
;
632 audioctrl
->ac
.ahiac_PreTimerFunc
=AllocVec(sizeof(struct Hook
),MEMF_PUBLIC
|MEMF_CLEAR
);
633 if(!audioctrl
->ac
.ahiac_PreTimerFunc
)
636 audioctrl
->ac
.ahiac_PostTimerFunc
=AllocVec(sizeof(struct Hook
),MEMF_PUBLIC
|MEMF_CLEAR
);
637 if(!audioctrl
->ac
.ahiac_PostTimerFunc
)
640 audioctrl
->ac
.ahiac_PreTimerFunc
->h_Entry
= (HOOKFUNC
) HookEntry
;
641 audioctrl
->ac
.ahiac_PreTimerFunc
->h_SubEntry
= (HOOKFUNC
) PreTimerFunc
;
643 audioctrl
->ac
.ahiac_PostTimerFunc
->h_Entry
= (HOOKFUNC
) HookEntry
;
644 audioctrl
->ac
.ahiac_PostTimerFunc
->h_SubEntry
= (HOOKFUNC
) PostTimerFunc
;
646 if( !InitMixroutine( audioctrl
) ) goto error
;
649 audioctrl
->ac
.ahiac_SamplerFunc
= AllocVec(sizeof(struct Hook
),
650 MEMF_PUBLIC
|MEMF_CLEAR
);
651 if(!audioctrl
->ac
.ahiac_SamplerFunc
)
654 audioctrl
->ac
.ahiac_SamplerFunc
->h_Entry
= (HOOKFUNC
) HookEntry
;
655 audioctrl
->ac
.ahiac_SamplerFunc
->h_SubEntry
= (HOOKFUNC
) SamplerFunc
;
657 /* Set default hardware properties, only if AHI_DEFAULT_ID was used!*/
658 if(GetTagData(AHIA_AudioID
, AHI_DEFAULT_ID
, tags
) == AHI_DEFAULT_ID
)
660 AHI_ControlAudio((struct AHIAudioCtrl
*)audioctrl
,
661 AHIC_MonitorVolume
, AHIBase
->ahib_MonitorVolume
,
662 AHIC_InputGain
, AHIBase
->ahib_InputGain
,
663 AHIC_OutputVolume
, AHIBase
->ahib_OutputVolume
,
664 AHIC_Input
, AHIBase
->ahib_Input
,
665 AHIC_Output
, AHIBase
->ahib_Output
,
670 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
672 KPrintF("=>0x%08lx\n", (ULONG
) audioctrl
);
674 return (struct AHIAudioCtrl
*) audioctrl
;
678 AHI_FreeAudio((struct AHIAudioCtrl
*)audioctrl
);
684 /******************************************************************************
685 ** AHI_FreeAudio **************************************************************
686 ******************************************************************************/
688 /****** ahi.device/AHI_FreeAudio *******************************************
691 * AHI_FreeAudio -- deallocates the audio hardware
694 * AHI_FreeAudio( audioctrl );
697 * void AHI_FreeAudio( struct AHIAudioCtrl * );
700 * Deallocates the AHIAudioCtrl structure and any other resources
701 * allocated by AHI_AllocAudioA(). After this call it must not be used
702 * by any other functions anymore. AHI_UnloadSound() is automatically
703 * called for every sound.
706 * audioctrl - A pointer to an AHIAudioCtrl structure obtained from
707 * AHI_AllocAudioA(). If NULL, this function does nothing.
716 * AHI_AllocAudioA(), AHI_UnloadSound()
718 ****************************************************************************
723 _AHI_FreeAudio( struct AHIPrivAudioCtrl
* audioctrl
,
724 struct AHIBase
* AHIBase
)
726 struct Library
*AHIsubBase
;
729 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
731 Debug_FreeAudio(audioctrl
);
736 if((AHIsubBase
=audioctrl
->ahiac_SubLib
))
739 struct AHIsubIFace
* IAHIsub
= audioctrl
->ahiac_IAHIsub
;
742 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_ERROR
))
744 //KPrintF("Called AHIsub_Stop(play|record)\n");
745 AHIsub_Stop(AHISF_PLAY
|AHISF_RECORD
,(struct AHIAudioCtrlDrv
*)audioctrl
);
747 for(i
=audioctrl
->ac
.ahiac_Sounds
-1;i
>=0;i
--)
749 AHI_UnloadSound(i
,(struct AHIAudioCtrl
*)audioctrl
);
752 //KPrintF("Called AHIsub_FreeAudio()\n");
753 AHIsub_FreeAudio((struct AHIAudioCtrlDrv
*) audioctrl
);
754 //KPrintF("Closed AHIsubbase\n");
756 DropInterface((struct Interface
*) IAHIsub
);
760 CloseLibrary(AHIsubBase
);
763 if(!(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOMIXING
))
765 CleanUpMixroutine( audioctrl
);
768 FreeVec( audioctrl
->ac
.ahiac_SamplerFunc
);
769 FreeVec( audioctrl
->ac
.ahiac_MixerFunc
);
770 FreeVec( audioctrl
->ac
.ahiac_PreTimerFunc
);
771 FreeVec( audioctrl
->ac
.ahiac_PostTimerFunc
);
773 AHIFreeVec( audioctrl
);
779 /******************************************************************************
780 ** AHI_KillAudio **************************************************************
781 ******************************************************************************/
783 /****i* ahi.device/AHI_KillAudio *******************************************
786 * AHI_KillAudio -- clean up
791 * void AHI_KillAudio( void );
794 * 'ahi.device' keeps track of most of what the user does. This call is
795 * used to clean up as much as possible. It must never, ever, be used
796 * in an application. It is included for development use only, and can
797 * be used to avoid rebooting the computer if your program has allocated
798 * the audio hardware and crashed. This call can lead to a system crash,
799 * so don't use it if you don't have to.
804 * This function returns nothing. In fact, it may never return.
815 ****************************************************************************
820 _AHI_KillAudio( struct AHIBase
* AHIBase
)
824 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
829 for(i
=0xffff;i
!= 0; i
--)
831 *((UWORD
*) 0xdff102)=i
;
834 AHI_FreeAudio(AHIBase
->ahib_AudioCtrl
);
835 AHIBase
->ahib_AudioCtrl
=NULL
;
840 /******************************************************************************
841 ** AHI_ControlAudioA **********************************************************
842 ******************************************************************************/
844 /****** ahi.device/AHI_ControlAudioA ***************************************
847 * AHI_ControlAudioA -- change audio attributes
848 * AHI_ControlAudio -- varargs stub for AHI_ControlAudioA()
851 * error = AHI_ControlAudioA( audioctrl, tags );
854 * ULONG AHI_ControlAudioA( struct AHIAudioCtrl *, struct TagItem * );
856 * error = AHI_ControlAudio( AudioCtrl, tag1, ...);
858 * ULONG AHI_ControlAudio( struct AHIAudioCtrl *, Tag, ... );
861 * This function should be used to change attributes for a given
862 * AHIAudioCtrl structure. It is also used to start and stop playback,
863 * and to control special hardware found on some sound cards.
866 * audioctrl - A pointer to an AHIAudioCtrl structure.
867 * tags - A pointer to a tag list.
870 * AHIC_Play (BOOL) - Starts (TRUE) and stops (FALSE) playback and
871 * PlayerFunc. NOTE: If the audio hardware cannot play at the same
872 * time as recording samples, the recording will be stopped.
874 * AHIC_Record (BOOL) - Starts (TRUE) and stops (FALSE) sampling and
875 * RecordFunc. NOTE: If the audio hardware cannot record at the same
876 * time as playing samples, the playback will be stopped.
878 * AHIC_MonitorVolume (Fixed) - Sets the input monitor volume, i.e. how
879 * much of the input signal is mixed with the output signal while
880 * recording. Use AHI_GetAudioAttrsA() to find the available range.
882 * AHIC_MonitorVolume_Query (Fixed *) - Get the current input monitor
883 * volume. ti_Data is a pointer to a Fixed variable, where the result
886 * AHIC_MixFreq_Query (ULONG *) - Get the current mixing frequency.
887 * ti_Data is a pointer to an ULONG variable, where the result will
890 * AHIC_InputGain (Fixed) - Set the input gain. Use AHI_GetAudioAttrsA()
891 * to find the available range. (V2)
893 * AHIC_InputGain_Query (Fixed *) - Get current input gain. (V2)
895 * AHIC_OutputVolume (Fixed) - Set the output volume. Use
896 * AHI_GetAudioAttrsA() to find the available range. (V2)
898 * AHIC_OutputVolume_Query (Fixed *) - Get current output volume. (V2)
900 * AHIC_Input (ULONG) - Select input source. See AHI_GetAudioAttrsA().
903 * AHIC_Input_Query (ULONG *) - Get current input source. (V2)
905 * AHIC_Output (ULONG) - Select destination for output. See
906 * AHI_GetAudioAttrsA(). (V2)
908 * AHIC_Output_Query (ULONG *) - Get destination for output. (V2)
910 * The following tags are also recognized by AHI_ControlAudioA(). See
911 * AHI_AllocAudioA() for what they do. They may be used from interrupts.
913 * AHIA_SoundFunc (struct Hook *)
914 * AHIA_PlayerFunc (struct Hook *)
915 * AHIA_PlayerFreq (Fixed)
916 * AHIA_RecordFunc (struct Hook *)
917 * AHIA_UserData (APTR)
919 * Note that AHIA_PlayerFreq must never be outside the limits specified
920 * with AHIA_MinPlayerFreq and AHIA_MaxPlayerFreq! Also note that the
921 * timing feature is designed to be used for music. When you change the
922 * frequency, be reasonable. Using 50 Hz one moment and 5 the other is
923 * to ask for trouble.
926 * An error code, defined in <devices/ahi.h>.
931 * The AHIC_Play and AHIC_Record tags *must not* be used from
937 * AHI_AllocAudioA(), AHI_GetAudioAttrsA(), <devices/ahi.h>
939 ****************************************************************************
944 _AHI_ControlAudioA( struct AHIPrivAudioCtrl
* audioctrl
,
945 struct TagItem
* tags
,
946 struct AHIBase
* AHIBase
)
948 ULONG
*ptr
, playflags
=0, stopflags
=0, rc
=AHIE_OK
;
950 struct TagItem
*tag
,*tstate
=tags
;
951 struct Library
*AHIsubBase
=audioctrl
->ahiac_SubLib
;
953 struct AHIsubIFace
* IAHIsub
= audioctrl
->ahiac_IAHIsub
;
956 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
958 Debug_ControlAudioA(audioctrl
,tags
);
961 while((tag
=NextTagItem(&tstate
)))
963 ptr
=(ULONG
*)tag
->ti_Data
; // For ..._Query tags
967 audioctrl
->ac
.ahiac_SoundFunc
=(struct Hook
*) tag
->ti_Data
;
970 case AHIA_RecordFunc
:
971 audioctrl
->ahiac_RecordFunc
=(struct Hook
*) tag
->ti_Data
;
974 case AHIA_PlayerFunc
:
975 audioctrl
->ac
.ahiac_PlayerFunc
=(struct Hook
*) tag
->ti_Data
;
978 case AHIA_PlayerFreq
:
979 audioctrl
->ac
.ahiac_PlayerFreq
=tag
->ti_Data
;
981 if(audioctrl
->ac
.ahiac_PlayerFreq
< 65536)
982 audioctrl
->ac
.ahiac_PlayerFreq
<<= 16;
984 if(!(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOTIMING
)) // Dont call unless timing is used.
985 RecalcBuff(audioctrl
->ac
.ahiac_PlayerFreq
,audioctrl
);
989 audioctrl
->ac
.ahiac_AudioCtrl
.ahiac_UserData
=(void *)tag
->ti_Data
;
994 playflags
|= AHISF_PLAY
;
995 stopflags
&= ~AHISF_PLAY
;
999 playflags
&= ~AHISF_PLAY
;
1000 stopflags
|= AHISF_PLAY
;
1007 playflags
|= AHISF_RECORD
;
1008 stopflags
&= ~AHISF_RECORD
;
1012 playflags
&= ~AHISF_RECORD
;
1013 stopflags
|= AHISF_RECORD
;
1017 case AHIC_MixFreq_Query
:
1018 *ptr
=audioctrl
->ac
.ahiac_MixFreq
;
1020 case AHIC_MonitorVolume
:
1021 case AHIC_InputGain
:
1022 case AHIC_OutputVolume
:
1025 AHIsub_HardwareControl(tag
->ti_Tag
, tag
->ti_Data
, (struct AHIAudioCtrlDrv
*)audioctrl
);
1026 //KPrintF("Called AHIsub_HardwareControl(%08lx:%08lx)\n",tag->ti_Tag, tag->ti_Data);
1028 case AHIC_MonitorVolume_Query
:
1029 case AHIC_InputGain_Query
:
1030 case AHIC_OutputVolume_Query
:
1031 case AHIC_Input_Query
:
1032 case AHIC_Output_Query
:
1033 *ptr
=AHIsub_HardwareControl(tag
->ti_Tag
, 0, (struct AHIAudioCtrlDrv
*)audioctrl
);
1034 //KPrintF("Called AHIsub_HardwareControl(%08lx:NULL)\n",tag->ti_Tag);
1042 AHIsub_Update(0,(struct AHIAudioCtrlDrv
*)audioctrl
);
1043 //KPrintF("Called AHIsub_Update()\n");
1048 rc
=AHIsub_Start(playflags
,(struct AHIAudioCtrlDrv
*)audioctrl
);
1049 //KPrintF("Called AHIsub_Start(%08lx)=>%ld\n",playflags,rc);
1054 AHIsub_Stop(stopflags
,(struct AHIAudioCtrlDrv
*)audioctrl
);
1055 //KPrintF("Called AHIsub_Stop(%08lx)\n",stopflags);
1058 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
1060 KPrintF("=>%ld\n",rc
);