w.i.p - correctly remap ColorModel_TrueColor images.
[AROS.git] / workbench / devs / AHI / Device / audioctrl.c
blob766a819db9031e875e9508427a539f5a296c9538
1 /*
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,
19 MA 02139, USA.
22 #include <config.h>
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>
32 #define __NOLIBBASE__
33 #define __NOGLOBALIFACE__
34 #include <proto/ahi.h>
35 #undef __NOLIBBASE__
36 #undef __NOGLOBALIFACE__
37 #include <proto/ahi_sub.h>
38 #include <clib/alib_protos.h>
40 #include <string.h>
42 #include "ahi_def.h"
43 #include "audioctrl.h"
44 #include "mixer.h"
45 #include "database.h"
46 #include "debug.h"
47 #include "misc.h"
48 #include "header.h"
49 #include "gateway.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)
66 static ULONG
67 RecalcBuff ( Fixed freq, struct AHIPrivAudioCtrl *audioctrl )
69 int length;
71 // If ULONG, convert to Fixed
72 // if(freq < 65536) freq <<= 16;
74 // Sanity check
75 if(freq == 0) return 0;
77 audioctrl->ac.ahiac_BuffSamples = (audioctrl->ac.ahiac_MixFreq << 8) /
78 (freq >> 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)
114 static IPTR
115 DummyHook( void )
117 return 0;
121 static const struct Hook DefPlayerHook =
123 {0, 0},
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 },
140 { TAG_DONE, 0 }
144 struct AHIPrivAudioCtrl *
145 CreateAudioCtrl(struct TagItem *tags)
147 struct AHIPrivAudioCtrl *audioctrl;
148 struct AHI_AudioDatabase *audiodb;
149 struct TagItem *dbtags;
150 BOOL error=TRUE;
152 ULONG data_flags = MEMF_ANY;
154 switch( MixBackend )
156 case MB_NATIVE:
157 data_flags = MEMF_PUBLIC | MEMF_CLEAR;
158 break;
160 #if defined( ENABLE_WARPUP )
161 case MB_WARPUP:
162 // Non-cached from both the PPC and m68k side
163 data_flags = MEMF_PUBLIC | MEMF_CLEAR | MEMF_CHIP;
164 break;
165 #endif
168 audioctrl = AHIAllocVec( sizeof( struct AHIPrivAudioCtrl ),
169 data_flags );
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) );
246 strcpy( driver_name,
247 (char *) GetTagData( AHIDB_Driver, (IPTR) "", dbtags ) );
248 strcat( driver_name, ".audio" );
250 AddPart(audioctrl->ahiac_DriverName, driver_name, sizeof(audioctrl->ahiac_DriverName));
252 error=FALSE;
254 UnlockDatabase(audiodb);
258 if(error)
260 AHIFreeVec(audioctrl);
261 return NULL;
263 else
264 return audioctrl;
267 static void
268 UpdateAudioCtrl(struct AHIPrivAudioCtrl *audioctrl)
270 ULONG temp;
272 temp=audioctrl->ac.ahiac_MinPlayerFreq;
273 if(temp>=65536)
274 temp >>=16;
275 if(temp)
276 audioctrl->ac.ahiac_MaxBuffSamples=audioctrl->ac.ahiac_MixFreq/temp;
277 else
278 audioctrl->ac.ahiac_MaxBuffSamples=AHIBase->ahib_Frequency/audioctrl->ac.ahiac_PlayerFreq;
280 temp=audioctrl->ac.ahiac_MaxPlayerFreq;
281 if(temp>=65536)
282 temp = (temp + 65535) >> 16;
283 if(temp)
284 audioctrl->ac.ahiac_MinBuffSamples=audioctrl->ac.ahiac_MixFreq/temp;
285 else
286 audioctrl->ac.ahiac_MinBuffSamples=AHIBase->ahib_Frequency/audioctrl->ac.ahiac_PlayerFreq;
291 /******************************************************************************
292 ** SamplerFunc ****************************************************************
293 ******************************************************************************/
296 static void
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 ******************************************
313 * NAME
314 * AHI_AllocAudioA -- allocates and initializes the audio hardware
315 * AHI_AllocAudio -- varargs stub for AHI_AllocAudioA()
317 * SYNOPSIS
318 * audioctrl = AHI_AllocAudioA( tags );
319 * D0 A1
321 * struct AHIAudioCtrl *AHI_AllocAudioA( struct TagItem * );
323 * audioctrl = AHI_AllocAudio( tag1, ... );
325 * struct AHIAudioCtrl *AHI_AllocAudio( Tag, ... );
327 * FUNCTION
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().
332 * INPUTS
333 * tags - A pointer to a tag list.
335 * TAGS
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
353 * supplied.
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.
367 * Default is NULL.
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
381 * parameters:
382 * A0 - (struct Hook *)
383 * A2 - (struct AHIAudioCtrl *)
384 * A1 - Undefined.
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.
392 * Default is NULL.
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
407 * interrupt feature!
409 * AHIA_MaxPlayerFreq (Fixed) - The maximum frequency (AHIA_PlayerFreq)
410 * you will use. You MUST supply this if you are using the device's
411 * interrupt feature!
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
424 * AHIST_S16S.
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.
435 * Default is NULL.
437 * AHIA_UserData (APTR) - Can be used to initialize the ahiac_UserData
438 * field. Default is 0.
440 * RESULT
441 * A pointer to an AHIAudioCtrl structure or NULL if an error occured.
443 * EXAMPLE
445 * NOTES
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.
450 * BUGS
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!
461 * SEE ALSO
462 * AHI_FreeAudio(), AHI_ControlAudioA()
464 ****************************************************************************
468 struct AHIAudioCtrl*
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;
476 #ifdef __AMIGAOS4__
477 struct AHIsubIFace* IAHIsub;
478 #endif
480 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
482 Debug_AllocAudioA(tags);
485 audioctrl = CreateAudioCtrl( tags );
486 if(!audioctrl)
487 goto error;
489 AHIBase->ahib_AudioCtrl=audioctrl; // Save latest (for KillAudio)
491 if(!audioctrl->ac.ahiac_Channels || !audioctrl->ac.ahiac_Sounds)
492 goto error;
494 audioctrl->ahiac_SubAllocRC = AHISF_ERROR;
495 audioctrl->ahiac_SubLib=
496 AHIsubBase = OpenLibrary(audioctrl->ahiac_DriverName,DriverVersion);
497 //KPrintF("Opened AHIsubBase()\n");
499 #ifdef __AMIGAOS4__
500 audioctrl->ahiac_IAHIsub = NULL;
501 #endif
503 if(!AHIsubBase)
504 goto error;
506 #ifdef __AMIGAOS4__
507 if ((audioctrl->ahiac_IAHIsub = (struct AHIsubIFace *) GetInterface((struct Library *) AHIsubBase, "main", 1, NULL)) == NULL)
509 goto error;
511 IAHIsub = audioctrl->ahiac_IAHIsub;
512 #endif
514 // Never allow drivers that are newer than ahi.device.
515 if(AHIsubBase->lib_Version > AHIBase->ahib_Library.lib_Version)
516 goto error;
518 audiodb=LockDatabase();
519 if(!audiodb)
520 goto error;
522 dbtags=GetDBTagList(audiodb,audioctrl->ahiac_AudioID);
523 if(dbtags)
524 audioctrl->ahiac_SubAllocRC=AHIsub_AllocAudio(dbtags,(struct AHIAudioCtrlDrv *)audioctrl);
525 //KPrintF("Called AHIsub_AllocAudio()\n");
526 UnlockDatabase(audiodb);
528 if(!dbtags)
529 goto error;
531 UpdateAudioCtrl(audioctrl);
533 if(audioctrl->ahiac_SubAllocRC & AHISF_ERROR)
534 goto error;
536 // Mixing
537 if(!(audioctrl->ahiac_SubAllocRC & AHISF_MIXING))
538 audioctrl->ac.ahiac_Flags |= AHIACF_NOMIXING;
540 // Timing
541 if(!(audioctrl->ahiac_SubAllocRC & AHISF_TIMING))
542 audioctrl->ac.ahiac_Flags |= AHIACF_NOTIMING;
544 // Stereo
545 if(!(audioctrl->ahiac_SubAllocRC & AHISF_KNOWSTEREO))
546 audioctrl->ac.ahiac_Flags &= ~AHIACF_STEREO;
548 // Multichannel 7.1
549 if(!(audioctrl->ahiac_SubAllocRC & AHISF_KNOWMULTICHANNEL))
550 audioctrl->ac.ahiac_Flags &= ~AHIACF_MULTICHANNEL;
552 // HiFi
554 if(!(audioctrl->ahiac_SubAllocRC & AHISF_KNOWHIFI))
555 audioctrl->ac.ahiac_Flags &= ~AHIACF_HIFI;
557 // Post-processing
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))
565 case 0:
566 audioctrl->ac.ahiac_BuffType=AHIST_M16S;
567 break;
568 case AHIACF_STEREO:
569 audioctrl->ac.ahiac_BuffType=AHIST_S16S;
570 break;
571 case AHIACF_HIFI:
572 audioctrl->ac.ahiac_Flags |= AHIACF_CLIPPING;
573 audioctrl->ac.ahiac_BuffType=AHIST_M32S;
574 break;
575 case (AHIACF_STEREO | AHIACF_HIFI):
576 audioctrl->ac.ahiac_Flags |= AHIACF_CLIPPING;
577 audioctrl->ac.ahiac_BuffType=AHIST_S32S;
578 break;
579 case (AHIACF_STEREO | AHIACF_HIFI | AHIACF_MULTICHANNEL):
580 audioctrl->ac.ahiac_Flags |= AHIACF_CLIPPING;
581 audioctrl->ac.ahiac_BuffType=AHIST_L7_1;
582 break;
583 default:
584 Alert(AT_Recovery|AG_BadParm);
585 goto error;
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;
591 else
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);
600 else // No timing
602 ULONG size;
604 size=audioctrl->ac.ahiac_BuffSamples*\
605 AHI_SampleFrameSize(audioctrl->ac.ahiac_BuffType)*\
606 (audioctrl->ac.ahiac_Flags & AHIACF_POSTPROC ? 2 : 1);
608 size +=7;
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)
616 goto error;
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;
626 else
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)
636 goto error;
638 audioctrl->ac.ahiac_PostTimerFunc=AllocVec(sizeof(struct Hook),MEMF_PUBLIC|MEMF_CLEAR);
639 if(!audioctrl->ac.ahiac_PostTimerFunc)
640 goto error;
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)
654 goto error;
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,
668 TAG_DONE);
671 exit:
672 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
674 KPrintF("=>0x%08lx\n", (IPTR) audioctrl);
676 return (struct AHIAudioCtrl *) audioctrl;
679 error:
680 AHI_FreeAudio((struct AHIAudioCtrl *)audioctrl);
681 audioctrl=NULL;
682 goto exit;
686 /******************************************************************************
687 ** AHI_FreeAudio **************************************************************
688 ******************************************************************************/
690 /****** ahi.device/AHI_FreeAudio *******************************************
692 * NAME
693 * AHI_FreeAudio -- deallocates the audio hardware
695 * SYNOPSIS
696 * AHI_FreeAudio( audioctrl );
697 * A2
699 * void AHI_FreeAudio( struct AHIAudioCtrl * );
701 * FUNCTION
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.
707 * INPUTS
708 * audioctrl - A pointer to an AHIAudioCtrl structure obtained from
709 * AHI_AllocAudioA(). If NULL, this function does nothing.
711 * EXAMPLE
713 * NOTES
715 * BUGS
717 * SEE ALSO
718 * AHI_AllocAudioA(), AHI_UnloadSound()
720 ****************************************************************************
724 ULONG
725 _AHI_FreeAudio( struct AHIPrivAudioCtrl* audioctrl,
726 struct AHIBase* AHIBase )
728 struct Library *AHIsubBase;
729 int i;
731 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
733 Debug_FreeAudio(audioctrl);
736 if(audioctrl)
738 if((AHIsubBase=audioctrl->ahiac_SubLib))
740 #ifdef __AMIGAOS4__
741 struct AHIsubIFace* IAHIsub = audioctrl->ahiac_IAHIsub;
742 #endif
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");
757 #ifdef __AMIGAOS4__
758 DropInterface((struct Interface *) IAHIsub);
759 IAHIsub = NULL;
760 #endif
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 );
777 return 0;
781 /******************************************************************************
782 ** AHI_KillAudio **************************************************************
783 ******************************************************************************/
785 /****i* ahi.device/AHI_KillAudio *******************************************
787 * NAME
788 * AHI_KillAudio -- clean up
790 * SYNOPSIS
791 * AHI_KillAudio();
793 * void AHI_KillAudio( void );
795 * FUNCTION
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.
803 * INPUTS
805 * RESULT
806 * This function returns nothing. In fact, it may never return.
808 * EXAMPLE
810 * NOTES
812 * BUGS
814 * SEE ALSO
815 * AHI_FreeAudio()
817 ****************************************************************************
821 ULONG
822 _AHI_KillAudio( struct AHIBase* AHIBase )
824 UWORD i;
826 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
828 Debug_KillAudio();
831 for(i=0xffff;i != 0; i--)
833 *((UWORD *) 0xdff102)=i;
836 AHI_FreeAudio(AHIBase->ahib_AudioCtrl);
837 AHIBase->ahib_AudioCtrl=NULL;
838 return 0;
842 /******************************************************************************
843 ** AHI_ControlAudioA **********************************************************
844 ******************************************************************************/
846 /****** ahi.device/AHI_ControlAudioA ***************************************
848 * NAME
849 * AHI_ControlAudioA -- change audio attributes
850 * AHI_ControlAudio -- varargs stub for AHI_ControlAudioA()
852 * SYNOPSIS
853 * error = AHI_ControlAudioA( audioctrl, tags );
854 * D0 A2 A1
856 * ULONG AHI_ControlAudioA( struct AHIAudioCtrl *, struct TagItem * );
858 * error = AHI_ControlAudio( AudioCtrl, tag1, ...);
860 * ULONG AHI_ControlAudio( struct AHIAudioCtrl *, Tag, ... );
862 * FUNCTION
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.
867 * INPUTS
868 * audioctrl - A pointer to an AHIAudioCtrl structure.
869 * tags - A pointer to a tag list.
871 * TAGS
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
886 * will be stored.
888 * AHIC_MixFreq_Query (IPTR *) - Get the current mixing frequency.
889 * ti_Data is a pointer to an IPTR variable, where the result will
890 * be stored.
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().
903 * (V2)
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.
927 * RESULT
928 * An error code, defined in <devices/ahi.h>.
930 * EXAMPLE
932 * NOTES
933 * The AHIC_Play and AHIC_Record tags *must not* be used from
934 * interrupts.
936 * BUGS
938 * SEE ALSO
939 * AHI_AllocAudioA(), AHI_GetAudioAttrsA(), <devices/ahi.h>
941 ****************************************************************************
945 ULONG
946 _AHI_ControlAudioA( struct AHIPrivAudioCtrl* audioctrl,
947 struct TagItem* tags,
948 struct AHIBase* AHIBase )
950 IPTR *ptr;
951 ULONG playflags=0, stopflags=0, rc=AHIE_OK;
952 UBYTE update=FALSE;
953 struct TagItem *tag,*tstate=tags;
954 struct Library *AHIsubBase=audioctrl->ahiac_SubLib;
955 #ifdef __AMIGAOS4__
956 struct AHIsubIFace* IAHIsub = audioctrl->ahiac_IAHIsub;
957 #endif
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
967 switch(tag->ti_Tag)
969 case AHIA_SoundFunc:
970 audioctrl->ac.ahiac_SoundFunc=(struct Hook *) tag->ti_Data;
971 update=TRUE;
972 break;
973 case AHIA_RecordFunc:
974 audioctrl->ahiac_RecordFunc=(struct Hook *) tag->ti_Data;
975 update=TRUE;
976 break;
977 case AHIA_PlayerFunc:
978 audioctrl->ac.ahiac_PlayerFunc=(struct Hook *) tag->ti_Data;
979 update=TRUE;
980 break;
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);
989 update=TRUE;
990 break;
991 case AHIA_UserData:
992 audioctrl->ac.ahiac_AudioCtrl.ahiac_UserData=(void *)tag->ti_Data;
993 break;
994 case AHIC_Play:
995 if(tag->ti_Data)
997 playflags |= AHISF_PLAY;
998 stopflags &= ~AHISF_PLAY;
1000 else
1002 playflags &= ~AHISF_PLAY;
1003 stopflags |= AHISF_PLAY;
1005 update=FALSE;
1006 break;
1007 case AHIC_Record:
1008 if(tag->ti_Data)
1010 playflags |= AHISF_RECORD;
1011 stopflags &= ~AHISF_RECORD;
1013 else
1015 playflags &= ~AHISF_RECORD;
1016 stopflags |= AHISF_RECORD;
1018 update=FALSE;
1019 break;
1020 case AHIC_MixFreq_Query:
1021 *ptr=audioctrl->ac.ahiac_MixFreq;
1022 break;
1023 case AHIC_MonitorVolume:
1024 case AHIC_InputGain:
1025 case AHIC_OutputVolume:
1026 case AHIC_Input:
1027 case AHIC_Output:
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);
1030 break;
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);
1038 break;
1042 // Let's act!
1043 if(update)
1045 AHIsub_Update(0,(struct AHIAudioCtrlDrv *)audioctrl);
1046 //KPrintF("Called AHIsub_Update()\n");
1049 if(playflags)
1051 rc=AHIsub_Start(playflags,(struct AHIAudioCtrlDrv *)audioctrl);
1052 //KPrintF("Called AHIsub_Start(%08lx)=>%ld\n",playflags,rc);
1055 if(stopflags)
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);
1066 return rc;