Remove STL dependency, enable all ABI's.

We were only using a very few STL functions (min, max, and iostream for
debug logging). This patch gets rid of those dependencies (implementing
the needed functions in synth.h), and turns on the "all" ABI target, so
that it works with all native architectures supported by the NDK.
bklimt
Raph Levien 13 years ago
parent 9b3f8d4734
commit 84a156abdb
  1. 3
      android/jni/Application.mk
  2. 16
      cpp/src/dx7note.cc
  3. 3
      cpp/src/env.cc
  4. 21
      cpp/src/fm_core.cc
  5. 3
      cpp/src/fm_op_kernel.cc
  6. 3
      cpp/src/freqlut.cc
  7. 7
      cpp/src/ringbuffer.cc
  8. 2
      cpp/src/sawtooth.cc
  9. 2
      cpp/src/sin.cc
  10. 10
      cpp/src/synth.h
  11. 20
      cpp/src/synth_unit.cc

@ -1,3 +1,2 @@
APP_STL := stlport_static APP_ABI := all
APP_ABI := armeabi-v7a

@ -14,7 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
#ifdef VERBOSE
#include <iostream> #include <iostream>
#endif
#include <math.h> #include <math.h>
#include "synth.h" #include "synth.h"
#include "freqlut.h" #include "freqlut.h"
@ -66,14 +68,14 @@ const uint8_t velocity_data[64] = {
// See "velocity" section of notes. Returns velocity delta in microsteps. // See "velocity" section of notes. Returns velocity delta in microsteps.
int ScaleVelocity(int velocity, int sensitivity) { int ScaleVelocity(int velocity, int sensitivity) {
int clamped_vel = std::max(0, std::min(127, velocity)); int clamped_vel = max(0, min(127, velocity));
int vel_value = velocity_data[clamped_vel >> 1] - 239; int vel_value = velocity_data[clamped_vel >> 1] - 239;
int scaled_vel = ((sensitivity * vel_value + 7) >> 3) << 4; int scaled_vel = ((sensitivity * vel_value + 7) >> 3) << 4;
return scaled_vel; return scaled_vel;
} }
int ScaleRate(int midinote, int sensitivity) { int ScaleRate(int midinote, int sensitivity) {
int x = std::min(31, std::max(0, midinote / 3 - 7)); int x = min(31, max(0, midinote / 3 - 7));
int qratedelta = (sensitivity * x) >> 3; int qratedelta = (sensitivity * x) >> 3;
#ifdef SUPER_PRECISE #ifdef SUPER_PRECISE
int rem = x & 7; int rem = x & 7;
@ -99,7 +101,7 @@ int ScaleCurve(int group, int depth, int curve) {
} else { } else {
// exponential // exponential
int n_scale_data = sizeof(exp_scale_data); int n_scale_data = sizeof(exp_scale_data);
int raw_exp = exp_scale_data[std::min(group, n_scale_data - 1)]; int raw_exp = exp_scale_data[min(group, n_scale_data - 1)];
scale = (raw_exp * depth * 329) >> 15; scale = (raw_exp * depth * 329) >> 15;
} }
if (curve < 2) { if (curve < 2) {
@ -129,17 +131,21 @@ Dx7Note::Dx7Note(const char patch[128], int midinote, int velocity) {
levels[i] = patch[off + 4 + i]; levels[i] = patch[off + 4 + i];
} }
int outlevel = patch[off + 14]; int outlevel = patch[off + 14];
#ifdef VERBOSE
for (int j = 8; j < 12; j++) { for (int j = 8; j < 12; j++) {
cout << (int)patch[off + j] << " "; cout << (int)patch[off + j] << " ";
} }
#endif
int level_scaling = ScaleLevel(midinote, patch[off + 8], patch[off + 9], 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] & 3, patch[off + 11] >> 2);
outlevel += level_scaling; outlevel += level_scaling;
outlevel = std::min(99, outlevel); outlevel = min(99, outlevel);
#ifdef VERBOSE
cout << op << ": " << level_scaling << " " << outlevel << endl; cout << op << ": " << level_scaling << " " << outlevel << endl;
#endif
outlevel = outlevel << 5; outlevel = outlevel << 5;
outlevel += ScaleVelocity(velocity, patch[off + 13] >> 2); outlevel += ScaleVelocity(velocity, patch[off + 13] >> 2);
outlevel = std::max(0, outlevel); outlevel = max(0, outlevel);
int rate_scaling = ScaleRate(midinote, patch[off + 12] & 7); int rate_scaling = ScaleRate(midinote, patch[off + 12] & 7);
env_[op].init(rates, levels, outlevel, rate_scaling); env_[op].init(rates, levels, outlevel, rate_scaling);

@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
#include <iostream>
#include "synth.h" #include "synth.h"
#include "env.h" #include "env.h"
@ -92,7 +91,7 @@ void Env::advance(int newix) {
// rate // rate
int qrate = (rates_[ix_] * 41) >> 6; int qrate = (rates_[ix_] * 41) >> 6;
qrate += rate_scaling_; qrate += rate_scaling_;
qrate = std::min(qrate, 63); qrate = min(qrate, 63);
inc_ = (4 + (qrate & 3)) << (2 + LG_N + (qrate >> 2)); inc_ = (4 + (qrate & 3)) << (2 + LG_N + (qrate >> 2));
} }
} }

