grub2: bring back build of aros-side grub2 tools
[AROS.git] / workbench / devs / AHI / Device / audioctrl.c
blob65517ba12816a8a460a740ab60d98e057a3899a3
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=(struct Hook *)&DefPlayerHook;
210 if(audioctrl->ac.ahiac_PlayerFreq == 0)
211 audioctrl->ac.ahiac_PlayerFreq = DEFPLAYERFREQ;
212 if(audioctrl->ac.ahiac_MinPlayerFreq == 0)
213 audioctrl->ac.ahiac_MinPlayerFreq = DEFPLAYERFREQ;
214 if(audioctrl->ac.ahiac_MaxPlayerFreq == 0)
215 audioctrl->ac.ahiac_MaxPlayerFreq = DEFPLAYERFREQ;
217 if(audioctrl->ac.ahiac_PlayerFreq < 65536)
218 audioctrl->ac.ahiac_PlayerFreq <<= 16;
219 if(audioctrl->ac.ahiac_MinPlayerFreq < 65536)
220 audioctrl->ac.ahiac_MinPlayerFreq <<= 16;
221 if(audioctrl->ac.ahiac_MaxPlayerFreq < 65536)
222 audioctrl->ac.ahiac_MaxPlayerFreq <<= 16;
224 if(audioctrl->ac.ahiac_AntiClickSamples == ~0)
225 audioctrl->ac.ahiac_AntiClickSamples =
226 ( AHIBase->ahib_AntiClickTime * audioctrl->ac.ahiac_MixFreq ) >> 16;
228 if((audiodb=LockDatabase()))
230 if((dbtags=GetDBTagList(audiodb,audioctrl->ahiac_AudioID)))
232 char driver_name[128];
234 audioctrl->ac.ahiac_Flags=PackBoolTags(GetTagData(AHIDB_Flags,0,
235 dbtags),dbtags,(struct TagItem *)boolmap);
237 if(AHIBase->ahib_Flags & AHIBF_CLIPPING)
239 audioctrl->ac.ahiac_Flags |= AHIACF_CLIPPING;
242 strcpy( audioctrl->ahiac_DriverName,
243 (char *) GetTagData( AHIDB_DriverBaseName, (ULONG) "DEVS:AHI", dbtags) );
245 strcpy( driver_name,
246 (char *) GetTagData( AHIDB_Driver, (ULONG) "", dbtags ) );
247 strcat( driver_name, ".audio" );
249 AddPart(audioctrl->ahiac_DriverName, driver_name, sizeof(audioctrl->ahiac_DriverName));
251 error=FALSE;
253 UnlockDatabase(audiodb);
257 if(error)
259 AHIFreeVec(audioctrl);
260 return NULL;
262 else
263 return audioctrl;
266 static void
267 UpdateAudioCtrl(struct AHIPrivAudioCtrl *audioctrl)
269 ULONG temp;
271 temp=audioctrl->ac.ahiac_MinPlayerFreq;
272 if(temp>=65536)
273 temp >>=16;
274 if(temp)
275 audioctrl->ac.ahiac_MaxBuffSamples=audioctrl->ac.ahiac_MixFreq/temp;
276 else
277 audioctrl->ac.ahiac_MaxBuffSamples=AHIBase->ahib_Frequency/audioctrl->ac.ahiac_PlayerFreq;
279 temp=audioctrl->ac.ahiac_MaxPlayerFreq;
280 if(temp>=65536)
281 temp = (temp + 65535) >> 16;
282 if(temp)
283 audioctrl->ac.ahiac_MinBuffSamples=audioctrl->ac.ahiac_MixFreq/temp;
284 else
285 audioctrl->ac.ahiac_MinBuffSamples=AHIBase->ahib_Frequency/audioctrl->ac.ahiac_PlayerFreq;
290 /******************************************************************************
291 ** SamplerFunc ****************************************************************
292 ******************************************************************************/
295 static void
296 SamplerFunc( struct Hook* hook,
297 struct AHIPrivAudioCtrl* actrl,
298 struct AHIRecordMessage* recmsg )
300 if(actrl->ahiac_RecordFunc)
302 CallHookPkt(actrl->ahiac_RecordFunc, actrl, recmsg);
306 /******************************************************************************
307 ** AHI_AllocAudioA ************************************************************
308 ******************************************************************************/
310 /****** ahi.device/AHI_AllocAudioA ******************************************
312 * NAME
313 * AHI_AllocAudioA -- allocates and initializes the audio hardware
314 * AHI_AllocAudio -- varargs stub for AHI_AllocAudioA()
316 * SYNOPSIS
317 * audioctrl = AHI_AllocAudioA( tags );
318 * D0 A1
320 * struct AHIAudioCtrl *AHI_AllocAudioA( struct TagItem * );
322 * audioctrl = AHI_AllocAudio( tag1, ... );
324 * struct AHIAudioCtrl *AHI_AllocAudio( Tag, ... );
326 * FUNCTION
327 * Allocates and initializes the audio hardware, selects the best
328 * mixing routine (if necessary) according to the supplied tags.
329 * To start playing you first need to call AHI_ControlAudioA().
331 * INPUTS
332 * tags - A pointer to a tag list.
334 * TAGS
336 * AHIA_AudioID (ULONG) - The audio mode to use. Default is
337 * AHI_DEFAULT_ID. (AHI_DEFAULT_ID is the ID the user has selected
338 * in the preferences program. It's a good value to use the first
339 * time she starts your application.)
341 * AHIA_MixFreq (ULONG) - Desired mixing frequency. The actual
342 * mixing rate may or may not be exactly what you asked for.
343 * Default is AHI_DEFAULT_FREQ. (AHI_DEFAULT_FREQ is the user's
344 * prefered frequency.)
346 * AHIA_Channels (UWORD) - Number of channel to use. The actual
347 * number of channels used will be equal or grater than the
348 * requested. If too many channels were requested, this function
349 * will fail. This tag must be supplied.
351 * AHIA_Sounds (UWORD) - Number of sounds to use. This tag must be
352 * supplied.
354 * AHIA_SoundFunc (struct Hook *) - A function to call each time
355 * when a sound has been started. The function receives the
356 * following parameters:
357 * A0 - (struct Hook *)
358 * A2 - (struct AHIAudioCtrl *)
359 * A1 - (struct AHISoundMessage *)
360 * The hook may be called from an interrupt, so normal interrupt
361 * restrictions apply.
363 * The called function should follow normal register conventions,
364 * which means that d2-d7 and a2-a6 must be preserved.
366 * Default is NULL.
368 * AHIA_PlayerFunc (struct Hook *) - A function to be called at regular
369 * intervals. By using this hook there is no need for music players
370 * to use other timing, such as VBLANK or CIA timers. But the real
371 * reason it's present is that it makes it possible to do non-
372 * realtime mixing to disk.
374 * Using this interrupt source is currently the only supported way
375 * to ensure that no mixing occurs between calls to AHI_SetVol(),
376 * AHI_SetFreq() or AHI_SetSound().
378 * If the sound playback is done without mixing, 'realtime.library'
379 * is used to provide timing. The function receives the following
380 * parameters:
381 * A0 - (struct Hook *)
382 * A2 - (struct AHIAudioCtrl *)
383 * A1 - Undefined.
384 * Do not assume A1 contains any particular value!
385 * The hook may be called from an interrupt, so normal interrupt
386 * restrictions apply.
388 * The called function should follow normal register conventions,
389 * which means that d2-d7 and a2-a6 must be preserved.
391 * Default is NULL.
393 * AHIA_PlayerFreq (Fixed) - If non-zero, enables timing and specifies
394 * how many times per second PlayerFunc will be called. This must
395 * be specified if AHIA_PlayerFunc is! Do not use any extreme
396 * frequencies. The result of MixFreq/PlayerFreq must fit an UWORD,
397 * ie it must be less or equal to 65535. It is also suggested that
398 * you keep the result over 80. For normal use this should not be a
399 * problem. Note that the data type is Fixed, not integer (see BUGS
400 * below). 50 Hz is 50<<16, which is a reasonable lower limit.
402 * Default is a reasonable value. Don't depend on it.
404 * AHIA_MinPlayerFreq (Fixed) - The minimum frequency (AHIA_PlayerFreq)
405 * you will use. You MUST supply this if you are using the device's
406 * interrupt feature!
408 * AHIA_MaxPlayerFreq (Fixed) - The maximum frequency (AHIA_PlayerFreq)
409 * you will use. You MUST supply this if you are using the device's
410 * interrupt feature!
412 * AHIA_RecordFunc (struct Hook *) - This function will be called
413 * regularly when sampling is turned on (see AHI_ControlAudioA())
414 * with the following parameters:
415 * A0 - (struct Hook *)
416 * A2 - (struct AHIAudioCtrl *)
417 * A1 - (struct AHIRecordMessage *)
418 * The message (AHIRecordMessage) is filled as follows:
419 * ahirm_Buffer - Pointer to the samples. The buffer is valid
420 * until next time the Hook is called.
421 * ahirm_Length - Number of sample FRAMES in buffer.
422 * To get the size in bytes, multiply by 4 if ahiim_Type is
423 * AHIST_S16S.
424 * ahirm_Type - Always AHIST_S16S at the moment, but you *must*
425 * check this, since it may change in the future!
426 * The hook may be called from an interrupt, so normal interrupt
427 * restrictions apply. Signal a process if you wish to save the
428 * buffer to disk. The called function should follow normal register
429 * conventions, which means that d2-d7 and a2-a6 must be preserved.
431 * NOTE: The function MUST return NULL (in d0). This was previously
432 * not documented. Now you know.
434 * Default is NULL.
436 * AHIA_UserData (APTR) - Can be used to initialize the ahiac_UserData
437 * field. Default is 0.
439 * RESULT
440 * A pointer to an AHIAudioCtrl structure or NULL if an error occured.
442 * EXAMPLE
444 * NOTES
445 * SoundFunc will be called in the same manner as Paula interrupts
446 * occur; when the device has updated its internal variables and can
447 * accept new commands.
449 * BUGS
450 * For compability reasons with some really old applications,
451 * AHIA_PlayerFreq, AHIA_MinPlayerFreq and AHIA_MaxPlayerFreq
452 * interpret values lower than 0x10000 as integers, not Fixed.
453 * This means that the lowest frequency possible is 1 Hz. However,
454 * you should *never* use a value than say 10-20 Hz anyway, because
455 * of the high latency and the impact on multitasking.
457 * This kludge will be removed some day. Always use Fixed!
460 * SEE ALSO
461 * AHI_FreeAudio(), AHI_ControlAudioA()
463 ****************************************************************************
467 struct AHIAudioCtrl*
468 _AHI_AllocAudioA( struct TagItem* tags,
469 struct AHIBase* AHIBase )
471 struct AHIPrivAudioCtrl* audioctrl;
472 struct Library *AHIsubBase;
473 struct AHI_AudioDatabase *audiodb;
474 struct TagItem *dbtags;
475 #ifdef __AMIGAOS4__
476 struct AHIsubIFace* IAHIsub;
477 #endif
479 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
481 Debug_AllocAudioA(tags);
484 audioctrl = CreateAudioCtrl( tags );
485 if(!audioctrl)
486 goto error;
488 AHIBase->ahib_AudioCtrl=audioctrl; // Save latest (for KillAudio)
490 if(!audioctrl->ac.ahiac_Channels || !audioctrl->ac.ahiac_Sounds)
491 goto error;
493 audioctrl->ahiac_SubAllocRC = AHISF_ERROR;
494 audioctrl->ahiac_SubLib=
495 AHIsubBase = OpenLibrary(audioctrl->ahiac_DriverName,DriverVersion);
496 //KPrintF("Opened AHIsubBase()\n");
498 #ifdef __AMIGAOS4__
499 audioctrl->ahiac_IAHIsub = NULL;
500 #endif
502 if(!AHIsubBase)
503 goto error;
505 #ifdef __AMIGAOS4__
506 if ((audioctrl->ahiac_IAHIsub = (struct AHIsubIFace *) GetInterface((struct Library *) AHIsubBase, "main", 1, NULL)) == NULL)
508 goto error;
510 IAHIsub = audioctrl->ahiac_IAHIsub;
511 #endif
513 // Never allow drivers that are newer than ahi.device.
514 if(AHIsubBase->lib_Version > AHIBase->ahib_Library.lib_Version)
515 goto error;
517 audiodb=LockDatabase();
518 if(!audiodb)
519 goto error;
521 dbtags=GetDBTagList(audiodb,audioctrl->ahiac_AudioID);
522 if(dbtags)
523 audioctrl->ahiac_SubAllocRC=AHIsub_AllocAudio(dbtags,(struct AHIAudioCtrlDrv *)audioctrl);
524 //KPrintF("Called AHIsub_AllocAudio()\n");
525 UnlockDatabase(audiodb);
527 if(!dbtags)
528 goto error;
530 UpdateAudioCtrl(audioctrl);
532 if(audioctrl->ahiac_SubAllocRC & AHISF_ERROR)
533 goto error;
535 // Mixing
536 if(!(audioctrl->ahiac_SubAllocRC & AHISF_MIXING))
537 audioctrl->ac.ahiac_Flags |= AHIACF_NOMIXING;
539 // Timing
540 if(!(audioctrl->ahiac_SubAllocRC & AHISF_TIMING))
541 audioctrl->ac.ahiac_Flags |= AHIACF_NOTIMING;
543 // Stereo
544 if(!(audioctrl->ahiac_SubAllocRC & AHISF_KNOWSTEREO))
545 audioctrl->ac.ahiac_Flags &= ~AHIACF_STEREO;
547 // Multichannel 7.1
548 if(!(audioctrl->ahiac_SubAllocRC & AHISF_KNOWMULTICHANNEL))
549 audioctrl->ac.ahiac_Flags &= ~AHIACF_MULTICHANNEL;
551 // HiFi
553 if(!(audioctrl->ahiac_SubAllocRC & AHISF_KNOWHIFI))
554 audioctrl->ac.ahiac_Flags &= ~AHIACF_HIFI;
556 // Post-processing
557 if(audioctrl->ahiac_SubAllocRC & AHISF_CANPOSTPROCESS)
558 audioctrl->ac.ahiac_Flags |= AHIACF_POSTPROC;
560 if(!(audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING))
562 switch(audioctrl->ac.ahiac_Flags & (AHIACF_STEREO | AHIACF_HIFI | AHIACF_MULTICHANNEL))
564 case 0:
565 audioctrl->ac.ahiac_BuffType=AHIST_M16S;
566 break;
567 case AHIACF_STEREO:
568 audioctrl->ac.ahiac_BuffType=AHIST_S16S;
569 break;
570 case AHIACF_HIFI:
571 audioctrl->ac.ahiac_Flags |= AHIACF_CLIPPING;
572 audioctrl->ac.ahiac_BuffType=AHIST_M32S;
573 break;
574 case (AHIACF_STEREO | AHIACF_HIFI):
575 audioctrl->ac.ahiac_Flags |= AHIACF_CLIPPING;
576 audioctrl->ac.ahiac_BuffType=AHIST_S32S;
577 break;
578 case (AHIACF_STEREO | AHIACF_HIFI | AHIACF_MULTICHANNEL):
579 audioctrl->ac.ahiac_Flags |= AHIACF_CLIPPING;
580 audioctrl->ac.ahiac_BuffType=AHIST_L7_1;
581 break;
582 default:
583 Alert(AT_Recovery|AG_BadParm);
584 goto error;
587 /* Max channels/2 channels per hardware channel if stereo w/o pan */
588 if((audioctrl->ac.ahiac_Flags & (AHIACF_STEREO | AHIACF_PAN)) == AHIACF_STEREO)
589 audioctrl->ahiac_Channels2=(audioctrl->ac.ahiac_Channels+1)/2;
590 else
591 audioctrl->ahiac_Channels2=audioctrl->ac.ahiac_Channels;
593 if(!(audioctrl->ac.ahiac_Flags & AHIACF_NOTIMING))
595 RecalcBuff(audioctrl->ac.ahiac_MinPlayerFreq,audioctrl);
596 audioctrl->ac.ahiac_BuffSize=audioctrl->ahiac_BuffSizeNow;
597 RecalcBuff(audioctrl->ac.ahiac_PlayerFreq,audioctrl);
599 else // No timing
601 ULONG size;
603 size=audioctrl->ac.ahiac_BuffSamples*\
604 AHI_SampleFrameSize(audioctrl->ac.ahiac_BuffType)*\
605 (audioctrl->ac.ahiac_Flags & AHIACF_POSTPROC ? 2 : 1);
607 size +=7;
608 size &= ~7; // byte align
610 audioctrl->ahiac_BuffSizeNow=size;
613 audioctrl->ac.ahiac_MixerFunc=AllocVec(sizeof(struct Hook),MEMF_PUBLIC|MEMF_CLEAR);
614 if(!audioctrl->ac.ahiac_MixerFunc)
615 goto error;
618 audioctrl->ac.ahiac_MixerFunc->h_Entry = (HOOKFUNC) HookEntryPreserveAllRegs;
619 audioctrl->ac.ahiac_MixerFunc->h_SubEntry = (HOOKFUNC) MixerFunc;
621 if((AHIBase->ahib_MaxCPU >= 0x10000) || (AHIBase->ahib_MaxCPU <= 0x0))
623 audioctrl->ahiac_MaxCPU = 0x100;
625 else
627 audioctrl->ahiac_MaxCPU = AHIBase->ahib_MaxCPU >> 8;
630 audioctrl->ac.ahiac_PreTimer = (BOOL (*)(void)) PreTimerPreserveAllRegs;
631 audioctrl->ac.ahiac_PostTimer = (void (*)(void)) PostTimerPreserveAllRegs;
633 audioctrl->ac.ahiac_PreTimerFunc=AllocVec(sizeof(struct Hook),MEMF_PUBLIC|MEMF_CLEAR);
634 if(!audioctrl->ac.ahiac_PreTimerFunc)
635 goto error;
637 audioctrl->ac.ahiac_PostTimerFunc=AllocVec(sizeof(struct Hook),MEMF_PUBLIC|MEMF_CLEAR);
638 if(!audioctrl->ac.ahiac_PostTimerFunc)
639 goto error;
641 audioctrl->ac.ahiac_PreTimerFunc->h_Entry = (HOOKFUNC) HookEntry;
642 audioctrl->ac.ahiac_PreTimerFunc->h_SubEntry = (HOOKFUNC) PreTimerFunc;
644 audioctrl->ac.ahiac_PostTimerFunc->h_Entry = (HOOKFUNC) HookEntry;
645 audioctrl->ac.ahiac_PostTimerFunc->h_SubEntry = (HOOKFUNC) PostTimerFunc;
647 if( !InitMixroutine( audioctrl ) ) goto error;
650 audioctrl->ac.ahiac_SamplerFunc = AllocVec(sizeof(struct Hook),
651 MEMF_PUBLIC|MEMF_CLEAR);
652 if(!audioctrl->ac.ahiac_SamplerFunc)
653 goto error;
655 audioctrl->ac.ahiac_SamplerFunc->h_Entry = (HOOKFUNC) HookEntry;
656 audioctrl->ac.ahiac_SamplerFunc->h_SubEntry = (HOOKFUNC) SamplerFunc;
658 /* Set default hardware properties, only if AHI_DEFAULT_ID was used!*/
659 if(GetTagData(AHIA_AudioID, AHI_DEFAULT_ID, tags) == AHI_DEFAULT_ID)
661 AHI_ControlAudio((struct AHIAudioCtrl *)audioctrl,
662 AHIC_MonitorVolume, AHIBase->ahib_MonitorVolume,
663 AHIC_InputGain, AHIBase->ahib_InputGain,
664 AHIC_OutputVolume, AHIBase->ahib_OutputVolume,
665 AHIC_Input, AHIBase->ahib_Input,
666 AHIC_Output, AHIBase->ahib_Output,
667 TAG_DONE);
670 exit:
671 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
673 KPrintF("=>0x%08lx\n", (ULONG) audioctrl);
675 return (struct AHIAudioCtrl *) audioctrl;
678 error:
679 AHI_FreeAudio((struct AHIAudioCtrl *)audioctrl);
680 audioctrl=NULL;
681 goto exit;
685 /******************************************************************************
686 ** AHI_FreeAudio **************************************************************
687 ******************************************************************************/
689 /****** ahi.device/AHI_FreeAudio *******************************************
691 * NAME
692 * AHI_FreeAudio -- deallocates the audio hardware
694 * SYNOPSIS
695 * AHI_FreeAudio( audioctrl );
696 * A2
698 * void AHI_FreeAudio( struct AHIAudioCtrl * );
700 * FUNCTION
701 * Deallocates the AHIAudioCtrl structure and any other resources
702 * allocated by AHI_AllocAudioA(). After this call it must not be used
703 * by any other functions anymore. AHI_UnloadSound() is automatically
704 * called for every sound.
706 * INPUTS
707 * audioctrl - A pointer to an AHIAudioCtrl structure obtained from
708 * AHI_AllocAudioA(). If NULL, this function does nothing.
710 * EXAMPLE
712 * NOTES
714 * BUGS
716 * SEE ALSO
717 * AHI_AllocAudioA(), AHI_UnloadSound()
719 ****************************************************************************
723 ULONG
724 _AHI_FreeAudio( struct AHIPrivAudioCtrl* audioctrl,
725 struct AHIBase* AHIBase )
727 struct Library *AHIsubBase;
728 int i;
730 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
732 Debug_FreeAudio(audioctrl);
735 if(audioctrl)
737 if((AHIsubBase=audioctrl->ahiac_SubLib))
739 #ifdef __AMIGAOS4__
740 struct AHIsubIFace* IAHIsub = audioctrl->ahiac_IAHIsub;
741 #endif
743 if(!(audioctrl->ahiac_SubAllocRC & AHISF_ERROR))
745 //KPrintF("Called AHIsub_Stop(play|record)\n");
746 AHIsub_Stop(AHISF_PLAY|AHISF_RECORD,(struct AHIAudioCtrlDrv *)audioctrl);
748 for(i=audioctrl->ac.ahiac_Sounds-1;i>=0;i--)
750 AHI_UnloadSound(i,(struct AHIAudioCtrl *)audioctrl);
753 //KPrintF("Called AHIsub_FreeAudio()\n");
754 AHIsub_FreeAudio((struct AHIAudioCtrlDrv *) audioctrl);
755 //KPrintF("Closed AHIsubbase\n");
756 #ifdef __AMIGAOS4__
757 DropInterface((struct Interface *) IAHIsub);
758 IAHIsub = NULL;
759 #endif
761 CloseLibrary(AHIsubBase);
764 if(!(audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING))
766 CleanUpMixroutine( audioctrl );
769 FreeVec( audioctrl->ac.ahiac_SamplerFunc );
770 FreeVec( audioctrl->ac.ahiac_MixerFunc );
771 FreeVec( audioctrl->ac.ahiac_PreTimerFunc );
772 FreeVec( audioctrl->ac.ahiac_PostTimerFunc );
774 AHIFreeVec( audioctrl );
776 return 0;
780 /******************************************************************************
781 ** AHI_KillAudio **************************************************************
782 ******************************************************************************/
784 /****i* ahi.device/AHI_KillAudio *******************************************
786 * NAME
787 * AHI_KillAudio -- clean up
789 * SYNOPSIS
790 * AHI_KillAudio();
792 * void AHI_KillAudio( void );
794 * FUNCTION
795 * 'ahi.device' keeps track of most of what the user does. This call is
796 * used to clean up as much as possible. It must never, ever, be used
797 * in an application. It is included for development use only, and can
798 * be used to avoid rebooting the computer if your program has allocated
799 * the audio hardware and crashed. This call can lead to a system crash,
800 * so don't use it if you don't have to.
802 * INPUTS
804 * RESULT
805 * This function returns nothing. In fact, it may never return.
807 * EXAMPLE
809 * NOTES
811 * BUGS
813 * SEE ALSO
814 * AHI_FreeAudio()
816 ****************************************************************************
820 ULONG
821 _AHI_KillAudio( struct AHIBase* AHIBase )
823 UWORD i;
825 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
827 Debug_KillAudio();
830 for(i=0xffff;i != 0; i--)
832 *((UWORD *) 0xdff102)=i;
835 AHI_FreeAudio(AHIBase->ahib_AudioCtrl);
836 AHIBase->ahib_AudioCtrl=NULL;
837 return 0;
841 /******************************************************************************
842 ** AHI_ControlAudioA **********************************************************
843 ******************************************************************************/
845 /****** ahi.device/AHI_ControlAudioA ***************************************
847 * NAME
848 * AHI_ControlAudioA -- change audio attributes
849 * AHI_ControlAudio -- varargs stub for AHI_ControlAudioA()
851 * SYNOPSIS
852 * error = AHI_ControlAudioA( audioctrl, tags );
853 * D0 A2 A1
855 * ULONG AHI_ControlAudioA( struct AHIAudioCtrl *, struct TagItem * );
857 * error = AHI_ControlAudio( AudioCtrl, tag1, ...);
859 * ULONG AHI_ControlAudio( struct AHIAudioCtrl *, Tag, ... );
861 * FUNCTION
862 * This function should be used to change attributes for a given
863 * AHIAudioCtrl structure. It is also used to start and stop playback,
864 * and to control special hardware found on some sound cards.
866 * INPUTS
867 * audioctrl - A pointer to an AHIAudioCtrl structure.
868 * tags - A pointer to a tag list.
870 * TAGS
871 * AHIC_Play (BOOL) - Starts (TRUE) and stops (FALSE) playback and
872 * PlayerFunc. NOTE: If the audio hardware cannot play at the same
873 * time as recording samples, the recording will be stopped.
875 * AHIC_Record (BOOL) - Starts (TRUE) and stops (FALSE) sampling and
876 * RecordFunc. NOTE: If the audio hardware cannot record at the same
877 * time as playing samples, the playback will be stopped.
879 * AHIC_MonitorVolume (Fixed) - Sets the input monitor volume, i.e. how
880 * much of the input signal is mixed with the output signal while
881 * recording. Use AHI_GetAudioAttrsA() to find the available range.
883 * AHIC_MonitorVolume_Query (Fixed *) - Get the current input monitor
884 * volume. ti_Data is a pointer to a Fixed variable, where the result
885 * will be stored.
887 * AHIC_MixFreq_Query (ULONG *) - Get the current mixing frequency.
888 * ti_Data is a pointer to an ULONG variable, where the result will
889 * be stored.
891 * AHIC_InputGain (Fixed) - Set the input gain. Use AHI_GetAudioAttrsA()
892 * to find the available range. (V2)
894 * AHIC_InputGain_Query (Fixed *) - Get current input gain. (V2)
896 * AHIC_OutputVolume (Fixed) - Set the output volume. Use
897 * AHI_GetAudioAttrsA() to find the available range. (V2)
899 * AHIC_OutputVolume_Query (Fixed *) - Get current output volume. (V2)
901 * AHIC_Input (ULONG) - Select input source. See AHI_GetAudioAttrsA().
902 * (V2)
904 * AHIC_Input_Query (ULONG *) - Get current input source. (V2)
906 * AHIC_Output (ULONG) - Select destination for output. See
907 * AHI_GetAudioAttrsA(). (V2)
909 * AHIC_Output_Query (ULONG *) - Get destination for output. (V2)
911 * The following tags are also recognized by AHI_ControlAudioA(). See
912 * AHI_AllocAudioA() for what they do. They may be used from interrupts.
914 * AHIA_SoundFunc (struct Hook *)
915 * AHIA_PlayerFunc (struct Hook *)
916 * AHIA_PlayerFreq (Fixed)
917 * AHIA_RecordFunc (struct Hook *)
918 * AHIA_UserData (APTR)
920 * Note that AHIA_PlayerFreq must never be outside the limits specified
921 * with AHIA_MinPlayerFreq and AHIA_MaxPlayerFreq! Also note that the
922 * timing feature is designed to be used for music. When you change the
923 * frequency, be reasonable. Using 50 Hz one moment and 5 the other is
924 * to ask for trouble.
926 * RESULT
927 * An error code, defined in <devices/ahi.h>.
929 * EXAMPLE
931 * NOTES
932 * The AHIC_Play and AHIC_Record tags *must not* be used from
933 * interrupts.
935 * BUGS
937 * SEE ALSO
938 * AHI_AllocAudioA(), AHI_GetAudioAttrsA(), <devices/ahi.h>
940 ****************************************************************************
944 ULONG
945 _AHI_ControlAudioA( struct AHIPrivAudioCtrl* audioctrl,
946 struct TagItem* tags,
947 struct AHIBase* AHIBase )
949 ULONG *ptr, playflags=0, stopflags=0, rc=AHIE_OK;
950 UBYTE update=FALSE;
951 struct TagItem *tag,*tstate=tags;
952 struct Library *AHIsubBase=audioctrl->ahiac_SubLib;
953 #ifdef __AMIGAOS4__
954 struct AHIsubIFace* IAHIsub = audioctrl->ahiac_IAHIsub;
955 #endif
957 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
959 Debug_ControlAudioA(audioctrl,tags);
962 while((tag=NextTagItem(&tstate)))
964 ptr=(ULONG *)tag->ti_Data; // For ..._Query tags
965 switch(tag->ti_Tag)
967 case AHIA_SoundFunc:
968 audioctrl->ac.ahiac_SoundFunc=(struct Hook *) tag->ti_Data;
969 update=TRUE;
970 break;
971 case AHIA_RecordFunc:
972 audioctrl->ahiac_RecordFunc=(struct Hook *) tag->ti_Data;
973 update=TRUE;
974 break;
975 case AHIA_PlayerFunc:
976 audioctrl->ac.ahiac_PlayerFunc=(struct Hook *) tag->ti_Data;
977 update=TRUE;
978 break;
979 case AHIA_PlayerFreq:
980 audioctrl->ac.ahiac_PlayerFreq=tag->ti_Data;
982 if(audioctrl->ac.ahiac_PlayerFreq < 65536)
983 audioctrl->ac.ahiac_PlayerFreq <<= 16;
985 if(!(audioctrl->ac.ahiac_Flags & AHIACF_NOTIMING)) // Dont call unless timing is used.
986 RecalcBuff(audioctrl->ac.ahiac_PlayerFreq,audioctrl);
987 update=TRUE;
988 break;
989 case AHIA_UserData:
990 audioctrl->ac.ahiac_AudioCtrl.ahiac_UserData=(void *)tag->ti_Data;
991 break;
992 case AHIC_Play:
993 if(tag->ti_Data)
995 playflags |= AHISF_PLAY;
996 stopflags &= ~AHISF_PLAY;
998 else
1000 playflags &= ~AHISF_PLAY;
1001 stopflags |= AHISF_PLAY;
1003 update=FALSE;
1004 break;
1005 case AHIC_Record:
1006 if(tag->ti_Data)
1008 playflags |= AHISF_RECORD;
1009 stopflags &= ~AHISF_RECORD;
1011 else
1013 playflags &= ~AHISF_RECORD;
1014 stopflags |= AHISF_RECORD;
1016 update=FALSE;
1017 break;
1018 case AHIC_MixFreq_Query:
1019 *ptr=audioctrl->ac.ahiac_MixFreq;
1020 break;
1021 case AHIC_MonitorVolume:
1022 case AHIC_InputGain:
1023 case AHIC_OutputVolume:
1024 case AHIC_Input:
1025 case AHIC_Output:
1026 AHIsub_HardwareControl(tag->ti_Tag, tag->ti_Data, (struct AHIAudioCtrlDrv *)audioctrl);
1027 //KPrintF("Called AHIsub_HardwareControl(%08lx:%08lx)\n",tag->ti_Tag, tag->ti_Data);
1028 break;
1029 case AHIC_MonitorVolume_Query:
1030 case AHIC_InputGain_Query:
1031 case AHIC_OutputVolume_Query:
1032 case AHIC_Input_Query:
1033 case AHIC_Output_Query:
1034 *ptr=AHIsub_HardwareControl(tag->ti_Tag, 0, (struct AHIAudioCtrlDrv *)audioctrl);
1035 //KPrintF("Called AHIsub_HardwareControl(%08lx:NULL)\n",tag->ti_Tag);
1036 break;
1040 // Let's act!
1041 if(update)
1043 AHIsub_Update(0,(struct AHIAudioCtrlDrv *)audioctrl);
1044 //KPrintF("Called AHIsub_Update()\n");
1047 if(playflags)
1049 rc=AHIsub_Start(playflags,(struct AHIAudioCtrlDrv *)audioctrl);
1050 //KPrintF("Called AHIsub_Start(%08lx)=>%ld\n",playflags,rc);
1053 if(stopflags)
1055 AHIsub_Stop(stopflags,(struct AHIAudioCtrlDrv *)audioctrl);
1056 //KPrintF("Called AHIsub_Stop(%08lx)\n",stopflags);
1059 if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
1061 KPrintF("=>%ld\n",rc);
1064 return rc;