alsa.audio: move handling of XRUN when writting to the slave task
[AROS.git] / workbench / devs / AHI / Device / audioctrl.c
blob9c5aedfb9ef2f4cdaf7c7a4ba5884286a469d68f
1 /*
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,
18 MA 02139, USA.
21 #include <config.h>
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>
31 #define __NOLIBBASE__
32 #define __NOGLOBALIFACE__
33 #include <proto/ahi.h>
34 #undef __NOLIBBASE__
35 #undef __NOGLOBALIFACE__
36 #include <proto/ahi_sub.h>
37 #include <clib/alib_protos.h>
39 #include <string.h>
41 #include "ahi_def.h"
42 #include "audioctrl.h"
43 #include "mixer.h"
44 #include "database.h"
45 #include "debug.h"
46 #include "misc.h"
47 #include "header.h"
48 #include "gateway.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)
65 static ULONG
66 RecalcBuff ( Fixed freq, struct AHIPrivAudioCtrl *audioctrl )
68 int length;
70 // If ULONG, convert to Fixed
71 // if(freq < 65536) freq <<= 16;
73 // Sanity check
74 if(freq == 0) return 0;
76 audioctrl->ac.ahiac_BuffSamples = (audioctrl->ac.ahiac_MixFreq << 8) /
77 (freq >> 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)
113 static ULONG
114 DummyHook( void )
116 return 0;
120 static const struct Hook DefPlayerHook =
122 {0, 0},
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 },
139 { TAG_DONE, 0 }
143 struct AHIPrivAudioCtrl *
144 CreateAudioCtrl(struct TagItem *tags)
146 struct AHIPrivAudioCtrl *audioctrl;
147 struct AHI_AudioDatabase *audiodb;
148 struct TagItem *dbtags;
149 BOOL error=TRUE;
151 ULONG data_flags = MEMF_ANY;
153 switch( MixBackend )
155 case MB_NATIVE:
156 data_flags = MEMF_PUBLIC | MEMF_CLEAR;
157 break;
159 #if defined( ENABLE_WARPUP )
160 case MB_WARPUP:
161 // Non-cached from both the PPC and m68k side
162 data_flags = MEMF_PUBLIC | MEMF_CLEAR | MEMF_CHIP;
163 break;
164 #endif
167 audioctrl = AHIAllocVec( sizeof( struct AHIPrivAudioCtrl ),
168 data_flags );
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) );
244 strcpy( driver_name,
245 (char *) GetTagData( AHIDB_Driver, (ULONG) "", dbtags ) );
246 strcat( driver_name, ".audio" );
248 AddPart(audioctrl->ahiac_DriverName, driver_name, sizeof(audioctrl->ahiac_DriverName));
250 error=FALSE;
252 UnlockDatabase(audiodb);
256 if(error)
258 AHIFreeVec(audioctrl);
259 return NULL;
261 else
262 return audioctrl;
265 static void
266 UpdateAudioCtrl(struct AHIPrivAudioCtrl *audioctrl)
268 ULONG temp;
270 temp=audioctrl->ac.ahiac_MinPlayerFreq;
271 if(temp>=65536)
272 temp >>=16;
273 if(temp)
274 audioctrl->ac.ahiac_MaxBuffSamples=audioctrl->ac.ahiac_MixFreq/temp;
275 else
276 audioctrl->ac.ahiac_MaxBuffSamples=AHIBase->ahib_Frequency/audioctrl->ac.ahiac_PlayerFreq;
278 temp=audioctrl->ac.ahiac_MaxPlayerFreq;
279 if(temp>=65536)
280 temp = (temp + 65535) >> 16;
281 if(temp)
282 audioctrl->ac.ahiac_MinBuffSamples=audioctrl->ac.ahiac_MixFreq/temp;
283 else
284 audioctrl->ac.ahiac_MinBuffSamples=AHIBase->ahib_Frequency/audioctrl->ac.ahiac_PlayerFreq;
289 /******************************************************************************
290 ** SamplerFunc ****************************************************************
291 ******************************************************************************/
294 static void
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 ******************************************
311 * NAME
312 * AHI_AllocAudioA -- allocates and initializes the audio hardware
313 * AHI_AllocAudio -- varargs stub for AHI_AllocAudioA()
315 * SYNOPSIS
316 * audioctrl = AHI_AllocAudioA( tags );
317 * D0 A1
319 * struct AHIAudioCtrl *AHI_AllocAudioA( struct TagItem * );
321 * audioctrl = AHI_AllocAudio( tag1, ... );
323 * struct AHIAudioCtrl *AHI_AllocAudio( Tag, ... );
325 * FUNCTION
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().
330 * INPUTS
331 * tags - A pointer to a tag list.
333 * TAGS
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
351 * supplied.
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.
365 * Default is NULL.
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
379 * parameters:
380 * A0 - (struct Hook *)
381 * A2 - (struct AHIAudioCtrl *)
382 * A1 - Undefined.
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.
390 * Default is NULL.
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
405 * interrupt feature!
407 * AHIA_MaxPlayerFreq (Fixed) - The maximum frequency (AHIA_PlayerFreq)
408 * you will use. You MUST supply this if you are using the device's
409 * interrupt feature!
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
422 * AHIST_S16S.
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.
433 * Default is NULL.
435 * AHIA_UserData (APTR) - Can be used to initialize the ahiac_UserData
436 * field. Default is 0.
438 * RESULT
439 * A pointer to an AHIAudioCtrl structure or NULL if an error occured.
441 * EXAMPLE
443 * NOTES
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.
448 * BUGS
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!
459 * SEE ALSO
460 * AHI_FreeAudio(), AHI_ControlAudioA()
462 ****************************************************************************
466 struct AHIAudioCtrl*
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;
474 #ifdef __AMIGAOS4__
475 struct AHIsubIFace* IAHIsub;
476 #endif
478 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
480 Debug_AllocAudioA(tags);
483 audioctrl = CreateAudioCtrl( tags );
484 if(!audioctrl)
485 goto error;
487 AHIBase->ahib_AudioCtrl=audioctrl; // Save latest (for KillAudio)
489 if(!audioctrl->ac.ahiac_Channels || !audioctrl->ac.ahiac_Sounds)
490 goto error;
492 audioctrl->ahiac_SubAllocRC = AHISF_ERROR;
493 audioctrl->ahiac_SubLib=
494 AHIsubBase = OpenLibrary(audioctrl->ahiac_DriverName,DriverVersion);
495 //KPrintF("Opened AHIsubBase()\n");
497 #ifdef __AMIGAOS4__
498 audioctrl->ahiac_IAHIsub = NULL;
499 #endif
501 if(!AHIsubBase)
502 goto error;
504 #ifdef __AMIGAOS4__
505 if ((audioctrl->ahiac_IAHIsub = (struct AHIsubIFace *) GetInterface((struct Library *) AHIsubBase, "main", 1, NULL)) == NULL)
507 goto error;
509 IAHIsub = audioctrl->ahiac_IAHIsub;
510 #endif
512 // Never allow drivers that are newer than ahi.device.
513 if(AHIsubBase->lib_Version > AHIBase->ahib_Library.lib_Version)
514 goto error;
516 audiodb=LockDatabase();
517 if(!audiodb)
518 goto error;
520 dbtags=GetDBTagList(audiodb,audioctrl->ahiac_AudioID);
521 if(dbtags)
522 audioctrl->ahiac_SubAllocRC=AHIsub_AllocAudio(dbtags,(struct AHIAudioCtrlDrv *)audioctrl);
523 //KPrintF("Called AHIsub_AllocAudio()\n");
524 UnlockDatabase(audiodb);
526 if(!dbtags)
527 goto error;
529 UpdateAudioCtrl(audioctrl);
531 if(audioctrl->ahiac_SubAllocRC & AHISF_ERROR)
532 goto error;
534 // Mixing
535 if(!(audioctrl->ahiac_SubAllocRC & AHISF_MIXING))
536 audioctrl->ac.ahiac_Flags |= AHIACF_NOMIXING;
538 // Timing
539 if(!(audioctrl->ahiac_SubAllocRC & AHISF_TIMING))
540 audioctrl->ac.ahiac_Flags |= AHIACF_NOTIMING;
542 // Stereo
543 if(!(audioctrl->ahiac_SubAllocRC & AHISF_KNOWSTEREO))
544 audioctrl->ac.ahiac_Flags &= ~AHIACF_STEREO;
546 // Multichannel 7.1
547 if(!(audioctrl->ahiac_SubAllocRC & AHISF_KNOWMULTICHANNEL))
548 audioctrl->ac.ahiac_Flags &= ~AHIACF_MULTICHANNEL;
550 // HiFi
552 if(!(audioctrl->ahiac_SubAllocRC & AHISF_KNOWHIFI))
553 audioctrl->ac.ahiac_Flags &= ~AHIACF_HIFI;
555 // Post-processing
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))
563 case 0:
564 audioctrl->ac.ahiac_BuffType=AHIST_M16S;
565 break;
566 case AHIACF_STEREO:
567 audioctrl->ac.ahiac_BuffType=AHIST_S16S;
568 break;
569 case AHIACF_HIFI:
570 audioctrl->ac.ahiac_Flags |= AHIACF_CLIPPING;
571 audioctrl->ac.ahiac_BuffType=AHIST_M32S;
572 break;
573 case (AHIACF_STEREO | AHIACF_HIFI):
574 audioctrl->ac.ahiac_Flags |= AHIACF_CLIPPING;
575 audioctrl->ac.ahiac_BuffType=AHIST_S32S;
576 break;
577 case (AHIACF_STEREO | AHIACF_HIFI | AHIACF_MULTICHANNEL):
578 audioctrl->ac.ahiac_Flags |= AHIACF_CLIPPING;
579 audioctrl->ac.ahiac_BuffType=AHIST_L7_1;
580 break;
581 default:
582 Alert(AT_Recovery|AG_BadParm);
583 goto error;
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;
589 else
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);
598 else // No timing
600 ULONG size;
602 size=audioctrl->ac.ahiac_BuffSamples*\
603 AHI_SampleFrameSize(audioctrl->ac.ahiac_BuffType)*\
604 (audioctrl->ac.ahiac_Flags & AHIACF_POSTPROC ? 2 : 1);
606 size +=7;
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)
614 goto error;
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;
624 else
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)
634 goto error;
636 audioctrl->ac.ahiac_PostTimerFunc=AllocVec(sizeof(struct Hook),MEMF_PUBLIC|MEMF_CLEAR);
637 if(!audioctrl->ac.ahiac_PostTimerFunc)
638 goto error;
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)
652 goto error;
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,
666 TAG_DONE);
669 exit:
670 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
672 KPrintF("=>0x%08lx\n", (ULONG) audioctrl);
674 return (struct AHIAudioCtrl *) audioctrl;
677 error:
678 AHI_FreeAudio((struct AHIAudioCtrl *)audioctrl);
679 audioctrl=NULL;
680 goto exit;
684 /******************************************************************************
685 ** AHI_FreeAudio **************************************************************
686 ******************************************************************************/
688 /****** ahi.device/AHI_FreeAudio *******************************************
690 * NAME
691 * AHI_FreeAudio -- deallocates the audio hardware
693 * SYNOPSIS
694 * AHI_FreeAudio( audioctrl );
695 * A2
697 * void AHI_FreeAudio( struct AHIAudioCtrl * );
699 * FUNCTION
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.
705 * INPUTS
706 * audioctrl - A pointer to an AHIAudioCtrl structure obtained from
707 * AHI_AllocAudioA(). If NULL, this function does nothing.
709 * EXAMPLE
711 * NOTES
713 * BUGS
715 * SEE ALSO
716 * AHI_AllocAudioA(), AHI_UnloadSound()
718 ****************************************************************************
722 ULONG
723 _AHI_FreeAudio( struct AHIPrivAudioCtrl* audioctrl,
724 struct AHIBase* AHIBase )
726 struct Library *AHIsubBase;
727 int i;
729 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
731 Debug_FreeAudio(audioctrl);
734 if(audioctrl)
736 if((AHIsubBase=audioctrl->ahiac_SubLib))
738 #ifdef __AMIGAOS4__
739 struct AHIsubIFace* IAHIsub = audioctrl->ahiac_IAHIsub;
740 #endif
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");
755 #ifdef __AMIGAOS4__
756 DropInterface((struct Interface *) IAHIsub);
757 IAHIsub = NULL;
758 #endif
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 );
775 return 0;
779 /******************************************************************************
780 ** AHI_KillAudio **************************************************************
781 ******************************************************************************/
783 /****i* ahi.device/AHI_KillAudio *******************************************
785 * NAME
786 * AHI_KillAudio -- clean up
788 * SYNOPSIS
789 * AHI_KillAudio();
791 * void AHI_KillAudio( void );
793 * FUNCTION
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.
801 * INPUTS
803 * RESULT
804 * This function returns nothing. In fact, it may never return.
806 * EXAMPLE
808 * NOTES
810 * BUGS
812 * SEE ALSO
813 * AHI_FreeAudio()
815 ****************************************************************************
819 ULONG
820 _AHI_KillAudio( struct AHIBase* AHIBase )
822 UWORD i;
824 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
826 Debug_KillAudio();
829 for(i=0xffff;i != 0; i--)
831 *((UWORD *) 0xdff102)=i;
834 AHI_FreeAudio(AHIBase->ahib_AudioCtrl);
835 AHIBase->ahib_AudioCtrl=NULL;
836 return 0;
840 /******************************************************************************
841 ** AHI_ControlAudioA **********************************************************
842 ******************************************************************************/
844 /****** ahi.device/AHI_ControlAudioA ***************************************
846 * NAME
847 * AHI_ControlAudioA -- change audio attributes
848 * AHI_ControlAudio -- varargs stub for AHI_ControlAudioA()
850 * SYNOPSIS
851 * error = AHI_ControlAudioA( audioctrl, tags );
852 * D0 A2 A1
854 * ULONG AHI_ControlAudioA( struct AHIAudioCtrl *, struct TagItem * );
856 * error = AHI_ControlAudio( AudioCtrl, tag1, ...);
858 * ULONG AHI_ControlAudio( struct AHIAudioCtrl *, Tag, ... );
860 * FUNCTION
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.
865 * INPUTS
866 * audioctrl - A pointer to an AHIAudioCtrl structure.
867 * tags - A pointer to a tag list.
869 * TAGS
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
884 * will be stored.
886 * AHIC_MixFreq_Query (ULONG *) - Get the current mixing frequency.
887 * ti_Data is a pointer to an ULONG variable, where the result will
888 * be stored.
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().
901 * (V2)
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.
925 * RESULT
926 * An error code, defined in <devices/ahi.h>.
928 * EXAMPLE
930 * NOTES
931 * The AHIC_Play and AHIC_Record tags *must not* be used from
932 * interrupts.
934 * BUGS
936 * SEE ALSO
937 * AHI_AllocAudioA(), AHI_GetAudioAttrsA(), <devices/ahi.h>
939 ****************************************************************************
943 ULONG
944 _AHI_ControlAudioA( struct AHIPrivAudioCtrl* audioctrl,
945 struct TagItem* tags,
946 struct AHIBase* AHIBase )
948 ULONG *ptr, playflags=0, stopflags=0, rc=AHIE_OK;
949 UBYTE update=FALSE;
950 struct TagItem *tag,*tstate=tags;
951 struct Library *AHIsubBase=audioctrl->ahiac_SubLib;
952 #ifdef __AMIGAOS4__
953 struct AHIsubIFace* IAHIsub = audioctrl->ahiac_IAHIsub;
954 #endif
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
964 switch(tag->ti_Tag)
966 case AHIA_SoundFunc:
967 audioctrl->ac.ahiac_SoundFunc=(struct Hook *) tag->ti_Data;
968 update=TRUE;
969 break;
970 case AHIA_RecordFunc:
971 audioctrl->ahiac_RecordFunc=(struct Hook *) tag->ti_Data;
972 update=TRUE;
973 break;
974 case AHIA_PlayerFunc:
975 audioctrl->ac.ahiac_PlayerFunc=(struct Hook *) tag->ti_Data;
976 update=TRUE;
977 break;
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);
986 update=TRUE;
987 break;
988 case AHIA_UserData:
989 audioctrl->ac.ahiac_AudioCtrl.ahiac_UserData=(void *)tag->ti_Data;
990 break;
991 case AHIC_Play:
992 if(tag->ti_Data)
994 playflags |= AHISF_PLAY;
995 stopflags &= ~AHISF_PLAY;
997 else
999 playflags &= ~AHISF_PLAY;
1000 stopflags |= AHISF_PLAY;
1002 update=FALSE;
1003 break;
1004 case AHIC_Record:
1005 if(tag->ti_Data)
1007 playflags |= AHISF_RECORD;
1008 stopflags &= ~AHISF_RECORD;
1010 else
1012 playflags &= ~AHISF_RECORD;
1013 stopflags |= AHISF_RECORD;
1015 update=FALSE;
1016 break;
1017 case AHIC_MixFreq_Query:
1018 *ptr=audioctrl->ac.ahiac_MixFreq;
1019 break;
1020 case AHIC_MonitorVolume:
1021 case AHIC_InputGain:
1022 case AHIC_OutputVolume:
1023 case AHIC_Input:
1024 case AHIC_Output:
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);
1027 break;
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);
1035 break;
1039 // Let's act!
1040 if(update)
1042 AHIsub_Update(0,(struct AHIAudioCtrlDrv *)audioctrl);
1043 //KPrintF("Called AHIsub_Update()\n");
1046 if(playflags)
1048 rc=AHIsub_Start(playflags,(struct AHIAudioCtrlDrv *)audioctrl);
1049 //KPrintF("Called AHIsub_Start(%08lx)=>%ld\n",playflags,rc);
1052 if(stopflags)
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);
1063 return rc;