From 904ff23afcf00b0a83db6e6c6788f01c1d2d935d Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Sat, 9 Feb 2013 15:27:43 -0800 Subject: [PATCH] Explicit unpack of dx7 patches Parameter changes and the like should work with unpacked patches, so now we have an explicit patch unpack. In the future, the unpacking will move out of the Dx7Note constructor. --- cpp/src/SynthApp/SynthMain.mm | 4 +- cpp/src/SynthApp/midi_in_mac.cc | 24 ++++++++++++ cpp/src/core.xcodeproj/project.pbxproj | 10 ++++- cpp/src/dx7note.cc | 27 ++++++++------ cpp/src/patch.cc | 51 ++++++++++++++++++++++++++ cpp/src/patch.h | 22 +++++++++++ 6 files changed, 124 insertions(+), 14 deletions(-) create mode 100644 cpp/src/patch.cc create mode 100644 cpp/src/patch.h 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