2 AHI - Hardware independent audio subsystem
3 Copyright (C) 2017 The AROS Dev Team
4 Copyright (C) 1996-2005 Martin Blom <martin@blom.org>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with this library; if not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
24 #include <exec/memory.h>
25 #include <exec/alerts.h>
26 #include <utility/utility.h>
27 #include <utility/tagitem.h>
29 #include <proto/exec.h>
30 #include <proto/utility.h>
31 #include <proto/dos.h>
33 #define __NOGLOBALIFACE__
34 #include <proto/ahi.h>
36 #undef __NOGLOBALIFACE__
37 #include <proto/ahi_sub.h>
38 #include <clib/alib_protos.h>
43 #include "audioctrl.h"
52 // Makes 'in' fit the given bounds.
54 #define inbounds(in,min,max) \
55 ( (in > max) ? max : ( (in < min) ? min : in ) )
58 /******************************************************************************
59 ** RecalcBuff *****************************************************************
60 ******************************************************************************/
62 // Calculates how many samples to mix each mixer pass. The result it
63 // both returned and stored in ahiac_BuffSamples.
64 // ahiac_BuffSizeNow will also be updated (For mixing routine)
67 RecalcBuff ( Fixed freq
, struct AHIPrivAudioCtrl
*audioctrl
)
71 // If ULONG, convert to Fixed
72 // if(freq < 65536) freq <<= 16;
75 if(freq
== 0) return 0;
77 audioctrl
->ac
.ahiac_BuffSamples
= (audioctrl
->ac
.ahiac_MixFreq
<< 8) /
80 // ahiac_BuffSamples *must* fit a WORD according to the driver autodocs!
81 if(audioctrl
->ac
.ahiac_BuffSamples
> 65535)
83 audioctrl
->ac
.ahiac_BuffSamples
= 65535;
86 // Now, calculate the required mixing buffer size.
88 length
= audioctrl
->ac
.ahiac_BuffSamples
*
89 AHI_SampleFrameSize(audioctrl
->ac
.ahiac_BuffType
);
91 if(audioctrl
->ac
.ahiac_Flags
& AHIACF_POSTPROC
)
93 length
<<= 1; // 2 buffers
96 // Pad to even 8 and add some more (because of an old Mungwall hit, but I
97 // think that bug was fixed a long, long time ago..?)
99 length
= ((length
+ 7) & (~7) ) + 80;
101 audioctrl
->ahiac_BuffSizeNow
= length
;
103 return audioctrl
->ac
.ahiac_BuffSamples
;
108 /******************************************************************************
109 ** CreateAudioCtrl & UpdateAudioCtrl ******************************************
110 ******************************************************************************/
112 #define DEFPLAYERFREQ (50<<16)
121 static const struct Hook DefPlayerHook
=
124 (HOOKFUNC
) HookEntry
,
125 (HOOKFUNC
) DummyHook
,
130 static const struct TagItem boolmap
[] =
132 { AHIDB_Volume
, AHIACF_VOL
},
133 { AHIDB_Panning
, AHIACF_PAN
},
134 { AHIDB_Stereo
, AHIACF_STEREO
},
135 { AHIDB_HiFi
, AHIACF_HIFI
},
136 { AHIDB_PingPong
, AHIACF_PINGPONG
},
137 { AHIDB_Record
, AHIACF_RECORD
},
138 { AHIDB_MultTable
, AHIACF_MULTTAB
},
139 { AHIDB_MultiChannel
, AHIACF_MULTICHANNEL
},
144 struct AHIPrivAudioCtrl
*
145 CreateAudioCtrl(struct TagItem
*tags
)
147 struct AHIPrivAudioCtrl
*audioctrl
;
148 struct AHI_AudioDatabase
*audiodb
;
149 struct TagItem
*dbtags
;
152 ULONG data_flags
= MEMF_ANY
;
157 data_flags
= MEMF_PUBLIC
| MEMF_CLEAR
;
160 #if defined( ENABLE_WARPUP )
162 // Non-cached from both the PPC and m68k side
163 data_flags
= MEMF_PUBLIC
| MEMF_CLEAR
| MEMF_CHIP
;
168 audioctrl
= AHIAllocVec( sizeof( struct AHIPrivAudioCtrl
),
171 if( audioctrl
!= NULL
)
173 audioctrl
->ac
.ahiac_AudioCtrl
.ahiac_UserData
=
174 (APTR
)GetTagData(AHIA_UserData
,0,tags
);
175 audioctrl
->ahiac_AudioID
=
176 GetTagData(AHIA_AudioID
,AHI_DEFAULT_ID
,tags
);
177 audioctrl
->ac
.ahiac_MixFreq
=
178 GetTagData(AHIA_MixFreq
,AHI_DEFAULT_FREQ
,tags
);
179 audioctrl
->ac
.ahiac_Channels
=
180 GetTagData(AHIA_Channels
,0,tags
);
181 audioctrl
->ac
.ahiac_Sounds
=
182 GetTagData(AHIA_Sounds
,0,tags
);
183 audioctrl
->ac
.ahiac_SoundFunc
=
184 (struct Hook
*)GetTagData(AHIA_SoundFunc
,0,tags
);
185 audioctrl
->ahiac_RecordFunc
=
186 (struct Hook
*)GetTagData(AHIA_RecordFunc
,0,tags
);
187 audioctrl
->ac
.ahiac_PlayerFunc
=
188 (struct Hook
*)GetTagData(AHIA_PlayerFunc
,0,tags
);
189 audioctrl
->ac
.ahiac_PlayerFreq
=
190 GetTagData(AHIA_PlayerFreq
,0,tags
);
191 audioctrl
->ac
.ahiac_MinPlayerFreq
=
192 GetTagData(AHIA_MinPlayerFreq
,0,tags
);
193 audioctrl
->ac
.ahiac_MaxPlayerFreq
=
194 GetTagData(AHIA_MaxPlayerFreq
,0,tags
);
195 audioctrl
->ac
.ahiac_AntiClickSamples
=
196 GetTagData(AHIA_AntiClickSamples
,~0,tags
);
198 audioctrl
->ahiac_MasterVolume
=0x00010000;
199 audioctrl
->ahiac_SetMasterVolume
=0x00010000;
200 audioctrl
->ahiac_EchoMasterVolume
=0x00010000;
202 if(audioctrl
->ahiac_AudioID
== AHI_DEFAULT_ID
)
203 audioctrl
->ahiac_AudioID
= AHIBase
->ahib_AudioMode
;
205 if(audioctrl
->ac
.ahiac_MixFreq
== AHI_DEFAULT_FREQ
)
206 audioctrl
->ac
.ahiac_MixFreq
= AHIBase
->ahib_Frequency
;
208 if(audioctrl
->ac
.ahiac_PlayerFunc
== NULL
)
209 audioctrl
->ac
.ahiac_PlayerFunc
=(struct Hook
*)&DefPlayerHook
;
211 if(audioctrl
->ac
.ahiac_PlayerFreq
== 0)
212 audioctrl
->ac
.ahiac_PlayerFreq
= DEFPLAYERFREQ
;
213 if(audioctrl
->ac
.ahiac_MinPlayerFreq
== 0)
214 audioctrl
->ac
.ahiac_MinPlayerFreq
= DEFPLAYERFREQ
;
215 if(audioctrl
->ac
.ahiac_MaxPlayerFreq
== 0)
216 audioctrl
->ac
.ahiac_MaxPlayerFreq
= DEFPLAYERFREQ
;
218 if(audioctrl
->ac
.ahiac_PlayerFreq
< 65536)
219 audioctrl
->ac
.ahiac_PlayerFreq
<<= 16;
220 if(audioctrl
->ac
.ahiac_MinPlayerFreq
< 65536)
221 audioctrl
->ac
.ahiac_MinPlayerFreq
<<= 16;
222 if(audioctrl
->ac
.ahiac_MaxPlayerFreq
< 65536)
223 audioctrl
->ac
.ahiac_MaxPlayerFreq
<<= 16;
225 if(audioctrl
->ac
.ahiac_AntiClickSamples
== ~0)
226 audioctrl
->ac
.ahiac_AntiClickSamples
=
227 ( AHIBase
->ahib_AntiClickTime
* audioctrl
->ac
.ahiac_MixFreq
) >> 16;
229 if((audiodb
=LockDatabase()))
231 if((dbtags
=GetDBTagList(audiodb
,audioctrl
->ahiac_AudioID
)))
233 char driver_name
[128];
235 audioctrl
->ac
.ahiac_Flags
=PackBoolTags(GetTagData(AHIDB_Flags
,0,
236 dbtags
),dbtags
,(struct TagItem
*)boolmap
);
238 if(AHIBase
->ahib_Flags
& AHIBF_CLIPPING
)
240 audioctrl
->ac
.ahiac_Flags
|= AHIACF_CLIPPING
;
243 strcpy( audioctrl
->ahiac_DriverName
,
244 (char *) GetTagData( AHIDB_DriverBaseName
, (IPTR
) "DEVS:AHI", dbtags
) );
247 (char *) GetTagData( AHIDB_Driver
, (IPTR
) "", dbtags
) );
248 strcat( driver_name
, ".audio" );
250 AddPart(audioctrl
->ahiac_DriverName
, driver_name
, sizeof(audioctrl
->ahiac_DriverName
));
254 UnlockDatabase(audiodb
);
260 AHIFreeVec(audioctrl
);
268 UpdateAudioCtrl(struct AHIPrivAudioCtrl
*audioctrl
)
272 temp
=audioctrl
->ac
.ahiac_MinPlayerFreq
;
276 audioctrl
->ac
.ahiac_MaxBuffSamples
=audioctrl
->ac
.ahiac_MixFreq
/temp
;
278 audioctrl
->ac
.ahiac_MaxBuffSamples
=AHIBase
->ahib_Frequency
/audioctrl
->ac
.ahiac_PlayerFreq
;
280 temp
=audioctrl
->ac
.ahiac_MaxPlayerFreq
;
282 temp
= (temp
+ 65535) >> 16;
284 audioctrl
->ac
.ahiac_MinBuffSamples
=audioctrl
->ac
.ahiac_MixFreq
/temp
;
286 audioctrl
->ac
.ahiac_MinBuffSamples
=AHIBase
->ahib_Frequency
/audioctrl
->ac
.ahiac_PlayerFreq
;
291 /******************************************************************************
292 ** SamplerFunc ****************************************************************
293 ******************************************************************************/
297 SamplerFunc( struct Hook
* hook
,
298 struct AHIPrivAudioCtrl
* actrl
,
299 struct AHIRecordMessage
* recmsg
)
301 if(actrl
->ahiac_RecordFunc
)
303 CallHookPkt(actrl
->ahiac_RecordFunc
, actrl
, recmsg
);
307 /******************************************************************************
308 ** AHI_AllocAudioA ************************************************************
309 ******************************************************************************/
311 /****** ahi.device/AHI_AllocAudioA ******************************************
314 * AHI_AllocAudioA -- allocates and initializes the audio hardware
315 * AHI_AllocAudio -- varargs stub for AHI_AllocAudioA()
318 * audioctrl = AHI_AllocAudioA( tags );
321 * struct AHIAudioCtrl *AHI_AllocAudioA( struct TagItem * );
323 * audioctrl = AHI_AllocAudio( tag1, ... );
325 * struct AHIAudioCtrl *AHI_AllocAudio( Tag, ... );
328 * Allocates and initializes the audio hardware, selects the best
329 * mixing routine (if necessary) according to the supplied tags.
330 * To start playing you first need to call AHI_ControlAudioA().
333 * tags - A pointer to a tag list.
337 * AHIA_AudioID (IPTR) - The audio mode to use. Default is
338 * AHI_DEFAULT_ID. (AHI_DEFAULT_ID is the ID the user has selected
339 * in the preferences program. It's a good value to use the first
340 * time she starts your application.)
342 * AHIA_MixFreq (IPTR) - Desired mixing frequency. The actual
343 * mixing rate may or may not be exactly what you asked for.
344 * Default is AHI_DEFAULT_FREQ. (AHI_DEFAULT_FREQ is the user's
345 * prefered frequency.)
347 * AHIA_Channels (UWORD) - Number of channel to use. The actual
348 * number of channels used will be equal or grater than the
349 * requested. If too many channels were requested, this function
350 * will fail. This tag must be supplied.
352 * AHIA_Sounds (UWORD) - Number of sounds to use. This tag must be
355 * AHIA_SoundFunc (struct Hook *) - A function to call each time
356 * when a sound has been started. The function receives the
357 * following parameters:
358 * A0 - (struct Hook *)
359 * A2 - (struct AHIAudioCtrl *)
360 * A1 - (struct AHISoundMessage *)
361 * The hook may be called from an interrupt, so normal interrupt
362 * restrictions apply.
364 * The called function should follow normal register conventions,
365 * which means that d2-d7 and a2-a6 must be preserved.
369 * AHIA_PlayerFunc (struct Hook *) - A function to be called at regular
370 * intervals. By using this hook there is no need for music players
371 * to use other timing, such as VBLANK or CIA timers. But the real
372 * reason it's present is that it makes it possible to do non-
373 * realtime mixing to disk.
375 * Using this interrupt source is currently the only supported way
376 * to ensure that no mixing occurs between calls to AHI_SetVol(),
377 * AHI_SetFreq() or AHI_SetSound().
379 * If the sound playback is done without mixing, 'realtime.library'
380 * is used to provide timing. The function receives the following
382 * A0 - (struct Hook *)
383 * A2 - (struct AHIAudioCtrl *)
385 * Do not assume A1 contains any particular value!
386 * The hook may be called from an interrupt, so normal interrupt
387 * restrictions apply.
389 * The called function should follow normal register conventions,
390 * which means that d2-d7 and a2-a6 must be preserved.
394 * AHIA_PlayerFreq (Fixed) - If non-zero, enables timing and specifies
395 * how many times per second PlayerFunc will be called. This must
396 * be specified if AHIA_PlayerFunc is! Do not use any extreme
397 * frequencies. The result of MixFreq/PlayerFreq must fit an UWORD,
398 * ie it must be less or equal to 65535. It is also suggested that
399 * you keep the result over 80. For normal use this should not be a
400 * problem. Note that the data type is Fixed, not integer (see BUGS
401 * below). 50 Hz is 50<<16, which is a reasonable lower limit.
403 * Default is a reasonable value. Don't depend on it.
405 * AHIA_MinPlayerFreq (Fixed) - The minimum frequency (AHIA_PlayerFreq)
406 * you will use. You MUST supply this if you are using the device's
409 * AHIA_MaxPlayerFreq (Fixed) - The maximum frequency (AHIA_PlayerFreq)
410 * you will use. You MUST supply this if you are using the device's
413 * AHIA_RecordFunc (struct Hook *) - This function will be called
414 * regularly when sampling is turned on (see AHI_ControlAudioA())
415 * with the following parameters:
416 * A0 - (struct Hook *)
417 * A2 - (struct AHIAudioCtrl *)
418 * A1 - (struct AHIRecordMessage *)
419 * The message (AHIRecordMessage) is filled as follows:
420 * ahirm_Buffer - Pointer to the samples. The buffer is valid
421 * until next time the Hook is called.
422 * ahirm_Length - Number of sample FRAMES in buffer.
423 * To get the size in bytes, multiply by 4 if ahiim_Type is
425 * ahirm_Type - Always AHIST_S16S at the moment, but you *must*
426 * check this, since it may change in the future!
427 * The hook may be called from an interrupt, so normal interrupt
428 * restrictions apply. Signal a process if you wish to save the
429 * buffer to disk. The called function should follow normal register
430 * conventions, which means that d2-d7 and a2-a6 must be preserved.
432 * NOTE: The function MUST return NULL (in d0). This was previously
433 * not documented. Now you know.
437 * AHIA_UserData (APTR) - Can be used to initialize the ahiac_UserData
438 * field. Default is 0.
441 * A pointer to an AHIAudioCtrl structure or NULL if an error occured.
446 * SoundFunc will be called in the same manner as Paula interrupts
447 * occur; when the device has updated its internal variables and can
448 * accept new commands.
451 * For compability reasons with some really old applications,
452 * AHIA_PlayerFreq, AHIA_MinPlayerFreq and AHIA_MaxPlayerFreq
453 * interpret values lower than 0x10000 as integers, not Fixed.
454 * This means that the lowest frequency possible is 1 Hz. However,
455 * you should *never* use a value than say 10-20 Hz anyway, because
456 * of the high latency and the impact on multitasking.
458 * This kludge will be removed some day. Always use Fixed!
462 * AHI_FreeAudio(), AHI_ControlAudioA()
464 ****************************************************************************
469 _AHI_AllocAudioA( struct TagItem
* tags
,
470 struct AHIBase
* AHIBase
)
472 struct AHIPrivAudioCtrl
* audioctrl
;
473 struct Library
*AHIsubBase
;
474 struct AHI_AudioDatabase
*audiodb
;
475 struct TagItem
*dbtags
;
477 struct AHIsubIFace
* IAHIsub
;
480 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
482 Debug_AllocAudioA(tags
);
485 audioctrl
= CreateAudioCtrl( tags
);
489 AHIBase
->ahib_AudioCtrl
=audioctrl
; // Save latest (for KillAudio)
491 if(!audioctrl
->ac
.ahiac_Channels
|| !audioctrl
->ac
.ahiac_Sounds
)
494 audioctrl
->ahiac_SubAllocRC
= AHISF_ERROR
;
495 audioctrl
->ahiac_SubLib
=
496 AHIsubBase
= OpenLibrary(audioctrl
->ahiac_DriverName
,DriverVersion
);
497 //KPrintF("Opened AHIsubBase()\n");
500 audioctrl
->ahiac_IAHIsub
= NULL
;
507 if ((audioctrl
->ahiac_IAHIsub
= (struct AHIsubIFace
*) GetInterface((struct Library
*) AHIsubBase
, "main", 1, NULL
)) == NULL
)
511 IAHIsub
= audioctrl
->ahiac_IAHIsub
;
514 // Never allow drivers that are newer than ahi.device.
515 if(AHIsubBase
->lib_Version
> AHIBase
->ahib_Library
.lib_Version
)
518 audiodb
=LockDatabase();
522 dbtags
=GetDBTagList(audiodb
,audioctrl
->ahiac_AudioID
);
524 audioctrl
->ahiac_SubAllocRC
=AHIsub_AllocAudio(dbtags
,(struct AHIAudioCtrlDrv
*)audioctrl
);
525 //KPrintF("Called AHIsub_AllocAudio()\n");
526 UnlockDatabase(audiodb
);
531 UpdateAudioCtrl(audioctrl
);
533 if(audioctrl
->ahiac_SubAllocRC
& AHISF_ERROR
)
537 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_MIXING
))
538 audioctrl
->ac
.ahiac_Flags
|= AHIACF_NOMIXING
;
541 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_TIMING
))
542 audioctrl
->ac
.ahiac_Flags
|= AHIACF_NOTIMING
;
545 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_KNOWSTEREO
))
546 audioctrl
->ac
.ahiac_Flags
&= ~AHIACF_STEREO
;
549 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_KNOWMULTICHANNEL
))
550 audioctrl
->ac
.ahiac_Flags
&= ~AHIACF_MULTICHANNEL
;
554 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_KNOWHIFI
))
555 audioctrl
->ac
.ahiac_Flags
&= ~AHIACF_HIFI
;
558 if(audioctrl
->ahiac_SubAllocRC
& AHISF_CANPOSTPROCESS
)
559 audioctrl
->ac
.ahiac_Flags
|= AHIACF_POSTPROC
;
561 if(!(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOMIXING
))
563 switch(audioctrl
->ac
.ahiac_Flags
& (AHIACF_STEREO
| AHIACF_HIFI
| AHIACF_MULTICHANNEL
))
566 audioctrl
->ac
.ahiac_BuffType
=AHIST_M16S
;
569 audioctrl
->ac
.ahiac_BuffType
=AHIST_S16S
;
572 audioctrl
->ac
.ahiac_Flags
|= AHIACF_CLIPPING
;
573 audioctrl
->ac
.ahiac_BuffType
=AHIST_M32S
;
575 case (AHIACF_STEREO
| AHIACF_HIFI
):
576 audioctrl
->ac
.ahiac_Flags
|= AHIACF_CLIPPING
;
577 audioctrl
->ac
.ahiac_BuffType
=AHIST_S32S
;
579 case (AHIACF_STEREO
| AHIACF_HIFI
| AHIACF_MULTICHANNEL
):
580 audioctrl
->ac
.ahiac_Flags
|= AHIACF_CLIPPING
;
581 audioctrl
->ac
.ahiac_BuffType
=AHIST_L7_1
;
584 Alert(AT_Recovery
|AG_BadParm
);
588 /* Max channels/2 channels per hardware channel if stereo w/o pan */
589 if((audioctrl
->ac
.ahiac_Flags
& (AHIACF_STEREO
| AHIACF_PAN
)) == AHIACF_STEREO
)
590 audioctrl
->ahiac_Channels2
=(audioctrl
->ac
.ahiac_Channels
+1)/2;
592 audioctrl
->ahiac_Channels2
=audioctrl
->ac
.ahiac_Channels
;
594 if(!(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOTIMING
))
596 RecalcBuff(audioctrl
->ac
.ahiac_MinPlayerFreq
,audioctrl
);
597 audioctrl
->ac
.ahiac_BuffSize
=audioctrl
->ahiac_BuffSizeNow
;
598 RecalcBuff(audioctrl
->ac
.ahiac_PlayerFreq
,audioctrl
);
604 size
=audioctrl
->ac
.ahiac_BuffSamples
*\
605 AHI_SampleFrameSize(audioctrl
->ac
.ahiac_BuffType
)*\
606 (audioctrl
->ac
.ahiac_Flags
& AHIACF_POSTPROC
? 2 : 1);
609 size
&= ~7; // byte align
611 audioctrl
->ahiac_BuffSizeNow
=size
;
614 audioctrl
->ac
.ahiac_MixerFunc
=AllocVec(sizeof(struct Hook
),MEMF_PUBLIC
|MEMF_CLEAR
);
615 if(!audioctrl
->ac
.ahiac_MixerFunc
)
619 audioctrl
->ac
.ahiac_MixerFunc
->h_Entry
= (HOOKFUNC
) HookEntryPreserveAllRegs
;
620 audioctrl
->ac
.ahiac_MixerFunc
->h_SubEntry
= (HOOKFUNC
) MixerFunc
;
622 if((AHIBase
->ahib_MaxCPU
>= 0x10000) || (AHIBase
->ahib_MaxCPU
<= 0x0))
624 audioctrl
->ahiac_MaxCPU
= 0x100;
628 audioctrl
->ahiac_MaxCPU
= AHIBase
->ahib_MaxCPU
>> 8;
631 audioctrl
->ac
.ahiac_PreTimer
= (BOOL (*)(void)) PreTimerPreserveAllRegs
;
632 audioctrl
->ac
.ahiac_PostTimer
= (void (*)(void)) PostTimerPreserveAllRegs
;
634 audioctrl
->ac
.ahiac_PreTimerFunc
=AllocVec(sizeof(struct Hook
),MEMF_PUBLIC
|MEMF_CLEAR
);
635 if(!audioctrl
->ac
.ahiac_PreTimerFunc
)
638 audioctrl
->ac
.ahiac_PostTimerFunc
=AllocVec(sizeof(struct Hook
),MEMF_PUBLIC
|MEMF_CLEAR
);
639 if(!audioctrl
->ac
.ahiac_PostTimerFunc
)
642 audioctrl
->ac
.ahiac_PreTimerFunc
->h_Entry
= (HOOKFUNC
) HookEntry
;
643 audioctrl
->ac
.ahiac_PreTimerFunc
->h_SubEntry
= (HOOKFUNC
) PreTimerFunc
;
645 audioctrl
->ac
.ahiac_PostTimerFunc
->h_Entry
= (HOOKFUNC
) HookEntry
;
646 audioctrl
->ac
.ahiac_PostTimerFunc
->h_SubEntry
= (HOOKFUNC
) PostTimerFunc
;
648 if( !InitMixroutine( audioctrl
) ) goto error
;
651 audioctrl
->ac
.ahiac_SamplerFunc
= AllocVec(sizeof(struct Hook
),
652 MEMF_PUBLIC
|MEMF_CLEAR
);
653 if(!audioctrl
->ac
.ahiac_SamplerFunc
)
656 audioctrl
->ac
.ahiac_SamplerFunc
->h_Entry
= (HOOKFUNC
) HookEntry
;
657 audioctrl
->ac
.ahiac_SamplerFunc
->h_SubEntry
= (HOOKFUNC
) SamplerFunc
;
659 /* Set default hardware properties, only if AHI_DEFAULT_ID was used!*/
660 if(GetTagData(AHIA_AudioID
, AHI_DEFAULT_ID
, tags
) == AHI_DEFAULT_ID
)
662 AHI_ControlAudio((struct AHIAudioCtrl
*)audioctrl
,
663 AHIC_MonitorVolume
, AHIBase
->ahib_MonitorVolume
,
664 AHIC_InputGain
, AHIBase
->ahib_InputGain
,
665 AHIC_OutputVolume
, AHIBase
->ahib_OutputVolume
,
666 AHIC_Input
, AHIBase
->ahib_Input
,
667 AHIC_Output
, AHIBase
->ahib_Output
,
672 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
674 KPrintF("=>0x%08lx\n", (IPTR
) audioctrl
);
676 return (struct AHIAudioCtrl
*) audioctrl
;
680 AHI_FreeAudio((struct AHIAudioCtrl
*)audioctrl
);
686 /******************************************************************************
687 ** AHI_FreeAudio **************************************************************
688 ******************************************************************************/
690 /****** ahi.device/AHI_FreeAudio *******************************************
693 * AHI_FreeAudio -- deallocates the audio hardware
696 * AHI_FreeAudio( audioctrl );
699 * void AHI_FreeAudio( struct AHIAudioCtrl * );
702 * Deallocates the AHIAudioCtrl structure and any other resources
703 * allocated by AHI_AllocAudioA(). After this call it must not be used
704 * by any other functions anymore. AHI_UnloadSound() is automatically
705 * called for every sound.
708 * audioctrl - A pointer to an AHIAudioCtrl structure obtained from
709 * AHI_AllocAudioA(). If NULL, this function does nothing.
718 * AHI_AllocAudioA(), AHI_UnloadSound()
720 ****************************************************************************
725 _AHI_FreeAudio( struct AHIPrivAudioCtrl
* audioctrl
,
726 struct AHIBase
* AHIBase
)
728 struct Library
*AHIsubBase
;
731 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
733 Debug_FreeAudio(audioctrl
);
738 if((AHIsubBase
=audioctrl
->ahiac_SubLib
))
741 struct AHIsubIFace
* IAHIsub
= audioctrl
->ahiac_IAHIsub
;
744 if(!(audioctrl
->ahiac_SubAllocRC
& AHISF_ERROR
))
746 //KPrintF("Called AHIsub_Stop(play|record)\n");
747 AHIsub_Stop(AHISF_PLAY
|AHISF_RECORD
,(struct AHIAudioCtrlDrv
*)audioctrl
);
749 for(i
=audioctrl
->ac
.ahiac_Sounds
-1;i
>=0;i
--)
751 AHI_UnloadSound(i
,(struct AHIAudioCtrl
*)audioctrl
);
754 //KPrintF("Called AHIsub_FreeAudio()\n");
755 AHIsub_FreeAudio((struct AHIAudioCtrlDrv
*) audioctrl
);
756 //KPrintF("Closed AHIsubbase\n");
758 DropInterface((struct Interface
*) IAHIsub
);
762 CloseLibrary(AHIsubBase
);
765 if(!(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOMIXING
))
767 CleanUpMixroutine( audioctrl
);
770 FreeVec( audioctrl
->ac
.ahiac_SamplerFunc
);
771 FreeVec( audioctrl
->ac
.ahiac_MixerFunc
);
772 FreeVec( audioctrl
->ac
.ahiac_PreTimerFunc
);
773 FreeVec( audioctrl
->ac
.ahiac_PostTimerFunc
);
775 AHIFreeVec( audioctrl
);
781 /******************************************************************************
782 ** AHI_KillAudio **************************************************************
783 ******************************************************************************/
785 /****i* ahi.device/AHI_KillAudio *******************************************
788 * AHI_KillAudio -- clean up
793 * void AHI_KillAudio( void );
796 * 'ahi.device' keeps track of most of what the user does. This call is
797 * used to clean up as much as possible. It must never, ever, be used
798 * in an application. It is included for development use only, and can
799 * be used to avoid rebooting the computer if your program has allocated
800 * the audio hardware and crashed. This call can lead to a system crash,
801 * so don't use it if you don't have to.
806 * This function returns nothing. In fact, it may never return.
817 ****************************************************************************
822 _AHI_KillAudio( struct AHIBase
* AHIBase
)
826 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
831 for(i
=0xffff;i
!= 0; i
--)
833 *((UWORD
*) 0xdff102)=i
;
836 AHI_FreeAudio(AHIBase
->ahib_AudioCtrl
);
837 AHIBase
->ahib_AudioCtrl
=NULL
;
842 /******************************************************************************
843 ** AHI_ControlAudioA **********************************************************
844 ******************************************************************************/
846 /****** ahi.device/AHI_ControlAudioA ***************************************
849 * AHI_ControlAudioA -- change audio attributes
850 * AHI_ControlAudio -- varargs stub for AHI_ControlAudioA()
853 * error = AHI_ControlAudioA( audioctrl, tags );
856 * ULONG AHI_ControlAudioA( struct AHIAudioCtrl *, struct TagItem * );
858 * error = AHI_ControlAudio( AudioCtrl, tag1, ...);
860 * ULONG AHI_ControlAudio( struct AHIAudioCtrl *, Tag, ... );
863 * This function should be used to change attributes for a given
864 * AHIAudioCtrl structure. It is also used to start and stop playback,
865 * and to control special hardware found on some sound cards.
868 * audioctrl - A pointer to an AHIAudioCtrl structure.
869 * tags - A pointer to a tag list.
872 * AHIC_Play (BOOL) - Starts (TRUE) and stops (FALSE) playback and
873 * PlayerFunc. NOTE: If the audio hardware cannot play at the same
874 * time as recording samples, the recording will be stopped.
876 * AHIC_Record (BOOL) - Starts (TRUE) and stops (FALSE) sampling and
877 * RecordFunc. NOTE: If the audio hardware cannot record at the same
878 * time as playing samples, the playback will be stopped.
880 * AHIC_MonitorVolume (Fixed) - Sets the input monitor volume, i.e. how
881 * much of the input signal is mixed with the output signal while
882 * recording. Use AHI_GetAudioAttrsA() to find the available range.
884 * AHIC_MonitorVolume_Query (Fixed *) - Get the current input monitor
885 * volume. ti_Data is a pointer to a Fixed variable, where the result
888 * AHIC_MixFreq_Query (IPTR *) - Get the current mixing frequency.
889 * ti_Data is a pointer to an IPTR variable, where the result will
892 * AHIC_InputGain (Fixed) - Set the input gain. Use AHI_GetAudioAttrsA()
893 * to find the available range. (V2)
895 * AHIC_InputGain_Query (Fixed *) - Get current input gain. (V2)
897 * AHIC_OutputVolume (Fixed) - Set the output volume. Use
898 * AHI_GetAudioAttrsA() to find the available range. (V2)
900 * AHIC_OutputVolume_Query (Fixed *) - Get current output volume. (V2)
902 * AHIC_Input (IPTR) - Select input source. See AHI_GetAudioAttrsA().
905 * AHIC_Input_Query (IPTR *) - Get current input source. (V2)
907 * AHIC_Output (IPTR) - Select destination for output. See
908 * AHI_GetAudioAttrsA(). (V2)
910 * AHIC_Output_Query (IPTR *) - Get destination for output. (V2)
912 * The following tags are also recognized by AHI_ControlAudioA(). See
913 * AHI_AllocAudioA() for what they do. They may be used from interrupts.
915 * AHIA_SoundFunc (struct Hook *)
916 * AHIA_PlayerFunc (struct Hook *)
917 * AHIA_PlayerFreq (Fixed)
918 * AHIA_RecordFunc (struct Hook *)
919 * AHIA_UserData (APTR)
921 * Note that AHIA_PlayerFreq must never be outside the limits specified
922 * with AHIA_MinPlayerFreq and AHIA_MaxPlayerFreq! Also note that the
923 * timing feature is designed to be used for music. When you change the
924 * frequency, be reasonable. Using 50 Hz one moment and 5 the other is
925 * to ask for trouble.
928 * An error code, defined in <devices/ahi.h>.
933 * The AHIC_Play and AHIC_Record tags *must not* be used from
939 * AHI_AllocAudioA(), AHI_GetAudioAttrsA(), <devices/ahi.h>
941 ****************************************************************************
946 _AHI_ControlAudioA( struct AHIPrivAudioCtrl
* audioctrl
,
947 struct TagItem
* tags
,
948 struct AHIBase
* AHIBase
)
951 ULONG playflags
=0, stopflags
=0, rc
=AHIE_OK
;
953 struct TagItem
*tag
,*tstate
=tags
;
954 struct Library
*AHIsubBase
=audioctrl
->ahiac_SubLib
;
956 struct AHIsubIFace
* IAHIsub
= audioctrl
->ahiac_IAHIsub
;
959 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
961 Debug_ControlAudioA(audioctrl
,tags
);
964 while((tag
=NextTagItem(&tstate
)))
966 ptr
=(IPTR
*)tag
->ti_Data
; // For ..._Query tags
970 audioctrl
->ac
.ahiac_SoundFunc
=(struct Hook
*) tag
->ti_Data
;
973 case AHIA_RecordFunc
:
974 audioctrl
->ahiac_RecordFunc
=(struct Hook
*) tag
->ti_Data
;
977 case AHIA_PlayerFunc
:
978 audioctrl
->ac
.ahiac_PlayerFunc
=(struct Hook
*) tag
->ti_Data
;
981 case AHIA_PlayerFreq
:
982 audioctrl
->ac
.ahiac_PlayerFreq
=tag
->ti_Data
;
984 if(audioctrl
->ac
.ahiac_PlayerFreq
< 65536)
985 audioctrl
->ac
.ahiac_PlayerFreq
<<= 16;
987 if(!(audioctrl
->ac
.ahiac_Flags
& AHIACF_NOTIMING
)) // Dont call unless timing is used.
988 RecalcBuff(audioctrl
->ac
.ahiac_PlayerFreq
,audioctrl
);
992 audioctrl
->ac
.ahiac_AudioCtrl
.ahiac_UserData
=(void *)tag
->ti_Data
;
997 playflags
|= AHISF_PLAY
;
998 stopflags
&= ~AHISF_PLAY
;
1002 playflags
&= ~AHISF_PLAY
;
1003 stopflags
|= AHISF_PLAY
;
1010 playflags
|= AHISF_RECORD
;
1011 stopflags
&= ~AHISF_RECORD
;
1015 playflags
&= ~AHISF_RECORD
;
1016 stopflags
|= AHISF_RECORD
;
1020 case AHIC_MixFreq_Query
:
1021 *ptr
=audioctrl
->ac
.ahiac_MixFreq
;
1023 case AHIC_MonitorVolume
:
1024 case AHIC_InputGain
:
1025 case AHIC_OutputVolume
:
1028 AHIsub_HardwareControl(tag
->ti_Tag
, tag
->ti_Data
, (struct AHIAudioCtrlDrv
*)audioctrl
);
1029 //KPrintF("Called AHIsub_HardwareControl(%08lx:%08lx)\n",tag->ti_Tag, tag->ti_Data);
1031 case AHIC_MonitorVolume_Query
:
1032 case AHIC_InputGain_Query
:
1033 case AHIC_OutputVolume_Query
:
1034 case AHIC_Input_Query
:
1035 case AHIC_Output_Query
:
1036 *ptr
=AHIsub_HardwareControl(tag
->ti_Tag
, 0, (struct AHIAudioCtrlDrv
*)audioctrl
);
1037 //KPrintF("Called AHIsub_HardwareControl(%08lx:NULL)\n",tag->ti_Tag);
1045 AHIsub_Update(0,(struct AHIAudioCtrlDrv
*)audioctrl
);
1046 //KPrintF("Called AHIsub_Update()\n");
1051 rc
=AHIsub_Start(playflags
,(struct AHIAudioCtrlDrv
*)audioctrl
);
1052 //KPrintF("Called AHIsub_Start(%08lx)=>%ld\n",playflags,rc);
1057 AHIsub_Stop(stopflags
,(struct AHIAudioCtrlDrv
*)audioctrl
);
1058 //KPrintF("Called AHIsub_Stop(%08lx)\n",stopflags);
1061 if(AHIBase
->ahib_DebugLevel
>= AHI_DEBUG_LOW
)
1063 KPrintF("=>%ld\n",rc
);