static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) { SndDoubleBufferHeader2 audio_dbh; int i; long initOptions; int sample_bits; SndDoubleBackUPP doubleBackProc; /* Check to make sure double-buffered audio is available */ if ( ! DoubleBufferAudio_Available() ) { SDL_SetError("Sound manager doesn't support double-buffering"); return(-1); } /* Very few conversions are required, but... */ switch (spec->format) { case AUDIO_S8: spec->format = AUDIO_U8; break; case AUDIO_U16LSB: spec->format = AUDIO_S16LSB; break; case AUDIO_U16MSB: spec->format = AUDIO_S16MSB; break; } SDL_CalculateAudioSpec(spec); /* initialize the double-back header */ memset(&audio_dbh, 0, sizeof(audio_dbh)); doubleBackProc = NewSndDoubleBackProc (sndDoubleBackProc); sample_bits = spec->size / spec->samples / spec->channels * 8; audio_dbh.dbhNumChannels = spec->channels; audio_dbh.dbhSampleSize = sample_bits; audio_dbh.dbhCompressionID = 0; audio_dbh.dbhPacketSize = 0; audio_dbh.dbhSampleRate = spec->freq << 16; audio_dbh.dbhDoubleBack = doubleBackProc; audio_dbh.dbhFormat = 0; /* Note that we install the 16bitLittleEndian Converter if needed. */ if ( spec->format == 0x8010 ) { audio_dbh.dbhCompressionID = fixedCompression; audio_dbh.dbhFormat = k16BitLittleEndianFormat; } /* allocate the 2 double-back buffers */ for ( i=0; i<2; ++i ) { audio_buf[i] = calloc(1, sizeof(SndDoubleBuffer)+spec->size); if ( audio_buf[i] == NULL ) { SDL_OutOfMemory(); return(-1); } audio_buf[i]->dbNumFrames = spec->samples; audio_buf[i]->dbFlags = dbBufferReady; audio_buf[i]->dbUserInfo[0] = (long)this; audio_dbh.dbhBufferPtr[i] = audio_buf[i]; } /* Create the sound manager channel */ channel = (SndChannelPtr)malloc(sizeof(*channel)); if ( channel == NULL ) { SDL_OutOfMemory(); return(-1); } if ( spec->channels >= 2 ) { initOptions = initStereo; } else { initOptions = initMono; } channel->userInfo = 0; channel->qLength = 128; if ( SndNewChannel(&channel, sampledSynth, initOptions, 0L) != noErr ) { SDL_SetError("Unable to create audio channel"); free(channel); channel = NULL; return(-1); } /* Start playback */ if ( SndPlayDoubleBuffer(channel, (SndDoubleBufferHeaderPtr)&audio_dbh) != noErr ) { SDL_SetError("Unable to play double buffered audio"); return(-1); } return 1; }
OSErr open_network_speaker() { short block_size = kBlockSize; short connection_threshold = kConnectionThreshhold; OSErr error; assert(!speaker); assert(block_size>0&&block_size<=MAXIMUM_DOUBLE_BUFFER_SIZE); assert(connection_threshold>1&&connection_threshold<16); /* install our atexit cleanup procedure and build a routine descriptor */ { static bool initialization= true; if (initialization) { // ZZZ: Sorry, it looks like the CarbonSndPlayDoubleBuffer stuff really wants a plain C function // pointer, sitting in the structure typed as a SndDoubleBackUPP. (Don't ask me!) #if defined(TARGET_API_MAC_CARBON) doubleback_routine_descriptor= (SndDoubleBackUPP)network_speaker_doubleback_procedure; #else // Thomas Herzog fix #if UNIVERSAL_INTERFACES_VERSION < 0x0340 doubleback_routine_descriptor= NewSndDoubleBackProc( (ProcPtr)network_speaker_doubleback_procedure); #else doubleback_routine_descriptor= NewSndDoubleBackUPP( network_speaker_doubleback_procedure); #endif // doubleback_routine_descriptor= NewSndDoubleBackProc((ProcPtr)network_speaker_doubleback_procedure); #endif assert(doubleback_routine_descriptor); atexit(close_network_speaker); } } speaker= (struct speaker_definition *) NewPtr(sizeof(struct speaker_definition)); if ((error= MemError())==noErr) { speaker->random_seed= 1; speaker->block_size= block_size; speaker->connection_threshold= connection_threshold; speaker->channel= (SndChannelPtr) NewPtrClear(sizeof(SndChannel)); speaker->header= (SndDoubleBufferHeaderPtr) NewPtrClear(sizeof(SndDoubleBufferHeader)); speaker->queue= NewPtr(sizeof(byte)*MAXIMUM_QUEUE_SIZE); if ((error= MemError())==noErr) { SndDoubleBufferHeaderPtr header= speaker->header; header->dbhNumChannels= 1; header->dbhSampleSize= 8; header->dbhCompressionID= 0; header->dbhPacketSize= 0; header->dbhSampleRate= rate11025hz; header->dbhDoubleBack= doubleback_routine_descriptor; header->dbhBufferPtr[0]= (SndDoubleBufferPtr) NewPtrClear( sizeof(SndDoubleBuffer)+MAXIMUM_DOUBLE_BUFFER_SIZE); header->dbhBufferPtr[1]= (SndDoubleBufferPtr) NewPtrClear( sizeof(SndDoubleBuffer)+MAXIMUM_DOUBLE_BUFFER_SIZE); if ((error= MemError())==noErr) { speaker->channel->qLength= stdQLength; #ifdef env68k speaker->channel->userInfo= (long) get_a5(); #endif error= SndNewChannel(&speaker->channel, sampledSynth, initMono|initMACE6, NULL); if (error==noErr) { quiet_network_speaker(); /* to set defaults */ } } } } #ifdef SPEEX init_speex_decoder(); #endif /* if something went wrong, zero the speaker definition (without freeing any of our memory like we should) */ if (error!=noErr) { speaker= (struct speaker_definition *) NULL; } return error; }
/* * generic new : returns error */ int start_fluid_sndmgr_audio_driver(fluid_settings_t* settings, fluid_sndmgr_audio_driver_t* dev, int buffer_size) { int i; SndDoubleBufferHeader2* doubleHeader = NULL; SndDoubleBufferPtr doubleBuffer = NULL; OSErr err; SndChannelPtr channel = NULL; double sample_rate; fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); dev->doubleCallbackProc = NewSndDoubleBackProc(fluid_sndmgr_callback); /* the channel */ FLUID_LOG(FLUID_DBG, "FLUID-SndManager@2"); err = SndNewChannel(&channel, sampledSynth, initStereo, NULL); if ((err != noErr) || (channel == NULL)) { FLUID_LOG(FLUID_ERR, "Failed to allocate a sound channel (error %i)", err); return err; } /* the double buffer struct */ FLUID_LOG(FLUID_DBG, "FLUID-SndManager@3"); doubleHeader = FLUID_NEW(SndDoubleBufferHeader2); if (doubleHeader == NULL) { FLUID_LOG(FLUID_PANIC, "Out of memory"); return -1; } doubleHeader->dbhBufferPtr[0] = NULL; doubleHeader->dbhBufferPtr[1] = NULL; doubleHeader->dbhNumChannels = 2; doubleHeader->dbhSampleSize = 16; doubleHeader->dbhCompressionID = 0; doubleHeader->dbhPacketSize = 0; doubleHeader->dbhSampleRate = fluid_sndmgr_double_to_fix((long double) sample_rate); doubleHeader->dbhDoubleBack = dev->doubleCallbackProc; doubleHeader->dbhFormat = 0; /* prepare dev */ FLUID_LOG(FLUID_DBG, "FLUID-SndManager@4"); dev->doubleHeader = doubleHeader; dev->channel = channel; dev->bufferFrameSize = buffer_size; dev->bufferByteSize = buffer_size * 2 * 2; /* the 2 doublebuffers */ FLUID_LOG(FLUID_DBG, "FLUID-SndManager@5"); for (i = 0; i < 2; i++) { doubleBuffer = (SndDoubleBufferPtr) FLUID_MALLOC(sizeof(SndDoubleBuffer) + dev->bufferByteSize); if (doubleBuffer == NULL) { FLUID_LOG(FLUID_PANIC, "Out of memory"); return -1; } doubleBuffer->dbNumFrames = 0; doubleBuffer->dbFlags = 0; doubleBuffer->dbUserInfo[0] = (long) dev; doubleHeader->dbhBufferPtr[i] = doubleBuffer; CallSndDoubleBackProc(doubleHeader->dbhDoubleBack, channel, doubleBuffer); } /* start */ FLUID_LOG(FLUID_DBG, "FLUID-SndManager@6"); err = SndPlayDoubleBuffer(channel, (SndDoubleBufferHeader *)doubleHeader); if (err != noErr) { FLUID_LOG(FLUID_ERR, "Failed to start the sound driver (error %i)", err); return err; } FLUID_LOG(FLUID_DBG, "FLUID-SndManager@7"); return 0; }