static void GetSliderAttrs(struct AHIAudioModeRequesterExt *req, LONG *levels, LONG *level) { *levels=0; *level=0; AHI_GetAudioAttrs(req->tempAudioID, NULL, AHIDB_Frequencies, (ULONG) levels, AHIDB_IndexArg, (req->tempAudioID == AHI_DEFAULT_ID ? AHIBase->ahib_Frequency : req->tempFrequency), AHIDB_Index, (ULONG) level, TAG_DONE); if(*level >= *levels) *level = *levels-1; AHI_GetAudioAttrs(req->tempAudioID, NULL, AHIDB_FrequencyArg, *level, AHIDB_Frequency, (ULONG) &req->tempFrequency, TAG_DONE); }
void FillUnit() { struct UnitNode *unit = NULL; struct ModeNode *mode = NULL; ULONG id; double db; unit = (struct UnitNode *) GetNode(state.UnitSelected, UnitList); if(unit->prefs.ahiup_Unit != AHI_NO_UNIT) { unit->prefs.ahiup_Channels = state.ChannelsSelected; unit->prefs.ahiup_ScaleMode = state.ScaleModeSelected; } else { unit->prefs.ahiup_Channels = 0; unit->prefs.ahiup_ScaleMode = 0; } if( state.ModeSelected != ~0 ) { mode = (struct ModeNode *) GetNode(state.ModeSelected, ModeList); } if( mode != NULL ) { unit->prefs.ahiup_AudioMode = mode->ID; AHI_GetAudioAttrs(mode->ID, NULL, AHIDB_FrequencyArg, state.FreqSelected, AHIDB_Frequency, (ULONG) &unit->prefs.ahiup_Frequency, TAG_DONE); } db = state.OutVolOffset + DBSTEP * (state.OutVolSelected - (state.OutVolMute ? 1 : 0) ); unit->prefs.ahiup_OutputVolume = pow(10.0, db/20) * 65536 + 0.5; if(state.OutVolMute && (state.OutVolSelected == 0)) unit->prefs.ahiup_OutputVolume = 0; db = state.MonVolOffset + DBSTEP * (state.MonVolSelected - (state.MonVolMute ? 1 : 0) ); unit->prefs.ahiup_MonitorVolume = pow(10.0, db/20) * 65536 + 0.5; if(state.MonVolMute && (state.MonVolSelected == 0)) unit->prefs.ahiup_MonitorVolume = 0; db = state.GainOffset + DBSTEP * (state.GainSelected - (state.GainMute ? 1 : 0) ); unit->prefs.ahiup_InputGain = pow(10.0, db/20) * 65536 + 0.5; if(state.GainMute && (state.GainSelected == 0)) unit->prefs.ahiup_InputGain = 0; unit->prefs.ahiup_Input = state.InputSelected; unit->prefs.ahiup_Output = state.OutputSelected; }
struct List *GetModes(struct AHIUnitPrefs *prefs) { struct List *list; list = AllocVec(sizeof(struct List), MEMF_CLEAR); if(list) { ULONG id = AHI_NextAudioID(AHI_INVALID_ID); NewList(list); while(id != AHI_INVALID_ID) { struct ModeNode *t; struct Node *node; t = AllocVec( sizeof(struct ModeNode), MEMF_CLEAR); if( t != NULL ) { LONG realtime; t->node.ln_Name = t->name; t->ID = id; realtime = FALSE; AHI_GetAudioAttrs(id, NULL, AHIDB_BufferLen, 80, AHIDB_Name, (ULONG) t->node.ln_Name, AHIDB_Realtime, (ULONG) &realtime, TAG_DONE); if((prefs->ahiup_Unit == AHI_NO_UNIT) || realtime ) { // Insert node alphabetically for(node = list->lh_Head; node->ln_Succ; node = node->ln_Succ) { if(Stricmp(t->node.ln_Name,node->ln_Name) < 0) break; } Insert(list, (struct Node *) t, node->ln_Pred); } else { FreeVec(t); } } id = AHI_NextAudioID(id); } } return list; }
LONG IndexToFrequency( struct Gadget *gad, WORD level ) { LONG freq = 0; ULONG id; id = ((struct AHIAudioModeRequesterExt *)gad->UserData)->tempAudioID; if(id != AHI_DEFAULT_ID) { AHI_GetAudioAttrs( id, NULL, AHIDB_FrequencyArg, level, AHIDB_Frequency, (ULONG) &freq, TAG_DONE ); } else { freq = AHIBase->ahib_Frequency; } return freq; }
char *getRecord(void) { ULONG record = FALSE, fullduplex = FALSE; struct ModeNode *mode = NULL; if( state.ModeSelected != ~0 ) { mode = (struct ModeNode *) GetNode(state.ModeSelected, ModeList); } if( mode != NULL ) { AHI_GetAudioAttrs( mode->ID, NULL, AHIDB_Record, (ULONG) &record, AHIDB_FullDuplex, (ULONG) &fullduplex, TAG_DONE); } return (char *) (record ? (fullduplex ? msgPropRecordFull : msgPropRecordHalf ) : msgPropRecordNone); }
char *getFreq(void) { LONG freq = 0; struct ModeNode *mode = NULL; if( state.ModeSelected != ~0 ) { mode = (struct ModeNode *) GetNode(state.ModeSelected, ModeList); } if( mode != NULL ) { AHI_GetAudioAttrs( mode->ID, NULL, AHIDB_FrequencyArg, state.FreqSelected, AHIDB_Frequency, (ULONG) &freq, TAG_DONE); } sprintf(freqBuffer, "%ld Hz", freq); return freqBuffer; }
static int MaxPlaySamples(ULONG mode_id, ULONG mix_freq, ULONG player_freq) { int rc = RETURN_OK; struct AHIAudioCtrl* actrl = AHI_AllocAudio(AHIA_AudioID, mode_id, AHIA_MixFreq, mix_freq, AHIA_PlayerFreq, player_freq << 16, AHIA_MinPlayerFreq, player_freq << 16, AHIA_MaxPlayerFreq, player_freq << 16, AHIA_Channels, 1, AHIA_Sounds, 1, TAG_DONE); if (actrl != NULL) { ULONG max_play_samples = 0; if (AHI_GetAudioAttrs(AHI_INVALID_ID, actrl, AHIDB_MaxPlaySamples, &max_play_samples, TAG_DONE)) { fprintf(stderr, "MaxPlaySamples for mode 0x%08lx (Fsample = %ld Hz, Fplayer = %ld Hz) is %ld\n", mode_id, mix_freq, player_freq, max_play_samples); } else { fprintf(stderr, "Unable to get MaxPlaySamples.\n"); rc = RETURN_ERROR; } AHI_FreeAudio(actrl); } else { fprintf(stderr, "Unable to allocate audio.\n"); rc = RETURN_ERROR; } return rc; }
static BOOL HandleReq( struct AHIAudioModeRequesterExt *req ) // Returns FALSE if requester was cancelled { BOOL done=FALSE,rc=TRUE; ULONG class,sec,oldsec=0,micro,oldmicro=0,oldid=AHI_INVALID_ID; UWORD code; UWORD qual; struct Gadget *pgsel; struct IntuiMessage *imsg; struct IDnode *idnode; LONG sliderlevels,sliderlevel,i,selected; struct MenuItem *item; while(!done) { Wait(1L << req->Window->UserPort->mp_SigBit); while ((imsg=GT_GetIMsg(req->Window->UserPort)) != NULL ) { if(imsg->IDCMPWindow == req->InfoWindow) { class = imsg->Class; GT_ReplyIMsg(imsg); switch(class) { case IDCMP_CLOSEWINDOW: CloseInfoWindow(req); break; case IDCMP_REFRESHWINDOW : GT_BeginRefresh(req->InfoWindow); GT_EndRefresh(req->InfoWindow,TRUE); break; } continue; // Get next IntuiMessage } else if(imsg->IDCMPWindow != req->Window) // Not my window! { if(req->IntuiMsgFunc) CallHookPkt(req->IntuiMsgFunc,req,imsg); // else what to do??? Reply and forget? FIXIT! continue; } sec=imsg->Seconds; micro=imsg->Micros; qual=imsg->Qualifier; class=imsg->Class; code=imsg->Code; pgsel=(struct Gadget *)imsg->IAddress; // pgsel illegal if not gadget GT_ReplyIMsg(imsg); switch ( class ) { case IDCMP_RAWKEY: switch (code) { case 0x4c: // Cursor Up selected=GetSelected(req); if(selected == ~0) selected=0; if(selected > 0) selected--; idnode=(struct IDnode *)req->list->mlh_Head; for(i=0;i<selected;i++) idnode=(struct IDnode *)idnode->node.ln_Succ; req->tempAudioID=idnode->ID; SetSelected(req,TRUE); break; case 0x4d: // Cursor Down selected=GetSelected(req); selected++; // ~0 => 0 idnode=(struct IDnode *)req->list->mlh_Head; for(i=0;i<selected;i++) if(idnode->node.ln_Succ->ln_Succ) idnode=(struct IDnode *)idnode->node.ln_Succ; req->tempAudioID=idnode->ID; SetSelected(req,TRUE); break; case 0x4e: // Cursor Right GetSliderAttrs(req,&sliderlevels,&sliderlevel); sliderlevel += (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT) ? 10 :1); if(sliderlevel >= sliderlevels) sliderlevel=sliderlevels-1; AHI_GetAudioAttrs(req->tempAudioID, NULL, AHIDB_FrequencyArg,sliderlevel, AHIDB_Frequency, (ULONG) &req->tempFrequency, TAG_DONE); SetSelected(req,FALSE); break; case 0x4f: // Cursor Left GetSliderAttrs(req,&sliderlevels,&sliderlevel); sliderlevel -= (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT) ? 10 :1); if(sliderlevel < 0) sliderlevel=0; AHI_GetAudioAttrs(req->tempAudioID, NULL, AHIDB_FrequencyArg,sliderlevel, AHIDB_Frequency, (ULONG) &req->tempFrequency, TAG_DONE); SetSelected(req,FALSE); break; } break; case IDCMP_GADGETUP : switch ( pgsel->GadgetID ) { case OKBUTTON: done=TRUE; break; case CANCELBUTTON: done=TRUE; rc=FALSE; break; case FREQSLIDER: AHI_GetAudioAttrs(req->tempAudioID, NULL, AHIDB_FrequencyArg,code, AHIDB_Frequency, (ULONG) &req->tempFrequency, TAG_DONE); break; case LISTVIEW: idnode=(struct IDnode *)req->list->mlh_Head; for(i=0;i<code;i++) idnode=(struct IDnode *)idnode->node.ln_Succ; req->tempAudioID=idnode->ID; SetSelected(req,FALSE); // Test doubleclick and save timestamp if( (oldid == req->tempAudioID) && DoubleClick(oldsec,oldmicro,sec,micro)) done=TRUE; oldsec=sec; oldmicro=micro; oldid=req->tempAudioID; break; } break; case IDCMP_NEWSIZE: if(!(LayOutReq(req,req->TextAttr))) if(!(LayOutReq(req,&Topaz80))) { // ERROR! Quit. done=TRUE; break; } break; case IDCMP_CLOSEWINDOW: done=TRUE; rc=FALSE; break; case IDCMP_REFRESHWINDOW : GT_BeginRefresh(req->Window); GT_EndRefresh(req->Window,TRUE); break; case IDCMP_SIZEVERIFY: break; case IDCMP_MENUPICK: while((code != MENUNULL) && !done) { item=ItemAddress(req->Menu, code); switch((ULONG)GTMENUITEM_USERDATA(item)) { case LASTMODEITEM: selected=GetSelected(req); if(selected == ~0) selected=0; if(selected > 0) selected--; idnode=(struct IDnode *)req->list->mlh_Head; for(i=0;i<selected;i++) idnode=(struct IDnode *)idnode->node.ln_Succ; req->tempAudioID=idnode->ID; SetSelected(req,TRUE); break; case NEXTMODEITEM: selected=GetSelected(req); selected++; // ~0 => 0 idnode=(struct IDnode *)req->list->mlh_Head; for(i=0;i<selected;i++) if(idnode->node.ln_Succ->ln_Succ) idnode=(struct IDnode *)idnode->node.ln_Succ; req->tempAudioID=idnode->ID; SetSelected(req,TRUE); break; case PROPERTYITEM: OpenInfoWindow(req); break; case RESTOREITEM: req->tempAudioID=req->Req.ahiam_AudioID; req->tempFrequency=req->Req.ahiam_MixFreq; SetSelected(req,TRUE); break; case OKITEM: done=TRUE; break; case CANCELITEM: done=TRUE; rc=FALSE; break; } code = item->NextSelect; } break; } } }
Fixed DizzyTestAudioID(ULONG id, struct TagItem *tags ) { ULONG volume=0,stereo=0,panning=0,hifi=0,pingpong=0,record=0,realtime=0, fullduplex=0,bits=0,channels=0,minmix=0,maxmix=0; ULONG total=0,hits=0; struct TagItem *tstate, *tag; if(tags == NULL) { return (Fixed) 0x10000; } if(id == AHI_DEFAULT_ID) { id = AHIBase->ahib_AudioMode; } AHI_GetAudioAttrs( id, NULL, AHIDB_Volume, (ULONG) &volume, AHIDB_Stereo, (ULONG) &stereo, AHIDB_Panning, (ULONG) &panning, AHIDB_HiFi, (ULONG) &hifi, AHIDB_PingPong, (ULONG) &pingpong, AHIDB_Record, (ULONG) &record, AHIDB_Bits, (ULONG) &bits, AHIDB_MaxChannels, (ULONG) &channels, AHIDB_MinMixFreq, (ULONG) &minmix, AHIDB_MaxMixFreq, (ULONG) &maxmix, AHIDB_Realtime, (ULONG) &realtime, AHIDB_FullDuplex, (ULONG) &fullduplex, TAG_DONE ); tstate = tags; while ((tag = NextTagItem(&tstate))) { switch (tag->ti_Tag) { // Check source mode case AHIDB_AudioID: total++; if( ((tag->ti_Data)&0xffff0000) == (id & 0xffff0000) ) hits++; break; // Boolean tags case AHIDB_Volume: total++; if(XNOR(tag->ti_Data, volume)) hits++; break; case AHIDB_Stereo: total++; if(XNOR(tag->ti_Data, stereo)) hits++; break; case AHIDB_Panning: total++; if(XNOR(tag->ti_Data, panning)) hits++; break; case AHIDB_HiFi: total++; if(XNOR(tag->ti_Data, hifi)) hits++; break; case AHIDB_PingPong: total++; if(XNOR(tag->ti_Data, pingpong)) hits++; break; case AHIDB_Record: total++; if(XNOR(tag->ti_Data, record)) hits++; break; case AHIDB_Realtime: total++; if(XNOR(tag->ti_Data, realtime)) hits++; break; case AHIDB_FullDuplex: total++; if(XNOR(tag->ti_Data, fullduplex)) hits++; break; // The rest case AHIDB_Bits: total++; if(tag->ti_Data <= bits) hits++; break; case AHIDB_MaxChannels: total++; if(tag->ti_Data <= channels ) hits++; break; case AHIDB_MinMixFreq: total++; if(tag->ti_Data >= minmix) hits++; break; case AHIDB_MaxMixFreq: total++; if(tag->ti_Data <= maxmix) hits++; break; } /* switch */ } /* while */ if(total) return (Fixed) ((hits<<16)/total); else return (Fixed) 0x10000; }
void NewMode(int selectedmode) { struct UnitNode *unit = NULL; struct ModeNode *mode = NULL; ULONG id = AHI_INVALID_ID; Fixed MinOutVol = 0, MaxOutVol = 0, MinMonVol = 0, MaxMonVol = 0; Fixed MinGain = 0, MaxGain = 0; double Min, Max, Current; int offset; state.ModeSelected = selectedmode; unit = (struct UnitNode *) GetNode(state.UnitSelected, UnitList); if( selectedmode != ~0 ) { mode = (struct ModeNode *) GetNode(selectedmode, ModeList); } if( mode != NULL ) { id = mode->ID; AHI_GetAudioAttrs(id, NULL, AHIDB_IndexArg, unit->prefs.ahiup_Frequency, AHIDB_Index, (ULONG) &state.FreqSelected, AHIDB_Frequencies, (ULONG) &state.Frequencies, AHIDB_MaxChannels, (ULONG) &state.Channels, AHIDB_Inputs, (ULONG) &state.Inputs, AHIDB_Outputs, (ULONG) &state.Outputs, AHIDB_MinOutputVolume, (ULONG) &MinOutVol, AHIDB_MaxOutputVolume, (ULONG) &MaxOutVol, AHIDB_MinMonitorVolume, (ULONG) &MinMonVol, AHIDB_MaxMonitorVolume, (ULONG) &MaxMonVol, AHIDB_MinInputGain, (ULONG) &MinGain, AHIDB_MaxInputGain, (ULONG) &MaxGain, AHIDB_BufferLen, 128, AHIDB_Author, (ULONG) authorBuffer, AHIDB_Copyright, (ULONG) copyrightBuffer, AHIDB_Driver, (ULONG) driverBuffer, AHIDB_Version, (ULONG) versionBuffer, AHIDB_Annotation, (ULONG) annotationBuffer, TAG_DONE); } state.ChannelsSelected = unit->prefs.ahiup_Channels; state.ScaleModeSelected = unit->prefs.ahiup_ScaleMode; state.InputSelected = unit->prefs.ahiup_Input; state.OutputSelected = unit->prefs.ahiup_Output; // Limit channels state.Channels = min(state.Channels, 32); if(unit->prefs.ahiup_Unit == AHI_NO_UNIT) { state.ChannelsDisabled = TRUE; } else { state.ChannelsDisabled = FALSE; } if(MinOutVol == 0) { MinOutVol = 1; state.OutVolMute = TRUE; state.OutVols = 1; } else { state.OutVolMute = FALSE; state.OutVols = 0; } if(MinMonVol == 0) { MinMonVol = 1; state.MonVolMute = TRUE; state.MonVols = 1; } else { state.MonVolMute = FALSE; state.MonVols = 0; } if(MinGain == 0) { MinGain = 1; state.GainMute = TRUE; state.Gains = 1; } else { state.GainMute = FALSE; state.Gains = 0; } if(MaxOutVol == 0) { state.OutVolSelected = 0; state.OutVolOffset = 0; } else { Current = 20 * log10( unit->prefs.ahiup_OutputVolume / 65536.0 ); Min = floor(20 * log10( MinOutVol / 65536.0 ) / DBSTEP + 0.5) * DBSTEP; Max = floor(20 * log10( MaxOutVol / 65536.0 ) / DBSTEP + 0.5) * DBSTEP; state.OutVolSelected = (Current - Min) / DBSTEP + 0.5 + state.OutVols; state.OutVols += ((Max - Min) / DBSTEP) + 1; state.OutVolOffset = Min; } if(MaxMonVol == 0) { state.MonVolSelected = 0; state.MonVolOffset = 0; } else { Current = 20 * log10( unit->prefs.ahiup_MonitorVolume / 65536.0 ); Min = floor(20 * log10( MinMonVol / 65536.0 ) / DBSTEP + 0.5) * DBSTEP; Max = floor(20 * log10( MaxMonVol / 65536.0 ) / DBSTEP + 0.5) * DBSTEP; state.MonVolSelected = (Current - Min) / DBSTEP + 0.5 + state.MonVols; state.MonVols += ((Max - Min) / DBSTEP) + 1; state.MonVolOffset = Min; } if(MaxGain == 0) { state.GainSelected = 0; state.GainOffset = 0; } else { Current = 20 * log10( unit->prefs.ahiup_InputGain / 65536.0 ); Min = floor(20 * log10( MinGain / 65536.0 ) / DBSTEP + 0.5) * DBSTEP; Max = floor(20 * log10( MaxGain / 65536.0 ) / DBSTEP + 0.5) * DBSTEP; state.GainSelected = (Current - Min) / DBSTEP + 0.5 + state.Gains; state.Gains += ((Max - Min) / DBSTEP) + 1; state.GainOffset = Min; } // Make sure everything is within bounds! state.FreqSelected = max(state.FreqSelected, 0); state.FreqSelected = min(state.FreqSelected, state.Frequencies); state.ChannelsSelected = max(state.ChannelsSelected, 1); state.ChannelsSelected = min(state.ChannelsSelected, state.Channels); state.ScaleModeSelected = max(state.ScaleModeSelected, 0); state.ScaleModeSelected = min(state.ScaleModeSelected, AHI_SCALE_FIXED_6_DB); state.OutVolSelected = max(state.OutVolSelected, 0); state.OutVolSelected = min(state.OutVolSelected, state.OutVols); state.MonVolSelected = max(state.MonVolSelected, 0); state.MonVolSelected = min(state.MonVolSelected, state.MonVols); state.GainSelected = max(state.GainSelected, 0); state.GainSelected = min(state.GainSelected, state.Gains); state.InputSelected = max(state.InputSelected, 0); state.InputSelected = min(state.InputSelected, state.Inputs); state.OutputSelected = max(state.OutputSelected, 0); state.OutputSelected = min(state.OutputSelected, state.Outputs); // Remove any \r's or \n's from version string offset = strlen(versionBuffer); while((offset > 0) && ((versionBuffer[offset-1] == '\r') || (versionBuffer[offset-1] == '\n'))) { versionBuffer[offset-1] = '\0'; offset--; } FreeVec(Inputs); FreeVec(Outputs); Inputs = GetInputs(id); Outputs = GetOutputs(id); }
VOID DispatcherThread(struct MOSWriteHandle* h) { struct MsgPort* ahi_port = NULL; struct AHIRequest* ahi_request = NULL; struct AHIAudioCtrl*ahi_control = NULL; BYTE* sample_bufs = NULL; ULONG sample_size = 2; BYTE ahi_device = -1; LONG switch_sig_bit = -1; LONG locked_buf = -1; struct DispatcherStartupMsg *startup_msg; struct DispatcherInitReport *init_report; struct MsgPort *task_port = NULL; struct ExecBase *SysBase = *(struct ExecBase **) 4; init_report = (struct DispatcherInitReport *) AllocVec(sizeof (struct DispatcherInitReport), MEMF_PUBLIC | MEMF_CLEAR); if (init_report == NULL) return; NewGetTaskAttrsA(NULL, &task_port, sizeof (task_port), TASKINFOTYPE_TASKMSGPORT, NULL); NewGetTaskAttrsA(NULL, &startup_msg, sizeof (startup_msg), TASKINFOTYPE_STARTUPMSG, NULL); if (task_port == NULL || startup_msg == NULL) { FreeVec(init_report); return; } startup_msg->dsm_Result = -1; switch_sig_bit = AllocSignal(-1); if (switch_sig_bit != -1 && (ahi_port = CreateMsgPort())) { if ((ahi_request = (struct AHIRequest *) CreateIORequest(ahi_port, sizeof (struct AHIRequest)))) { ahi_request->ahir_Version = 4; if ((ahi_device = OpenDevice(AHINAME, AHI_NO_UNIT, (struct IORequest *) ahi_request, 0)) == 0) { AHIBase = (struct Library*) ahi_request->ahir_Std.io_Device; /*dprintf("AllocAudio with %d channels, %d sounds and frequency %d\n", h->wh_Channels, AHI_BUFFERS, h->wh_Frequency);*/ ahi_control = AHI_AllocAudio(AHIA_AudioID, AHI_DEFAULT_ID, AHIA_Channels, h->wh_Channels, AHIA_Sounds, AHI_BUFFERS, AHIA_MixFreq, h->wh_Frequency, AHIA_SoundFunc, (ULONG) &OpenAL_SoundHook, AHIA_UserData, (ULONG) h, TAG_DONE ); if (ahi_control) { ULONG buf_size; ULONG samples, fs, fm; AHI_GetAudioAttrs(AHI_INVALID_ID, ahi_control, AHIDB_MaxPlaySamples, (ULONG) &samples, TAG_DONE); AHI_ControlAudio(ahi_control, AHIC_MixFreq_Query, (ULONG) &fm, TAG_DONE); fs = h->wh_Frequency; buf_size = samples*fs/fm; /*dprintf("OpenAL: Minimum buffer size is %d, requested buffer size is %d\n", buf_size, h->wh_BufSize);*/ if (buf_size > h->wh_BufSize) h->wh_BufSize = buf_size; sample_bufs = AllocVec(h->wh_BufSize*AHI_BUFFERS, MEMF_PUBLIC | MEMF_CLEAR); if (sample_bufs) { struct Buffer* bn; ULONG buf; LONG err = AHIE_OK; sample_size = AHI_SampleFrameSize(h->wh_SampleType); for (buf = 0; buf < AHI_BUFFERS && err == AHIE_OK; buf++) { bn = &h->wh_Buffers[buf]; bn->bn_SampleNo = buf; bn->bn_SampleInfo.ahisi_Type = h->wh_SampleType; bn->bn_SampleInfo.ahisi_Address = &sample_bufs[buf*h->wh_BufSize]; bn->bn_SampleInfo.ahisi_Length = h->wh_BufSize/sample_size; InitSemaphore(&bn->bn_Semaphore); bn->bn_FillSize = 0; err = AHI_LoadSound(buf, AHIST_DYNAMICSAMPLE, &bn->bn_SampleInfo, ahi_control); } if (err != AHIE_OK) { FreeVec(sample_bufs); sample_bufs = NULL; } } } } } } if (sample_bufs) { BOOL dispatcher_running = TRUE; ULONG signal_mask = 1 << task_port->mp_SigBit; ULONG signal_set; struct MsgPort *reply_port; reply_port = CreateMsgPort(); if (reply_port == NULL) reply_port = task_port; if (startup_msg) startup_msg->dsm_Result = 0; init_report->dir_Msg.mn_Node.ln_Type = NT_MESSAGE; init_report->dir_Msg.mn_ReplyPort = reply_port; init_report->dir_Msg.mn_Length = sizeof (struct DispatcherInitReport); AHI_ControlAudio(ahi_control, AHIC_MixFreq_Query, (ULONG) &init_report->dir_RealFrequency, TAG_DONE); init_report->dir_RealBufSize = h->wh_BufSize; PutMsg(startup_msg->dsm_Msg.mn_ReplyPort, (struct Message*) init_report); WaitPort(reply_port); GetMsg(reply_port); FreeVec(init_report); init_report = NULL; if (reply_port != task_port) DeleteMsgPort(reply_port); h->wh_SwitchSignal = 1UL << switch_sig_bit; h->wh_ReadBuf = 0; while (dispatcher_running) { signal_set = Wait(signal_mask); if (signal_set & (1 << task_port->mp_SigBit)) { struct DispatcherMsg *msg; while ((msg = (struct DispatcherMsg *) GetMsg(task_port))) { if (msg->dm_Msg.mn_Length == sizeof (struct DispatcherMsg)) { switch (msg->dm_Command) { case DISPATCHER_CMD_START: { /* * First buffer has been filled and we were previously not * playing any sound yet */ ULONG chan; ULONG cur_buf; cur_buf = h->wh_ReadBuf; AHI_ControlAudio(ahi_control, AHIC_Play, TRUE, TAG_DONE); /* Lock first audio buffer */ ObtainSemaphore(&h->wh_Buffers[cur_buf].bn_Semaphore); locked_buf = cur_buf; for (chan = 0; chan < h->wh_Channels; chan++) { AHI_SetFreq(chan, h->wh_Frequency, ahi_control, AHISF_IMM); AHI_SetVol(chan, 0x10000L, -0x8000L, ahi_control, AHISF_IMM); AHI_SetSound(chan, cur_buf, 0, 0, ahi_control, AHISF_IMM); } Wait(1 << switch_sig_bit); cur_buf++; if (cur_buf >= AHI_BUFFERS) cur_buf = 0; h->wh_ReadBuf = cur_buf; signal_mask |= 1UL << switch_sig_bit; break; } case DISPATCHER_CMD_PAUSE: case DISPATCHER_CMD_RESUME: AHI_ControlAudio(ahi_control, AHIC_Play, msg->dm_Command == DISPATCHER_CMD_RESUME, TAG_DONE); break; case DISPATCHER_CMD_BREAK: /* Break requests and quit */ /*dprintf("Dispatcher thread: break requested\n");*/ AHI_ControlAudio(ahi_control, AHIC_Play, FALSE, TAG_DONE); dispatcher_running = FALSE; break; } } ReplyMsg((struct Message *) msg); } } if (signal_set & (1UL << switch_sig_bit)) { /* Switch to next read buffer */ ULONG cur_buf; cur_buf = h->wh_ReadBuf; /*dprintf("Dispatcher thread: buffer switch requested. Releasing lock on %d, locking %d\n", locked_buf, cur_buf);*/ memset(h->wh_Buffers[locked_buf].bn_SampleInfo.ahisi_Address, 0, h->wh_BufSize); ReleaseSemaphore(&h->wh_Buffers[locked_buf].bn_Semaphore); cur_buf++; if (cur_buf >= AHI_BUFFERS) cur_buf = 0; ObtainSemaphore(&h->wh_Buffers[cur_buf].bn_Semaphore); locked_buf = cur_buf; h->wh_ReadBuf = cur_buf; /*dprintf("Dispatcher thread: buffer switch done\n");*/ } } } /* Cleanup */ if (init_report) { FreeVec(init_report); init_report = NULL; } if (locked_buf != -1) { ReleaseSemaphore(&h->wh_Buffers[locked_buf].bn_Semaphore); locked_buf = -1; } if (switch_sig_bit != -1) { FreeSignal(switch_sig_bit); switch_sig_bit = -1; } if (ahi_control) { AHI_FreeAudio(ahi_control); /* Also unloads all sounds */ ahi_control = NULL; } if (ahi_request) { CloseDevice((struct IORequest*) ahi_request); DeleteIORequest((struct IORequest*) ahi_request); ahi_request = NULL; ahi_device = -1; } if (sample_bufs) { FreeVec(sample_bufs); sample_bufs = NULL; } if (ahi_port) { DeleteMsgPort(ahi_port); ahi_port = NULL; } }
int PlaySineEverywhere( void ) { int rc = RETURN_OK; int sine_length = 44100 / 100; BYTE* sine_m8s; BYTE* sine_s8s; WORD* sine_s16s; WORD* sine_m16s; LONG* sine_s32s; LONG* sine_m32s; sine_m8s = AllocVec( 1 * sizeof( BYTE ) * sine_length, MEMF_ANY | MEMF_PUBLIC ); sine_s8s = AllocVec( 2 * sizeof( BYTE ) * sine_length, MEMF_ANY | MEMF_PUBLIC ); sine_m16s = AllocVec( 1 * sizeof( WORD ) * sine_length, MEMF_ANY | MEMF_PUBLIC ); sine_s16s = AllocVec( 2 * sizeof( WORD ) * sine_length, MEMF_ANY | MEMF_PUBLIC ); sine_m32s = AllocVec( 1 * sizeof( LONG ) * sine_length, MEMF_ANY | MEMF_PUBLIC ); sine_s32s = AllocVec( 2 * sizeof( LONG ) * sine_length, MEMF_ANY | MEMF_PUBLIC ); if( sine_m8s != NULL && sine_s8s != NULL && sine_m16s != NULL && sine_s16s != NULL && sine_m32s != NULL && sine_s32s != NULL ) { ULONG mode = AHI_INVALID_ID; int i; for( i = 0; i < sine_length; ++i ) { double value = sin( i * 2 * M_PI / sine_length ); sine_m8s[ i ] = (BYTE) ( SCHAR_MAX * value ); sine_m16s[ i ] = (WORD) ( SHRT_MAX * value ); sine_m32s[ i ] = (LONG) ( LONG_MAX * value ); sine_s8s[ i * 2 + 0 ] = (BYTE) ( SCHAR_MAX * value ); sine_s8s[ i * 2 + 1 ] = (BYTE) ( SCHAR_MAX * value ); sine_s16s[ i * 2 + 0 ] = (WORD) ( SHRT_MAX * value ); sine_s16s[ i * 2 + 1 ] = (WORD) ( SHRT_MAX * value ); sine_s32s[ i * 2 + 0 ] = (LONG) ( LONG_MAX * value ); sine_s32s[ i * 2 + 1 ] = (LONG) ( LONG_MAX * value ); } while( rc == RETURN_OK && ( mode = AHI_NextAudioID( mode ) ) != AHI_INVALID_ID ) { struct AHIAudioCtrl* actrl; char name[ 64 ]; struct Hook sound_hook = { { NULL, NULL }, HookEntry, (HOOKFUNC) SoundFunc, FindTask( NULL ) }; AHI_GetAudioAttrs( mode, NULL, AHIDB_Name, (ULONG) &name, AHIDB_BufferLen, 64, TAG_DONE ); printf( "Mode 0x%08lx: %s\n", mode, name ); actrl = AHI_AllocAudio( AHIA_AudioID, mode, AHIA_MixFreq, 44100, AHIA_Channels, 1, AHIA_Sounds, 6, AHIA_SoundFunc, (ULONG) &sound_hook, AHIA_UserData, 0, TAG_DONE ); if( actrl != NULL ) { struct AHISampleInfo sample_m8s = { AHIST_M8S, sine_m8s, sine_length }; struct AHISampleInfo sample_s8s = { AHIST_S8S, sine_s8s, sine_length }; struct AHISampleInfo sample_m16s = { AHIST_M16S, sine_m16s, sine_length }; struct AHISampleInfo sample_s16s = { AHIST_S16S, sine_s16s, sine_length }; struct AHISampleInfo sample_m32s = { AHIST_M32S, sine_m32s, sine_length }; struct AHISampleInfo sample_s32s = { AHIST_S32S, sine_s32s, sine_length }; if( AHI_LoadSound( 0, AHIST_SAMPLE, &sample_m8s, actrl) == AHIE_OK && AHI_LoadSound( 1, AHIST_SAMPLE, &sample_s8s, actrl) == AHIE_OK && AHI_LoadSound( 2, AHIST_SAMPLE, &sample_m16s, actrl) == AHIE_OK && AHI_LoadSound( 3, AHIST_SAMPLE, &sample_s16s, actrl) == AHIE_OK && AHI_LoadSound( 4, AHIST_SAMPLE, &sample_m32s, actrl) == AHIE_OK && AHI_LoadSound( 5, AHIST_SAMPLE, &sample_s32s, actrl) == AHIE_OK ) { AHI_Play( actrl, AHIP_BeginChannel, 0, AHIP_Sound, 0, AHIP_Freq, 44100, AHIP_Vol, 0x10000, AHIP_Pan, 0x00000, AHIP_EndChannel, 0, TAG_DONE ); // Now, when everything is "armed", lets start processing. SetSignal( 0, SIGF_SINGLE ); if( AHI_ControlAudio( actrl, AHIC_Play, TRUE, TAG_DONE ) == AHIE_OK ) { Wait( SIGF_SINGLE ); AHI_ControlAudio( actrl, AHIC_Play, FALSE, TAG_DONE ); } else { fprintf( stderr, "Unable start playback.\n" ); rc = RETURN_ERROR; } // AHI_FreeAudio() will unload the sounds } else { fprintf( stderr, "Unable load sound.\n" ); rc = RETURN_ERROR; } AHI_FreeAudio( actrl ); } else { fprintf( stderr, "Unable to allocate audio.\n" ); rc = RETURN_ERROR; } } } else { fprintf( stderr, "Unable to allocate memory for sine\n" ); } FreeVec( sine_m8s ); FreeVec( sine_s8s ); FreeVec( sine_s16s ); FreeVec( sine_m16s ); FreeVec( sine_s32s ); FreeVec( sine_m32s ); return rc; }