diff --git a/cpp/src/SynthApp/SynthMain.mm b/cpp/src/SynthApp/SynthMain.mm index d41e3d8..9eadd39 100644 --- a/cpp/src/SynthApp/SynthMain.mm +++ b/cpp/src/SynthApp/SynthMain.mm @@ -170,7 +170,9 @@ int SynthMain::SynthInit() { cout << err << endl; return 1; } - midi_in_mac_.Init(CFSTR("KeyRig 49"), &ring_buffer_); + CFStringRef usbname = CFSTR("MPK mini"); + // CFStringRef usbname = CFST("KeyRig 49"); + midi_in_mac_.Init(usbname, &ring_buffer_); startplayback(); return 0; } diff --git a/cpp/src/SynthApp/midi_in_mac.cc b/cpp/src/SynthApp/midi_in_mac.cc index ac5abf3..21cf5f6 100644 --- a/cpp/src/SynthApp/midi_in_mac.cc +++ b/cpp/src/SynthApp/midi_in_mac.cc @@ -17,9 +17,25 @@ #include #include "midi_in_mac.h" +#define DEBUG_MIDI_BYTES + +using std::cout; +using std::endl; + void MidiInMac::OnRead(const MIDIPacketList *pktlist) { const MIDIPacket *packet = &(pktlist->packet[0]); for (int i = 0; i < pktlist->numPackets; ++i) { +#if defined(DEBUG_MIDI_BYTES) + cout << "MIDI DATA:"; + cout.fill('0'); + for (size_t i = 0; i < packet->length; i++) { + cout << " "; + cout.width(2); + cout << std::hex << static_cast(packet->data[i]); + cout.width(); + } + cout << endl; +#endif ring_buffer_->Write(packet->data, packet->length); packet = MIDIPacketNext(packet); } @@ -44,6 +60,14 @@ bool MidiInMac::Init(CFStringRef name, RingBuffer *ring_buffer) { MIDIObjectGetProperties(device_ref, &midi_device_properties, true); CFStringRef dev_name = NULL; s = MIDIObjectGetStringProperty(device_ref, kMIDIPropertyName, &dev_name); +#if defined(DEBUG_USB_NAMES) + char buf[64]; + if (CFStringGetCString(dev_name, buf, sizeof(buf), kCFStringEncodingASCII)) { + std::cout << "midi name =" << buf << std::endl; + } else { + std::cout << "error converting" << std::endl; + } +#endif CFComparisonResult comparison = CFStringCompare(dev_name, name, 0); CFRelease(dev_name); if (comparison == kCFCompareEqualTo) { diff --git a/cpp/src/core.xcodeproj/project.pbxproj b/cpp/src/core.xcodeproj/project.pbxproj index fb2b048..e068dfe 100644 --- a/cpp/src/core.xcodeproj/project.pbxproj +++ b/cpp/src/core.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 45; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ @@ -17,6 +17,7 @@ 8D41064389CC8FD281956BF7 /* fm_op_kernel.cc in Sources */ = {isa = PBXBuildFile; fileRef = 509D811344DB98984FD6C126 /* fm_op_kernel.cc */; }; 908EAB1EE59231C41FD88BCD /* ringbuffer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 68FD17910F296961541A67E4 /* ringbuffer.cc */; }; A16F70FD02394895C6FA7326 /* synth_unit.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2082841A11DF6E62596265CF /* synth_unit.cc */; }; + AECC016D16C70F9300FBD4E4 /* patch.cc in Sources */ = {isa = PBXBuildFile; fileRef = AECC016C16C70F9300FBD4E4 /* patch.cc */; }; D5ECD09EBEB1684C00616248 /* resofilter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 97A5CBACD479212282D0BFD6 /* resofilter.cc */; }; /* End PBXBuildFile section */ @@ -30,6 +31,7 @@ 8B1FC9FF853D5C32F4771091 /* libcore.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libcore.a; sourceTree = BUILT_PRODUCTS_DIR; }; 97A5CBACD479212282D0BFD6 /* resofilter.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = resofilter.cc; sourceTree = ""; }; 9FF02D488CE6FD5017D7D81A /* freqlut.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = freqlut.cc; sourceTree = ""; }; + AECC016C16C70F9300FBD4E4 /* patch.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = patch.cc; sourceTree = ""; }; B73D485E55EBD9CD5950A375 /* env.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = env.cc; sourceTree = ""; }; BA00975977E2704F74104728 /* dx7note.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dx7note.cc; sourceTree = ""; }; D1D8B6FB01C9E7E2D99378F0 /* sin.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = sin.cc; sourceTree = ""; }; @@ -50,6 +52,7 @@ 1CE02724939AB46300B24440 = { isa = PBXGroup; children = ( + AECC016C16C70F9300FBD4E4 /* patch.cc */, 521E615727EAD5BFC2BFE8C3 /* Source */, ADABDC1FC75C07B5469F92DE /* Products */, 72A5A7469C1AF9FDDAB23BD1 /* Build */, @@ -119,7 +122,11 @@ }; buildConfigurationList = 2F684B8427DC8F5001D9A5B0 /* Build configuration list for PBXProject "core" */; compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; hasScannedForEncodings = 1; + knownRegions = ( + en, + ); mainGroup = 1CE02724939AB46300B24440; projectDirPath = ""; projectRoot = ""; @@ -145,6 +152,7 @@ 4FB7FFF436D333023EC91E2C /* sin.cc in Sources */, A16F70FD02394895C6FA7326 /* synth_unit.cc in Sources */, 80D3C6DC6F5236826B6AB404 /* test_ringbuffer.cc in Sources */, + AECC016D16C70F9300FBD4E4 /* patch.cc in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/cpp/src/dx7note.cc b/cpp/src/dx7note.cc index 7392cff..2cb4a0d 100644 --- a/cpp/src/dx7note.cc +++ b/cpp/src/dx7note.cc @@ -20,6 +20,7 @@ #include #include "synth.h" #include "freqlut.h" +#include "patch.h" #include "dx7note.h" using namespace std; @@ -121,46 +122,48 @@ int ScaleLevel(int midinote, int break_pt, int left_depth, int right_depth, } // Considering making this an init method... -Dx7Note::Dx7Note(const char patch[128], int midinote, int velocity) { +Dx7Note::Dx7Note(const char bulk[128], int midinote, int velocity) { + char patch[156]; + UnpackPatch(bulk, patch); // TODO: move this out, take unpacked patch for (int op = 0; op < 6; op++) { - int off = op * 17; + int off = op * 21; int rates[4]; int levels[4]; for (int i = 0; i < 4; i++) { rates[i] = patch[off + i]; levels[i] = patch[off + 4 + i]; } - int outlevel = patch[off + 14]; + int outlevel = patch[off + 16]; #ifdef VERBOSE for (int j = 8; j < 12; j++) { cout << (int)patch[off + j] << " "; } #endif int level_scaling = ScaleLevel(midinote, patch[off + 8], patch[off + 9], - patch[off + 10], patch[off + 11] & 3, patch[off + 11] >> 2); + patch[off + 10], patch[off + 11], patch[off + 12]); outlevel += level_scaling; outlevel = min(99, outlevel); #ifdef VERBOSE cout << op << ": " << level_scaling << " " << outlevel << endl; #endif outlevel = outlevel << 5; - outlevel += ScaleVelocity(velocity, patch[off + 13] >> 2); + outlevel += ScaleVelocity(velocity, patch[off + 15]); outlevel = max(0, outlevel); - int rate_scaling = ScaleRate(midinote, patch[off + 12] & 7); + int rate_scaling = ScaleRate(midinote, patch[off + 13]); env_[op].init(rates, levels, outlevel, rate_scaling); - int mode = patch[off + 15] & 1; - int coarse = patch[off + 15] >> 1; - int fine = patch[off + 16]; - int detune = (patch[off + 12] >> 3) - 7; + int mode = patch[off + 17]; + int coarse = patch[off + 18]; + int fine = patch[off + 19]; + int detune = patch[off + 20]; int32_t freq = osc_freq(midinote, mode, coarse, fine, detune); params_[op].freq = freq; // cout << op << " freq: " << freq << endl; params_[op].phase = 0; params_[op].gain[1] = 0; } - algorithm_ = patch[110]; - int feedback = patch[111] & 7; + algorithm_ = patch[134]; + int feedback = patch[135]; fb_shift_ = feedback != 0 ? 8 - feedback : 16; } diff --git a/cpp/src/patch.cc b/cpp/src/patch.cc new file mode 100644 index 0000000..b8ede4d --- /dev/null +++ b/cpp/src/patch.cc @@ -0,0 +1,51 @@ +/* + * Copyright 2013 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 + +#include "patch.h" + +void UnpackPatch(const char bulk[128], char patch[156]) { + for (int op = 0; op < 6; op++) { + // eg rate and level, brk pt, depth, scaling + memcpy(patch + op * 21, bulk + op * 17, 11); + char leftrightcurves = bulk[op * 17 + 11]; + patch[op * 21 + 11] = leftrightcurves & 3; + patch[op * 21 + 12] = (leftrightcurves >> 2) & 3; + char detune_rs = bulk[op * 17 + 12]; + patch[op * 21 + 13] = detune_rs & 7; + patch[op * 21 + 20] = detune_rs >> 3; + char kvs_ams = bulk[op * 17 + 13]; + patch[op * 21 + 14] = kvs_ams & 3; + patch[op * 21 + 15] = kvs_ams >> 2; + patch[op * 21 + 16] = bulk[op * 17 + 14]; // output level + char fcoarse_mode = bulk[op * 17 + 15]; + patch[op * 21 + 17] = fcoarse_mode & 1; + patch[op * 21 + 18] = fcoarse_mode >> 1; + patch[op * 21 + 19] = bulk[op * 17 + 16]; // fine freq + } + memcpy(patch + 126, bulk + 102, 9); // pitch env, algo + char oks_fb = bulk[111]; + patch[135] = oks_fb & 7; + patch[136] = oks_fb >> 3; + memcpy(patch + 137, bulk + 112, 4); // lfo + char lpms_lfw_lks = bulk[116]; + patch[141] = lpms_lfw_lks & 1; + patch[142] = (lpms_lfw_lks >> 1) & 7; + patch[143] = lpms_lfw_lks >> 4; + memcpy(patch + 144, bulk + 117, 11); // transpose, name + patch[155] = 0x3f; // operator on/off +} diff --git a/cpp/src/patch.h b/cpp/src/patch.h new file mode 100644 index 0000000..228163e --- /dev/null +++ b/cpp/src/patch.h @@ -0,0 +1,22 @@ +/* + * Copyright 2013 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. + */ + +#ifndef SYNTH_PATCH_H_ +#define SYNTH_PATCH_H_ + +void UnpackPatch(const char bulk[128], char patch[156]); + +#endif \ No newline at end of file