Files
-
blinds / hardware_design / pcb / blinds_v60.brd
-
blinds / hardware_design / pcb / blinds_v60.sch
-
braids / hardware_design / pcb / braids_v50.brd
-
braids / hardware_design / pcb / braids_v50.sch
-
branches / hardware_design / pcb / branches_v40.brd
-
branches / hardware_design / pcb / branches_v40.sch
-
clouds / hardware_design / pcb / clouds_v30.brd
-
clouds / hardware_design / pcb / clouds_v30.sch
-
ears / hardware_design / panel / ears_panel_v30.brd
-
ears / hardware_design / panel / ears_panel_v30.sch
-
ears / hardware_design / pcb / ears_v40.brd
-
ears / hardware_design / pcb / ears_v40.sch
-
edges / hardware_design / pcb / edges_expander_v01.brd
-
edges / hardware_design / pcb / edges_expander_v01.sch
-
edges / hardware_design / pcb / edges_v20.brd
-
edges / hardware_design / pcb / edges_v20.sch
-
elements / hardware_design / pcb / elements_v02.brd
-
elements / hardware_design / pcb / elements_v02.sch
-
frames / hardware_design / pcb / frames_v03.brd
-
frames / hardware_design / pcb / frames_v03.sch
-
grids / hardware_design / pcb / grids_v02.brd
-
grids / hardware_design / pcb / grids_v02.sch
-
kinks / hardware_design / pcb / kinks_v41.brd
-
kinks / hardware_design / pcb / kinks_v41.sch
-
links / hardware_design / pcb / links_v40.brd
-
links / hardware_design / pcb / links_v40.sch
-
marbles / hardware_design / pcb / marbles_v70.brd
-
marbles / hardware_design / pcb / marbles_v70.sch
-
peaks / hardware_design / pcb / peaks_v30.brd
-
peaks / hardware_design / pcb / peaks_v30.sch
-
plaits / hardware_design / pcb / plaits_v50.brd
-
plaits / hardware_design / pcb / plaits_v50.sch
-
rings / hardware_design / pcb / rings_v30.brd
-
rings / hardware_design / pcb / rings_v30.sch
-
ripples / hardware_design / pcb / ripples_v40.brd
-
ripples / hardware_design / pcb / ripples_v40.sch
-
shades / hardware_design / pcb / shades_v30.brd
-
shades / hardware_design / pcb / shades_v30.sch
-
shelves / hardware_design / pcb / shelves_expander_v10.brd
-
shelves / hardware_design / pcb / shelves_expander_v10.sch
-
shelves / hardware_design / pcb / shelves_v05.brd
-
shelves / hardware_design / pcb / shelves_v05.sch
-
stages / hardware_design / pcb / stages_v70.brd
-
stages / hardware_design / pcb / stages_v70.sch
-
streams / hardware_design / pcb / streams_v02_bargraph.brd
-
streams / hardware_design / pcb / streams_v02_bargraph.sch
-
streams / hardware_design / pcb / streams_v05.brd
-
streams / hardware_design / pcb / streams_v05.sch
-
tides / hardware_design / pcb / tides_v40.brd
-
tides / hardware_design / pcb / tides_v40.sch
-
veils / hardware_design / pcb / veils_v40.brd
-
veils / hardware_design / pcb / veils_v40.sch
-
volts / hardware_design / pcb / volts_v01.brd
-
volts / hardware_design / pcb / volts_v01.sch
-
warps / hardware_design / pcb / warps_v30.brd
-
warps / hardware_design / pcb / warps_v30.sch
-
yarns / hardware_design / pcb / yarns_v03.brd
-
yarns / hardware_design / pcb / yarns_v03.sch
Last update 6 years 3 months
by
Olivier Gillet
Filesmarblestest | |
---|---|
.. | |
fixtures.h | |
makefile | |
marbles_test.cc | |
ramp_checker.h |
marbles_test.cc// Copyright 2015 Olivier Gillet. // // Author: Olivier Gillet (ol.gillet@gmail.com) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "marbles/cv_reader_channel.h" #include "marbles/note_filter.h" #include "marbles/ramp/ramp_divider.h" #include "marbles/ramp/ramp_extractor.h" #include "marbles/random/distributions.h" #include "marbles/random/output_channel.h" #include "marbles/random/random_generator.h" #include "marbles/random/random_sequence.h" #include "marbles/random/random_stream.h" #include "marbles/random/t_generator.h" #include "marbles/random/x_y_generator.h" #include "marbles/scale_recorder.h" #include "marbles/test/fixtures.h" #include "marbles/test/ramp_checker.h" #include "stmlib/test/wav_writer.h" #include "stmlib/utils/random.h" using namespace marbles; using namespace std; using namespace stmlib; void TestBetaDistribution() { // Plot result with: // import numpy // import pylab // data = numpy.loadtxt('marbles_histograms.txt') // n = 0 // for i in xrange(9): // for j in xrange(13): // pylab.subplot(9, 13, n + 1) // pylab.plot(data[(n * 101):((n + 1) * 101)]) // pylab.gca().get_xaxis().set_visible(False) // pylab.gca().get_yaxis().set_visible(False) // n += 1 // pylab.show() FILE* fp = fopen("marbles_histograms.txt", "w"); for (int i = 0; i < 9; ++i) { for (int j = 0; j < 13; ++j) { float bias = float(i) / 8.0f; float range = float(j) / 12.0f; vector<int> histogram(101); for (int n = 0; n < 1000000; ++n) { float value = BetaDistributionSample(Random::GetFloat(), range, bias); histogram[int(value * 100.0f)]++; } for (int n = 0; n < 101; ++n) { fprintf(fp, "%d\n", histogram[n]); } } } fclose(fp); } void TestQuantizer() { // Plot result with: // import numpy // import pylab // // data = numpy.loadtxt('marbles_quantizer.txt') // pylab.figure(figsize=(25,5)) // for i in xrange(9): // pylab.subplot(1, 9, i + 1) // indices = numpy.where(data[:, 0] == i)[0] // pylab.plot(data[indices, 1], data[indices, 2]) // pylab.show() FILE* fp = fopen("marbles_quantizer.txt", "w"); Quantizer q; Scale scale; scale.InitMajor(); q.Init(scale); for (int i = 0; i <= 8; ++i) { float amount = float(i) / 8.0f; for (int j = 0; j <= 4000; ++j) { float value = j / 1000.0f - 2.0f; fprintf(fp, "%d %f %f\n", i, value, q.Process(value, amount, false)); } } fclose(fp); } void TestQuantizerNoise() { // Plot result with: // import numpy // import pylab // // data = numpy.loadtxt('marbles_quantizer_hysteresis.txt') // pylab.plot(data) // pylab.show() FILE* fp = fopen("marbles_quantizer_hysteresis.txt", "w"); Quantizer q; Scale scale; scale.InitTenth(); q.Init(scale); for (int j = 0; j <= 4000; ++j) { float noise = (rand() % 500) / 250.0f - 1.0f; float tri = j / 2000.0f; if (tri >= 1.0f) tri = 2.0f - tri; float value = 1.0f * tri + noise * 1.0f / 60.0f; float result = q.Process(value, 0.18f, true); fprintf(fp, "%f %f\n", value, result); } fclose(fp); } void TestRampExtractorClockBug() { WavWriter wav_writer(2, ::kSampleRate, 20); wav_writer.Open("marbles_ramp_extractor_clock_bug.wav"); RandomGenerator random_generator; RandomStream random_stream; random_generator.Init(33); random_stream.Init(&random_generator); PulseGenerator pulse_generator; for (size_t i = 0; i < 700; ++i) { int t = (rand() % 8) + 796; pulse_generator.AddPulses(t, t >> 1, 1); } TGenerator generator; generator.Init(&random_stream, kSampleRate); generator.set_model(T_GENERATOR_MODEL_COMPLEMENTARY_BERNOULLI); generator.set_rate(0.0f); generator.set_pulse_width_mean(0.5f); generator.set_pulse_width_std(0.0f); generator.set_bias(0.5f); generator.set_jitter(0.0f); generator.set_deja_vu(0.0f); generator.set_length(8); generator.set_range(T_GENERATOR_RANGE_1X); MasterSlaveRampGenerator ms_ramp_generator; Ramps ramps = ms_ramp_generator.ramps(); float phase = 0.0f; for (size_t i = 0; i < ::kSampleRate * 10; i += kAudioBlockSize) { phase += 0.0001f; if (phase >= 1.0f) { phase -= 1.0f; } float tri = phase < 0.5f ? 2.0f * phase : 2.0f - 2.0f * phase; bool gate[kAudioBlockSize * 2]; GateFlags clock[kAudioBlockSize]; pulse_generator.Render(clock, kAudioBlockSize); generator.set_rate(tri * 24.0f - 12.0f); generator.Process( true, clock, ramps, gate, kAudioBlockSize); for (size_t j = 0; j < kAudioBlockSize; ++j) { float s[6]; s[0] = clock[j] ? 1.0f : 0.0f; s[1] = ramps.external[j]; wav_writer.Write(s, 2, 32767.0f); } } } void TestRampExtractorPause() { WavWriter wav_writer(6, ::kSampleRate, 10); wav_writer.Open("marbles_ramp_pause.wav"); RandomGenerator random_generator; RandomStream random_stream; random_generator.Init(33); random_stream.Init(&random_generator); TGenerator generator; generator.Init(&random_stream, kSampleRate); generator.set_model(T_GENERATOR_MODEL_COMPLEMENTARY_BERNOULLI); generator.set_rate(0.0f); generator.set_pulse_width_mean(0.0f); generator.set_pulse_width_std(0.0f); generator.set_bias(0.9f); generator.set_jitter(0.0f); generator.set_deja_vu(0.0f); generator.set_length(8); generator.set_range(T_GENERATOR_RANGE_0_25X); ClockGeneratorPatterns patterns(PAUSE_PATTERNS); MasterSlaveRampGenerator ms_ramp_generator; Ramps ramps = ms_ramp_generator.ramps(); for (size_t i = 0; i < ::kSampleRate * 10; i += kAudioBlockSize) { bool gate[kAudioBlockSize * 2]; patterns.Render(kAudioBlockSize); generator.Process( true, patterns.clock(), ramps, gate, kAudioBlockSize); for (size_t j = 0; j < kAudioBlockSize; ++j) { float s[6]; s[5] = s[0] = patterns.clock()[j] & GATE_FLAG_HIGH ? 0.8f : 0.0f; s[1] = ramps.external[j]; s[2] = ramps.master[j]; s[3] = ramps.slave[0][j]; s[4] = ramps.slave[1][j]; wav_writer.Write(s, 6, 32767.0f); } } } void TestRampDivider(PatternDifficulty difficulty, const char* file_name) { WavWriter wav_writer(4, ::kSampleRate, 10); wav_writer.Open(file_name); ClockGeneratorPatterns patterns(difficulty); RampExtractor ramp_extractor; RampDivider ramp_divider; RampDivider ramp_divider_double; RampDivider ramp_divider_half; ramp_extractor.Init(0.25f); ramp_divider.Init(); ramp_divider_double.Init(); ramp_divider_half.Init(); RampChecker ramp_checker[4]; Ratio r8x; r8x.p = 8; r8x.q = 1; Ratio r2x; r2x.p = 2; r2x.q = 1; Ratio half; half.p = 1; half.q = 2; Ratio one; one.p = 1; one.q = 1; for (size_t i = 0; i < ::kSampleRate * 10; i += kAudioBlockSize) { float ramp[kAudioBlockSize]; float divided_ramp[kAudioBlockSize]; float divided_ramp_double[kAudioBlockSize]; float divided_ramp_half[kAudioBlockSize]; // switch ((i / (kSampleRate / 4)) % 3) { // case 0: // ramp_divider.set_ratio(1, 2); // break; // case 1: // ramp_divider.set_ratio(4, 1); // break; // case 2: // ramp_divider.set_ratio(3, 2); // break; // } patterns.Render(kAudioBlockSize); ramp_extractor.Process(one, true, patterns.clock(), ramp, kAudioBlockSize); ramp_divider.Process(r8x, ramp, divided_ramp, kAudioBlockSize); ramp_divider_double.Process(r2x, divided_ramp, divided_ramp_double, kAudioBlockSize); ramp_divider_half.Process(half, divided_ramp, divided_ramp_half, kAudioBlockSize); for (size_t j = 0; j < kAudioBlockSize; ++j) { float s[4]; s[0] = ramp[j]; s[1] = divided_ramp[j]; s[2] = divided_ramp_double[j]; s[3] = divided_ramp_half[j]; wav_writer.Write(s, 4, 32767.0f); } ramp_checker[0].Check(ramp, kAudioBlockSize); ramp_checker[1].Check(divided_ramp, kAudioBlockSize); ramp_checker[2].Check(divided_ramp_double, kAudioBlockSize); ramp_checker[3].Check(divided_ramp_half, kAudioBlockSize); } } void TestOutputChannel() { WavWriter wav_writer(2, ::kSampleRate, 3); wav_writer.Open("marbles_random_voltage.wav"); RampExtractor ramp_extractor; RandomGenerator random_generator; RandomStream random_stream; RandomSequence random_sequence; OutputChannel output_channel; PulseGenerator pulse_generator; ramp_extractor.Init(0.25f); random_generator.Init(32); random_stream.Init(&random_generator); random_sequence.Init(&random_stream); output_channel.Init(); // Steady clock pulse_generator.AddPulses(400, 10, 250); pulse_generator.AddPulses(200, 10, 250); output_channel.set_register_mode(false); output_channel.set_steps(0.5f); output_channel.set_bias(0.5f); Ratio one; one.p = 1; one.q = 1; for (size_t i = 0; i < ::kSampleRate * 3; i += kAudioBlockSize) { GateFlags gate_flags[kAudioBlockSize]; float ramp[kAudioBlockSize]; float voltage[kAudioBlockSize]; pulse_generator.Render(gate_flags, kAudioBlockSize); ramp_extractor.Process(one, false, gate_flags, ramp, kAudioBlockSize); output_channel.set_spread(wav_writer.triangle(3)); output_channel.Process(&random_sequence, ramp, voltage, kAudioBlockSize, 1); for (size_t j = 0; j < kAudioBlockSize; ++j) voltage[j] *= 0.1f; wav_writer.Write(ramp, voltage, kAudioBlockSize); } } void TestXYGenerator() { WavWriter wav_writer(4, ::kSampleRate, 10); wav_writer.Open("marbles_xy.wav"); RandomGenerator random_generator; RandomStream random_stream; random_generator.Init(32); random_stream.Init(&random_generator); XYGenerator generator; generator.Init(&random_stream, ::kSampleRate); GroupSettings x_settings, y_settings; x_settings.control_mode = CONTROL_MODE_IDENTICAL; x_settings.voltage_range = VOLTAGE_RANGE_FULL; x_settings.register_mode = false; x_settings.register_value = 0.0f; x_settings.spread = 0.8f; x_settings.bias = 0.8f; x_settings.steps = 0.3f; x_settings.deja_vu = 0.0f; x_settings.length = 8; x_settings.ratio.p = 1; x_settings.ratio.q = 1; y_settings.control_mode = CONTROL_MODE_IDENTICAL; y_settings.voltage_range = VOLTAGE_RANGE_FULL; y_settings.register_mode = false; y_settings.register_value = 0.0f; y_settings.spread = 0.5f; y_settings.bias = 0.5f; y_settings.steps = 0.1f; y_settings.deja_vu = 0.0f; y_settings.length = 8; y_settings.ratio.p = 1; y_settings.ratio.q = 8; ClockGeneratorPatterns patterns(TRICKY_PATTERNS); MasterSlaveRampGenerator ms_ramp_generator; for (size_t i = 0; i < ::kSampleRate * 10; i += kAudioBlockSize) { patterns.Render(kAudioBlockSize); ms_ramp_generator.Process(patterns.clock(), kAudioBlockSize); float samples[kAudioBlockSize * 4]; generator.Process( CLOCK_SOURCE_INTERNAL_T1_T2_T3, x_settings, y_settings, patterns.clock(), ms_ramp_generator.ramps(), samples, kAudioBlockSize); wav_writer.Write(samples, kAudioBlockSize * 4, 3276.7f); } } void TestXYGeneratorASR() { WavWriter wav_writer(4, ::kSampleRate, 10); wav_writer.Open("marbles_xy_asr.wav"); RandomGenerator random_generator; RandomStream random_stream; random_generator.Init(32); random_stream.Init(&random_generator); XYGenerator generator; generator.Init(&random_stream, ::kSampleRate); GroupSettings x_settings, y_settings; x_settings.control_mode = CONTROL_MODE_IDENTICAL; x_settings.voltage_range = VOLTAGE_RANGE_FULL; x_settings.register_mode = false; x_settings.register_value = 0.0f; x_settings.spread = 0.2f; x_settings.bias = 0.7f; x_settings.steps = 0.5f; x_settings.deja_vu = 0.0f; x_settings.length = 8; x_settings.ratio.p = 1; x_settings.ratio.q = 1; y_settings.control_mode = CONTROL_MODE_IDENTICAL; y_settings.voltage_range = VOLTAGE_RANGE_FULL; y_settings.register_mode = false; y_settings.register_value = 0.0f; y_settings.spread = 0.5f; y_settings.bias = 0.5f; y_settings.steps = 0.1f; y_settings.deja_vu = 0.0f; y_settings.length = 8; y_settings.ratio.p = 1; y_settings.ratio.q = 8; ClockGeneratorPatterns patterns(TRICKY_PATTERNS); MasterSlaveRampGenerator ms_ramp_generator; for (size_t i = 0; i < ::kSampleRate * 10; i += kAudioBlockSize) { patterns.Render(kAudioBlockSize); ms_ramp_generator.Process(patterns.clock(), kAudioBlockSize); float samples[kAudioBlockSize * 4]; x_settings.register_mode = true; x_settings.register_value = wav_writer.triangle(1); generator.Process( CLOCK_SOURCE_EXTERNAL, x_settings, y_settings, patterns.clock(), ms_ramp_generator.ramps(), samples, kAudioBlockSize); wav_writer.Write(samples, kAudioBlockSize * 4, 3276.7f); } } void TestTGenerator() { WavWriter wav_writer(6, ::kSampleRate, 10); wav_writer.Open("marbles_t.wav"); RandomGenerator random_generator; RandomStream random_stream; random_generator.Init(33); random_stream.Init(&random_generator); TGenerator generator; generator.Init(&random_stream, kSampleRate); generator.set_model(T_GENERATOR_MODEL_COMPLEMENTARY_BERNOULLI); generator.set_rate(24.0f); generator.set_pulse_width_mean(0.0f); generator.set_pulse_width_std(0.0f); generator.set_bias(0.9f); generator.set_jitter(0.5f); generator.set_deja_vu(0.0f); generator.set_length(8); generator.set_range(T_GENERATOR_RANGE_4X); ClockGeneratorPatterns patterns(FRIENDLY_PATTERNS); MasterSlaveRampGenerator ms_ramp_generator; Ramps ramps = ms_ramp_generator.ramps(); RampChecker ramp_checker[4]; for (size_t i = 0; i < ::kSampleRate * 10; i += kAudioBlockSize) { bool gate[kAudioBlockSize * 2]; patterns.Render(kAudioBlockSize); generator.Process( true, patterns.clock(), ramps, gate, kAudioBlockSize); if (i >= kSampleRate * 5) { // generator.set_deja_vu(1.0f); // generator.set_jitter(0.5f); } for (size_t j = 0; j < kAudioBlockSize; ++j) { float s[6]; s[0] = ramps.external[j]; s[1] = ramps.master[j]; s[2] = ramps.slave[0][j]; s[3] = ramps.slave[1][j]; s[4] = gate[j * 2] ? 1.0f : 0.0f; s[5] = gate[j * 2 + 1] ? 1.0f : 0.0f; wav_writer.Write(s, 6, 32767.0f); } ramp_checker[0].Check(ramps.external, kAudioBlockSize); ramp_checker[1].Check(ramps.master, kAudioBlockSize); ramp_checker[2].Check(ramps.slave[0], kAudioBlockSize); ramp_checker[3].Check(ramps.slave[1], kAudioBlockSize); } } void TestTGeneratorSuperFastClock() { WavWriter wav_writer(6, ::kSampleRate, 10); wav_writer.Open("marbles_t_super_fast.wav"); RandomGenerator random_generator; RandomStream random_stream; random_generator.Init(33); random_stream.Init(&random_generator); TGenerator generator; generator.Init(&random_stream, kSampleRate); generator.set_model(T_GENERATOR_MODEL_COMPLEMENTARY_BERNOULLI); generator.set_rate(60.0f); generator.set_pulse_width_mean(0.0f); generator.set_pulse_width_std(0.0f); generator.set_bias(0.5f); generator.set_jitter(0.0f); generator.set_deja_vu(0.0f); generator.set_length(8); generator.set_range(T_GENERATOR_RANGE_4X); ClockGeneratorPatterns patterns(FAST_PATTERNS); MasterSlaveRampGenerator ms_ramp_generator; Ramps ramps = ms_ramp_generator.ramps(); for (size_t i = 0; i < ::kSampleRate * 10; i += kAudioBlockSize) { bool gate[kAudioBlockSize * 2]; patterns.Render(kAudioBlockSize); generator.Process( true, patterns.clock(), ramps, gate, kAudioBlockSize); for (size_t j = 0; j < kAudioBlockSize; ++j) { float s[6]; s[0] = ramps.external[j]; s[1] = ramps.master[j]; s[2] = ramps.slave[0][j]; s[3] = ramps.slave[1][j]; s[4] = gate[j * 2] ? 1.0f : 0.0f; s[5] = gate[j * 2 + 1] ? 1.0f : 0.0f; wav_writer.Write(s, 6, 32767.0f); } } } void TestTGeneratorRampIntegrity( bool internal_clock, float rate, TGeneratorModel model, float jitter) { printf("Testing ramp integrity for intclock = %d\trate = %04.3f\tmodel = %d\tjitter = %04.3f\n", internal_clock, rate, model, jitter); RandomGenerator random_generator; RandomStream random_stream; random_generator.Init(33); random_stream.Init(&random_generator); TGenerator generator; generator.Init(&random_stream, kSampleRate); generator.set_model(model); generator.set_rate(rate + 36.0f); generator.set_pulse_width_mean(0.0f); generator.set_pulse_width_std(0.0f); generator.set_bias(0.7f); generator.set_jitter(jitter); if (internal_clock) { generator.set_range(T_GENERATOR_RANGE_4X); } else { generator.set_range(T_GENERATOR_RANGE_1X); } ClockGeneratorPatterns patterns(FRIENDLY_PATTERNS); MasterSlaveRampGenerator ms_ramp_generator; Ramps ramps = ms_ramp_generator.ramps(); RampChecker ramp_checker[4]; for (size_t i = 0; i < ::kSampleRate * 10; i += kAudioBlockSize) { bool gate[kAudioBlockSize * 2]; patterns.Render(kAudioBlockSize); generator.Process( !internal_clock, patterns.clock(), ramps, gate, kAudioBlockSize); ramp_checker[0].Check(ramps.external, kAudioBlockSize); ramp_checker[1].Check(ramps.master, kAudioBlockSize); ramp_checker[2].Check(ramps.slave[0], kAudioBlockSize); ramp_checker[3].Check(ramps.slave[1], kAudioBlockSize); } } void TestTGeneratorRampIntegrity() { for (size_t clock_source = 0; clock_source < 2; ++clock_source) { for (size_t model = 0; model < 6; ++model) { for (size_t jitter = 0; jitter < 5; ++jitter) { for (size_t rate = 0; rate < 5; ++rate) { TestTGeneratorRampIntegrity( clock_source, float(rate) * 12.0f - 24.0f, TGeneratorModel(model), float(jitter) * 0.2f); } } } } } void TestScaleRecorder() { int prelude[] = { 0, 4, 7, 7, 12, 12, 16, 16, 7, 7, 12, 12, 16, 0, 0, 4, 16, 4, 7, 7, 12, 12, 16, 16, 7, 7, 12, 12, 16, 0, 0, 4, 16, 2, 9, 9, 14, 14, 17, 17, 9, 9, 14, 14, 17, 0, 0, 2, 17, 2, 9, 9, 14, 14, 17, 17, 9, 9, 14, 14, 17, -1, 0, 2, 17, 2, 7, 7, 14, 14, 17, 17, 7, 7, 14, 14, 17, -1, -1, 2, 17, 2, 7, 7, 14, 14, 17, 17, 7, 7, 14, 14, 17, -1, 0, 2, 17, 4, 7, 7, 12, 12, 16, 16, 7, 7, 12, 12, 16, 0, 0, 4, 16, 4, 7, 7, 12, 12, 16, 16, 7, 7, 12, 12, 16, 0, 0, 4, 16, 4, 9, 9, 16, 16, 21, 21, 9, 9, 16, 16, 21, 0, 0, 4, 21, 4, 9, 9, 16, 16, 21, 21, 9, 9, 16, 16, 21, 0, 0, 4, 21, 2, 6, 6, 9, 9, 14, 14, 6, 6, 9, 9, 14, 0, 0, 2, 14, 2, 6, 6, 9, 9, 14, 14, 6, 6, 9, 9, 14, -1, 0, 2, 14, 2, 7, 7, 14, 14, 19, 19, 7, 7, 14, 14, 19, -1, -1, 2, 19, 2, 7, 7, 14, 14, 19, 19, 7, 7, 14, 14, 19, -1, -1, 2, 19, 0, 4, 4, 7, 7, 12, 12, 4, 4, 7, 7, 12, -1, -1, 0, 12, 0, 4, 4, 7, 7, 12, 12, 4, 4, 7, 7, 12, -3, -1, 0, 12, 0, 4, 4, 7, 7, 12, 12, 4, 4, 7, 7, 12, -3, -3, 0, 12, 0, 4, 4, 7, 7, 12, 12, 4, 4, 7, 7, 12, -10, -3, 0, 12, -3, 2, 2, 6, 6, 12, 12, 2, 2, 6, 6, 12, -10, -10, -3, 12, -3, 2, 2, 6, 6, 12, 12, 2, 2, 6, 6, 12, -10, -5, -3, 12, -1, 2, 2, 7, 7, 11, 11, 2, 2, 7, 7, 11, -5, -5, -1, 11, -1, 2, 2, 7, 7, 11, 11, 2, 2, 7, 7, 11, -5, -5, -1, 11, -2, 4, 4, 7, 7, 13, 13, 4, 4, 7, 7, 13, -5, -5, -2, 13, -2, 4, 4, 7, 7, 13, 13, 4, 4, 7, 7, 13, -7, -5, -2, 13, -3, 2, 2, 9, 9, 14, 14, 2, 2, 9, 9, 14, -7, -7, -3, 14, -3, 2, 2, 9, 9, 14, 14, 2, 2, 9, 9, 14, -7, -7, -3, 14, -4, 2, 2, 5, 5, 11, 11, 2, 2, 5, 5, 11, -7, -7, -4, 11, -4, 2, 2, 5, 5, 11, 11, 2, 2, 5, 5, 11, -8, -7, -4, 11, -5, 0, 0, 7, 7, 12, 12, 0, 0, 7, 7, 12, -8, -8, -5, 12, -5, 0, 0, 7, 7, 12, 12, 0, 0, 7, 7, 12, -8, -8, -5, 12, -7, -3, -3, 0, 0, 5, 5, -3, -3, 0, 0, 5, -8, -8, -7, 5, -7, -3, -3, 0, 0, 5, 5, -3, -3, 0, 0, 5, -10, -8, -7, 5, -7, -3, -3, 0, 0, 5, 5, -3, -3, 0, 0, 5, -10, -10, -7, 5, -7, -3, -3, 0, 0, 5, 5, -3, -3, 0, 0, 5, -17, -10, -7, 5, -10, -5, -5, -1, -1, 5, 5, -5, -5, -1, -1, 5, -17, -17, -10, 5, -10, -5, -5, -1, -1, 5, 5, -5, -5, -1, -1, 5, -17, -12, -10, 5, -8, -5, -5, 0, 0, 4, 4, -5, -5, 0, 0, 4, -12, -12, -8, 4, -8, -5, -5, 0, 0, 4, 4, -5, -5, 0, 0, 4, -12, -12, -8, 4, -5, -2, -2, 0, 0, 4, 4, -2, -2, 0, 0, 4, -12, -12, -5, 4, -5, -2, -2, 0, 0, 4, 4, -2, -2, 0, 0, 4, -19, -12, -5, 4, -7, -3, -3, 0, 0, 4, 4, -3, -3, 0, 0, 4, -19, -19, -7, 4, -7, -3, -3, 0, 0, 4, 4, -3, -3, 0, 0, 4, -19, -18, -7, 4, -12, -3, -3, 0, 0, 3, 3, -3, -3, 0, 0, 3, -18, -18, -12, 3, -12, -3, -3, 0, 0, 3, 3, -3, -3, 0, 0, 3, -18, -16, -12, 3, -7, -1, -1, 0, 0, 2, 2, -1, -1, 0, 0, 2, -16, -16, -7, 2, -7, -1, -1, 0, 0, 2, 2, -1, -1, 0, 0, 2, -17, -16, -7, 2, -7, -5, -5, -1, -1, 2, 2, -5, -5, -1, -1, 2, -17, -17, -7, 2, -7, -5, -5, -1, -1, 2, 2, -5, -5, -1, -1, 2, -17, -17, -7, 2, -8, -5, -5, 0, 0, 4, 4, -5, -5, 0, 0, 4, -17, -17, -8, 4, -8, -5, -5, 0, 0, 4, 4, -5, -5, 0, 0, 4, -17, -17, -8, 4, -10, -5, -5, 0, 0, 5, 5, -5, -5, 0, 0, 5, -17, -17, -10, 5, -10, -5, -5, 0, 0, 5, 5, -5, -5, 0, 0, 5, -17, -17, -10, 5,-10, -5, -5, -1, -1, 5, 5, -5, -5, -1, -1, 5, -17, -17, -10, 5, -10, -5, -5,-1, -1, 5, 5, -5, -5, -1, -1, 5, -17, -17, -10, 5, -9, -3, -3, 0, 0, 6, 6, -3,-3, 0, 0, 6, -17, -17, -9, 6, -9, -3, -3, 0, 0, 6, 6, -3, -3, 0, 0, 6, -17,-17, -9, 6, -8, -5, -5, 0, 0, 7, 7, -5, -5, 0, 0, 7, -17, -17, -8, 7, -8, -5,-5, 0, 0, 7, 7, -5, -5, 0, 0, 7, -17, -17, -8, 7, -10, -5, -5, 0, 0, 5, 5, -5,-5, 0, 0, 5, -17, -17, -10, 5, -10, -5, -5, 0, 0, 5, 5, -5, -5, 0, 0, 5, -17,-17, -10, 5, -10, -5, -5, -1, -1, 5, 5, -5, -5, -1, -1, 5, -17, -17, -10, 5,-10, -5, -5, -1, -1, 5, 5, -5, -5, -1, -1, 5, -24, -17, -10, 5, -12, -5, -5,-2, -2, 4, 4, -5, -5, -2, -2, 4, -24, -24, -12, 4, -12, -5, -5, -2, -2, 4, 4,-5, -5, -2, -2, 4, -24, -24, -12, 4, -12, -7, -7, -3, -3, 0, 0, 5, 0, 5, -3, 0,-3, 0, -3, 0, -7, -3, -7, -3, -7, -3, -10, -7, -10, -7, -10, -7, -12, -10, -24,-24, -10, 7, 7, 11, 11, 14, 14, 17, 14, 17, 11, 14, 11, 14, 11, 14, 7, 11, 7,11, 2, 11, 2, 5, 4, 5, 2, 4, -10, 2, -24, -24, -12, 4, 7, 12, -24, -12, 4, 7, 12 }; ScaleRecorder recorder; recorder.Init(); for (size_t i = 0; i < sizeof(prelude) / sizeof(int); ++i) { float voltage = prelude[i] / 12.0f + Random::GetFloat() * 0.0001f; recorder.NewNote(voltage); recorder.UpdateVoltage(voltage); recorder.AcceptNote(); } Scale s; recorder.ExtractScale(&s); for (int i = 0; i < s.num_degrees; ++i) { printf("%f %d\n", s.degree[i].voltage, s.degree[i].weight); } } int main(void) { // Test distributions and value processors. // TestBetaDistribution(); // TestQuantizer(); // TestQuantizerNoise(); // Ramp tests. // TestRampExtractor(FRIENDLY_PATTERNS, "marbles_ramp_extractor_friendly.wav"); // TestRampExtractor(TRICKY_PATTERNS, "marbles_ramp_extractor_tricky.wav"); // TestRampExtractor(FAST_PATTERNS, "marbles_ramp_extractor_fast.wav"); // TestRampDivider(TRICKY_PATTERNS, "marbles_ramp_divider_tricky.wav"); // TestRampExtractorClockBug(); // TestRampExtractorPause(); // TestOutputChannel(); // TestXYGenerator(); // TestXYGeneratorASR(); // TestTGeneratorRampIntegrity(); TestTGenerator(); // TestScaleRecorder(); }