@ -1,4 +1,23 @@
/*
* 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.
*/
#ifdef VERBOSE
#include <iostream> #include <iostream>
#endif
#include "synth.h" #include "synth.h"
#include "fm_op_kernel.h" #include "fm_op_kernel.h"
#include "fm_core.h" #include "fm_core.h"
@ -68,6 +87,7 @@ int n_out(const FmAlgorithm &alg) {
} }
void FmCore::dump() { void FmCore::dump() {
#ifdef VERBOSE
for (int i = 0; i < 32; i++) { for (int i = 0; i < 32; i++) {
cout << (i + 1) << ":"; cout << (i + 1) << ":";
const FmAlgorithm &alg = algorithms[i]; const FmAlgorithm &alg = algorithms[i];
@ -84,6 +104,7 @@ void FmCore::dump() {
cout << " " << n_out(alg); cout << " " << n_out(alg);
cout << endl; cout << endl;
} }
#endif
} }
void FmCore::compute(int32_t *output, FmOpParams *params, int algorithm, void FmCore::compute(int32_t *output, FmOpParams *params, int algorithm,

@ -15,9 +15,6 @@
*/ */
#include <math.h> #include <math.h>
#include <iostream>
using namespace std;
#include "synth.h" #include "synth.h"

@ -19,12 +19,9 @@
// The LUT is just a global, and we'll need the init function to be called before // The LUT is just a global, and we'll need the init function to be called before
// use. // use.
#include <iostream> // for debugging
#include <stdint.h> #include <stdint.h>
#include <math.h> #include <math.h>
using namespace std;
#include "freqlut.h" #include "freqlut.h"
#define LG_N_SAMPLES 10 #define LG_N_SAMPLES 10

@ -16,7 +16,6 @@
#include <time.h> #include <time.h>
#include <string.h> #include <string.h>
#include <algorithm>
#include "synth.h" #include "synth.h"
#include "ringbuffer.h" #include "ringbuffer.h"
@ -33,7 +32,7 @@ int RingBuffer::BytesAvailable() {
int RingBuffer::Read(int size, uint8_t *bytes) { int RingBuffer::Read(int size, uint8_t *bytes) {
int rd_ix = rd_ix_; int rd_ix = rd_ix_;
SynthMemoryBarrier(); // read barrier, make sure data is committed before ix SynthMemoryBarrier(); // read barrier, make sure data is committed before ix
int fragment_size = std::min(size, kBufSize - rd_ix); int fragment_size = min(size, kBufSize - rd_ix);
memcpy(bytes, buf_ + rd_ix, fragment_size); memcpy(bytes, buf_ + rd_ix, fragment_size);
if (size > fragment_size) { if (size > fragment_size) {
memcpy(bytes + fragment_size, buf_, size - fragment_size); memcpy(bytes + fragment_size, buf_, size - fragment_size);
@ -55,8 +54,8 @@ int RingBuffer::Write(const uint8_t *bytes, int size) {
sleepTime.tv_nsec = 1000000; sleepTime.tv_nsec = 1000000;
nanosleep(&sleepTime, NULL); nanosleep(&sleepTime, NULL);
} else { } else {
int wr_size = std::min(remaining, space_available); int wr_size = min(remaining, space_available);
int fragment_size = std::min(wr_size, kBufSize - wr_ix); int fragment_size = min(wr_size, kBufSize - wr_ix);
memcpy(buf_ + wr_ix, bytes, fragment_size); memcpy(buf_ + wr_ix, bytes, fragment_size);
if (wr_size > fragment_size) { if (wr_size > fragment_size) {
memcpy(buf_, bytes + fragment_size, wr_size - fragment_size); memcpy(buf_, bytes + fragment_size, wr_size - fragment_size);

@ -15,8 +15,6 @@
*/ */
#include <math.h> #include <math.h>
#include <iostream>
using namespace std;
#include "module.h" #include "module.h"
#include "sawtooth.h" #include "sawtooth.h"

@ -15,8 +15,6 @@
*/ */
#include <math.h> #include <math.h>
#include <iostream>
using namespace std;
#include "sin.h" #include "sin.h"

@ -40,4 +40,14 @@
#define SynthMemoryBarrier() #define SynthMemoryBarrier()
#endif #endif
template<typename T>
inline static T min(const T& a, const T& b) {
return a < b ? a : b;
}
template<typename T>
inline static T max(const T& a, const T& b) {
return a > b ? a : b;
}
#endif // __SYNTH_H #endif // __SYNTH_H

@ -14,7 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
#ifdef VERBOSE
#include <iostream> #include <iostream>
#endif
#include <string.h>
#include "synth.h" #include "synth.h"
#include "synth_unit.h" #include "synth_unit.h"
@ -37,7 +41,7 @@ SynthUnit::SynthUnit(RingBuffer *ring_buffer) {
active_note_[note].dx7_note = NULL; active_note_[note].dx7_note = NULL;
} }
input_buffer_index_ = 0; input_buffer_index_ = 0;
std::memcpy(patch_data_, epiano, sizeof(epiano)); memcpy(patch_data_, epiano, sizeof(epiano));
current_patch_ = 0; current_patch_ = 0;
current_note_ = 0; current_note_ = 0;
} }
@ -48,7 +52,7 @@ SynthUnit::SynthUnit(RingBuffer *ring_buffer) {
// optimizing for simplicity of implementation. // optimizing for simplicity of implementation.
void SynthUnit::TransferInput() { void SynthUnit::TransferInput() {
size_t bytes_available = ring_buffer_->BytesAvailable(); size_t bytes_available = ring_buffer_->BytesAvailable();
int bytes_to_read = std::min(bytes_available, int bytes_to_read = min(bytes_available,
sizeof(input_buffer_) - input_buffer_index_); sizeof(input_buffer_) - input_buffer_index_);
if (bytes_to_read > 0) { if (bytes_to_read > 0) {
ring_buffer_->Read(bytes_to_read, input_buffer_ + input_buffer_index_); ring_buffer_->Read(bytes_to_read, input_buffer_ + input_buffer_index_);
@ -58,7 +62,7 @@ void SynthUnit::TransferInput() {
void SynthUnit::ConsumeInput(int n_input_bytes) { void SynthUnit::ConsumeInput(int n_input_bytes) {
if (n_input_bytes < input_buffer_index_) { if (n_input_bytes < input_buffer_index_) {
std::memmove(input_buffer_, input_buffer_ + n_input_bytes, memmove(input_buffer_, input_buffer_ + n_input_bytes,
input_buffer_index_ - n_input_bytes); input_buffer_index_ - n_input_bytes);
} }
input_buffer_index_ -= n_input_bytes; input_buffer_index_ -= n_input_bytes;
@ -97,12 +101,14 @@ int SynthUnit::ProcessMidiMessage(const uint8_t *buf, int buf_size) {
if (buf_size >= 2) { if (buf_size >= 2) {
// program change // program change
int program_number = buf[1]; int program_number = buf[1];
current_patch_ = std::min(program_number, 31); current_patch_ = min(program_number, 31);
char name[11]; char name[11];
std::memcpy(name, patch_data_ + 128 * current_patch_ + 118, 10); memcpy(name, patch_data_ + 128 * current_patch_ + 118, 10);
name[10] = 0; name[10] = 0;
#ifdef VERBOSE
std::cout << "Loaded patch " << current_patch_ << ": " << name << "\r"; std::cout << "Loaded patch " << current_patch_ << ": " << name << "\r";
std::cout.flush(); std::cout.flush();
#endif
return 2; return 2;
} }
return 0; return 0;
@ -112,7 +118,7 @@ int SynthUnit::ProcessMidiMessage(const uint8_t *buf, int buf_size) {
buf[4] == 0x20 && buf[5] == 0x00) { buf[4] == 0x20 && buf[5] == 0x00) {
if (buf_size >= 4104) { if (buf_size >= 4104) {
// TODO: check checksum? // TODO: check checksum?
std::memcpy(patch_data_, buf + 6, 4096); memcpy(patch_data_, buf + 6, 4096);
return 4104; return 4104;
} }
return 0; return 0;
@ -120,8 +126,10 @@ int SynthUnit::ProcessMidiMessage(const uint8_t *buf, int buf_size) {
} }
// TODO: more robust handling // TODO: more robust handling
#ifdef VERBOSE
std::cout << "Unknown message " << std::hex << (int)cmd << std::cout << "Unknown message " << std::hex << (int)cmd <<
", skipping " << std::dec << buf_size << " bytes" << std::endl; ", skipping " << std::dec << buf_size << " bytes" << std::endl;
#endif
return buf_size; return buf_size;
} }

Loading…
Cancel
Save