/* * Copyright 2012 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "SynthMain.h" #include #include #include #import #import #import "synth.h" #import "module.h" #import "freqlut.h" #import "sin.h" #import "sawtooth.h" using namespace ::std; OSStatus audiocallback(void *data, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { //cout << "callback!" << inNumberFrames << endl; SynthUnit *synth_unit = (SynthUnit *)data; SInt16 *buffer = (SInt16 *)ioData->mBuffers[0].mData; synth_unit->GetSamples(inNumberFrames, buffer); return noErr; } // Set up audio playback for Mac OSStatus SynthMain::setupplayback(SynthUnit *synth_unit) { Component component; ComponentDescription description; OSStatus err = noErr; AURenderCallbackStruct callback; description.componentType = kAudioUnitType_Output; description.componentSubType = kAudioUnitSubType_HALOutput; description.componentManufacturer = kAudioUnitManufacturer_Apple; description.componentFlags = 0; description.componentFlagsMask = 0; if (component = FindNextComponent(NULL, &description)) { err = OpenAComponent(component, &audioUnit_); if (err != noErr) return err; } UInt32 param = 0; err = AudioUnitSetProperty(audioUnit_, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, ¶m, sizeof(param)); if (err != noErr) return err; param = 1; err = AudioUnitSetProperty(audioUnit_, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, ¶m, sizeof(param)); if (err != noErr) return err; AudioDeviceID deviceId = kAudioObjectUnknown; UInt32 deviceIdSize = sizeof(deviceId); AudioObjectPropertyAddress propertyAddress = { kAudioHardwarePropertyDefaultOutputDevice, // mSelector kAudioObjectPropertyScopeGlobal, // mScope kAudioObjectPropertyElementMaster // mElement }; err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &deviceIdSize, &deviceId); if (err != noErr) return err; err = AudioUnitSetProperty(audioUnit_, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(deviceId)); if (err != noErr) return err; callback.inputProc = audiocallback; callback.inputProcRefCon = synth_unit; err = AudioUnitSetProperty(audioUnit_, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callback, sizeof(callback)); if (err != noErr) return err; AudioStreamBasicDescription deviceFormat; deviceFormat.mChannelsPerFrame = 1; deviceFormat.mSampleRate = 44100.0; deviceFormat.mFormatID = kAudioFormatLinearPCM; deviceFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; deviceFormat.mBytesPerFrame = 2; deviceFormat.mBitsPerChannel = deviceFormat.mBytesPerFrame * 8; deviceFormat.mFramesPerPacket = 1; deviceFormat.mBytesPerPacket = deviceFormat.mBytesPerFrame; err = AudioUnitSetProperty(audioUnit_, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &deviceFormat, sizeof(deviceFormat)); if (err != noErr) return err; err = AudioUnitInitialize(audioUnit_); if (err != noErr) return err; } OSStatus SynthMain::startplayback() { return AudioOutputUnitStart(audioUnit_); } OSStatus SynthMain::stopplayback() { return AudioOutputUnitStop(audioUnit_); } int SynthMain::Load(const char *filename) { uint8_t syx_data[4104]; ifstream fp_in; fp_in.open(filename, ifstream::in); if (fp_in.fail()) { std::cerr << "error opening file" << std::endl; return 1; } fp_in.read((char *)syx_data, 4104); if (fp_in.fail()) { std::cerr << "error reading file" << std::endl; return 1; } ring_buffer_.Write(syx_data, 4104); #if 0 const uint8_t *data = syx_data + 6 + 128 * patch_num; for (int i = 0; i < 6; i++) { for (int j = 0; j < 17; j++) { if (j == 4 || j == 8) std::cout << " |"; std::cout << " " << (int)data[i * 17 + j]; } std::cout << std::endl; } for (int j = 102; j < 118; j++) { if (j == 106 || j == 110) std::cout << " |"; std::cout << " " << (int)data[j]; } std::cout << std::endl; #endif } int SynthMain::SynthInit() { double sample_rate = 44100.0; Freqlut::init(sample_rate); Sawtooth::init(sample_rate); Sin::init(); synth_unit_ = new SynthUnit(&ring_buffer_); if (true) { const char *fn = "/Users/raph/dx7/ROM1A.SYX"; Load(fn); } OSStatus err = setupplayback(synth_unit_); if (err != noErr) { cout << err << endl; return 1; } CFStringRef usbname = CFSTR("MPK mini"); // CFStringRef usbname = CFST("KeyRig 49"); midi_in_mac_.Init(usbname, &ring_buffer_); startplayback(); return 0; } int SynthMain::SynthDone() { midi_in_mac_.Done(); stopplayback(); delete synth_unit_; return 0; }