[Fuse-for-macosx-commits] SF.net SVN: fuse-for-macosx: [260] branches/fusegl/fuse
Brought to you by:
fredm
From: <fr...@us...> - 2006-12-23 01:32:27
|
Revision: 260 http://svn.sourceforge.net/fuse-for-macosx/?rev=260&view=rev Author: fredm Date: 2006-12-22 17:32:26 -0800 (Fri, 22 Dec 2006) Log Message: ----------- Add CoreAudio sound driver - still getting lots of clicking from bad syncronisation between drawing and sound threads. Modified Paths: -------------- branches/fusegl/fuse/Makefile.am branches/fusegl/fuse/configure.in branches/fusegl/fuse/fusepb/Fuse.xcodeproj/project.pbxproj branches/fusegl/fuse/fusepb/config.h branches/fusegl/fuse/sound/Makefile.am branches/fusegl/fuse/sound/lowlevel.h branches/fusegl/fuse/sound/sdlsound.c branches/fusegl/fuse/sound/sfifo.c branches/fusegl/fuse/timer.c Added Paths: ----------- branches/fusegl/fuse/sound/coreaudiosound.c Modified: branches/fusegl/fuse/Makefile.am =================================================================== --- branches/fusegl/fuse/Makefile.am 2006-12-20 08:57:32 UTC (rev 259) +++ branches/fusegl/fuse/Makefile.am 2006-12-23 01:32:26 UTC (rev 260) @@ -107,6 +107,7 @@ @GLIB_LIBS@ \ @PNG_LIBS@ \ @AO_LIBS@ \ +@COREAUDIO_LIBS@ \ @X_LIBS@ \ @XML_LIBS@ \ compat/libcompat.a Modified: branches/fusegl/fuse/configure.in =================================================================== --- branches/fusegl/fuse/configure.in 2006-12-20 08:57:32 UTC (rev 259) +++ branches/fusegl/fuse/configure.in 2006-12-23 01:32:26 UTC (rev 260) @@ -398,8 +398,7 @@ AC_CHECK_LIB( ao, ao_open_live, [AC_CHECK_HEADER( ao/ao.h, - [AC_DEFINE([USE_LIBAO], 1, [Defined if we're going to be using the instal -ed libao]) AO_LIBS='-lao'], + [AC_DEFINE([USE_LIBAO], 1, [Defined if we're going to be using the installed libao]) AO_LIBS='-lao'], [AC_MSG_WARN(ao/ao.h not found - no libao sound output)] )], [AC_MSG_WARN(ao_open_live not found - no libao sound output)] @@ -407,6 +406,15 @@ AC_SUBST(AO_LIBS) fi +dnl Check if a version of libao which supplies ao_open_live is available + CoreAudio/AudioHardware.h +AC_CHECK_HEADER( + CoreAudio/AudioHardware.h, + [AC_DEFINE([USE_COREAUDIO], 1, [Defined if we're going to be using CoreAudio]) COREAUDIO_LIBS='-framework CoreAudio -framework AudioUnit -framework CoreServices'], + [AC_MSG_WARN(CoreAudio/AudioHardware.h not found - no CoreAudio sound output)] +) +AC_SUBST(COREAUDIO_LIBS) + dnl Are we supplying the ROMs or relying on another package? AC_MSG_CHECKING(where to find the Spectrum ROM images) AC_ARG_WITH(roms-dir, Modified: branches/fusegl/fuse/fusepb/Fuse.xcodeproj/project.pbxproj =================================================================== --- branches/fusegl/fuse/fusepb/Fuse.xcodeproj/project.pbxproj 2006-12-20 08:57:32 UTC (rev 259) +++ branches/fusegl/fuse/fusepb/Fuse.xcodeproj/project.pbxproj 2006-12-23 01:32:26 UTC (rev 260) @@ -226,7 +226,6 @@ B61F468509121DF100C8096C /* kempmouse.c in Sources */ = {isa = PBXBuildFile; fileRef = B68C17DC06C8C0DC004981AE /* kempmouse.c */; }; B61F468609121DF100C8096C /* if1.c in Sources */ = {isa = PBXBuildFile; fileRef = B6C8B723076D2B1A0007B7B5 /* if1.c */; }; B61F468709121DF100C8096C /* RollbackController.m in Sources */ = {isa = PBXBuildFile; fileRef = B63F994A077182B4004D6DFA /* RollbackController.m */; }; - B61F468809121DF100C8096C /* sdlsound.c in Sources */ = {isa = PBXBuildFile; fileRef = B6F06092078FB36500CD5D95 /* sdlsound.c */; }; B61F468909121DF100C8096C /* ts2068.c in Sources */ = {isa = PBXBuildFile; fileRef = B6F060A5078FB55400CD5D95 /* ts2068.c */; }; B61F468A09121DF100C8096C /* sfifo.c in Sources */ = {isa = PBXBuildFile; fileRef = B6F06100078FC2C900CD5D95 /* sfifo.c */; }; B61F468B09121DF100C8096C /* PreferencesController.m in Sources */ = {isa = PBXBuildFile; fileRef = B650F73F07E7CD3F00E4F3AF /* PreferencesController.m */; }; @@ -264,6 +263,7 @@ B650987109366CA2003AF1BF /* szx.icns in Resources */ = {isa = PBXBuildFile; fileRef = B650987009366CA2003AF1BF /* szx.icns */; }; B6825549091817F30014B5EE /* divide.c in Sources */ = {isa = PBXBuildFile; fileRef = B6825547091817F30014B5EE /* divide.c */; }; B682554A091817F30014B5EE /* divide.h in Headers */ = {isa = PBXBuildFile; fileRef = B6825548091817F30014B5EE /* divide.h */; }; + B6A6F0960B3C108C000B88E9 /* coreaudiosound.c in Sources */ = {isa = PBXBuildFile; fileRef = B6A6F0950B3C108C000B88E9 /* coreaudiosound.c */; }; B6CE7F400B2830A300EB65B3 /* cocoadisplay.c in Sources */ = {isa = PBXBuildFile; fileRef = B6CE7F3A0B2830A300EB65B3 /* cocoadisplay.c */; }; B6CE7F410B2830A300EB65B3 /* cocoadisplay.h in Headers */ = {isa = PBXBuildFile; fileRef = B6CE7F3B0B2830A300EB65B3 /* cocoadisplay.h */; }; B6CE7F420B2830A300EB65B3 /* cocoajoystick.c in Sources */ = {isa = PBXBuildFile; fileRef = B6CE7F3C0B2830A300EB65B3 /* cocoajoystick.c */; }; @@ -448,6 +448,7 @@ B68CB2C503DD920300A804BA /* debugger.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = debugger.h; path = ../debugger/debugger.h; sourceTree = "<group>"; }; B68CB2C603DD920300A804BA /* disassemble.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = disassemble.c; path = ../debugger/disassemble.c; sourceTree = "<group>"; }; B68CB2CC03DD923C00A804BA /* memory.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = memory.c; sourceTree = "<group>"; }; + B6A6F0950B3C108C000B88E9 /* coreaudiosound.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = coreaudiosound.c; path = sound/coreaudiosound.c; sourceTree = "<group>"; }; B6A7F0E904C9A11D001025EB /* NumberFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NumberFormatter.h; sourceTree = "<group>"; }; B6A7F0EA04C9A11D001025EB /* NumberFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NumberFormatter.m; sourceTree = "<group>"; }; B6AA8A3C03D2FC1C00FED55D /* trdos.rom */ = {isa = PBXFileReference; lastKnownFileType = file; name = trdos.rom; path = ../roms/trdos.rom; sourceTree = SOURCE_ROOT; }; @@ -517,7 +518,6 @@ B6F048160952B5EC006D8005 /* snp.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = snp.icns; path = resources/snp.icns; sourceTree = SOURCE_ROOT; }; B6F048170952B5EC006D8005 /* sp.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = sp.icns; path = resources/sp.icns; sourceTree = SOURCE_ROOT; }; B6F0481A0952B5FD006D8005 /* zxs.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = zxs.icns; path = resources/zxs.icns; sourceTree = SOURCE_ROOT; }; - B6F06092078FB36500CD5D95 /* sdlsound.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = sdlsound.c; path = ../sound/sdlsound.c; sourceTree = SOURCE_ROOT; }; B6F060A5078FB55400CD5D95 /* ts2068.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = ts2068.c; path = ../machines/ts2068.c; sourceTree = SOURCE_ROOT; }; B6F060AB078FB63A00CD5D95 /* tc2068.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = tc2068.h; path = ../machines/tc2068.h; sourceTree = SOURCE_ROOT; }; B6F06100078FC2C900CD5D95 /* sfifo.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = sfifo.c; path = ../sound/sfifo.c; sourceTree = SOURCE_ROOT; }; @@ -819,9 +819,9 @@ B678E3E20608FAA600678A33 /* sound */ = { isa = PBXGroup; children = ( + B6A6F0950B3C108C000B88E9 /* coreaudiosound.c */, B6F06100078FC2C900CD5D95 /* sfifo.c */, B6F06101078FC2C900CD5D95 /* sfifo.h */, - B6F06092078FB36500CD5D95 /* sdlsound.c */, ); name = sound; sourceTree = "<group>"; @@ -1418,7 +1418,6 @@ B61F468509121DF100C8096C /* kempmouse.c in Sources */, B61F468609121DF100C8096C /* if1.c in Sources */, B61F468709121DF100C8096C /* RollbackController.m in Sources */, - B61F468809121DF100C8096C /* sdlsound.c in Sources */, B61F468909121DF100C8096C /* ts2068.c in Sources */, B61F468A09121DF100C8096C /* sfifo.c in Sources */, B61F468B09121DF100C8096C /* PreferencesController.m in Sources */, @@ -1442,6 +1441,7 @@ B6CE7F520B283A0700EB65B3 /* main.mm in Sources */, B6CE7FCE0B28FBD600EB65B3 /* DisplayOpenGLView.m in Sources */, B6E0252C0B38AFE500E23A0F /* keysyms.m in Sources */, + B6A6F0960B3C108C000B88E9 /* coreaudiosound.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; Modified: branches/fusegl/fuse/fusepb/config.h =================================================================== --- branches/fusegl/fuse/fusepb/config.h 2006-12-20 08:57:32 UTC (rev 259) +++ branches/fusegl/fuse/fusepb/config.h 2006-12-23 01:32:26 UTC (rev 260) @@ -63,6 +63,9 @@ /* Defined if Xlib UI in use */ /* #undef UI_X */ +/* Defined if we're going to be using CoreAudio */ +#define USE_COREAUDIO 1 + /* Defined if we're using hardware joysticks */ #define USE_JOYSTICK 1 Modified: branches/fusegl/fuse/sound/Makefile.am =================================================================== --- branches/fusegl/fuse/sound/Makefile.am 2006-12-20 08:57:32 UTC (rev 259) +++ branches/fusegl/fuse/sound/Makefile.am 2006-12-23 01:32:26 UTC (rev 260) @@ -30,6 +30,7 @@ libsound_a_SOURCES = dxsound.c \ aosound.c \ + coreaudiosound.c \ hpsound.c \ nullsound.c \ osssound.c \ Added: branches/fusegl/fuse/sound/coreaudiosound.c =================================================================== --- branches/fusegl/fuse/sound/coreaudiosound.c (rev 0) +++ branches/fusegl/fuse/sound/coreaudiosound.c 2006-12-23 01:32:26 UTC (rev 260) @@ -0,0 +1,275 @@ +/* coreaudiosound.c: Mac OS X CoreAudio sound I/O + Copyright (c) 2006 Fredrick Meunier + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include <config.h> + +#include "lowlevel.h" + +#ifdef SOUND_COREAUDIO + +#include <errno.h> +#include <unistd.h> +#include <CoreAudio/AudioHardware.h> +#include <AudioUnit/AudioUnit.h> + +#include "event.h" +#include "sfifo.h" +#include "sound.h" +#include "ui/ui.h" + +sfifo_t sound_fifo; + +static +OSStatus coreaudiowrite( void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData ); + +/* info about the format used for writing to output unit */ +static AudioStreamBasicDescription deviceFormat; + +/* converts from Fuse format (signed 16 bit ints) to CoreAudio format (floats) + */ +static AudioUnit gOutputUnit; + +int +sound_lowlevel_init( const char *dev, int *freqptr, int *stereoptr ) +{ + OSStatus err = kAudioHardwareNoError; + UInt32 count; + AudioDeviceID device = kAudioDeviceUnknown; /* the default device */ + UInt32 deviceBufferSize; /* bufferSize returned by + kAudioDevicePropertyBufferSize */ + int error; + + /* get the default output device for the HAL */ + count = sizeof( device ); + err = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice, + &count, (void *)&device ); + if ( err != kAudioHardwareNoError ) { + ui_error( UI_ERROR_ERROR, + "get kAudioHardwarePropertyDefaultOutputDevice error %ld", + err ); + return 1; + } + + /* get the buffersize that the default device uses for IO */ + count = sizeof( deviceBufferSize ); + err = AudioDeviceGetProperty( device, 0, false, kAudioDevicePropertyBufferSize, + &count, &deviceBufferSize ); + if( err != kAudioHardwareNoError ) { + ui_error( UI_ERROR_ERROR, "get kAudioDevicePropertyBufferSize error %ld", + err ); + return 1; + } + + /* get a description of the data format used by the default device */ + count = sizeof( deviceFormat ); + err = AudioDeviceGetProperty( device, 0, false, + kAudioDevicePropertyStreamFormat, &count, + &deviceFormat ); + if( err != kAudioHardwareNoError ) { + ui_error( UI_ERROR_ERROR, + "get kAudioDevicePropertyStreamFormat error %ld", err ); + return 1; + } + + *freqptr = deviceFormat.mSampleRate; + + deviceFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger +#ifdef WORDS_BIGENDIAN + | kLinearPCMFormatFlagIsBigEndian +#endif /* #ifdef WORDS_BIGENDIAN */ + | kLinearPCMFormatFlagIsPacked + | kAudioFormatFlagIsNonInterleaved; + deviceFormat.mBytesPerPacket = 2; + deviceFormat.mFramesPerPacket = 1; + deviceFormat.mBytesPerFrame = 2; + deviceFormat.mBitsPerChannel = 16; + deviceFormat.mChannelsPerFrame = *stereoptr ? 2 : 1; + + /* Open the default output unit */ + ComponentDescription desc; + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_DefaultOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + Component comp = FindNextComponent( NULL, &desc ); + if( comp == NULL ) { + ui_error( UI_ERROR_ERROR, "FindNextComponent" ); + return 1; + } + + err = OpenAComponent( comp, &gOutputUnit ); + if( comp == NULL ) { + ui_error( UI_ERROR_ERROR, "OpenAComponent=%ld", err ); + return 1; + } + + /* Set up a callback function to generate output to the output unit */ + AURenderCallbackStruct input; + input.inputProc = coreaudiowrite; + input.inputProcRefCon = NULL; + + err = AudioUnitSetProperty( gOutputUnit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &input, + sizeof( input ) ); + if( err ) { + ui_error( UI_ERROR_ERROR, "AudioUnitSetProperty-CB=%ld", err ); + return 1; + } + + err = AudioUnitSetProperty( gOutputUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &deviceFormat, + sizeof( AudioStreamBasicDescription ) ); + if( err ) { + ui_error( UI_ERROR_ERROR, "AudioUnitSetProperty-SF=%4.4s, %ld", (char*)&err, err ); + return 1; + } + + err = AudioUnitInitialize( gOutputUnit ); + if( err ) { + ui_error( UI_ERROR_ERROR, "AudioUnitInitialize=%ld", err ); + return 1; + } + + if( ( error = sfifo_init( &sound_fifo, 2 * deviceFormat.mChannelsPerFrame + * deviceBufferSize + 1 ) ) ) { + ui_error( UI_ERROR_ERROR, "Problem initialising sound fifo: %s", + strerror ( error ) ); + return 1; + } + + /* Start the rendering + The DefaultOutputUnit will do any format conversions to the format of the + default device */ + err = AudioOutputUnitStart( gOutputUnit ); + if( err ) { + ui_error( UI_ERROR_ERROR, "AudioOutputUnitStart=%ld", err ); + return 1; + } + + return 0; +} + +void +sound_lowlevel_end( void ) +{ + OSStatus err; + + verify_noerr( AudioOutputUnitStop( gOutputUnit ) ); + + err = AudioUnitUninitialize( gOutputUnit ); + if( err ) { + printf( "AudioUnitUninitialize=%ld", err ); + } + + CloseComponent( gOutputUnit ); + + sfifo_flush( &sound_fifo ); + sfifo_close( &sound_fifo ); +} + +/* Copy data to fifo */ +void +sound_lowlevel_frame( libspectrum_signed_word *data, int len ) +{ + int i = 0; + + /* Convert to bytes */ + libspectrum_signed_byte* bytes = (libspectrum_signed_byte*)data; + len <<= 1; + + while( len ) { + if( ( i = sfifo_write( &sound_fifo, bytes, len ) ) < 0 ) { + break; + } else if( !i ) { + usleep( 10000 ); + } + bytes += i; + len -= i; + } + if( i < 0 ) { + ui_error( UI_ERROR_ERROR, "Couldn't write sound fifo: %s", + strerror( i ) ); + } +} + +/* This is the audio processing callback. */ +OSStatus coreaudiowrite( void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData ) +{ + int f; + int len = deviceFormat.mBytesPerFrame * inNumberFrames; + + uint8_t* out_l = ioData->mBuffers[0].mData; + uint8_t* out_r = deviceFormat.mChannelsPerFrame > 1 ? + ioData->mBuffers[1].mData : 0; + + if( out_r ) { + /* Deinterleave the left and right stereo channels into their approptiate + buffers */ + while( sfifo_used( &sound_fifo ) && len ) { + f = sfifo_read( &sound_fifo, out_l, deviceFormat.mBytesPerFrame ); + out_l += deviceFormat.mBytesPerFrame; + f = sfifo_read( &sound_fifo, out_r, deviceFormat.mBytesPerFrame ); + out_r += deviceFormat.mBytesPerFrame; + len -= deviceFormat.mBytesPerFrame; + } + + /* If we ran out of sound, make do with silence :( */ + if( len ) { + for( f=0; f<len; f++ ) { + *out_l++ = 0; + *out_r++ = 0; + } + } + } else { + /* Read input_size bytes from fifo into sound stream */ + while( ( f = sfifo_read( &sound_fifo, out_l, len ) ) > 0 ) { + out_l += f; + len -= f; + } + + /* If we ran out of sound, make do with silence :( */ + if( f < 0 ) { + for( f=0; f<len; f++ ) { + *out_l++ = 0; + } + } + } + + return noErr; +} + +#endif /* #ifdef SOUND_COREAUDIO */ Modified: branches/fusegl/fuse/sound/lowlevel.h =================================================================== --- branches/fusegl/fuse/sound/lowlevel.h 2006-12-20 08:57:32 UTC (rev 259) +++ branches/fusegl/fuse/sound/lowlevel.h 2006-12-23 01:32:26 UTC (rev 260) @@ -68,6 +68,11 @@ #define HAVE_SOUND #define SOUND_DX +#elif defined USE_COREAUDIO /* #if defined UI_SDL */ + +#define HAVE_SOUND +#define SOUND_COREAUDIO + #endif /* #if defined UI_SDL */ #endif /* #ifndef FUSE_SOUND_LOWLEVEL_H */ Modified: branches/fusegl/fuse/sound/sdlsound.c =================================================================== --- branches/fusegl/fuse/sound/sdlsound.c 2006-12-20 08:57:32 UTC (rev 259) +++ branches/fusegl/fuse/sound/sdlsound.c 2006-12-23 01:32:26 UTC (rev 260) @@ -150,6 +150,7 @@ SDL_LockAudio(); SDL_CloseAudio(); SDL_QuitSubSystem( SDL_INIT_AUDIO ); + sfifo_flush( &sound_fifo ); sfifo_close( &sound_fifo ); } Modified: branches/fusegl/fuse/sound/sfifo.c =================================================================== --- branches/fusegl/fuse/sound/sfifo.c 2006-12-20 08:57:32 UTC (rev 259) +++ branches/fusegl/fuse/sound/sfifo.c 2006-12-23 01:32:26 UTC (rev 260) @@ -18,7 +18,7 @@ #include "lowlevel.h" -#ifdef SOUND_SDL +#if defined SOUND_SDL || defined SOUND_COREAUDIO #ifdef __KERNEL__ # include <linux/string.h> Modified: branches/fusegl/fuse/timer.c =================================================================== --- branches/fusegl/fuse/timer.c 2006-12-20 08:57:32 UTC (rev 259) +++ branches/fusegl/fuse/timer.c 2006-12-23 01:32:26 UTC (rev 260) @@ -228,7 +228,7 @@ return event_remove_type( EVENT_TYPE_TIMER ); } -#ifdef UI_SDL +#if defined UI_SDL || defined USE_COREAUDIO /* Callback-style sound based timer */ #include "sound/sfifo.h" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |