From 42823955287b1d13dd0ddb81c4e40597057bd75d Mon Sep 17 00:00:00 2001 From: Stefanos Kornilios Mitsis Poiitidis Date: Mon, 28 Sep 2015 14:59:42 +0200 Subject: [PATCH] apple: Add primitive core audio support Also made the project xcode 7 friendly --- core/oslib/audiobackend_coreaudio.cpp | 142 ++++++++++++++++++ core/oslib/audiobackend_coreaudio.h | 5 + core/oslib/audiostream.cpp | 4 + .../reicast-ios.xcodeproj/project.pbxproj | 12 ++ .../emulator-osx/emulator-osx/EmuGLView.swift | 8 +- .../reicast-osx.xcodeproj/project.pbxproj | 15 ++ 6 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 core/oslib/audiobackend_coreaudio.cpp create mode 100644 core/oslib/audiobackend_coreaudio.h diff --git a/core/oslib/audiobackend_coreaudio.cpp b/core/oslib/audiobackend_coreaudio.cpp new file mode 100644 index 000000000..d2bfb9383 --- /dev/null +++ b/core/oslib/audiobackend_coreaudio.cpp @@ -0,0 +1,142 @@ +/* + Simple Core Audio backend for osx (and maybe ios?) + Based off various audio core samples and dolphin's code + + This is part of the Reicast project, please consult the + LICENSE file for licensing & related information + + This could do with some locking logic to avoid + race conditions, and some variable length buffer + logic to support chunk sizes other than 512 bytes + + It does work on my macmini though + */ + +#include "oslib/audiobackend_coreaudio.h" + +#if HOST_OS == OS_DARWIN + +//#include +#include + +AudioUnit audioUnit; + +u8 samples_temp[1024 * 4]; + +volatile int samples_ptr = 0; + +OSStatus coreaudio_callback(void* ctx, AudioUnitRenderActionFlags* flags, const AudioTimeStamp* ts, + UInt32 bus, UInt32 frames, AudioBufferList* abl) +{ + verify(frames <= 1024); + + u8* src = samples_temp; + + for (int i = 0; i < abl->mNumberBuffers; i++) { + memcpy(abl->mBuffers[i].mData, src, abl->mBuffers[i].mDataByteSize); + src += abl->mBuffers[i].mDataByteSize; + } + + samples_ptr -= frames * 2 * 2; + + if (samples_ptr < 0) + samples_ptr = 0; + + return noErr; +} + +// We're making these functions static - there's no need to pollute the global namespace +static void coreaudio_init() +{ + OSStatus err; + AURenderCallbackStruct callback_struct; + AudioStreamBasicDescription format; + AudioComponentDescription desc; + AudioComponent component; + + desc.componentType = kAudioUnitType_Output; +#if !defined(TARGET_IPHONE) + desc.componentSubType = kAudioUnitSubType_DefaultOutput; +#else + desc.componentSubType = kAudioUnitSubType_RemoteIO; +#endif + //desc.componentSubType = kAudioUnitSubType_GenericOutput; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + component = AudioComponentFindNext(nullptr, &desc); + + verify(component != nullptr); + + err = AudioComponentInstanceNew(component, &audioUnit); + verify(err == noErr); + + FillOutASBDForLPCM(format, 44100, + 2, 16, 16, false, false, false); + err = AudioUnitSetProperty(audioUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, 0, &format, + sizeof(AudioStreamBasicDescription)); + verify(err == noErr); + + callback_struct.inputProc = coreaudio_callback; + callback_struct.inputProcRefCon = 0; + err = AudioUnitSetProperty(audioUnit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, 0, &callback_struct, + sizeof callback_struct); + verify(err == noErr); + + /* + err = AudioUnitSetParameter(audioUnit, + kHALOutputParam_Volume, + kAudioUnitParameterFlag_Output, 0, + 1, 0); + verify(err == noErr); + + */ + + err = AudioUnitInitialize(audioUnit); + + verify(err == noErr); + + err = AudioOutputUnitStart(audioUnit); + + verify(err == noErr); +} + +static u32 coreaudio_push(void* frame, u32 samples, bool wait) +{ + /* Yeah, right */ + while (samples_ptr != 0 && wait) ; + + if (samples_ptr == 0) { + memcpy(&samples_temp[samples_ptr], frame, samples * 4); + samples_ptr += samples * 4; + } + + return 1; +} + +static void coreaudio_term() +{ + OSStatus err; + + err = AudioOutputUnitStop(audioUnit); + verify(err == noErr); + + err = AudioUnitUninitialize(audioUnit); + verify(err == noErr); + + err = AudioComponentInstanceDispose(audioUnit); + verify(err == noErr); +} + +audiobackend_t audiobackend_coreaudio = { + "coreaudio", // Slug + "Core Audio", // Name + &coreaudio_init, + &coreaudio_push, + &coreaudio_term +}; +#endif diff --git a/core/oslib/audiobackend_coreaudio.h b/core/oslib/audiobackend_coreaudio.h new file mode 100644 index 000000000..8f3172317 --- /dev/null +++ b/core/oslib/audiobackend_coreaudio.h @@ -0,0 +1,5 @@ +#pragma once +#include "oslib/audiostream.h" + +extern audiobackend_t audiobackend_coreaudio; + diff --git a/core/oslib/audiostream.cpp b/core/oslib/audiostream.cpp index c8f8e639c..63c816274 100644 --- a/core/oslib/audiostream.cpp +++ b/core/oslib/audiostream.cpp @@ -7,6 +7,7 @@ #include "oslib/audiobackend_alsa.h" #include "oslib/audiobackend_oss.h" #include "oslib/audiobackend_pulseaudio.h" +#include "oslib/audiobackend_coreaudio.h" struct SoundFrame { s16 l;s16 r; }; #define SAMPLE_COUNT 512 @@ -85,6 +86,9 @@ void RegisterAllAudioBackends() { #if USE_PULSEAUDIO RegisterAudioBackend(&audiobackend_pulseaudio); #endif + #if HOST_OS == OS_DARWIN + RegisterAudioBackend(&audiobackend_coreaudio); + #endif audiobackends_registered = true; } diff --git a/shell/apple/emulator-ios/reicast-ios.xcodeproj/project.pbxproj b/shell/apple/emulator-ios/reicast-ios.xcodeproj/project.pbxproj index f95058d05..816fb7705 100644 --- a/shell/apple/emulator-ios/reicast-ios.xcodeproj/project.pbxproj +++ b/shell/apple/emulator-ios/reicast-ios.xcodeproj/project.pbxproj @@ -237,6 +237,8 @@ 9C7A3B4E18C806E00070BB5F /* stdclass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9C7A3A9918C806E00070BB5F /* stdclass.cpp */; }; 9C7A3B5918C81A4F0070BB5F /* SWRevealViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C7A3B5818C81A4F0070BB5F /* SWRevealViewController.m */; }; 9C7A3BC418C84EA10070BB5F /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9C7A3BC318C84EA10070BB5F /* MainStoryboard.storyboard */; }; + EBDF37561BB96E1B001191B5 /* audiobackend_coreaudio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EBDF37541BB96E1B001191B5 /* audiobackend_coreaudio.cpp */; settings = {ASSET_TAGS = (); }; }; + EBDF375A1BB96ECD001191B5 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDF37591BB96ECD001191B5 /* AudioToolbox.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -635,6 +637,10 @@ 9C7A3B5718C81A4F0070BB5F /* SWRevealViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWRevealViewController.h; sourceTree = ""; }; 9C7A3B5818C81A4F0070BB5F /* SWRevealViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWRevealViewController.m; sourceTree = ""; }; 9C7A3BC318C84EA10070BB5F /* MainStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = MainStoryboard.storyboard; sourceTree = ""; }; + EBDF37541BB96E1B001191B5 /* audiobackend_coreaudio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audiobackend_coreaudio.cpp; sourceTree = ""; }; + EBDF37551BB96E1B001191B5 /* audiobackend_coreaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audiobackend_coreaudio.h; sourceTree = ""; }; + EBDF37571BB96E75001191B5 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; }; + EBDF37591BB96ECD001191B5 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -642,6 +648,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EBDF375A1BB96ECD001191B5 /* AudioToolbox.framework in Frameworks */, 87D92F4E1B7A1B5700D8FD9E /* GameController.framework in Frameworks */, 87C4AA561A4414070048DBF4 /* AssetsLibrary.framework in Frameworks */, 87C4AA541A440BEB0048DBF4 /* libz.dylib in Frameworks */, @@ -681,6 +688,8 @@ 8497BCC31A41BFBA00EFB9ED /* oslib */ = { isa = PBXGroup; children = ( + EBDF37541BB96E1B001191B5 /* audiobackend_coreaudio.cpp */, + EBDF37551BB96E1B001191B5 /* audiobackend_coreaudio.h */, 877652B61B6157BD00437F10 /* audiobackend_alsa.cpp */, 877652B71B6157BD00437F10 /* audiobackend_alsa.h */, 877652B81B6157BD00437F10 /* audiobackend_android.h */, @@ -753,6 +762,8 @@ 87078A8518A47FE90034C7A0 /* Frameworks */ = { isa = PBXGroup; children = ( + EBDF37591BB96ECD001191B5 /* AudioToolbox.framework */, + EBDF37571BB96E75001191B5 /* AudioUnit.framework */, 87D92F4D1B7A1B5700D8FD9E /* GameController.framework */, 87C4AA551A4414070048DBF4 /* AssetsLibrary.framework */, 87C4AA531A440BEB0048DBF4 /* libz.dylib */, @@ -1642,6 +1653,7 @@ 84967C901B8F492C005F1140 /* filter_neon.S in Sources */, 876AA3771B818A4000617242 /* ini.cpp in Sources */, 84967C9B1B8F492C005F1140 /* pngset.c in Sources */, + EBDF37561BB96E1B001191B5 /* audiobackend_coreaudio.cpp in Sources */, 9C7A3B3618C806E00070BB5F /* chd.cpp in Sources */, 9C7A3B2118C806E00070BB5F /* sh4_fpu.cpp in Sources */, 9C7A3B3218C806E00070BB5F /* sh4_opcode_list.cpp in Sources */, diff --git a/shell/apple/emulator-osx/emulator-osx/EmuGLView.swift b/shell/apple/emulator-osx/emulator-osx/EmuGLView.swift index 5877938bd..320baa974 100644 --- a/shell/apple/emulator-osx/emulator-osx/EmuGLView.swift +++ b/shell/apple/emulator-osx/emulator-osx/EmuGLView.swift @@ -24,11 +24,11 @@ class EmuGLView: NSOpenGLView { //glClearColor(0.65f, 0.65f, 0.65f, 1.0f); //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - openGLContext.makeCurrentContext() + openGLContext!.makeCurrentContext() while !emu_single_frame(Int32(dirtyRect.width), Int32(dirtyRect.height)) { } - openGLContext.flushBuffer() + openGLContext!.flushBuffer() } override func awakeFromNib() { @@ -49,12 +49,12 @@ class EmuGLView: NSOpenGLView { let pf = NSOpenGLPixelFormat(attributes:attrs) - let context = NSOpenGLContext(format: pf, shareContext: nil); + let context = NSOpenGLContext(format: pf!, shareContext: nil); self.pixelFormat = pf; self.openGLContext = context; - openGLContext.makeCurrentContext() + openGLContext!.makeCurrentContext() emu_gles_init(); } diff --git a/shell/apple/emulator-osx/reicast-osx.xcodeproj/project.pbxproj b/shell/apple/emulator-osx/reicast-osx.xcodeproj/project.pbxproj index 153d7aa6c..818f3c750 100644 --- a/shell/apple/emulator-osx/reicast-osx.xcodeproj/project.pbxproj +++ b/shell/apple/emulator-osx/reicast-osx.xcodeproj/project.pbxproj @@ -192,6 +192,9 @@ 84B7BF7F1B72720200F9733F /* stdclass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B7BEA71B72720200F9733F /* stdclass.cpp */; }; 84B7BF831B727AD700F9733F /* osx-main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84B7BF821B727AD700F9733F /* osx-main.mm */; }; 84B7BF861B72871600F9733F /* EmuGLView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B7BF851B72871600F9733F /* EmuGLView.swift */; }; + EBDF374F1BB96581001191B5 /* audiobackend_coreaudio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EBDF374D1BB96581001191B5 /* audiobackend_coreaudio.cpp */; settings = {ASSET_TAGS = (); }; }; + EBDF37511BB969EE001191B5 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDF37501BB969EE001191B5 /* CoreAudio.framework */; }; + EBDF37531BB969F8001191B5 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBDF37521BB969F8001191B5 /* AudioUnit.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -536,6 +539,10 @@ 84B7BF821B727AD700F9733F /* osx-main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "osx-main.mm"; sourceTree = ""; }; 84B7BF841B72821900F9733F /* emulator-osx-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "emulator-osx-Bridging-Header.h"; sourceTree = ""; }; 84B7BF851B72871600F9733F /* EmuGLView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmuGLView.swift; sourceTree = ""; }; + EBDF374D1BB96581001191B5 /* audiobackend_coreaudio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audiobackend_coreaudio.cpp; sourceTree = ""; }; + EBDF374E1BB96581001191B5 /* audiobackend_coreaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audiobackend_coreaudio.h; sourceTree = ""; }; + EBDF37501BB969EE001191B5 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; }; + EBDF37521BB969F8001191B5 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -543,6 +550,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EBDF37531BB969F8001191B5 /* AudioUnit.framework in Frameworks */, + EBDF37511BB969EE001191B5 /* CoreAudio.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -569,6 +578,8 @@ 84A388AA1B1CDD3E000166C0 = { isa = PBXGroup; children = ( + EBDF37521BB969F8001191B5 /* AudioUnit.framework */, + EBDF37501BB969EE001191B5 /* CoreAudio.framework */, 84B7BD111B7271CF00F9733F /* core */, 84A388B51B1CDD3E000166C0 /* reicast-osx */, 84A388C61B1CDD3F000166C0 /* reicast-osxTests */, @@ -1212,6 +1223,8 @@ 84B7BE791B72720200F9733F /* audiostream.cpp */, 84B7BE7A1B72720200F9733F /* audiostream.h */, 84B7BE7B1B72720200F9733F /* oslib.h */, + EBDF374D1BB96581001191B5 /* audiobackend_coreaudio.cpp */, + EBDF374E1BB96581001191B5 /* audiobackend_coreaudio.h */, ); name = oslib; path = ../../../core/oslib; @@ -1319,6 +1332,7 @@ 84A388AB1B1CDD3E000166C0 /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 0610; ORGANIZATIONNAME = reicast; TargetAttributes = { @@ -1401,6 +1415,7 @@ 84B7BF431B72720200F9733F /* decoder.cpp in Sources */, 84B7BEBB1B72720200F9733F /* elf64.cpp in Sources */, 84B7BF1B1B72720200F9733F /* inffast.c in Sources */, + EBDF374F1BB96581001191B5 /* audiobackend_coreaudio.cpp in Sources */, 84967CC31B8F49EE005F1140 /* pngmem.c in Sources */, 84B7BF581B72720200F9733F /* sh4_rom.cpp in Sources */, 84B7BF441B72720200F9733F /* driver.cpp in Sources */,