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; }
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; } }
BOOL PlaySound( struct AHIUnitPrefs* prefs ) { struct AHIAudioCtrl* actrl; BOOL rc = FALSE; actrl = AHI_AllocAudio( AHIA_AudioID, prefs->ahiup_AudioMode, AHIA_MixFreq, prefs->ahiup_Frequency, AHIA_Channels, max( prefs->ahiup_Channels, 1 ), AHIA_Sounds, 1, TAG_DONE ); if( actrl != NULL ) { BYTE* sample; int length = 48000/440; struct AHISampleInfo sound; sample = AllocVec( length, MEMF_PUBLIC ); if( sample != NULL ) { int i; for( i = 0; i < length; ++i ) { sample[ i ] = 127 * sin( i * 2 * M_PI / length ); } sound.ahisi_Type = AHIST_M8S; sound.ahisi_Address = sample; sound.ahisi_Length = length; if( AHI_LoadSound( 0, AHIST_SAMPLE, &sound, actrl ) == AHIE_OK ) { if( AHI_ControlAudio( actrl, AHIC_Play, TRUE, AHIC_MonitorVolume, prefs->ahiup_MonitorVolume, AHIC_InputGain, prefs->ahiup_InputGain, AHIC_OutputVolume, prefs->ahiup_OutputVolume, AHIC_Input, prefs->ahiup_Input, AHIC_Output, prefs->ahiup_Output, TAG_DONE ) == AHIE_OK ) { AHI_Play( actrl, AHIP_BeginChannel, 0, AHIP_Freq, 48000, AHIP_Vol, 0x10000, AHIP_Pan, 0x8000, AHIP_Sound, 0, AHIP_EndChannel, NULL, TAG_DONE ); Delay( 50 ); AHI_Play( actrl, AHIP_BeginChannel, 0, AHIP_Sound, AHI_NOSOUND, AHIP_EndChannel, NULL, TAG_DONE ); // Give the anti-click code a break ... Delay( 1 ); AHI_ControlAudio( actrl, AHIC_Play, FALSE, TAG_DONE ); } AHI_UnloadSound( 0, actrl ); } FreeVec( sample ); } AHI_FreeAudio( actrl ); } return rc; }
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; }