Repository: eh2k/squares-and-circles Branch: main Commit: 410eddc485f8 Files: 465 Total size: 4.4 MB Directory structure: gitextract_pmlbt8sa/ ├── .clangd ├── .github/ │ └── workflows/ │ └── build.yml ├── .gitignore ├── .gitmodules ├── README.md ├── app/ │ ├── SEQ/ │ │ └── patterns_303.h │ ├── index.json │ ├── squares-and-circles-loader.sha │ └── upload.py ├── doc/ │ ├── .conv.sh │ ├── .screenshots.py │ └── output-routing.xml ├── lib/ │ ├── .fetch_deps.py │ ├── MoogLadders/ │ │ ├── LICENSE │ │ ├── README.md │ │ └── src/ │ │ ├── Filters.h │ │ ├── HuovilainenModel.h │ │ ├── ImprovedModel.h │ │ ├── KrajeskiModel.h │ │ ├── LadderFilterBase.h │ │ ├── MicrotrackerModel.h │ │ ├── MusicDSPModel.h │ │ ├── NoiseGenerator.h │ │ ├── OberheimVariationModel.h │ │ ├── RKSimulationModel.h │ │ ├── SimplifiedModel.h │ │ ├── StilsonModel.h │ │ └── Util.h │ ├── SAM/ │ │ ├── README.md │ │ ├── ReciterTabs.h │ │ ├── RenderTabs.h │ │ ├── SamTabs.h │ │ ├── debug.c │ │ ├── debug.h │ │ ├── reciter.c │ │ ├── reciter.h │ │ ├── render.c │ │ ├── render.h │ │ ├── sam.c │ │ └── sam.h │ ├── bbd/ │ │ ├── LICENSE │ │ ├── README.md │ │ ├── bbd_filter.cc │ │ ├── bbd_filter.h │ │ ├── bbd_line.cc │ │ └── bbd_line.h │ ├── braids/ │ │ ├── README.md │ │ ├── analog_oscillator.cc │ │ ├── analog_oscillator.h │ │ ├── chords_stack.cc │ │ ├── digital_oscillator.cc │ │ ├── digital_oscillator.h │ │ ├── envelope.h │ │ ├── excitation.h │ │ ├── macro_oscillator.cc │ │ ├── macro_oscillator.h │ │ ├── parameter_interpolation.h │ │ ├── quantizer.cc │ │ ├── quantizer.h │ │ ├── quantizer_scales.h │ │ ├── resources.cc │ │ ├── resources.h │ │ ├── settings.cc │ │ ├── settings.h │ │ ├── svf.h │ │ └── vco_jitter_source.h │ ├── claps/ │ │ ├── cp808.h │ │ └── cp909.h │ ├── clouds/ │ │ └── dsp/ │ │ └── fx/ │ │ ├── diffuser.h │ │ ├── fx_engine.h │ │ ├── pitch_shifter.h │ │ └── reverb.h │ ├── drumsynth/ │ │ ├── drumsynth.cpp │ │ ├── drumsynth.h │ │ └── drumsynth_claps.h │ ├── faust/ │ │ ├── build.sh │ │ ├── djembe.dsp │ │ ├── djembe.dsp.h │ │ ├── rev_dattorro.dsp │ │ ├── rev_dattorro.dsp.h │ │ └── ui.hxx │ ├── fft/ │ │ ├── fft4g.c │ │ └── fft4g.h │ ├── fv1/ │ │ ├── README.md │ │ ├── factory.json │ │ └── spn/ │ │ ├── OEM1_4.spn │ │ └── dance_ir_h_l.spn │ ├── marbles/ │ │ ├── note_filter.h │ │ ├── ramp/ │ │ │ ├── ramp.h │ │ │ ├── ramp_divider.h │ │ │ ├── ramp_extractor.cc │ │ │ ├── ramp_extractor.h │ │ │ ├── ramp_generator.h │ │ │ └── slave_ramp.h │ │ ├── random/ │ │ │ ├── discrete_distribution_quantizer.cc │ │ │ ├── discrete_distribution_quantizer.h │ │ │ ├── distributions.h │ │ │ ├── lag_processor.cc │ │ │ ├── lag_processor.h │ │ │ ├── output_channel.cc │ │ │ ├── output_channel.h │ │ │ ├── quantizer.cc │ │ │ ├── quantizer.h │ │ │ ├── random_generator.h │ │ │ ├── random_sequence.h │ │ │ ├── random_stream.h │ │ │ ├── t_generator.cc │ │ │ ├── t_generator.h │ │ │ ├── x_y_generator.cc │ │ │ └── x_y_generator.h │ │ ├── resources.cc │ │ ├── resources.h │ │ └── scale_recorder.h │ ├── misc/ │ │ ├── Biquad.cpp │ │ ├── Biquad.h │ │ ├── analyze_fft.hxx │ │ ├── cubic_spline.hxx │ │ ├── dspinst.h │ │ ├── euclidean.h │ │ ├── nes_noise.hxx │ │ ├── noise.hxx │ │ └── patterns_303.h │ ├── msfa/ │ │ ├── aligned_buf.h │ │ ├── controllers.h │ │ ├── doc/ │ │ │ └── origin.url │ │ ├── dx7note.cc │ │ ├── dx7note.h │ │ ├── env.cc │ │ ├── env.h │ │ ├── exp2.cc │ │ ├── exp2.h │ │ ├── fm_core.cc │ │ ├── fm_core.h │ │ ├── fm_op_kernel.cc │ │ ├── fm_op_kernel.h │ │ ├── freqlut.cc │ │ ├── freqlut.h │ │ ├── lfo.cc │ │ ├── lfo.h │ │ ├── midinotes.h │ │ ├── module.h │ │ ├── patch.cc │ │ ├── patch.h │ │ ├── pitchenv.cc │ │ ├── pitchenv.h │ │ ├── porta.cc │ │ ├── porta.h │ │ ├── sin.cc │ │ ├── sin.h │ │ └── synth.h │ ├── open303/ │ │ └── src/ │ │ ├── GlobalDefinitions.h │ │ ├── GlobalFunctions.cpp │ │ ├── GlobalFunctions.h │ │ ├── rosic_AnalogEnvelope.cpp │ │ ├── rosic_AnalogEnvelope.h │ │ ├── rosic_BiquadFilter.cpp │ │ ├── rosic_BiquadFilter.h │ │ ├── rosic_BlendOscillator.cpp │ │ ├── rosic_BlendOscillator.h │ │ ├── rosic_DecayEnvelope.cpp │ │ ├── rosic_DecayEnvelope.h │ │ ├── rosic_EllipticQuarterBandFilter.cpp │ │ ├── rosic_EllipticQuarterBandFilter.h │ │ ├── rosic_FunctionTemplates.cpp │ │ ├── rosic_FunctionTemplates.h │ │ ├── rosic_LeakyIntegrator.cpp │ │ ├── rosic_LeakyIntegrator.h │ │ ├── rosic_MidiNoteEvent.cpp │ │ ├── rosic_MidiNoteEvent.h │ │ ├── rosic_NumberManipulations.cpp │ │ ├── rosic_NumberManipulations.h │ │ ├── rosic_OnePoleFilter.cpp │ │ ├── rosic_OnePoleFilter.h │ │ ├── rosic_Open303.cpp │ │ ├── rosic_Open303.h │ │ ├── rosic_RealFunctions.cpp │ │ ├── rosic_RealFunctions.h │ │ ├── rosic_TeeBeeFilter.cpp │ │ ├── rosic_TeeBeeFilter.h │ │ ├── sequencer/ │ │ │ ├── rosic_AcidPattern.cpp │ │ │ ├── rosic_AcidPattern.h │ │ │ ├── rosic_AcidSequencer.cpp │ │ │ └── rosic_AcidSequencer.h │ │ └── wavetable_gen/ │ │ ├── fft4g.h │ │ ├── rosic_Complex.cpp │ │ ├── rosic_Complex.h │ │ ├── rosic_FourierTransformerRadix2.cpp │ │ ├── rosic_FourierTransformerRadix2.h │ │ ├── rosic_MipMappedWaveTable.cpp │ │ └── rosic_MipMappedWaveTable.h │ ├── peaks/ │ │ ├── drums/ │ │ │ ├── bass_drum.cc │ │ │ ├── bass_drum.h │ │ │ ├── excitation.h │ │ │ ├── fm_drum.cc │ │ │ ├── fm_drum.h │ │ │ ├── high_hat.cc │ │ │ ├── high_hat.h │ │ │ ├── snare_drum.cc │ │ │ ├── snare_drum.h │ │ │ └── svf.h │ │ ├── gate_processor.h │ │ ├── modulations/ │ │ │ ├── bouncing_ball.h │ │ │ ├── lfo.cc │ │ │ ├── lfo.h │ │ │ ├── mini_sequencer.h │ │ │ ├── multistage_envelope.cc │ │ │ └── multistage_envelope.h │ │ ├── number_station/ │ │ │ ├── number_station.cc │ │ │ └── number_station.h │ │ ├── pulse_processor/ │ │ │ ├── pulse_randomizer.cc │ │ │ ├── pulse_randomizer.h │ │ │ ├── pulse_shaper.cc │ │ │ └── pulse_shaper.h │ │ ├── resources.cc │ │ └── resources.h │ ├── plaits/ │ │ ├── dsp/ │ │ │ ├── chords/ │ │ │ │ ├── chord_bank.cc │ │ │ │ └── chord_bank.h │ │ │ ├── downsampler/ │ │ │ │ └── 4x_downsampler.h │ │ │ ├── drums/ │ │ │ │ ├── analog_bass_drum.h │ │ │ │ ├── analog_snare_drum.h │ │ │ │ ├── hi_hat.h │ │ │ │ ├── synthetic_bass_drum.h │ │ │ │ └── synthetic_snare_drum.h │ │ │ ├── dsp.h │ │ │ ├── engine/ │ │ │ │ ├── additive_engine.cc │ │ │ │ ├── additive_engine.h │ │ │ │ ├── bass_drum_engine.cc │ │ │ │ ├── bass_drum_engine.h │ │ │ │ ├── chord_engine.cc │ │ │ │ ├── chord_engine.h │ │ │ │ ├── engine.h │ │ │ │ ├── fm_engine.cc │ │ │ │ ├── fm_engine.h │ │ │ │ ├── grain_engine.cc │ │ │ │ ├── grain_engine.h │ │ │ │ ├── hi_hat_engine.cc │ │ │ │ ├── hi_hat_engine.h │ │ │ │ ├── modal_engine.cc │ │ │ │ ├── modal_engine.h │ │ │ │ ├── noise_engine.cc │ │ │ │ ├── noise_engine.h │ │ │ │ ├── particle_engine.cc │ │ │ │ ├── particle_engine.h │ │ │ │ ├── snare_drum_engine.cc │ │ │ │ ├── snare_drum_engine.h │ │ │ │ ├── speech_engine.cc │ │ │ │ ├── speech_engine.h │ │ │ │ ├── string_engine.cc │ │ │ │ ├── string_engine.h │ │ │ │ ├── swarm_engine.cc │ │ │ │ ├── swarm_engine.h │ │ │ │ ├── virtual_analog_engine.cc │ │ │ │ ├── virtual_analog_engine.h │ │ │ │ ├── waveshaping_engine.cc │ │ │ │ ├── waveshaping_engine.h │ │ │ │ ├── wavetable_engine.cc │ │ │ │ └── wavetable_engine.h │ │ │ ├── engine2/ │ │ │ │ ├── arpeggiator.h │ │ │ │ ├── chiptune_engine.cc │ │ │ │ ├── chiptune_engine.h │ │ │ │ ├── phase_distortion_engine.cc │ │ │ │ ├── phase_distortion_engine.h │ │ │ │ ├── six_op_engine.cc │ │ │ │ ├── six_op_engine.h │ │ │ │ ├── string_machine_engine.cc │ │ │ │ ├── string_machine_engine.h │ │ │ │ ├── virtual_analog_vcf_engine.cc │ │ │ │ ├── virtual_analog_vcf_engine.h │ │ │ │ ├── wave_terrain_engine.cc │ │ │ │ └── wave_terrain_engine.h │ │ │ ├── envelope.h │ │ │ ├── fm/ │ │ │ │ ├── algorithms.cc │ │ │ │ ├── algorithms.h │ │ │ │ ├── dx_units.cc │ │ │ │ ├── dx_units.h │ │ │ │ ├── envelope.h │ │ │ │ ├── lfo.h │ │ │ │ ├── operator.h │ │ │ │ ├── patch.h │ │ │ │ └── voice.h │ │ │ ├── fx/ │ │ │ │ ├── diffuser.h │ │ │ │ ├── ensemble.h │ │ │ │ ├── fx_engine.h │ │ │ │ ├── low_pass_gate.h │ │ │ │ ├── overdrive.h │ │ │ │ └── sample_rate_reducer.h │ │ │ ├── noise/ │ │ │ │ ├── clocked_noise.h │ │ │ │ ├── dust.h │ │ │ │ ├── fractal_random_generator.h │ │ │ │ ├── particle.h │ │ │ │ └── smooth_random_generator.h │ │ │ ├── oscillator/ │ │ │ │ ├── formant_oscillator.h │ │ │ │ ├── grainlet_oscillator.h │ │ │ │ ├── harmonic_oscillator.h │ │ │ │ ├── nes_triangle_oscillator.h │ │ │ │ ├── oscillator.h │ │ │ │ ├── sine_oscillator.h │ │ │ │ ├── string_synth_oscillator.h │ │ │ │ ├── super_square_oscillator.h │ │ │ │ ├── variable_saw_oscillator.h │ │ │ │ ├── variable_shape_oscillator.h │ │ │ │ ├── vosim_oscillator.h │ │ │ │ ├── wavetable_oscillator.h │ │ │ │ └── z_oscillator.h │ │ │ ├── physical_modelling/ │ │ │ │ ├── delay_line.h │ │ │ │ ├── modal_voice.cc │ │ │ │ ├── modal_voice.h │ │ │ │ ├── resonator.cc │ │ │ │ ├── resonator.h │ │ │ │ ├── string.cc │ │ │ │ ├── string.h │ │ │ │ ├── string_voice.cc │ │ │ │ └── string_voice.h │ │ │ ├── speech/ │ │ │ │ ├── lpc_speech_synth.cc │ │ │ │ ├── lpc_speech_synth.h │ │ │ │ ├── lpc_speech_synth_controller.cc │ │ │ │ ├── lpc_speech_synth_controller.h │ │ │ │ ├── lpc_speech_synth_phonemes.cc │ │ │ │ ├── lpc_speech_synth_words.cc │ │ │ │ ├── lpc_speech_synth_words.h │ │ │ │ ├── naive_speech_synth.cc │ │ │ │ ├── naive_speech_synth.h │ │ │ │ ├── sam_speech_synth.cc │ │ │ │ └── sam_speech_synth.h │ │ │ ├── voice.cc │ │ │ └── voice.h │ │ ├── resources.cc │ │ └── resources.h │ ├── rings/ │ │ ├── dsp/ │ │ │ ├── dsp.h │ │ │ ├── fm_voice.cc │ │ │ ├── fm_voice.h │ │ │ ├── follower.h │ │ │ ├── fx/ │ │ │ │ ├── chorus.h │ │ │ │ ├── ensemble.h │ │ │ │ ├── fx_engine.h │ │ │ │ └── reverb.h │ │ │ ├── limiter.h │ │ │ ├── note_filter.h │ │ │ ├── onset_detector.h │ │ │ ├── part.cc │ │ │ ├── part.h │ │ │ ├── patch.h │ │ │ ├── performance_state.h │ │ │ ├── plucker.h │ │ │ ├── resonator.cc │ │ │ ├── resonator.h │ │ │ ├── string.cc │ │ │ ├── string.h │ │ │ ├── string_synth_envelope.h │ │ │ ├── string_synth_oscillator.h │ │ │ ├── string_synth_part.cc │ │ │ ├── string_synth_part.h │ │ │ ├── string_synth_voice.h │ │ │ └── strummer.h │ │ ├── resources.cc │ │ └── resources.h │ ├── soundpipe/ │ │ ├── revsc.c │ │ ├── revsc.h │ │ ├── soundpipe.c │ │ └── soundpipe.h │ ├── stmlib/ │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── README.md │ │ ├── algorithms/ │ │ │ ├── note_stack.h │ │ │ ├── pattern_predictor.h │ │ │ ├── tiny_map.h │ │ │ └── voice_allocator.h │ │ ├── dsp/ │ │ │ ├── atan.cc │ │ │ ├── atan.h │ │ │ ├── atan_approximations.py │ │ │ ├── cosine_oscillator.h │ │ │ ├── delay_line.h │ │ │ ├── dsp.h │ │ │ ├── filter.h │ │ │ ├── hysteresis_filter.h │ │ │ ├── hysteresis_quantizer.h │ │ │ ├── limiter.h │ │ │ ├── parameter_interpolator.h │ │ │ ├── polyblep.h │ │ │ ├── rsqrt.h │ │ │ ├── sample_rate_converter.h │ │ │ ├── units.cc │ │ │ └── units.h │ │ ├── makefile.inc │ │ ├── midi/ │ │ │ └── midi.h │ │ ├── stmlib.h │ │ └── utils/ │ │ ├── buffer_allocator.h │ │ ├── crc32.h │ │ ├── dsp.h │ │ ├── gate_flags.h │ │ ├── murmurhash3.h │ │ ├── random.cc │ │ ├── random.h │ │ ├── ring_buffer.h │ │ └── stream_buffer.h │ ├── streams/ │ │ ├── audio_cv_meter.h │ │ ├── compressor.cc │ │ ├── compressor.h │ │ ├── envelope.cc │ │ ├── envelope.h │ │ ├── filter_controller.h │ │ ├── follower.cc │ │ ├── follower.h │ │ ├── gain.h │ │ ├── lorenz_generator.cc │ │ ├── lorenz_generator.h │ │ ├── meta_parameters.h │ │ ├── resources.cc │ │ ├── resources.h │ │ ├── svf.cc │ │ ├── svf.h │ │ ├── vactrol.cc │ │ └── vactrol.h │ └── xz_lzma2/ │ ├── xz.h │ ├── xz_config.h │ ├── xz_dec_lzma2.c │ ├── xz_lzma2.h │ └── xz_private.h ├── src/ │ ├── CV/ │ │ ├── EnvFollower.cpp │ │ ├── EnvGen.cpp │ │ ├── LFO.cpp │ │ └── V_OCT.cpp │ ├── DRUMS/ │ │ ├── 808ish-BD.cpp │ │ ├── 808ish-HiHat.cpp │ │ ├── 808ish-SD.cpp │ │ ├── Claps.cpp │ │ ├── Djembe.cpp │ │ ├── DrumSynth.cpp │ │ ├── FM-Drum.cpp │ │ ├── RZ-1.cpp │ │ ├── TR707.cpp │ │ └── TR909-HiHat.cpp │ ├── FILTER/ │ │ ├── MoogLadder.cpp │ │ ├── SVF.cpp │ │ └── TeeBee.cpp │ ├── FX/ │ │ ├── Delay.cpp │ │ ├── JU60_chorus.cpp │ │ ├── Rev-Dattorro.cpp │ │ ├── Reverb.cpp │ │ └── ReverbSC.cpp │ ├── GND/ │ │ ├── FFT.cpp │ │ └── Scope.cpp │ ├── M-OSC/ │ │ └── Waveforms.cpp │ ├── MIDI/ │ │ ├── Clock.cpp │ │ ├── Monitor.cpp │ │ └── VAx6.cpp │ ├── NOISE/ │ │ ├── 808_squares.cpp │ │ ├── NES.cpp │ │ └── WhitePink.cpp │ ├── SEQ/ │ │ ├── 303-Patterns.cpp │ │ ├── EuclidArp.cpp │ │ ├── EuclidRythm.cpp │ │ └── TuringMachine.cpp │ ├── SPEECH/ │ │ ├── LPC.cpp │ │ └── SAM.cpp │ ├── SYNTH/ │ │ ├── DxFM.cpp │ │ ├── Open303.cpp │ │ ├── Resonator.cpp │ │ └── plaits.cpp │ ├── build.sh │ ├── dump.py │ ├── squares-and-circles-api.h │ ├── test.cxx │ └── test.sh └── test/ └── test_midi.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .clangd ================================================ Diagnostics: Suppress: - "xunused-includes" - "xasm_invalid_output_constraint" CompileFlags: Add: - "-I./" - "-I./lib/" ================================================ FILE: .github/workflows/build.yml ================================================ name: Build on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Set up Python uses: actions/setup-python@v2 - name: build run: | git submodule update --init bash -ex ./src/build.sh --rebuild - name: deploy run: | git remote add --mirror=fetch secondary https://${{ secrets.CODEBERG_AUTH }}@codeberg.org/eh2k/squares-and-circles.git git fetch origin git push secondary --all --force ================================================ FILE: .gitignore ================================================ .pio .vscode .test *.elf *.log *.txt *.bin.h src/__pycache__/app_hex.cpython-310.pyc .build/ .venv/ ================================================ FILE: .gitmodules ================================================ [submodule "lib/udynlink"] path = lib/udynlink url = https://github.com/eh2k/udynlink.git ================================================ FILE: README.md ================================================ > Feedback welcome: Feel free to leave a message or any hints in the ["General Feedback"](https://github.com/eh2k/squares-and-circles/issues/1) issue. # □︎●︎ [![WebFlasher](https://img.shields.io/badge/Web-Flasher-blue)](https://eh2k.github.io/□●/flash/?firmware) [![MODULAGrid](https://img.shields.io/badge/MODULAR-Grid-white)](https://www.modulargrid.net/e/modules/browser?SearchName=squares+and+circles&SearchShowothers=1) **squares-and-circles** is an alternate firmware for the Eurorack module Ornament & Crime (O_C), specifically targeting the Teensy 4.0. > CHANGELOG.txt ## ■ Demos | [![](https://img.youtube.com/vi/WQj3YqGpxRU/0.jpg)](https://www.youtube.com/watch?v=WQj3YqGpxRU) | [![](https://img.youtube.com/vi/QdlwETEaE3A/0.jpg)](https://youtu.be/QdlwETEaE3A) | [![](https://img.youtube.com/vi/lb-pbm1ddRw/0.jpg)](https://youtu.be/lb-pbm1ddRw) | [![](https://img.youtube.com/vi/J1vmVwwdVU4/0.jpg)](https://youtu.be/J1vmVwwdVU4) |--|--|--|--| ## Acknowledgments & Credits Thanks to the creators of ornament & crime (o_C) and PJRC for the Teensy, and all those who have worked on the [code and algorithms](https://github.com/eh2k/squares-and-circles/wiki/credits) that are reused here, especially Mutable Instruments. They served a great source of learning and provided a huge playground and the foundation for this project. ## Motivation / Challenge Given are the following ingredients: Two buttons, two encoders and a 128x64 display. Sixteen I/O ports (4x trigs, 4x cv and 4x dac) and a Cortex-M7. Damn many possibilities to complicate it. Mono, stereo and then again CV. A tricky task to design a simple UI logic, not get lost in menu diving, and to get as much out of the hardware as possible (work in progress). ## Concept Similar to the Monomachine and Machinedrum, this device features four fully configurable engine instances. Each instance can be assigned a synthesizer, effects, or sequencer engine, which can be controlled via trigger inputs, CV inputs, or clock signals. The available engine types include drums, synthesizers, oscillators, sequencers, and audio processors. The hardware ports and the generated output signals can be internally routed to any engine. For example, you can route the mono audio signal from an oscillator engine to a neighboring effects engine with stereo outputs, enabling seamless signal chaining. * [Short Press [LEFT]/[RIGHT]] scrolls through the 4 machine-tracks. * [Long press [LEFT]] enters the machine-selection-page. * [Long press [RIGHT]] enters the menu-page. * [Long press left or right [ENCODER]] shows the modulation popup * [Long press [L-ENCODER] + [R-ENCODER]] saves the patch - will be restored at startup - DEBUG: skip restore - press [RIGHT] button while startup ).
# Machines [wiki](https://github.com/eh2k/squares-and-circles/wiki/%E2%96%A1%EF%B8%8E%E2%97%8F%EF%B8%8E-Machines-&-Engines) * [Long press [LEFT]] enters the machine-selection-page.
* [Short press [R-ENCODER]] loads the selected engine.
* [Long press [R-ENCODER]] loads the selected engine - extended mode.
* Load & reset I/O settings * Load & keep IO settings * Copy #1-4 (parameter values + modulations + I/O settings)
--- ###### Screenshots --- ## Engines * **GND** * `---` * [Scope](https://github.com/eh2k/squares-and-circles/wiki/Scope) * [FFT](https://github.com/eh2k/squares-and-circles/wiki/FFT) * **CV** * [V_OCT](https://github.com/eh2k/squares-and-circles/wiki/V_OCT) * [Slew](https://github.com/eh2k/squares-and-circles/wiki/Slew) * [EnvGen_AD](https://github.com/eh2k/squares-and-circles/wiki/EnvGen_AD) * [EnvGen_ADSR](https://github.com/eh2k/squares-and-circles/wiki/EnvGen_ADSR) * [LFO](https://github.com/eh2k/squares-and-circles/wiki/LFO) * [EnvFollower](https://github.com/eh2k/squares-and-circles/wiki/EnvFollower) * **Drums** * [Analog-BD](https://github.com/eh2k/squares-and-circles/wiki/Analog-BD), * [Analog-SD](https://github.com/eh2k/squares-and-circles/wiki/Analog-SD), * [Analog-HH](https://github.com/eh2k/squares-and-circles/wiki/Analog-HH), * [Analog-HH2](https://github.com/eh2k/squares-and-circles/wiki/Analog-HH2), * [909ish-BD](https://github.com/eh2k/squares-and-circles/wiki/909ish-BD), * [909ish-SD](https://github.com/eh2k/squares-and-circles/wiki/909ish-SD), * [TR909-HiHat](https://github.com/eh2k/squares-and-circles/wiki/TR909_HiHats) * [808ish-BD](https://github.com/eh2k/squares-and-circles/wiki/808ish-BD), * [808ish-SD](https://github.com/eh2k/squares-and-circles/wiki/808ish-SD), * [808ish-HiHat](https://github.com/eh2k/squares-and-circles/wiki/808ish-HiHat), * [TR707](https://github.com/eh2k/squares-and-circles/wiki/TR707), * [RZ-1](https://github.com/eh2k/squares-and-circles/wiki/RZ-1), * [FM-Drum](https://github.com/eh2k/squares-and-circles/wiki/FM-Drum) * [Djembe](https://github.com/eh2k/squares-and-circles/wiki/Djembe) * [Claps](https://github.com/eh2k/squares-and-circles/wiki/Claps) * **M-OSC** * [Waveforms](https://github.com/eh2k/squares-and-circles/wiki/Waveforms) * [Virt.Analog](https://github.com/eh2k/squares-and-circles/wiki/Virt.Analog) * [Waveshaping](https://github.com/eh2k/squares-and-circles/wiki/Waveshaping) * [2-OP-FM](https://github.com/eh2k/squares-and-circles/wiki/2-OP-FM) * [Formant/PD](https://github.com/eh2k/squares-and-circles/wiki/Formant-PD) * [Harmonic](https://github.com/eh2k/squares-and-circles/wiki/Harmonic) * [Wavetable](https://github.com/eh2k/squares-and-circles/wiki/Waveforms) * [Chord](https://github.com/eh2k/squares-and-circles/wiki/Waveforms) * **SYNTH** * [Resonator](https://github.com/eh2k/squares-and-circles/wiki/Resonator) * [DxFM](https://github.com/eh2k/squares-and-circles/wiki/DxFM) * [DxFM_BNK1-3](lib/plaits/resources.cc#L41) * [Open303](https://github.com/eh2k/squares-and-circles/wiki/Open303) * [ClassicVAVCF](lib/plaits/dsp/engine2/virtual_analog_vcf_engine.cc) * **FX** * [Reverb](https://github.com/eh2k/squares-and-circles/wiki/clouds_reverb) * [ReverbSC](https://github.com/eh2k/squares-and-circles/wiki/ReverbSC) * [Rev-Dattorro](https://github.com/eh2k/squares-and-circles/wiki/Rev-Dattorro) * [Delay](https://github.com/eh2k/squares-and-circles/wiki/Delay) * [Gated-Reverb](https://github.com/eh2k/squares-and-circles/wiki/Gated-Reverb) * [Reverb-HP-LP](https://github.com/eh2k/squares-and-circles/wiki/Reverb-HP-LP) * [JU60_chorus](https://github.com/eh2k/squares-and-circles/wiki/JU60_chorus) * **NOISE** * [White/Pink](https://github.com/eh2k/squares-and-circles/wiki/White_Pink_noise) * [NES_noise](https://github.com/eh2k/squares-and-circles/wiki/NES_noise) * [808_squares](https://github.com/eh2k/squares-and-circles/wiki/808_squares) * **FILTER** * [SVF](https://github.com/eh2k/squares-and-circles/wiki/filter_plaits_svf) * [MoogLadder](https://github.com/eh2k/squares-and-circles/wiki/moog_ladder) * [TeeBee](https://github.com/eh2k/squares-and-circles/wiki/filter_teebee) * **SPEECH** * [LPC](https://github.com/eh2k/squares-and-circles/wiki/LPC) * [SAM](https://github.com/eh2k/squares-and-circles/wiki/SAM) * **MIDI** * [Monitor](https://github.com/eh2k/squares-and-circles/wiki/Monitor) * [Clock](https://github.com/eh2k/squares-and-circles/wiki/Clock) * [VAx6](https://github.com/eh2k/squares-and-circles/wiki/VAx6) * **SEQ** * [EuclidRythm](https://github.com/eh2k/squares-and-circles/wiki/EuclidRythm) * [EuclidArp](https://github.com/eh2k/squares-and-circles/wiki/EuclidArp) * [TuringMachine](https://github.com/eh2k/squares-and-circles/wiki/TM) * [303-Patterns](https://github.com/eh2k/squares-and-circles/wiki/303-Patterns) ## Machine/Engine Machines/Engines are controlled by individual parameters. >[Short press left/right [ENCODER]] changes parameter selection
>[Rotate left/right [ENCODER]] changes parameter value ### Modulations >[Long press left or right [ENCODER]] shows/hides the modulation popup* For each parameter a modulation can be assigned: * **CV**: * SRC: * `C1`, `C2`, `C3`, `C4` - Analog inputs * OP: `THRU`, `SLEW`, `S&H`, `T&H` * THRU - Thru Input * SLEW - Slew Limiter - Rising - Falling * S&H - Sample and Hold - Trig Source * T&H - Track and Hold - Gate Source * `+` - Constant internal voltage * 10V with 1/1000 resolution - nice for fine adjustments (detuning etc) * Hints: * Parameter 0 (top-left) is primarily used for V/OCT control. Therefore, a single V/OCT signal or CV input can be shared by applying modulation to parameter 0 with an attenuverter set to +1, within the -3V to +6V range. It is also possible to select the V/OCT input in the io-configuration page. * All other parameters can be modulated via CV-input with a assumed voltage-range of -4V..4V at 2kHz sample rate. * Be aware the CV-range is probably limited by hardware to: -3.5v..6.5V * **RND**: Trigger generates a random voltage * TRIG: `!`, `T1`, `T2`, `T3`, `T4`, `C1`, `C2`, `C3`, `C4`

* **ENV**: Triggered Envelope (Attack, Decay) * TRIG: `!`, `T1`, `T2`, `T3`, `T4`, `C1`, `C2`, `C3`, `C4` * ATTACK * DECAY * **LFO**: Free/Triggered Sine-LFO * TRIG: `-`, `!`, `T1`, `T2`, `T3`, `T4`, `C1`, `C2`, `C3`, `C4` * SHAPE: `SIN`, `TRI`, `SQR`, `STEPS`, `NOISE` * FREQUENCY: `0-127` * WAVEFORM: `0-127` * **EF**: Envelope Follower * SRC: `C1`, `C2`, `C3`, `C4` * ATTACK * RELEASE * **TM**: Turing Machine * TRIG: `!`, `CLK`, `T1`, `T2`, `T3`, `T4`, `C1`, `C2`, `C3`, `C4` * PROB: `0-9` (0-100%) * STEPS: `1-16` * **SEQ**: 4-Step Sequencer * TRIG: `!`, `T1`, `T2`, `T3`, `T4`, `C1`, `C2`, `C3`, `C4`, `CLK/1`, `CLK/4`, `CLK/16`, `CLK/32`, `CLK/96` * RESET: `-`, `T1`, `T2`, `T3`, `T4`, `C1`, `C2`, `C3`, `C4` * 4-STEPS: `-64..64` >`!` = current engine trigger
>`CLK` = internal clock
All modulations have an attenuverter parameter (-/+). * The modulation-voltage is attenuverted/multiplied by -1..+1;
## I/O-Configuration >[Long press [RIGHT]] enters the I/O-Configuration page. The I/O-Configuration page lets you virtually patch the engine with the hardware ports and internal gate/cv signals ($1a-$4d). Depending on the engine interface, trigger, gate, accent and V/OCT can be configured. In addition to the trigger, which is set with a rising edge, a gate state is also provided, that can be processed by the engine. Engines like Closed/Open-HiHats have an additional accent input - this works technically like a second trigger. The V/OCT input can optionally be quantized and transposed. In addition to the Tx inputs, the Cx inputs can also be used as a source for triggers and accents. The output can be configured as mono or stereo. Several engines can share the same output - the signal is mixed. ### Ctrl / Inputs *In case the Engine supports Triggers/Gates - Trigger Input is configurable:* * **Trig-Input**: * `-` * `T1`, `T2`, `T3`, `T4`, `C1`, `C2`, `C3`, `C4` * `$1-$9` *In case the Engine supports Clock-Input - Clock-Source is configurable:* * **Clock-Source**: * `CLK` - global clock -> Midi/Clock/Timing settings. * `T1`, `T2`, `T3`, `T4`, `C1`, `C2`, `C3`, `C4` * `$1-$9` *In case the Engine supports Accents (Closed/Open HiHat) - Accent Input is configurable:* * **Accent-Input**: * `-` * `T1`, `T2`, `T3`, `T4`, `C1`, `C2`, `C3`, `C4` * `$1-$9` *In case the Engine is an AUDIO_PROCESSOR - Input signal mix is configurable:* * **Aux-Input**: `-`, `C1`, `C2`, `C3`, `C4` * AUX-IN: -3V..3V for additional audio source for effects (prefer CV4). * **Insert-1**: Feed-in signal from engine-1 * **Insert-2**: Feed-in signal from engine-2 * **Insert-3**: Feed-in signal from engine-3 * **Insert-Aux**: Feed-in signal from aux-input
*In case the Engine supports V/OCT - V/OCT Input is configurable:* * **CV-Input**: `-`, `C1`, `C2`, `C3`, `C4` * V/OCT: -3V..6V for frequency-control (default) * **Quantizer**: [Off, Semitones, Ionian, Dorian, ...](lib/braids/quantizer_scales.h) * **ROOT**: `C`, `C#`, `D`, `D#`, `E`, `F`, `F#`, `G`, `G#`, `A`, `A#`, `B` * **Transpose**: -48 to 24 (semitone per step) * **FINE**: semitone/128 ### Mix / Outputs * **Level**: Output volume level - can result in distortion - not available on CV-Engines * **Pan**: Stereo panning - on stereo engines with mono output, panning is also used for mixing * **Output** * `-`, `A`, `A+B`, `B`, `C`, `C+D`, `D` - The option `-(no output)` is useful if the signal is to be routed into an AUDIO_PROCESSOR engine * **Stereo** * Experimental stereo feature - see STERIOLIZED Flag ;-)
## CLOCK+TIMING+MIDI-Settings >[Long press [LEFT] + [RIGHT]] for getting to the CLOCK+TIMING+MIDI-Settings page. ### - **CLOCK-Source**: * `-` none * `INT` Internal Clock-Source (BPM) * `T1` T1 as Clock-Input (4ppqn) * `MIDI` Clock received from MIDI > Default Clock-Source for `SEQ/...` engines.
> Clock-Source is also used by engines like `FX/Delay` (clocked sync) or `MIDI/Clock` ### - **TRIG-In-Delay**: * `0-50ms`Trigger input processing delay in ms. Usecase: sync trig signals with midi or CV ### - **MIDI-Control**: - `-` disabled - In case OC_T40 - `USB+T1` [T1 input can be used as MIDI-Input](https://github.com/eh2k/squares-and-circles/wiki/Ornament%E2%80%90and%E2%80%90Crime#-midi-expander) - else - `MIDI/USB` the USB-MIDI and/or hardware Midi-Input In case the MIDI-Control is enabled, you can setup the Midi-Channel for each engine. > Each engine can be assigned to a MIDI-Channel - it is possible to control single mono engines together polyphonically (for this all engines have to be set to the same midi channel). [Midi-Engines](app/MIDI/VAx6.cpp) consume the MIDI-Stream directly, therefore the MIDI-Messages are not converted as incoming CVs or triggers. #### Midi-Control * Engines can be loaded/selected by midi program change * Default Parameter CC-Mappings ```` | HEX | DEC | parameter-index | CH | |-----|-----|-----------------|----| | 07 | 07 | LEVEL | * | | 0A | 10 | PAN | * | | 10 | 16 | 0 | * | | 11 | 17 | 1 | * | | 12 | 18 | 2 | * | | 13 | 19 | 3 | * | | 14 | 20 | 4 | * | | 15 | 21 | 5 | * | | 16 | 22 | 6 | * | | 17 | 23 | 7 | * | ```` > CC 48-56 (HEX 30-38) for LSB (14Bit CC) * **Midi-Channel**: `-`, `1`...`16` - The Midi messages are translated to analog events - Trig: NoteOn - Gate: NoteOn until NoteOff - CV: 0V = Key 60 - [Multi-Trig-Drum-Engines](https://github.com/eh2k/squares-and-circles/wiki/DrumSynth) - In case trigger to `-` - individual drums/instruments are triggered by individual keys: - GM Standard Drum Map: https://github.com/eh2k/squares-and-circles/wiki/TR707#midi-mapping - or Keys 60-75 for instrument 1-16 # Patch Storage > [Press `L-ENC + R-ENC`] to enter the patch storage page * Use `L-ENC` for patch slot selection * Use `R-ENC` for LOAD/SAVE * Load `empty` - restores all engines to `GND/-` # Supported Hardware * [Ornament-and-Crime T4.0](https://github.com/eh2k/squares-and-circles/wiki/Ornament%E2%80%90and%E2%80%90Crime) * [Squares-and-Circles DSM0](https://github.com/eh2k/squares-and-circles/wiki/Squares&Circles-D_SM-Prototype) * [O_C T4.1](https://github.com/eh2k/squares-and-circles/wiki/O_C_T41) ## Hardware setup procedure > Use [![WebFlasher](https://img.shields.io/badge/Web-Flasher-blue)](https://eh2k.github.io/□●/flash/?firmware) to enter callibration mode, or execute advanced setup commands
>Press and hold the [LEFT] button during power-on to enter the setup procedure. ### Display setup * Press left encoder to flip180. * Press right encoder for changing display brightness (50%, maximal). ### Encoder setup * Check the encoder rotation direction. * Press encoder for reversed setup.

### DAC calibration To calibrate the DAC, use a multimeter to accurately set the reference voltages at `0V`, `-2V` and `+2V`. Start with DAC1 (channel A) - connect the multimeter typically using alligator clip on a patch cable inserted in the jack. Use the right encoder to set the voltage as accurately as possible (press the encoder for coarse adjustment). Do it on all outputs - use the left encoder for channel selection. After calibrating `0V` on all outputs, press [right] to step to the `-2V` calibration. Repeat the procedure and press [right] to calibrating `+2V`. ### ADC calibration To calibrate the ADC `0V` reference, remove all patch cables from the module. Use the right encoder to adjust the offset (press the encoder for fast adjustment). Do it on all cv-inputs, select the channel with the left encoder. Press [right] to enter the `-2V` calibration. Now you need to connect the DAC outputs to the cv-inputs. The DAC output produces the reference voltage, that is calibrated on the input. Repeat the calibration procedure and step to the `+2V` calibration. ### I/O Test: * Test/Verify your TRIG or CV inputs. * The output voltage is set by the cv input voltage (DACx = ADCx).
## ⧉ Conclusions and the future The project started as a kind of personal research in embedded DSP that I did over half a year. At some point, it turned out by chance that the O_C was very well suited for this by only upgrading the Teensy. Apart from the small optional [mod](https://github.com/eh2k/squares-and-circles/wiki/Ornament%E2%80%90and%E2%80%90Crime#optional-dac-voltage-range-mod--5v5v-range) on the DAC voltage range, the current O_C hardware unfortunately has some unchangeable limitations for audio applications. As you know, the Teensy 4.0 doesn't have "high-end" ADCs and a limited amount of RAM. On the other hand, it is the the combination of limitations that make the project unique. I have mixed feelings about the user interface and the firmware concept. On the one hand, the two buttons and the two encoders are sufficient and actually practical for a multifunction module, but on the other hand, something is missing. Additional buttons/encoders could definitely simplify the operation/interaction - let's see if this [puzzle](https://github.com/eh2k/squares-and-circles/wiki/Squares&Circles-D_SM-Prototype) can be solved. ## License The application code respectively the suite of machines/engines and the third-party source files are published under permissive software licenses. For the exact license and copyright holder - see the header of individual source code files or readme/license file in the sub folder. The firmware as a whole is for personal use only. If you are considering commercial distributing hardware with this firmware, please contact me (eh2k◯gmx.de). ================================================ FILE: app/SEQ/patterns_303.h ================================================ #include constexpr uint8_t REST = 0x0; /* between 0x0 and 0xA, the VCO voltage pins, so these notes arent really * 'effective' in that they all sound the same. */ // lowest octave constexpr uint8_t C1 = 0x0B; constexpr uint8_t C1_SHARP = 0x0C; constexpr uint8_t D1 = 0x0D; constexpr uint8_t D1_SHARP = 0x0E; constexpr uint8_t E1 = 0x0F; constexpr uint8_t F1 = 0x10; constexpr uint8_t F1_SHARP = 0x11; constexpr uint8_t G1 = 0x12; constexpr uint8_t G1_SHARP = 0x13; // middle octave constexpr uint8_t A1 = 0x14; constexpr uint8_t A1_SHARP = 0x15; constexpr uint8_t B1 = 0x16; constexpr uint8_t C2 = 0x17; constexpr uint8_t C2_SHARP = 0x18; constexpr uint8_t D2 = 0x19; constexpr uint8_t D2_SHARP = 0x1A; constexpr uint8_t E2 = 0x1B; constexpr uint8_t F2 = 0x1C; constexpr uint8_t F2_SHARP = 0x1D; constexpr uint8_t G2 = 0x1E; constexpr uint8_t G2_SHARP = 0x1F; // high octave constexpr uint8_t A2 = 0x20; constexpr uint8_t A2_SHARP = 0x21; constexpr uint8_t B2 = 0x22; constexpr uint8_t C3 = 0x23; constexpr uint8_t C3_SHARP = 0x24; constexpr uint8_t D3 = 0x25; constexpr uint8_t D3_SHARP = 0x26; constexpr uint8_t E3 = 0x27; constexpr uint8_t F3 = 0x28; constexpr uint8_t F3_SHARP = 0x29; constexpr uint8_t G3 = 0x2A; constexpr uint8_t G3_SHARP = 0x2B; constexpr uint8_t A3 = 0x2C; constexpr uint8_t A3_SHARP = 0x2D; constexpr uint8_t B3 = 0x2E; constexpr uint8_t C4 = 0x2F; constexpr uint8_t C4_SHARP = 0x30; constexpr uint8_t D4 = 0x31; constexpr uint8_t D4_SHARP = 0x32; constexpr uint8_t E4 = 0x33; constexpr uint8_t F4 = 0x34; constexpr uint8_t F4_SHARP = 0x35; constexpr uint8_t G4 = 0x36; constexpr uint8_t G4_SHARP = 0x37; constexpr uint8_t A4 = 0x38; constexpr uint8_t A4_SHARP = 0x39; constexpr uint8_t B4 = 0x3A; constexpr uint8_t C5 = 0x3B; constexpr uint8_t C5_SHARP = 0x3C; constexpr uint8_t D5 = 0x3D; constexpr uint8_t D5_SHARP = 0x3E; // no more notes! constexpr uint8_t NOTE_MASK = 0x3F; constexpr uint8_t SLIDE = 0x80; constexpr uint8_t ACCENT = 0x40; //"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" // Daft Punk - Da Funk const uint8_t da_funk[16] = {A2_SHARP, F4, D3 | SLIDE, C5, A3_SHARP | SLIDE | ACCENT, G3, F2_SHARP | SLIDE | ACCENT, G3_SHARP, A4_SHARP | SLIDE, A2, C4 | SLIDE, D4 | SLIDE | ACCENT, F3, D3 | SLIDE, F2 | SLIDE, D3_SHARP | SLIDE}; ================================================ FILE: app/index.json ================================================ { "apps": [ "CV/EnvFollower.bin", "CV/EnvGen.bin", "CV/LFO.bin", "CV/V_OCT.bin", "DRUMS/808ish-BD.bin", "DRUMS/808ish-HiHat.bin", "DRUMS/808ish-SD.bin", "DRUMS/Claps.bin", "DRUMS/Djembe.bin", "DRUMS/DrumSynth.bin", "DRUMS/FM-Drum.bin", "DRUMS/RZ-1.bin", "DRUMS/TR707.bin", "DRUMS/TR909-HiHat.bin", "FILTER/MoogLadder.bin", "FILTER/SVF.bin", "FILTER/TeeBee.bin", "FX/Delay.bin", "FX/FV1emu.bin", "FX/Gated-Reverb.bin", "FX/JU60_chorus.bin", "FX/Rev-Dattorro.bin", "FX/Reverb-HP-LP.bin", "FX/Reverb.bin", "FX/ReverbSC.bin", "GND/FFT.bin", "GND/Scope.bin", "M-OSC/Waveforms.bin", "MIDI/Clock.bin", "MIDI/Monitor.bin", "MIDI/VAx6.bin", "NOISE/808_squares.bin", "NOISE/NES.bin", "NOISE/WhitePink.bin", "SEQ/303-Patterns.bin", "SEQ/EuclidArp.bin", "SEQ/EuclidRythm.bin", "SEQ/TuringMachine.bin", "SPEECH/LPC.bin", "SPEECH/SAM.bin", "SYNTH/DxFM.bin", "SYNTH/Open303.bin", "SYNTH/Resonator.bin", "SYNTH/plaits.bin" ] } ================================================ FILE: app/squares-and-circles-loader.sha ================================================ 0e8b51c ================================================ FILE: app/upload.py ================================================ #!/usr/bin/env python3 import json import zlib import os, glob import sys try: import usb.core import usb.util except ImportError: print("pyusb is required. Install with: pip install pyusb") sys.exit(1) class bcolors: HEADER = "\033[95m" OKBLUE = "\033[94m" OKCYAN = "\033[96m" OKGREEN = "\033[92m" WARNING = "\033[93m" FAIL = "\033[91m" ENDC = "\033[0m" BOLD = "\033[1m" UNDERLINE = "\033[4m" print("-------------------------------------------------") os.chdir(os.path.dirname(os.path.abspath(__file__))) USB_VENDOR_ID = 0x16C0 USB_INTERFACE = 3 USB_ENDPOINT = 5 USB_TIMEOUT_MS = 5000 def _safe_usb_string(device, index): if not index: return "" try: return usb.util.get_string(device, index) or "" except usb.core.USBError: return "" def _find_bulk_endpoint(interface, direction): for endpoint in interface: if usb.util.endpoint_direction(endpoint.bEndpointAddress) != direction: continue if usb.util.endpoint_type(endpoint.bmAttributes) != usb.util.ENDPOINT_TYPE_BULK: continue if endpoint.bEndpointAddress & 0x0F == USB_ENDPOINT: return endpoint for endpoint in interface: if usb.util.endpoint_direction(endpoint.bEndpointAddress) != direction: continue if usb.util.endpoint_type(endpoint.bmAttributes) == usb.util.ENDPOINT_TYPE_BULK: return endpoint return None def open_device(): devices = list(usb.core.find(find_all=True, idVendor=USB_VENDOR_ID) or []) if not devices: return None selected = None for device in devices: product = _safe_usb_string(device, device.iProduct) if product.startswith("S&C") or product.startswith("Squares&Circles"): selected = device break if selected is None: selected = devices[0] #selected.set_configuration() config = selected.get_active_configuration() interface = usb.util.find_descriptor(config, bInterfaceNumber=USB_INTERFACE) if interface is None: raise RuntimeError(f"USB interface {USB_INTERFACE} not found") if selected.is_kernel_driver_active(USB_INTERFACE): selected.detach_kernel_driver(USB_INTERFACE) usb.util.claim_interface(selected, USB_INTERFACE) ep_out = _find_bulk_endpoint(interface, usb.util.ENDPOINT_OUT) ep_in = _find_bulk_endpoint(interface, usb.util.ENDPOINT_IN) if ep_out is None or ep_in is None: usb.util.release_interface(selected, USB_INTERFACE) raise RuntimeError("Bulk IN/OUT endpoints not found") return selected, ep_out, ep_in def close_device(device): if device is None: return try: usb.util.release_interface(device, USB_INTERFACE) except Exception: pass usb.util.dispose_resources(device) device_bundle = open_device() if device_bundle is None: print(" -> S&C Device not found") exit(1) else: dev, ep_out, ep_in = device_bundle product = _safe_usb_string(dev, dev.iProduct) serial_number = _safe_usb_string(dev, dev.iSerialNumber) print(" -> S&C Device found:", product or "Unknown", serial_number) def usb_write(ep_out, payload): ep_out.write(payload, timeout=USB_TIMEOUT_MS) def usb_read_until_nul(ep_in, timeout_ms=USB_TIMEOUT_MS, chunk_size=512): data = bytearray() while True: chunk = ep_in.read(chunk_size, timeout=timeout_ms) for byte in chunk: if byte == 0: return data.decode(errors="replace") data.append(byte) def get_blobs(ep_out, ep_in): usb_write(ep_out, b"blobs\0") buffer = usb_read_until_nul(ep_in) try: blobs = json.loads(buffer) except Exception as e: print(buffer) print("Error parsing blobs:", e) return [] for blob in blobs[:]: if os.path.exists(blob["name"]) == False: del blobs[blobs.index(blob)] continue with open(blob["name"], "rb") as f: blob["crc32_local"] = "%X" % zlib.crc32(f.read()) #print("blobs:", json.dumps(blobs, indent=2)) return blobs def update_blob(ep_out, ep_in, filename): blob = bytearray() blob.extend("WRI".encode()[:3] + bytes([0])) blob.extend(filename.encode() + bytes([0])) blob.extend(bytes(0x0 for _ in range(4 - (len(blob) % 4)))) blob.extend(os.path.getsize(filename).to_bytes(4, "little")) crc32 = 0 with open(filename, "rb") as f: crc32 =zlib.crc32(f.read()) blob.extend(crc32.to_bytes(4, "little")) f.seek(0) blob.extend(f.read()) blob.extend(bytes(0xFF for _ in range(64 - (len(blob) % 64)))) #return for i in range(0, len(blob), 512): chunk = blob[i : i + 512] usb_write(ep_out, chunk) r = usb_read_until_nul(ep_in) print(r) if r.startswith("ERR"): return False #r = usb_read_until_nul(ep_in) #print(r) #crc_ret = int.from_bytes(r[4:8], "little") #print("FLASH RESULT:", "%X" % crc32, "%X" % crc_ret) return True def reset(ep_out): usb_write(ep_out, b"ui:reset\0") print("Reset command sent") #dev.read(endpoint_in.bEndpointAddress, 64, 1000).tobytes() updated = False map = {} if device_bundle is None: print("-> S&C Device not connected") exit(1) dev, ep_out, ep_in = device_bundle try: print("-> S&C Device connected") print("-------------------------------------------------") for blob in get_blobs(ep_out, ep_in): map[blob["name"]] = blob if blob["crc32"] != blob["crc32_local"]: print( bcolors.WARNING, blob, bcolors.ENDC, ) updated |= update_blob(ep_out, ep_in, blob["name"]) #else: # print(bcolors.OKBLUE, blob, bcolors.ENDC) # glob for .bin files in current directory for local_file in glob.glob("*/*.bin"): local_file = local_file.replace("\\", "/") if local_file.endswith(".bin") and local_file not in map: print(bcolors.WARNING, "NEW FILE:", local_file, bcolors.ENDC) #updated |= update_blob(local_file) if updated: reset(ep_out) else: print("all apps up to date") finally: close_device(dev) ================================================ FILE: doc/.conv.sh ================================================ set +x cd $(dirname $0) montage -background '#25282c' -tile 5x -geometry +10+10 gnd_*.png cv_*.png drums_*.png mosc_*.png synth_*.png noise_*.png fx_*.png midi_*.png filter_*.png seq_*.png engines.png for f in $1; do convert $f -sample 256x128 ${f%.*}.png done ================================================ FILE: doc/.screenshots.py ================================================ import base64 import math, struct from array import array e = "////Bwfn52dnZ2dnZ+fnBwf//4eHZ2d/fwcHBwcfH///5+fn5+fnBwfn539///8HB+fnZ2dnZ2dn5+cHB////////////////////////39/Px8fH4+Ph8fHx+Pj4+Pj4+Pj4+PHx8eHj48fHx8/f3////////////////////////8AAH9/YGBgYGBgf38AAP//eXnm5h4e4OB4ePj4Hx/5+QcH+fkYGIGBHh7//wAAf39gYGBgYGB/fwAA/////////////38/Hw+Hw+Hw+Pz8/v///////////////////////////////////vz8+PDhw4cPHz9//////////////4aGnp4GBoaGnp5mZmZm5+f4+GdnhoZ5eX5+//8eHv//fn6BgRgYn58YGB8fBgb+/h4e5uZ+fmZmhob///////9/HwMB4Pj8////wb6+vsH/5+vtgO//gLa2tr7/+ba21uH/gLa2tr7/2Lq6usb////////8+OABAx9/////////h4fn5wAAn5+BgX5+ZmZhYWFhAADn5+bmYGBhYX5+h4fm5mdnAAAHB5iYfn4eHv//eHjn5wYGHh4ZGf//////BwAA+P/////////Bvr6+wf+Avr7d4/+A9vb2/v/+jvb6/P/Bvr6+wf/n6+2A7//////////////4AAAH//////9nZ+Hh4OAZGZmZ+PhmZpiY4OCGhgEB//9mZn5+ZmZ5eXl5/v5mZvj4BwdmZnh4//9gYIeHHh6AgP7+///////AAAA//////////////////////////////////////////////////////////////////////z8AAMD//////35+Z2d/f2BgYWF5eWZm+fkHB5mZmJgfH/7+4OBgYObmfn4BAXh4BwcGBuDgZmbh4QAABweAgB8fn5/////////88IABDz9///////////////////////////////////////////////////////////9/Pw8BgPD8////////AAD+/gYGBgYGBv7+AAD//xgYh4eBgZ6e4eF5efj45+ceHoaGgIB+fgAABwfm5gcHgICYmGdn5uYBAf/////////////8+PDhw4cPHz9/f/////////////////////////////////////9/fz8fD4fD4fD4/P/////////////g4Ofn5ubm5ubm5+fg4P//5ubn5+fn5+f//+bm+fn5+eDg///5+ebm4OD+/v//+Pj5+fn5/v7h4f7+///////////////////////+/Pz48PHx4+PDx8fHj4+Pj4+Pj4+Pj8fHx8Pj4/Hx8Pj8/P7//////////////////w==" a = "AH9BQSIcAH8JGSlGAD9AQEA/AH8CDAJ/AEZJSUkxACAQCAQCAAZJSSkeAD5BQUE+AAZJSSkeAABEfUAAAEhUVFQgAH8IBAR4AAgICAgIAEF/SUk2AH9BQSIcAAAAAAAAAAAAAAAAAAAAAAAAHD4+PhwcIiIiHBwiIiIcHCIiIhwCAgICAgKCgoKCggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoKCgoKCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuAYBAIBAQY4wAAAAQECBBjgAAAAAPCQkJAQAMCAQECAAIBAQECAAIBAQIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4BgEAgEBAACAgICBgYKEGOAAAAAA8JCQkGAAwAAAAMAAwIBAQIAAgEBAQAAA8IBAQIAAAAAAAAAAAAAAAAAAAwwQIEBAgICAgIBAQCAQDAMAAAAABwAAAAAABwAAAAAAAwUFBQEAAQICAQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAADDBAgQECAgICAgEBAIBAMAwAAAAAHAAAAAAADBAQCBwAHAAAABwADBAQEAgAHAAAABwAAAAAAAAAAAAAAAAAAAAAAgEAgICAgIECAAAAAAAAAAACAgICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQCAgICAgQIAAAAAAAAAAAICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8gQICAhISERCAfAAAAAAAAAAAAPwAAABwiIiIcAD4EAgI8ABwqKioMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHyBAgICEhIJCIB8AAAAAAAAAPyAgEQ4AHCoqKgwAHCIiIhAAECoqKjwADlBQUD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI+A==" mod = "fwIMAn8ACAgICAgAPkFBQT4ARklJSTEAPkFBQSIAIBAIBAIABxhgGAcAAER9QAAAfAgEBAgABD9EQCAAAGBgAAAAfBIREnwAfAgEBHgAIFRUVHgAAEF/QAAAOERERDgAGKSkpHwAAAAAAAAAHD4+PhwcIiIiHBwiIiIcHCIiIhz5+fn5+fn5CdnZCfkZ6ekZ+Qnp6Rn5Cfn5CfkJ+fn5+RlpaRn56Qnp6fnpCen5+Rnp6Rn5Cbl5Cfn5+fn5+fkBAQEBAQEBgUFBQUFBgQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf8DAwMDAwMC85OSkxMC8kODAvICc4MCgnICAwICAgIDAgMDAgMDEhMTExKCQiMjExISExMiI0OCExN/ExMD/wAAAAAAPkGAAAAIECCAQT4AAAAAAAAAfwgICH8AIFRUVHgAfAgEBAgAfAQYBHgAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAACHhISEBICHgAABh4CAAQYBgICAAAAAAAAAAIAAAAAAAAAAPsEAAAAAAAgEBAIBAcE+AAAAAAD/AAD8/DwcDAwFBQUFBQgIECDAAAAAAACAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAAIBPQIAAT8JCTQBIz0hAAAcKCg4AAACJAAAACwAAAMBAQMAAAAECAgQEBAQEAgIBAAAAAAAAAP8AAB9ggABAIBAIBAAAAAAAgGAfAAAAAD8BBgE/ABwiIiIcAD4EAgIEAH4SEhIMAD8EAgI8AAAAAAAAAAAAAAAAAP8AAAAAAAAA5yIixwDgp6AgAMAnICAAAAAEAAAAAEQAAAAAAAAA56SkpwCgoKBAAAAAAAAAAAAAAAAAAAAA/wAAAAAAgUIiFBTUFBQiQoEAAAAAAAAAgEBAQIAAAAAAAAAAAEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/xAQEBAQEBATEhIREBMSEhIQERISEhAQEBIQEBAQEtDQ0NDQ0NDT0tLT0BISEhEQEBAQEBAQEBAQEBAQEBD/AAAAAAAPECBAQENAQCAQDwAAAAAAAAAPEBAQCAAOERERDgAAEB8QAAAOERERDgAfAgEBAgAAAAAAAAAAAAAAAAD7+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+oqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiouIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI+A==" c = "/////wP3z/cD/w+3u7cP/wf7+/t3/wPf398D///7A/v//wPv378D/wPb29v7////AP////8D29vb+/8D79+/A/8H+9vbF///+wP7//8D79+/A/8D29vb+///////////////////////////////////////////////////////BwcHhkdHR4YHxgcHB8YHx0ZGhgcHBgcHBwYHBwYGBgcHBgcHBwYHBgYGBgYHBwf4BwcHBwaGRoYGBwYHBwcGBwcGBgYGBwdGxgYHBwYHBwcGBwYGBgYGBwcHBwcHB8cHBwfHB8cHBwfHBwcHBwcHBwcHBwcHBwcHBwcHBwcHV/8AAAAPEBISHgAfAQIEHwAfEBAIBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAAAHwQEBB8AHwIBAR4ACBUVFR4AABAfEAAADhEREQ4ABikpKR8AAAAAAAAAHwICAh8AHwICAh8AAAAAAAAAAAAAAAAAAAAAAAAAAABV/wAAAD5BQUEiAAcYYBgHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAB8EhESfAB8CAQEeAAgVFRUeAAAQX9AAAA4REREOAAYpKSkfAAAAAAAAAB/CAgIfwB/CAgIfwBCYVFJRgAAAAAAAAAAAAAAAAAAAFX/AP//A/v7d4//A9ubW+f/A////wP/A/fP9wP/59vb2zv//////////////////wD/AP///+fb21uH/wf7+/sH/+fb21uH///vC////9+vr69//wPf7+8f/9/f39/f//sD29sn/wP7+3eP//////////////////////////8A/f8ABwf2JsYn9weGh4eHhgfnFhYW5wdml5eXFgfmFhYWJwcHBwcHBwcHBwcHBwcHAP8ABwcHZ5aWl+cH5xYWFucHZ5aWl+cHB0bWBgcHhkZGRgcH9odHR4YHh4eHh4cHZpaWlhcH9hYWJ8cHBwcHBwcHBwcHBwcHBwcHBwcHBwBf/wAAAMdAQEBHAMAAAADAAAMEBAQDAAQEBAQDAAMEBAQCAAAAAAAAAAAAAAAAAAAA/wAAAABARMRCQQDDREREgwCARERCgQCAREdEgACERUVFggAHAAAABwCAQEBAgADEBAQEwwAHBAQCAQCAQEBAgADAAAAAwAAAAAAAAAAAAFX/+Pj4//r6+vj4+P36/fj4+Pj4+Pj4+Pj4+Pj4+Pj4+IiIiIiIiIiIiIiIiIiIiIiPiIiIiIiIj4iIiI+KjoqJiImKioqPiI+IiIiPiImKioqPiIqKioqKiI+IiIiIiI+KioqPiIqKioqKiI+IiIiPiI+KioqPiIiIiIiIiIiI/Q==" config = "////////ewF/////k5P/////////////fQF9//+DfX19g//v7+/v7/+DfX19u/+DfX19g/8B9+/fAf8B7e3t/f//fQF9//+DfW1tC/////////////////////////////////////////////////////////////////////8DAwMDAwMDQ0PDQ0MDw0NDQ4MDA0PDQwMDg0NDQ4MDAwMDAwMDA0PDQwMDwwMDA8MDw0NDQ4MDwwMDA8MDQ0PDQ0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNDQ8NDQwPDQ0NDgwMDg8MDAwMDAwMDAwMDAwMDAwMD/wAAAAAAAAAAgJ+AAACfAgYKkQAAEB8QAAAPkJKSHgCCAgICggCAkJ+QAACfAQIEnwCfgoKCgQAPEBAQDwAAAB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAn4AAAJ8CBgqRAAAQnxAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAAB8gICARAAMMMAwDAAQEBAQEAAAgPyAAAD8CBAg/AD8EBAQDAB8gICAfAAAAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHyAgIBEAAwwwDAMAACE/IAAAAAAAAAAAAAAAAAAAAP8AAEEiFAgAPkFRIV4AP0BAQD8AfBIREnwAfwQIEH8AAQF/AQEAAEF/QQAAYVFJRUMAf0lJSUEAfwkZKUYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUNnc2FAAgQEE/AQB8EhESfAB/CQkJBgB8EhESfAAAAAAAAAAA/wAAAAAAAAACAv4CAgD+EjJSjAD4JCIk+AD+CBAg/gCMkpKSYgD+EhISDAB8goKCfACMkpKSYgD+kpKSggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQAITCopKMADAoJP4gAAAAAAAAAAAAAAAAAAD/AAAAAAAAAPgEBAT4APwAAAD8AAQE/AQEAPwkJCQYAPwAAAD8AAQE/AQEACAgICAgAPgEJCToAPBIREjwAAAE/AQAAPwQIED8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AQEBPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/4+Pj4+Pj4+Pn5+fj4+Pn5+fj4+Pj5+Pj4+fj4+Pj4+ImJiYiIiIiJiIiIiIiIiIiIiImJiYmIiYiIiImIiImJiYiIiYiIiImIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiYmJiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI/w==" config_midi = "//////8D98/3A///+wP7//8D+/t3j///+wP7///f39/f3//n29vbO/8D29vb+//7+wP7+//7+wP7+///+wP7//8D79+/A/8H+9vbF//n29vbO/////////////////////////////////////////////////////////////8HB0eHBwYHB0fGRwcGxgYHB8YGRkfHR0cGBgYHBwcHh0dHR4YGxgYHBwYGxgYGh0cHBgcHBwcHBgeHRwcGRsZHR4YHx0dGR4cGxoYGh8YGBkaHBwcHBwcHBwcHh8eHBwcHh8cHBwcHh8cHBwcHh8cHBwcHBwcHBweHR0dHhwcH/wAAEAgFAgCAEB8QgAAfgYKEHwCAgJ8AAAACgoKCAgAPEBAQCAAfkJCQEACfAgUIkACAgICAAACABwgQgACQn5KSjQAfAgICAQAfAAMAHwAAEAgHAAAAAAAAAAUNHQ0FAIAQHxCAAACQn5CAAICQn5AAAAAYGAAAABAYFBIRAAD/AAAAAAAAAD8BBgE/AAAgPyAAAD8gIBEOAAAgPyAAAAQEBAQEAAAgPyAAAD8CBAg/AD8EBAQDAB8gICAfAAAAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHyAgIB8AIyQkJBgAID8kJBsAAAAAAAAAAAAAAAAAAP8AAAAAAAAAfwIMAn8AAEF/QQAAf0FBIhwAAEF/QQAACAgICAgAPkFBQSIAfwgICH8AAAAAAAAAFH8UfxQAAEJ/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQn9AAAAAAAAAAAAAHCJBAAB8EhESfAAAQSIcAAAA/wAAAAAAAAD+BBgE/gAAgv6CAAD+goJEOAAAgv6CAAAQEBAQEAB8goKCRAD+EBAQ/gAAAAAAAAAo/ij+KACEwqKSjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACE/oAAAAAAAAAAAAA4RIIAAIL+kpJsAACCRDgAAABXAAAAAAAAAPwIMAj8AAAE/AQAAPwEBIhwAAAE/AQAACAgICAgAPgEBASIAPwgICD8AAAAAAAAAFD8UPxQAIQEFCzEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj8AAAAAAAAAAAAAHCIBAAA+AQEBIgAAASIcAAAAFUAAAAAAAAA+RBgEPkAAAn5CQAA+QkJEOAAAAn5CQAAQEBAQEAA8AkJCRAA+UBAQPkAAAAAAAAAoPmg+aAAwKGR+YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEfkBAAAAAAAAAAAA4BAJAAD4CQkR4AAACRDgAAAABQ==" config_fx = "///////P19sB3///k5P/////////////fQF9//+DfX19g//v7+/v7/+DfX19u/+DfX19g/8B9+/fAf8B7e3t/f//fQF9//+DfW1tC/////////////////////////////////////////////////////////////////////8DAwMDAwMDQ0PDQ0MDw0NDQ4MDA0PDQwMDg0NDQ4MDAwMDAwMDA0PDQwMDwwMDA8MDw0NDQ4MDwwMDA8MDQ0PDQ0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNDQ8NDQwPDQ0NDgwMDA4PDAwMDAwMDAwMDAwMDAwMDVwAAAAAAAAAAAJ8AAACfAgYKkQCAEB8QgAAPEBISHgACgoKCAgCAEB8QgACfgYKEHwCfAgICgQCPkJCQjwAAAB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAAB8CBgoRAAYFBB8EAAAAAAAAAAAAAAAAAAD1AAAAAAAAAD4JCAk+AB8gICAfADEKBAoxAAQEBAQEAAAgPyAAAD8CBAg/AD8EBAQDAB8gICAfAAAAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAEEiFAgAAEF/QQAAfwQIEH8ARklJSTEAf0lJSUEAfwkZKUYAAQF/AQEACAgICAgAAEJ/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUNnc2FAAAQn9AAAA+QUFBPgAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAAAAgv6CAAD+CBAg/gCMkpKSYgD+kpKSggD+EjJSjAACAv4CAgAQEBAQEACEwqKSjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE6KiopyAEKCipZiAAAAAAAAAAAAAAAAAAAAAAAAAABXAAAAAAAAAAAE/AQAAPwQIED8ABgkJCTEAPwkJCQEAPwkZKQYAAQE/AQEACAgICAgAIQEFCzEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhAQULMQA+AQEBPgAAAAAAAAAAAAAAAAAAAAAAAAAAFX4iIiIiIiIiImJiYiIiYiIiImIiYmJiYiIiYmJiYmIiYiIiImIiIiJiIiIiIiIiIiIiImJiYiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIj4+fn5+Pj4+fn5+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4/Q==" encoder_setup = "////A9vb2/v/A+/fvwP/B/v7+3f/B/v7+wf/A/v7d4//A9vb2/v/A9ubW+f/////////59vb2zv/A9vb2/v/+/sD+/v/A////wP/A9vb2+f/////////////////////////////////////////////////////////////////BwcGBgYGBgcGBwcHBgcHBgYGBwcHBgYGBwcGBgYHBwcGBgYGBgcGBwcHBgcHBwcHBwcGBgYGBwcGBgYGBgcHBwYHBwcHBgYGBwcGBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcH//8AAAAAAAAAAPBQUCAA8FBQoADwUFAQACBQUJAAIFBQkAAAAAAAAPBQUBAA8ECA8ADgEBAQAAAAAAAAEPAQEADgEBDgAAAAAAAA8FBQoADwUFAQAPAAAPAA8FBQEADwUFCgACBQUJAA8FBQEAAAAAAAAAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAQAAAAABAAABAAEBAQEAAQEBAAABAQEAAAAAAAAAAQEBAQABAAABAAABAQEAAAAAAAAAAQAAAAABAQAAAAAAAAABAAABAAEBAQEAAAEBAAABAQEBAAEAAAEAAQEBAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAP//AAAAAADAMAgEAgIBAf0BAQICBAgwwAAAAADgAAAAAAAAgICAAAAAwCAgQACA4IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwDAIBAICAQH9AQECAgQIMMAAAAAA4CAgIMAAAICgAAAAAICAgIAA4ACAgAAAgOCAAAAAAAAAAAAA//8AAAAAAAcYIECAgAAAAQAAgIBAIBgHAAAAAA8ICAgIAAcKCgoDAAEPAQAAAAAHCAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAHGCBAgIAAAAEAAICAQCAYBwAAAAAPAQMFCAAACA8IAAADFBQUDwAPAQAADwAABwgIBAAAAAAAAAD//wAAAAAAAAAAAAAAAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//+Pj4+Pj4+Pj4+Pj4+IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI/w==" io_test = "////////+wP7//9/v9/v9/8H+/v7B//////////7+wP7+/8D29vb+//n29vbO//7+wP7+///////////////////////////////////////////////////////////////////////////////////////////////////////BwcHBwcGBgYHBwcHBwcHBwcGBgYHBwcHBwcHBwcHBgcHBwYGBgYGBwYGBgYHBwcHBgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcH//8AAAAAAgL+AgIA/hIyUowAAIT+gAAAAAAAAAAAfIKCgnwAAABAwAAAAAAAAAAAfIKCgkQADjDAMA4AAIT+gAAAAAAAAAAAEBAQEBAAfIKCgnwAAMDAAAAAfIKCgnwAfIKCgnwAhMKikowADjDAMA4AAAAAAAAAAAAAAAAAAAD//wAAAAAICPgICAD4SMhIMAAQCIhIMAAAAAAAAADwCAgI8AAAAAEAAAAAAAAAAADwCAgIEAA4wADAOAAQCIhIMAAAAAAAAABAQPBAQADwCAgI8AAAAAAAAADwCAgI8ADwCAgI8AAQCIhIMAA4wADAOAAAAAAAAAAAAAAAAAAAAP//AAAAACAg4yAgAOMgICHCACIjomIiAAAAAAAAAMEiIiLBAAAABQMAAAAAAAAAAMEiIiJBAOAAAwDgACIjomIiAAAAAAAAAAAAwQAAAMEiIiLBAAADAwAAAMEiIiLBAMEiIiLBAEIjIiLCAOAAAwDgAAAAAAAAAAAAAAAAAAAA//8AAAAAgICPgIAAj4GDhQgABAgIiQYAAAAAAAAAB4iIiAcAAAAUDAAAAAAAAAAAB4iIiAQAgAMMA4AABAgIiQYAAAAAAAAAAQEHAQEAB4iIiAcAAAwMAAAAB4iIiAcAB4iIiAcACIyKiQgAgAMMA4AAAAAAAAAAAAAAAAAAAAD//wAAAAAAAD8AAAA/BAwUIwAMCgk/CAAAAAAAAAAfICAgHwAAAFAwAAAAAAAAAAAfICAgEQADDDAMAwAMCgk/CAAAAAAAAAAEBB8EBAAfICAgHwAAMDAAAAAfICAgHwAfICAgHwAhMCgkIwADDDAMAwAAAAAAAAAAAAAAAAAAAP//iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIj4+Pj4+Pj4+Pj4+Pj4+IiIiIiIiIiIiIiIiIiI/w==" display_setup = "////A/v7d4////sD+///59vb2zv/A9vb2+f/A///////D7e7tw//498/3+P/////////59vb2zv/A9vb2/v/+/sD+/v/A////wP/A9vb2+f/////////////////////////////////////////////////////////////////BwcGBgYHBwcHBgYGBwcGBgYGBwcGBwcHBwcGBgYGBgcGBwcHBgcHBwYHBwcHBwcHBwcGBgYGBwcGBgYGBgcHBwYHBwcHBgYGBwcGBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcH//8AAAAA8JCQkGAA8JCQkGAA8JCQkBAAYJCQkBAAYJCQkBAAAGBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAAAAAHAAAAAADHAAECBAAHBAQEBADEREREQwDEBAQEwwCAQ0NAgAAAgIAAAAAAAAAAAADAQEBAQADAAAAAAAAAQMBAAADAQEBAgAAAgMAAAACAQEBAgACAQEBAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAB8QEBAQAAICAgICAB8SEhIQAB8BAgQfAA8QEBAIAAANDQAAAAAAAAAAAB8CAgIAAB8QEBAQAAAQHxAAAB8CAgIBAAAQHxAAAA0SEhINAA8QEBAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAfwkZKUYACAgICAgAf0lJSUEAfwQIEH8APkFBQSIAADY2AAAAAAAAAAAAQX9JSTYAfwkZKUYAAEF/QQAAPkFJSXoAfwgICH8AAQF/AQEAfwQIEH8Af0lJSUEARklJSTEARklJSTEAAAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//+Pj4+Pj4+Pj4+PiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI/w==" dac_calib = "////A/v7d4//D7e7tw//B/v7+3f///8f7+/v/x9vbx//D//////vD+///w+vr1//D6+vX/8fb28f/+8P7+//7w/v//8f7+8f/w+/fw/////f////////////////////398H39//B/v7+wf//39/////B/v7+wf/459/n+P/////BwcGBgYHBwcGBwcHBgcHBgYGBwcHBwcGBgYHBgcHBgcGBgYGBwYGBgcHBgYGBwcGBwcGBwYHBwYHBwYHBwcGBgYHBwcGBgcHBgcHBgcHBwYHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBgYGBwcHBgYHBwcHBgYGBwcHBwYHBwcH//8AAACCRCgQAP6CgkQ4APgkIiT4AHyCgoJEAACE/oAAAADAwAAAAADAwAAAAADAwAAAAADAwAAAAADAwAAAAADAwAAAAADAwAAAAADAwAAAAADAwAAAAADAwAAAAAAAKGzubCgAEBB8EBAAfIKCgnwAAAAAAAAAAAAAAAAAAAD//wAAAAAAAAAA+AgIEOAA4JCIkOAA8AgICBAAEAiISDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQPBAQADwCAgI8AAAAAAAAAAAAAAAAAAAAP//AAAAAAAAAADjIiJBgACDQCBAgwDBIiIiQQAiI6JiIgAAAwMAAAAAAwMAAAAAAwMAAAAAAwMAAAAAAwMAAAAAAwMAAAAAAwMAAAAAAwMAAAAAAwMAAAAAAwMAAAAAAAAAAAAAAAAAwQAAAMEiIiLBAAAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAI+IiAQDAA8CggIPAAeIiIgEAAQICIkGAAAMDAAAAAAMDAAAAAAMDAAAAAAMDAAAAAAMDAAAAAAMDAAAAAAMDAAAAAAMDAAAAAAMDAAAAAAMDAAAAAAAAAAAAAAAAQEHAQEAB4iIiAcAAAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAPyAgEQ4APgkICT4AHyAgIBEADAoJPwgAADAwAAAAADAwAAAAADAwAAAAADAwAAAAADAwAAAAADAwAAAAADAwAAAAADAwAAAAADAwAAAAADAwAAAAAAAAAAAAAAAEBB8EBAAfICAgHwAAAAAAAAAAAAAAAAAAAP//iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI+Pj4+Pj4+Pj4+Pj4iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI/w==" adc_calib = "////D7e7tw//A/v7d4//B/v7+3f///8f7+/v/x9vbx//D//////vD+///w+vr1//D6+vX/8fb28f/+8P7+//7w/v//8f7+8f/w+/fw/////f////////////////////398H39//B/v7+wf//39/////B/v7+wf/459/n+P/////BwcGBwcHBgcGBgYHBwcHBgYGBwcHBwcGBgYHBgcHBgcGBgYGBwYGBgcHBgYGBwcGBwcGBwYHBwYHBwYHBwcGBgYHBwcGBgcHBgcHBgcHBwYHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBgYGBwcHBgYHBwcHBgYGBwcHBwYHBwcH//8AAACCRCgQAPgkIiT4AP6CgkQ4AHyCgoJEAACE/oAAAAAAACgoKCgoAAAAAAAAABAQfBAQAHyCgoJ8AADAwAAAAHyCgoJ8AHyCgoJ8AACE/oAAAA4wwDAOAAAAAAAAKGzubCgAEBB8EBAAAIT+gAAAbJKSkmwAfIKCgnwAAAD//wAAAAAAAAAA4JCIkOAA+AgIEOAA8AgICBAAEAiISDAAAAAAoKCgoKAAAAAAAAAAQEDwQEAA8AgICPAAAAAAAAAA8AgICPAA8AgICPAAEAiISDAAOMAAwDgAAAAAAAAAAAAAAABAQPBAQAA4KCgoyAA4KCgoyAAAAAAAAAAAAP//AAAAAAAAAACDQCBAgwDjIiJBgADBIiIiQQAiI6JiIgAAAACAgICAgAAAAAAAAAAAAMEAAADBIiIiwQAAAwMAAADBIiIiwQDBIiIiwQAiI6JiIgDgAAMA4AAAAAAAAAAAAAAAAAAAwQAAAAFC4gIBAOGioqIhAMAgICDAAAAA//8AAAAAAAAAAA8CggIPAI+IiAQDAAeIiIgEAAQICIkGAAAAAAICAgICAAAAAAAAAAEBBwEBAAeIiIgHAAAMDAAAAAeIiIgHAAeIiIgHAAQIiAkGAIADDAOAAAAAAAAAAAAAAAAAAQEHAQEAAAiPCAAAhIiIiIcABwiIiAcAAAD//wAAAAAAAAAAPgkICT4APyAgEQ4AHyAgIBEADAoJPwgAAAAACgoKCgoAAAAAAAAABAQfBAQAHyAgIB8AADAwAAAAHyAgIB8AHyAgIB8AACE/IAAAAwwwDAMAAAAAAAAAAAAAAAAEBAQEBAAAIT8gAAAQICIlGAAeJSQkGAAAAP//iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI+Pj4+Pj4+Pj4+Pj4iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI/w==" osc = "fwIMAn8ACAgICAgAPkFBQT4ARklJSTEAPkFBQSIAIBAIBAIABxhgGAcAAER9QAAAfAgEBAgABD9EQCAAAGBgAAAAfBIREnwAfAgEBHgAIFRUVHgAAEF/QAAAOERERDgAGKSkpHwAAAAAAAAAHD4+PhwcIiIiHBwiIiIcHCIiIhwCgkIiEhIKCuoKChISIkKCAgICAuIioqIiIiKiIiIioqIioqIiIiKiIiIioiIiIqKiIuICAgICgoKCAgICAgICAgICAgICgkJCQkJCggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAj7BAAAAAAAADwAAAAAAAME+AAAA/wD/H/AA8P/wAPD//wD///AA8P/wAPD/8ADw//8A/wAAAOeIiOgAAAAAAAAAAAAAPkGAAAAIECCAQT4AAAAAAAAAfwgICH8AIFRUVHgAfAgEBAgAfAQYBHgAAAAAAAAAAAAAAAAAAAAAAAAAAAABAoREKCgoKChEhAIBAAAAAAAHhIWEhYQFBQWEBQUFBAUFBQQFhQUEBQUFBAUFBQQHAAAAAAAAAwAAAAAAAAAAwCAQCAgFBfUFBQgIECDAAAAAAACAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAfIECQiISAgEAgHwAAAAAAAAAAAD8AAAAAIj4gAAA+AgwCPAA/JCIiHAA+BAICBAAcKioqDAAAAAAAAAAAAB9ggAAAAAAABwAAAAAAgGAfAAAAAD8BBgE/ABwiIiIcAD4EAgIEAH4SEhIMAD8EAgI8AAAAAAAAAAAAAAAAAAAAAIBAIBAQ0BAQIECAAAAAAAAAAMBAQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgUIiFBTUFBQiQoEAAAAAAAAAgEBAQIAAAAAAAAAAAEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxAgQEBDQEAgEA8AAAAAAAAAHxAQCAcADhUVFQYADhEREQgACBUVFR4ABygoKB8AAAAAAAAAAAAAAAAAAAAAAAAPECBAQENAQCAQDwAAAAAAAAAPEBAQCAAOERERDgAAEB8QAAAOERERDgAfAgEBAgAAAAAAAAAAAAAAAAD4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI+A==" screenshots = { "io_test" : io_test, "splash": e, "osc": osc, "encoder_setup" : encoder_setup, "display_setup" : display_setup, "dac_calib" : dac_calib, "adc_calib" : adc_calib, "engine" : a, "modulation" : mod, "menu" : c, "config" : config, "config_midi" : config_midi, "config_fx" : config_fx, } mult4 = lambda n: int(math.ceil(n/4))*4 mult8 = lambda n: int(math.ceil(n/8))*8 lh = lambda n: struct.pack("> (x % 8)) else: row[int(x/8)] &= ~(0b10000000 >> (x % 8)) for key in screenshots: s = base64.b64decode(screenshots[key]) print(len(s)) rrr = [] for y in range(64): # comma, or other r = list(s[y*16:][:16]) for x in range(128): setPixel(r, x, getPixel(s, x, y)) rrr.append(r) smile = [[0xFF,0xFF], [0x81,0xFF], [0xA5,0xFF], [0x81,0xFF], [0xA5,0xFF], [0xBD,0xFF], [0x81,0xFF], [0xFF,0xFF]] f = open(key + ".bmp", "wb") f.write(bmp(rrr, 128)) f.close() ================================================ FILE: doc/output-routing.xml ================================================ 7V1Nc9s4Ev01rpo92EWA4Ncxjh1vdhJXdpxMkrlsqSyOpYkseiU6tufXD2URMtkQCRACiKasXCJRMEg2XjceuhuNI//t7ePFYnQ3+ZiN09kR9caPR/7ZEaXES+Liv9WVp/WVIA7XF24W03HZ6OXC1fTvlP9lefV+Ok6XtYZ5ls3y6V394nU2n6fXee3aaLHIHurN/sxm9bvejW5S4cLV9WgmXv06HeeT9dWYRi/X/51Obyb8ziRM1r/cjnjj8k2Wk9E4e6hc8s+P/LeLLMvXn24f36azlfC4XL6+f/o6+/AjvPjPf5f/H305/fXz5e/H687edfmTzSss0nlutmt/3fXP0ey+lNf55cX7y/PiWnnXZf7ERbnI7ufjdNUdOfJPHybTPL26G12vfn0owFNcm+S3s/LnP7N5XqKBFKI6vZmNlquh9IrPy3yR/dgMx6r1RrarnxVft3zAn+kiTx8rg12+/kWa3ab54qloUv7KyoF8qn99qMCivDSpIII3G5VAvNn0+yLs4kMp7+2y//X7p/Sn9yP06enF3YzR33+cX5TDtVX2dO9kT0JcwifNwvf3Tvgb0SIRPm0WPts74TMPl/CZIPyLN+8vBbEXPRVTdCoXuTWLAUBLqCg41qfgwoEILkQmt2ggcvM9ZIKLByI4RpEJjojU6uzNWwmn9RwKsC4/6rkmRyI7WsuvjZc6lB8kl+4FKDKctQDbuKVDAUKC6F6A4sJ0LcA2fuhUg7EJMBAEKE4c8/GblYel+Ha94snT67qw6pJNH6f5t9Xnk6D89r1st/p89lhpdvakxamX2f3iOm1pV4IiHddcPuKgVIQebBE6v7ZIZ6N8+rPuKNo2EuUdPmXT4jUqfKE+60VgLNevU/5R1TED+mniubyffLS4SXOhn2dYbF56B6SIvHZXpMyLJ6pAZfX1e/W3F7A8f9NDy1osCiwACVzgMIeacElAP37PcBHpvAPD0g/EqgapzYUnhSJDhUQCFzqeJhSFjuB01oDFAhyjp0qzu1WDZfMD04YHfoH2ukezQBeXX68X6EzV5hJcSCcAOEQX6bCjoGermxzACH33UjBGuLDY5CXpjEXYEWQSlrHIb3/A4gvG5IaR4gIjXLxAFqkMRtkqyDYYRVfV6wUjVQRjjAuLTMIilbEIO4p7xiI9YBFiTG4YcTl1NsSuiegpgxF2lPQMxtec2hNzuu4sw0GMsleTe7xf3n37194NAlymux8F0Qm+x1k+PsUmftGzXM3z2U8lYDGyUeAEHX0aQQDNRyJKrtc0Ar8pDD6MNALiOYeeSIhR5xGIfmbnEmyKgyNNJIBzEAIJikwMdyYBjBM6lyATJxBx8tBc1tLIryxsvZOE8e9mF7erTj6li2khkXShxQCkC14+z0pXvD6yFW9UB1yiHQ2EHVmKBgYgFpNEXutz+XHH9mFrezvRRmbRj+nXlIyceCRUVTLKwpqanXhhpKFqzy0s6x9fbcj1D1deCAVTZqIboxQ66jlGyUS2ZwzCUVSfJkigiuDQDwCCKUGKYPUZBFc+CcyES3Qjm0JHPUc2mcgVjSE4pKRuhD2JEW4CYakQNAGwDqgM1gcj3MwpAPJi3ey8gLM76MToC8KiyxOnt8eHLnvX3h5mPg92p+hdXb2jQKLdhhWZJYqKzDUeiSJD8h7rxu/gNjqBlhlazTCgB4nfvjoR2jNJ+4ZVmWr7uN7e0upHTCp+8+WboH6dYgO2DFeILdbI7CWq1ki3IuUmdcMls1vj0XKyGVLTRkw1OyvAlRHDiCE2AjsSfDudjZhxviImtr6/vDp6dnB7v5z99r3o9ev5ZzFOqExgKjHC2Kbflu+44mMWB4JZaIOMcbPAO3bLZ6yqd4BKa0Ootbp5bE0OSDxaGxj3Vu6AEyTDL4yaLvOEa1FVP15nP3qDv9Aq0wuoVeToshAdxmPamqmuuJCZPR8uMPRdJzDyqbgTtke7Z95BuENAs7/d2K3ZdXLAJrgAC10Euhu3BeTvzK67PbCqiyDuI4AZiI7HNZEXk6XQUXcwEUbcELlyRQYqe6wLZboqv2aLfJLdZPPR7PzlKjA0L20+ZNldKeC/0jx/KiU8us+zuvhrMysYC25/SIcJE8nOBJ4ZL/cKqE603QxSV/WHW6xiiYcQto9oN3MB2lsyF6K3fW0utiAdu7mIXJsL0QFYyHKbAxWbKAOFZOl+Ramyz3qIlncLJy0uvpvO+C2XhTnMeaN5Nk/5tbKNDUOsmsZgOMNN2zEjaL5icLcz4YOZ8BKLD9vz57JqwTkp7VczdvZB7mTZpJAOVNdE5rnFbrVNraUf6hHEuveG9hz8Vh5FZMHvgCQnhXHb/CN1KxJ6JyHTs3ztPScePQmjZPMvtmIVYWQ6CiS8Fpr9PnhtaNy/aTKLpG89Us0GQ6dHAGmwkIC62myHoO0kEkAYLEG9ZY/z3u8wZ64LfIYte5tFkzN06YvHR7gWf8ve5v3bWi4eIOFa/KKH9BVsLUdng4ZSoR6eJbHZZOnsLAnRz4RTctDuuhYc5/ToBcfQSW7Y1QxC18YuEld2qIsZQMrkXoADq2UASY97AQ6tlAE6FR74oQity3AkvhMQfA50C4tCxhYlJ0nS1cVoytUR7esZCZwUIAEPGPSV17ll0DVPTGA9b8mMDicmiG4rKTJDXFty4FEHTDfLFXYUWEoahLWs+ANbdQlHhzMTRATLjTDFBXUCp15dqBNozns2vBYPTdijwlV8eOU4RVa4ypfM67o17AXOaimAHdRNskilWcf2tLW9HZPPKduhcJX2PKG6S5nDB4v+QbauXTgOdqRYOM4YhC3WXnsVhavUZxBcvgqSSAiKMoJhRz2XXoupPQS/jsJVQzXCDDo3dHcds6ReuIrBnCfbEBajAzgDezDZ2nlgL7ZYtW54hatiVUUOcR0PB8k7092kAMuA2nIwwSOvg3p6rby9rNBVw6pMtT3rIwcyFiNKeAtXQcPlOhwX26u4VyPdwytcFSt7yZEZscgQGxE62nmnlXG+IkZ1hlm4yo/qhatY5LhwVYwiiGBVvXE5UgOobLoxe8EBGegE7XvUYeMBgj0oYwXH0DcSg4frVFUfX2dW2uBLtMoC+bsdilppr8aQmUQfLj703SogB27nMsKmjWBi3vs93JpWoeqOxRgZ8YbeA930FAj83Yl3twdW9R70ks6SUEE1hlLTCh56tJG3Ky9lIvp3RSEOsbIKip3WPAlYarc4pF3XtIJb2STOQ9je74XWiY71odSoEtQ/dK3+W8sDDqJGlcKuy35FqeI2PVhS2wnK3DpYr17VENfovhQJgE1QjPB2zjyGCiMJ3Ah7TDu25+9hdy6IXOgY8mpXnEw4YB27WVBrHuYhVrtSHkVkwabVlrBaTSoQxwj0y13Juk5AvStwG1O+TL+V9Moj4KQPw2gxyX5wBa8S1WUYOlUCSNPd8gE7YrZOTYPuoD5qu222bqHPUYM5QM4PVySeeS/zPu7F2UAMiWE4hnu4tE+HBw6J4kXNxoYb1grwLB3J0Qlwd6asffvR8rbMELWnS3ux5UY6/WJTswI5bXwzfqayQvXVrip4LDuhynKKN/FUYgCHjTbDwe0xcCnpn/xeIDz2KgiPwWxBit/9ynTRM3Atptjvxf6a4VlclpyEFcSBU9sLOFK/kZyoo9rtYfDEG8pp8PCEK/frlabzaYr3GFR6L/GRnUtLPBT1cGzm9270Domxg0k92gegwOVOiDu/l3jGHf3DT/CFY8iM5PdSyAQtHVoLg4u9HFpLPLuJ4gNO8N1MlAoMEJdRTKAt01+61DpCeGztxon3GnJ8FYCI67QReAaeGYMM4W1pFzB8eJl/tf0oW0vmm4jBB7S7dOFhnBxkrjbpEjKAxF3dTAoEOw4IoYp2y9JxiZ1Td0OwoOwl9MqlJKzHh5BCCrOXt54YG/Sq1MyFDvd5aHSPaXCb+UVOPTiMkSTCEWKtIvoAU3/V1zLKprgnZ7bfHj4MjYQPn+9SjcFQwDBpzaMO7mKIb5IYvFsfVV4IEV2WBQK8j9k8Oz6f30zn6VJQm+XD9HY2ej5HuadphsKFqDDJ8KPdayCkMNnLoHkR/W++ILfi7oVIvKs8XaRZ8eFdMaF761/xCZVuiUxslaqQQmdQqqI3ij42StC7SvP7O3ySDLfUTdsuSRg105Hkb49/n0afP/0vnYy//PHh/p58/OOvY/NeEbf1h8B0ZPIkV9Va5uuTXF1NhCHwxWkHOkJZxMSiT6/4usiyvNq8WLhMPmbjdNXiHw== ================================================ FILE: lib/.fetch_deps.py ================================================ import subprocess import os import io import urllib.request import zipfile import shutil subprocess.run('git submodule update --init', shell=True) from os.path import isdir, join from SCons.Script import DefaultEnvironment env = DefaultEnvironment() platform = env.PioPlatform() board = env.BoardConfig() print(env["PIOENV"]) ================================================ FILE: lib/MoogLadders/LICENSE ================================================ This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to ================================================ FILE: lib/MoogLadders/README.md ================================================ # Moog Ladder Filters This project contains different digital implementations of the classic 4-pole, 24 dB/octave analog filter introduced in 1965. The filter is well-regarded to add a nice character to any sound source, either synthesized or acoustic. The ladder structure consists of four one-pole filters and a global negative feedback loop. Several academics have attempted to discretize this filter, and some academic publications on the topic can be found in the `research/` directory. The filter classes do not rely on external libraries and can be used with little to no modification in other DSP projects. Every filter has been modified from its original implementation for code clarity and/or runtime performance. The project includes a test app that will pass white noise through each of the implemented filter variants. # Filter Tuning & A Word of Warning Each model is unique. The newest is from 2015 while the oldest dates back over 20 years. Some try to remain true to their analog counterpart, where others are more approximate. The filters have not been rigorously verified for all combinations of cutoff, resonance, and sampling rate. Some are purposely built to self-oscillate, but beware the occasional blow-up with parameters that exceed some undiscovered value. # Models & Licenses “Closed-Source Friendly” indicates if the individual license permits redistribution in a closed-source product (like a VST plugin). Filtered output audio is fair game for any kind of sample library or music production, commercial or otherwise. In the case of copyright-only code, it is possible to contact the original author to request an explicit license. Implementation | License | Original Source | Closed-Source Friendly ------------- | ------------- | ----------------- | ----------------- Simplified | Custom | DAFX | No Huovilainen | LGPLv3 | CSound | If dynamically linked Stilson | Unlicense | Moog~ by D. Lowenfels | Yes Microtracker | Unlicense | Magnus Jonsson | Yes Krajeski | Unlicense | Aaron Krajeski | Yes MusicDSP | Suggested CC-BY-SA | MusicDSP.org | Yes Oberheim | Custom | Will Pirkle | Yes Improved | ISC | Via Author | Yes RKSimulation | BSD | Bob~ by Miller Puckette | Yes # ToDo Community contributions are welcome. * Several filters have extra parameters that could be exposed (drive, thermal coefficients, Q, etc). * Many filters could be easily modified for HPF or other types of output. * Filter response graphs. * The Huovilainen and Simplified models need to be oversampled and nyquist filtered. # License If not otherwise stated in the header of a file, all other code in this project is released under the Unlicense. ================================================ FILE: lib/MoogLadders/src/Filters.h ================================================ #pragma once #ifndef FILTERS_H #define FILTERS_H #include #include #include "Util.h" class BiQuadBase { public: BiQuadBase() { bCoef = {{0.0f, 0.0f, 0.0f}}; aCoef = {{0.0f, 0.0f}}; w = {{0.0f, 0.0f}}; } ~BiQuadBase() { } // DF-II impl void Process(float * samples, const uint32_t n) { float out = 0; for (int s = 0; s < n; ++s) { out = bCoef[0] * samples[s] + w[0]; w[0] = bCoef[1] * samples[s] - aCoef[0] * out + w[1]; w[1] = bCoef[2] * samples[s] - aCoef[1] * out; samples[s] = out; } } float Tick(float s) { float out = bCoef[0] * s + w[0]; w[0] = bCoef[1] * s - aCoef[0] * out + w[1]; w[1] = bCoef[2] * s - aCoef[1] * out; return out; } void SetBiquadCoefs(std::array b, std::array a) { bCoef = b; aCoef = a; } protected: std::array bCoef; // b0, b1, b2 std::array aCoef; // a1, a2 std::array w; // delays }; class RBJFilter : public BiQuadBase { public: enum FilterType { LOWPASS, HIGHPASS, BANDPASS, ALLPASS, NOTCH, PEAK, LOW_SHELF, HIGH_SHELF }; RBJFilter(FilterType type = FilterType::LOWPASS, float cutoff = 1, float sampleRate = 44100) : sampleRate(sampleRate), t(type) { Q = 1; A = 1; a = {{0.0f, 0.0f, 0.0f}}; b = {{0.0f, 0.0f, 0.0f}}; SetCutoff(cutoff); } ~RBJFilter() { } void UpdateCoefficients() { cosOmega = cos(omega); sinOmega = sin(omega); switch (t) { case LOWPASS: { alpha = sinOmega / (2.0 * Q); b[0] = (1 - cosOmega) / 2; b[1] = 1 - cosOmega; b[2] = b[0]; a[0] = 1 + alpha; a[1] = -2 * cosOmega; a[2] = 1 - alpha; } break; case HIGHPASS: { alpha = sinOmega / (2.0 * Q); b[0] = (1 + cosOmega) / 2; b[1] = -(1 + cosOmega); b[2] = b[0]; a[0] = 1 + alpha; a[1] = -2 * cosOmega; a[2] = 1 - alpha; } break; case BANDPASS: { alpha = sinOmega * sinhf(logf(2.0) / 2.0 * Q * omega/sinOmega); b[0] = sinOmega / 2; b[1] = 0; b[2] = -b[0]; a[0] = 1 + alpha; a[1] = -2 * cosOmega; a[2] = 1 - alpha; } break; case ALLPASS: { alpha = sinOmega / (2.0 * Q); b[0] = 1 - alpha; b[1] = -2 * cosOmega; b[2] = 1 + alpha; a[0] = b[2]; a[1] = b[1]; a[2] = b[0]; } break; case NOTCH: { alpha = sinOmega * sinhf(logf(2.0) / 2.0 * Q * omega/sinOmega); b[0] = 1; b[1] = -2 * cosOmega; b[2] = 1; a[0] = 1 + alpha; a[1] = b[1]; a[2] = 1 - alpha; } break; case PEAK: { alpha = sinOmega * sinhf(logf(2.0) / 2.0 * Q * omega/sinOmega); b[0] = 1 + (alpha * A); b[1] = -2 * cosOmega; b[2] = 1 - (alpha * A); a[0] = 1 + (alpha / A); a[1] = b[1]; a[2] = 1 - (alpha / A); } break; case LOW_SHELF: { alpha = sinOmega / 2.0 * sqrt( (A + 1.0 / A) * (1.0 / Q - 1.0) + 2.0); b[0] = A * ((A + 1) - ((A - 1) * cosOmega) + (2 * sqrtf(A) * alpha)); b[1] = 2 * A * ((A - 1) - ((A + 1) * cosOmega)); b[2] = A * ((A + 1) - ((A - 1) * cosOmega) - (2 * sqrtf(A) * alpha)); a[0] = ((A + 1) + ((A - 1) * cosOmega) + (2 * sqrtf(A) * alpha)); a[1] = -2 * ((A - 1) + ((A + 1) * cosOmega)); a[2] = ((A + 1) + ((A - 1) * cosOmega) - (2 * sqrtf(A) * alpha)); } break; case HIGH_SHELF: { alpha = sinOmega / 2.0 * sqrt( (A + 1.0 / A) * (1.0 / Q - 1.0) + 2.0); b[0] = A * ((A + 1) + ((A - 1) * cosOmega) + (2 * sqrtf(A) * alpha)); b[1] = -2 * A * ((A - 1) + ((A + 1) * cosOmega)); b[2] = A * ((A + 1) + ((A - 1) * cosOmega) - (2 * sqrtf(A) * alpha)); a[0] = ((A + 1) - ((A - 1) * cosOmega) + (2 * sqrtf(A) * alpha)); a[1] = 2 * ((A - 1) - ((A + 1) * cosOmega)); a[2] = ((A + 1) - ((A - 1) * cosOmega) - (2 * sqrtf(A) * alpha)); } break; } // Normalize filter coefficients float factor = 1.0f / a[0]; std::array aNorm; std::array bNorm; aNorm[0] = a[1] * factor; aNorm[1] = a[2] * factor; bNorm[0] = b[0] * factor; bNorm[1] = b[1] * factor; bNorm[2] = b[2] * factor; SetBiquadCoefs(bNorm, aNorm); } // In Hertz, 0 to Nyquist void SetCutoff(float c) { omega = HZ_TO_RAD(c) / sampleRate; UpdateCoefficients(); } float GetCutoff() { return omega; } // Arbitrary, from 0.01f to ~20 void SetQValue(float q) { Q = q; UpdateCoefficients(); } float GetQValue() { return Q; } void SetType(FilterType newType) { t = newType; UpdateCoefficients(); } FilterType GetType() { return t; } private: float sampleRate; float omega; float cosOmega; float sinOmega; float Q; float alpha; float A; std::array a; std::array b; FilterType t; }; // +/-0.05dB above 9.2Hz @ 44,100Hz class PinkingFilter { double b0, b1, b2, b3, b4, b5, b6; public: PinkingFilter() : b0(0), b1(0), b2(0), b3(0), b4(0), b5(0), b6(0) {} float process(const float s) { b0 = 0.99886 * b0 + s * 0.0555179; b1 = 0.99332 * b1 + s * 0.0750759; b2 = 0.96900 * b2 + s * 0.1538520; b3 = 0.86650 * b3 + s * 0.3104856; b4 = 0.55000 * b4 + s * 0.5329522; b5 = -0.7616 * b5 - s * 0.0168980; const double pink = (b0 + b1 + b2 + b3 + b4 + b5 + b6 + (s * 0.5362)) * 0.11; b6 = s * 0.115926; return pink; } }; class BrowningFilter { float l; public: BrowningFilter() : l(0) {} float process(const float s) { float brown = (l + (0.02f * s)) / 1.02f; l = brown; return brown * 3.5f; // compensate for gain } }; #endif ================================================ FILE: lib/MoogLadders/src/HuovilainenModel.h ================================================ // Based on implementation in CSound5 (LGPLv2.1) // https://github.com/csound/csound/blob/develop/COPYING #pragma once #ifndef HUOVILAINEN_LADDER_H #define HUOVILAINEN_LADDER_H #include "LadderFilterBase.h" /* Huovilainen developed an improved and physically correct model of the Moog Ladder filter that builds upon the work done by Smith and Stilson. This model inserts nonlinearities inside each of the 4 one-pole sections on account of the smoothly saturating function of analog transistors. The base-emitter voltages of the transistors are considered with an experimental value of 1.22070313 which maintains the characteristic sound of the analog Moog. This model also permits self-oscillation for resonances greater than 1. The model depends on five hyperbolic tangent functions (tanh) for each sample, and an oversampling factor of two (preferably higher, if possible). Although a more faithful representation of the Moog ladder, these dependencies increase the processing time of the filter significantly. Lastly, a half-sample delay is introduced for phase compensation at the final stage of the filter. References: Huovilainen (2004), Huovilainen (2010), DAFX - Zolzer (ed) (2nd ed) Original implementation: Victor Lazzarini for CSound5 Considerations for oversampling: http://music.columbia.edu/pipermail/music-dsp/2005-February/062778.html http://www.synthmaker.co.uk/dokuwiki/doku.php?id=tutorials:oversampling */ class HuovilainenMoog : public LadderFilterBase { public: HuovilainenMoog(float sampleRate) : LadderFilterBase(sampleRate), thermal(0.000025) { memset(stage, 0, sizeof(stage)); memset(delay, 0, sizeof(delay)); memset(stageTanh, 0, sizeof(stageTanh)); SetCutoff(1000.0f); SetResonance(0.10f); } virtual ~HuovilainenMoog() { } virtual void Process(float * samples, uint32_t n) override { for (int s = 0; s < n; ++s) { // Oversample for (int j = 0; j < 2; j++) { float input = samples[s] - resQuad * delay[5]; delay[0] = stage[0] = delay[0] + tune * (tanh(input * thermal) - stageTanh[0]); for (int k = 1; k < 4; k++) { input = stage[k-1]; stage[k] = delay[k] + tune * ((stageTanh[k-1] = tanh(input * thermal)) - (k != 3 ? stageTanh[k] : tanh(delay[k] * thermal))); delay[k] = stage[k]; } // 0.5 sample delay for phase compensation delay[5] = (stage[3] + delay[4]) * 0.5; delay[4] = stage[3]; } samples[s] = delay[5]; } } virtual void SetResonance(float r) override { resonance = r; resQuad = 4.0 * resonance * acr; } virtual void SetCutoff(float c) override { cutoff = c; double fc = cutoff / sampleRate; double f = fc * 0.5; // oversampled double fc2 = fc * fc; double fc3 = fc * fc * fc; double fcr = 1.8730 * fc3 + 0.4955 * fc2 - 0.6490 * fc + 0.9988; acr = -3.9364 * fc2 + 1.8409 * fc + 0.9968; tune = (1.0 - exp(-((2 * MOOG_PI) * f * fcr))) / thermal; SetResonance(resonance); } private: double stage[4]; double stageTanh[3]; double delay[6]; double thermal; double tune; double acr; double resQuad; }; #endif ================================================ FILE: lib/MoogLadders/src/ImprovedModel.h ================================================ /* Copyright 2012 Stefano D'Angelo Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #pragma once #ifndef IMPROVED_LADDER_H #define IMPROVED_LADDER_H #include "LadderFilterBase.h" /* This model is based on a reference implementation of an algorithm developed by Stefano D'Angelo and Vesa Valimaki, presented in a paper published at ICASSP in 2013. This improved model is based on a circuit analysis and compared against a reference Ngspice simulation. In the paper, it is noted that this particular model is more accurate in preserving the self-oscillating nature of the real filter. References: "An Improved Virtual Analog Model of the Moog Ladder Filter" Original Implementation: D'Angelo, Valimaki */ // Thermal voltage (26 milliwats at room temperature) #define VT 0.312 class ImprovedMoog : public LadderFilterBase { public: ImprovedMoog(float sampleRate) : LadderFilterBase(sampleRate) { memset(V, 0, sizeof(V)); memset(dV, 0, sizeof(dV)); memset(tV, 0, sizeof(tV)); drive = 1.0f; SetCutoff(1000.0f); // normalized cutoff frequency SetResonance(0.1f); // [0, 4] } virtual ~ImprovedMoog() { } virtual void Process(float * samples, uint32_t n) override { double dV0, dV1, dV2, dV3; for (int i = 0; i < n; i++) { dV0 = -g * (tanh((drive * samples[i] + resonance * V[3]) / (2.0 * VT)) + tV[0]); V[0] += (dV0 + dV[0]) / (2.0 * sampleRate); dV[0] = dV0; tV[0] = tanh(V[0] / (2.0 * VT)); dV1 = g * (tV[0] - tV[1]); V[1] += (dV1 + dV[1]) / (2.0 * sampleRate); dV[1] = dV1; tV[1] = tanh(V[1] / (2.0 * VT)); dV2 = g * (tV[1] - tV[2]); V[2] += (dV2 + dV[2]) / (2.0 * sampleRate); dV[2] = dV2; tV[2] = tanh(V[2] / (2.0 * VT)); dV3 = g * (tV[2] - tV[3]); V[3] += (dV3 + dV[3]) / (2.0 * sampleRate); dV[3] = dV3; tV[3] = tanh(V[3] / (2.0 * VT)); samples[i] = V[3]; } } virtual void SetResonance(float r) override { if (r > 1.0) r = 1.0; if (r < 0.001) r = 0.001; resonance = r * 6.844399855f; } virtual void SetCutoff(float c) override { #define CUTOFF_MAX (20000.0f) cutoff = c; if (cutoff > CUTOFF_MAX) { cutoff = CUTOFF_MAX; } x = (MOOG_PI * cutoff) / sampleRate; g = 4.0 * MOOG_PI * VT * cutoff * (1.0 - x) / (1.0 + x); } private: double V[4]; double dV[4]; double tV[4]; double x; double g; double drive; }; #endif ================================================ FILE: lib/MoogLadders/src/KrajeskiModel.h ================================================ #pragma once #ifndef KRAJESKI_LADDER_H #define KRAJESKI_LADDER_H #include "LadderFilterBase.h" #include "Util.h" /* This class implements Tim Stilson's MoogVCF filter using 'compromise' poles at z = -0.3 Several improments are built in, such as corrections for cutoff and resonance parameters, removal of the necessity of the separation table, audio rate update of cutoff and resonance and a smoothly saturating tanh() function, clamping output and creating inherent nonlinearities. This code is Unlicensed (i.e. public domain); in an email exchange on 4.21.2018 Aaron Krajeski stated: "That work is under no copyright. You may use it however you might like." Source: http://song-swap.com/MUMT618/aaron/Presentation/demo.html */ class KrajeskiMoog final : public LadderFilterBase { public: KrajeskiMoog(float sampleRate) : LadderFilterBase(sampleRate) { memset(state, 0, sizeof(state)); memset(delay, 0, sizeof(delay)); drive = 1.0; gComp = 1.0; SetCutoff(1000.0f); SetResonance(0.1f); } virtual ~KrajeskiMoog() { } virtual void Process(float * samples, const uint32_t n) override { for (int s = 0; s < n; ++s) { state[0] = tanh(drive * (samples[s] - 4 * gRes * (state[4] - gComp * samples[s]))); for(int i = 0; i < 4; i++) { state[i+1] = fclamp(g * (0.3 / 1.3 * state[i] + 1 / 1.3 * delay[i] - state[i + 1]) + state[i + 1], -1e30, 1e30); delay[i] = state[i]; } samples[s] = state[4]; } } virtual void SetResonance(float r) override { resonance = r; gRes = resonance * (1.0029 + 0.0526 * wc - 0.926 * pow(wc, 2) + 0.0218 * pow(wc, 3)); } virtual void SetCutoff(float c) override { cutoff = c; wc = 2 * MOOG_PI * cutoff / sampleRate; g = 0.9892 * wc - 0.4342 * pow(wc, 2) + 0.1381 * pow(wc, 3) - 0.0202 * pow(wc, 4); } private: double state[5]; double delay[5]; double wc; // The angular frequency of the cutoff. double g; // A derived parameter for the cutoff frequency double gRes; // A similar derived parameter for resonance. double gComp; // Compensation factor. double drive; // A parameter that controls intensity of nonlinearities. inline float fclamp(float in, float min, float max){ return fmin(fmax(in, min), max); } }; #endif ================================================ FILE: lib/MoogLadders/src/LadderFilterBase.h ================================================ #pragma once #ifndef LADDER_FILTER_BASE_H #define LADDER_FILTER_BASE_H #include "Util.h" class LadderFilterBase { public: LadderFilterBase(float sampleRate) : sampleRate(sampleRate) {} virtual ~LadderFilterBase() {} virtual void Process(float * samples, uint32_t n) = 0; virtual void SetResonance(float r) = 0; virtual void SetCutoff(float c) = 0; float GetResonance() { return resonance; } float GetCutoff() { return cutoff; } protected: float cutoff; float resonance; float sampleRate; }; #endif ================================================ FILE: lib/MoogLadders/src/MicrotrackerModel.h ================================================ // Based on an implementation by Magnus Jonsson // https://github.com/magnusjonsson/microtracker (unlicense) #pragma once #ifndef MICROTRACKER_MODEL_H #define MICROTRACKER_MODEL_H #include "LadderFilterBase.h" #include "Util.h" class MicrotrackerMoog : public LadderFilterBase { public: MicrotrackerMoog(float sampleRate) : LadderFilterBase(sampleRate) { p0 = p1 = p2 = p3 = p32 = p33 = p34 = 0.0; SetCutoff(1000.0f); SetResonance(0.10f); } virtual ~MicrotrackerMoog() {} virtual void Process(float * samples, uint32_t n) override { double k = resonance * 4; for (int s = 0; s < n; ++s) { // Coefficients optimized using differential evolution // to make feedback gain 4.0 correspond closely to the // border of instability, for all values of omega. double out = p3 * 0.360891 + p32 * 0.417290 + p33 * 0.177896 + p34 * 0.0439725; p34 = p33; p33 = p32; p32 = p3; p0 += (fast_tanh(samples[s] - k * out) - fast_tanh(p0)) * cutoff; p1 += (fast_tanh(p0) - fast_tanh(p1)) * cutoff; p2 += (fast_tanh(p1) - fast_tanh(p2)) * cutoff; p3 += (fast_tanh(p2) - fast_tanh(p3)) * cutoff; samples[s] = out; } } virtual void SetResonance(float r) override { resonance = r; } virtual void SetCutoff(float c) override { cutoff = c * 2 * MOOG_PI / sampleRate; cutoff = moog_min(cutoff, 1); } private: double p0; double p1; double p2; double p3; double p32; double p33; double p34; }; #endif ================================================ FILE: lib/MoogLadders/src/MusicDSPModel.h ================================================ // This file is unlicensed and uncopyright as found at: // http://www.musicdsp.org/showone.php?id=24 // Considering how widely this same code has been used in ~100 projects on GitHub with // various licenses, it might be reasonable to suggest that the license is CC-BY-SA #pragma once #ifndef MUSICDSP_MOOG_H #define MUSICDSP_MOOG_H #include "LadderFilterBase.h" #include "Util.h" class MusicDSPMoog : public LadderFilterBase { public: MusicDSPMoog(float sampleRate) : LadderFilterBase(sampleRate) { memset(stage, 0, sizeof(stage)); memset(delay, 0, sizeof(delay)); SetCutoff(1000.0f); SetResonance(0.10f); } virtual ~MusicDSPMoog() { } virtual void Process(float * samples, uint32_t n) override { for (int s = 0; s < n; ++s) { float x = samples[s] - resonance * stage[3]; // Four cascaded one-pole filters (bilinear transform) stage[0] = x * p + delay[0] * p - k * stage[0]; stage[1] = stage[0] * p + delay[1] * p - k * stage[1]; stage[2] = stage[1] * p + delay[2] * p - k * stage[2]; stage[3] = stage[2] * p + delay[3] * p - k * stage[3]; // Clipping band-limited sigmoid stage[3] -= (stage[3] * stage[3] * stage[3]) / 6.0; delay[0] = x; delay[1] = stage[0]; delay[2] = stage[1]; delay[3] = stage[2]; samples[s] = stage[3]; } } virtual void SetResonance(float r) override { resonance = r * (t2 + 6.0 * t1) / (t2 - 6.0 * t1); } virtual void SetCutoff(float c) override { cutoff = 2.0 * c / sampleRate; p = cutoff * (1.8 - 0.8 * cutoff); k = 2.0 * sin(cutoff * MOOG_PI * 0.5) - 1.0; t1 = (1.0 - p) * 1.386249; t2 = 12.0 + t1 * t1; SetResonance(resonance); } private: double stage[4]; double delay[4]; double p; double k; double t1; double t2; }; #endif ================================================ FILE: lib/MoogLadders/src/NoiseGenerator.h ================================================ #pragma once #ifndef NOISE_GENERATOR_H #define NOISE_GENERATOR_H #include #include #include #include #include #include "Util.h" #include "Filters.h" struct WhiteNoiseSource { WhiteNoiseSource() : dist(-1, 1) {} std::mt19937 engine; std::uniform_real_distribution dist; }; // Full spectrum noise struct WhiteNoise : public WhiteNoiseSource { float operator()() { return dist(engine); } }; // Pink noise has a decrease of 3dB/Octave struct PinkNoise : public WhiteNoiseSource { float operator()() { return f.process(dist(engine)); } PinkingFilter f; }; // Brown noise has a decrease of 6dB/Octave struct BrownNoise : public WhiteNoiseSource { float operator()() { return f.process(dist(engine)); } BrowningFilter f; }; // Note! This noise is only valid for 44100 because of the hard-coded filter coefficients struct NoiseGenerator { enum NoiseType { WHITE, PINK, BROWN, }; std::vector produce(NoiseType t, int sampleRate, int channels, float seconds) { int samplesToGenerate = sampleRate * seconds * channels; std::vector samples; samples.resize(samplesToGenerate); switch (t) { case NoiseType::WHITE: { WhiteNoise n; for(int s = 0; s < samplesToGenerate; s++) samples[s] = n(); } break; case NoiseType::PINK: { PinkNoise n; for(int s = 0; s < samplesToGenerate; s++) samples[s] = n(); } break; case NoiseType::BROWN: { BrownNoise n; for(int s = 0; s < samplesToGenerate; s++) samples[s] = n(); } break; default: throw std::runtime_error("Invalid noise type"); } return samples; } }; #endif ================================================ FILE: lib/MoogLadders/src/OberheimVariationModel.h ================================================ // See: http://www.willpirkle.com/forum/licensing-and-book-code/licensing-and-using-book-code/ // The license is "You may also use the code from the FX and Synth books without licensing or fees. // The code is for you to develop your own plugins for your own use or for commercial use." #pragma once #ifndef OBERHEIM_VARIATION_LADDER_H #define OBERHEIM_VARIATION_LADDER_H #include "LadderFilterBase.h" #include "Util.h" class VAOnePole { public: VAOnePole(float sr) : sampleRate(sr) { Reset(); } void Reset() { alpha = 1.0; beta = 0.0; gamma = 1.0; delta = 0.0; epsilon = 0.0; a0 = 1.0; feedback = 0.0; z1 = 0.0; } double Tick(double s) { s = s * gamma + feedback + epsilon * GetFeedbackOutput(); double vn = (a0 * s - z1) * alpha; double out = vn + z1; z1 = vn + out; return out; } void SetFeedback(double fb) { feedback = fb; } double GetFeedbackOutput(){ return beta * (z1 + feedback * delta); } void SetAlpha(double a) { alpha = a; }; void SetBeta(double b) { beta = b; }; private: float sampleRate; double alpha; double beta; double gamma; double delta; double epsilon; double a0; double feedback; double z1; }; class OberheimVariationMoog : public LadderFilterBase { public: OberheimVariationMoog(float sampleRate) : LadderFilterBase(sampleRate) { LPF1 = new VAOnePole(sampleRate); LPF2 = new VAOnePole(sampleRate); LPF3 = new VAOnePole(sampleRate); LPF4 = new VAOnePole(sampleRate); saturation = 1.0; Q = 3.0; SetCutoff(1000.f); SetResonance(0.1f); } virtual ~OberheimVariationMoog() { delete LPF1; delete LPF2; delete LPF3; delete LPF4; } virtual void Process(float * samples, uint32_t n) noexcept override { for (int s = 0; s < n; ++s) { float input = samples[s]; double sigma = LPF1->GetFeedbackOutput() + LPF2->GetFeedbackOutput() + LPF3->GetFeedbackOutput() + LPF4->GetFeedbackOutput(); input *= 1.0 + K; // calculate input to first filter double u = (input - K * sigma) * alpha0; u = tanh(saturation * u); double stage1 = LPF1->Tick(u); double stage2 = LPF2->Tick(stage1); double stage3 = LPF3->Tick(stage2); double stage4 = LPF4->Tick(stage3); // Oberheim variations samples[s] = oberheimCoefs[0] * u + oberheimCoefs[1] * stage1 + oberheimCoefs[2] * stage2 + oberheimCoefs[3] * stage3 + oberheimCoefs[4] * stage4; } } virtual void SetResonance(float r) override { // this maps resonance = 1->10 to K = 0 -> 4 K = (4.0) * (r - 1.0)/(10.0 - 1.0); } virtual void SetCutoff(float c) override { cutoff = c; // prewarp for BZT double wd = 2.0 * MOOG_PI * cutoff; double T = 1.0 / sampleRate; double wa = (2.0 / T) * tan(wd * T / 2.0); double g = wa * T / 2.0; // Feedforward coeff double G = g / (1.0 + g); LPF1->SetAlpha(G); LPF2->SetAlpha(G); LPF3->SetAlpha(G); LPF4->SetAlpha(G); LPF1->SetBeta(G*G*G / (1.0 + g)); LPF2->SetBeta(G*G / (1.0 + g)); LPF3->SetBeta(G / (1.0 + g)); LPF4->SetBeta(1.0 / (1.0 + g)); gamma = G*G*G*G; alpha0 = 1.0 / (1.0 + K * gamma); // Oberheim variations / LPF4 oberheimCoefs[0] = 0.0; oberheimCoefs[1] = 0.0; oberheimCoefs[2] = 0.0; oberheimCoefs[3] = 0.0; oberheimCoefs[4] = 1.0; } private: VAOnePole * LPF1; VAOnePole * LPF2; VAOnePole * LPF3; VAOnePole * LPF4; double K; double gamma; double alpha0; double Q; double saturation; double oberheimCoefs[5]; }; #endif ================================================ FILE: lib/MoogLadders/src/RKSimulationModel.h ================================================ /* Copyright (c) 2015, Miller Puckette. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #ifndef RK_SIMULATION_LADDER_H #define RK_SIMULATION_LADDER_H #include "LadderFilterBase.h" #include "Util.h" /* Imitates a Moog resonant filter by Runge-Kutte numerical integration of a differential equation approximately describing the dynamics of the circuit. Useful references: * Tim Stilson "Analyzing the Moog VCF with Considerations for Digital Implementation" Sections 1 and 2 are a reasonably good introduction but the model they use is highly idealized. * Timothy E. Stinchcombe "Analysis of the Moog Transistor Ladder and Derivative Filters" Long, but a very thorough description of how the filter works including its nonlinearities * Antti Huovilainen "Non-linear digital implementation of the moog ladder filter" Comes close to giving a differential equation for a reasonably realistic model of the filter The differential equations are: y1' = k * (S(x - r * y4) - S(y1)) y2' = k * (S(y1) - S(y2)) y3' = k * (S(y2) - S(y3)) y4' = k * (S(y3) - S(y4)) where k controls the cutoff frequency, r is feedback (<= 4 for stability), and S(x) is a saturation function. */ class RKSimulationMoog : public LadderFilterBase { public: RKSimulationMoog(float sampleRate) : LadderFilterBase(sampleRate) { memset(state, 0, sizeof(state)); saturation = 3.0; saturationInv = 1.0 / saturation; oversampleFactor = 1; stepSize = 1.0 / (oversampleFactor * sampleRate); SetCutoff(1000.f); SetResonance(1.0f); } virtual ~RKSimulationMoog() { } virtual void Process(float * samples, uint32_t n) override { for (int s = 0; s < n; ++s) { for (int j = 0; j < oversampleFactor; j++) { rungekutteSolver(samples[s], state); } samples[s] = state[3]; } } virtual void SetResonance(float r) override { // 0 to 10 resonance = r; } virtual void SetCutoff(float c) override { cutoff = (2.0 * MOOG_PI * c); } private: void calculateDerivatives(float input, double * dstate, double * state) { double satstate0 = clip(state[0], saturation, saturationInv); double satstate1 = clip(state[1], saturation, saturationInv); double satstate2 = clip(state[2], saturation, saturationInv); dstate[0] = cutoff * (clip(input - resonance * state[3], saturation, saturationInv) - satstate0); dstate[1] = cutoff * (satstate0 - satstate1); dstate[2] = cutoff * (satstate1 - satstate2); dstate[3] = cutoff * (satstate2 - clip(state[3], saturation, saturationInv)); } void rungekutteSolver(float input, double * state) { int i; double deriv1[4], deriv2[4], deriv3[4], deriv4[4], tempState[4]; calculateDerivatives(input, deriv1, state); for (i = 0; i < 4; i++) tempState[i] = state[i] + 0.5 * stepSize * deriv1[i]; calculateDerivatives(input, deriv2, tempState); for (i = 0; i < 4; i++) tempState[i] = state[i] + 0.5 * stepSize * deriv2[i]; calculateDerivatives(input, deriv3, tempState); for (i = 0; i < 4; i++) tempState[i] = state[i] + stepSize * deriv3[i]; calculateDerivatives(input, deriv4, tempState); for (i = 0; i < 4; i++) state[i] += (1.0 / 6.0) * stepSize * (deriv1[i] + 2.0 * deriv2[i] + 2.0 * deriv3[i] + deriv4[i]); } double state[4]; double saturation, saturationInv; int oversampleFactor; double stepSize; }; #endif ================================================ FILE: lib/MoogLadders/src/SimplifiedModel.h ================================================ /* ------------------------------------------------------------------------- * This source code is provided without any warranties as published in * DAFX book 2nd edition, copyright Wiley & Sons 2011, available at * http://www.dafx.de. It may be used for educational purposes and not * for commercial applications without further permission. * ------------------------------------------------------------------------- */ #pragma once #ifndef SIMPLIFIED_LADDER_H #define SIMPLIFIED_LADDER_H #include "LadderFilterBase.h" /* The simplified nonlinear Moog filter is based on the full Huovilainen model, with five nonlinear (tanh) functions (4 first-order sections and a feedback). Like the original, this model needs an oversampling factor of at least two when these nonlinear functions are used to reduce possible aliasing. This model maintains the ability to self oscillate when the feedback gain is >= 1.0. References: DAFX - Zolzer (ed) (2nd ed) Original implementation: Valimaki, Bilbao, Smith, Abel, Pakarinen, Berners (DAFX) This is a transliteration into C++ of the original matlab source (moogvcf.m) Considerations for oversampling: http://music.columbia.edu/pipermail/music-dsp/2005-February/062778.html http://www.synthmaker.co.uk/dokuwiki/doku.php?id=tutorials:oversampling */ class SimplifiedMoog : public LadderFilterBase { public: SimplifiedMoog(float sampleRate) : LadderFilterBase(sampleRate) { // To keep the overall level approximately constant, comp should be set // to 0.5 resulting in a 6 dB passband gain decrease at the maximum resonance // (compared to a 12 dB decrease in the original Moog model gainCompensation = 0.5; memset(stage, 0, sizeof(stage)); memset(stageZ1, 0, sizeof(stageZ1)); memset(stageTanh, 0, sizeof(stageTanh)); SetCutoff(1000.0f); SetResonance(0.10f); } virtual ~SimplifiedMoog() { } // This system is nonlinear so we are probably going to create a signal with components that exceed nyquist. // To prevent aliasing distortion, we need to oversample this processing chunk. Where do these extra samples // come from? Todo! We can use polynomial interpolation to generate the extra samples, but this is expensive. // The cheap solution is to zero-stuff the incoming sample buffer. // With resampling, numSamples should be 2x the frame size of the existing sample rate. // The output of this filter needs to be run through a decimator to return to the original samplerate. virtual void Process(float * samples, uint32_t n) override { // Processing still happens at sample rate... for (int s = 0; s < n; ++s) { for (int stageIdx = 0; stageIdx < 4; ++stageIdx) { if (stageIdx) { input = stage[stageIdx-1]; stageTanh[stageIdx-1] = tanh(input); stage[stageIdx] = (h * stageZ1[stageIdx] + h0 * stageTanh[stageIdx-1]) + (1.0 - g) * (stageIdx != 3 ? stageTanh[stageIdx] : tanh(stageZ1[stageIdx])); } else { input = samples[s] - ((4.0 * resonance) * (output - gainCompensation * samples[s])); stage[stageIdx] = (h * tanh(input) + h0 * stageZ1[stageIdx]) + (1.0 - g) * stageTanh[stageIdx]; } stageZ1[stageIdx] = stage[stageIdx]; } output = stage[3]; SNAP_TO_ZERO(output); samples[s] = output; } } virtual void SetResonance(float r) override { resonance = r; } virtual void SetCutoff(float c) override { cutoff = c; // Not being oversampled at the moment... * 2 when functional float fs2 = sampleRate; // Normalized cutoff [0, 1] in radians: ((2*pi) * cutoff / samplerate) g = (2 * MOOG_PI) * cutoff / fs2; // feedback coefficient at fs*2 because of doublesampling g *= MOOG_PI / 1.3; // correction factor that allows _cutoff to be supplied Hertz // FIR part with gain g h = g / 1.3; h0 = g * 0.3 / 1.3; } private: double output; double lastStage; double stage[4]; double stageZ1[4]; double stageTanh[3]; double input; double h; double h0; double g; float gainCompensation; }; #endif ================================================ FILE: lib/MoogLadders/src/StilsonModel.h ================================================ // Copyright (c) 2003, David Lowenfels // Released as the moog~ pd extern. // This code is Unlicensed (i.e. public domain); in an email exchange on // 6.14.2019 David Lowenfels stated "You're welcome to use the Moog~ code, // license it free as in beer or whatever :)" #pragma once #ifndef STILSON_LADDER_H #define STILSON_LADDER_H #include "LadderFilterBase.h" /* A digital model of the classic Moog filter was presented first by Stilson and Smith. This model uses a cascade of one-pole IIR filters in series with a global feedback to produce resonance. A digital realization of this filter introduces a unit delay, effectively making it a fifth-order filter. Unfortunately, this delay also has the effect of coupling the cutoff and resonance parameters, uncharacteristic of the uncoupled control of the original Moog ladder. As a compromise, a zero can be inserted at z = -0.3 inside each one pole section to minimize the coupling the parameters (humans are not particularly sensitive to variations in Q factor). Although fast coefficient updates can be achieved since the nonlinearities of the Moog are not considered, the filter becomes unstable with very large resonance values and does not enter self-oscillation. References: Stilson and Smith (1996), DAFX - Zolzer (ed) (2nd ed) Original implementation: Tim Stilson, David Lowenfels */ static float S_STILSON_GAINTABLE[199] = { 0.999969, 0.990082, 0.980347, 0.970764, 0.961304, 0.951996, 0.94281, 0.933777, 0.924866, 0.916077, 0.90741, 0.898865, 0.890442, 0.882141 , 0.873962, 0.865906, 0.857941, 0.850067, 0.842346, 0.834686, 0.827148, 0.819733, 0.812378, 0.805145, 0.798004, 0.790955, 0.783997, 0.77713, 0.770355, 0.763672, 0.75708 , 0.75058, 0.744141, 0.737793, 0.731537, 0.725342, 0.719238, 0.713196, 0.707245, 0.701355, 0.695557, 0.689819, 0.684174, 0.678558, 0.673035, 0.667572, 0.66217, 0.65686, 0.651581, 0.646393, 0.641235, 0.636169, 0.631134, 0.62619, 0.621277, 0.616425, 0.611633, 0.606903, 0.602234, 0.597626, 0.593048, 0.588531, 0.584045, 0.579651, 0.575287 , 0.570953, 0.566681, 0.562469, 0.558289, 0.554169, 0.550079, 0.546051, 0.542053, 0.538116, 0.53421, 0.530334, 0.52652, 0.522736, 0.518982, 0.515289, 0.511627, 0.507996 , 0.504425, 0.500885, 0.497375, 0.493896, 0.490448, 0.487061, 0.483704, 0.480377, 0.477081, 0.473816, 0.470581, 0.467377, 0.464203, 0.46109, 0.457977, 0.454926, 0.451874, 0.448883, 0.445892, 0.442932, 0.440033, 0.437134, 0.434265, 0.431427, 0.428619, 0.425842, 0.423096, 0.42038, 0.417664, 0.415009, 0.412354, 0.409729, 0.407135, 0.404572, 0.402008, 0.399506, 0.397003, 0.394501, 0.392059, 0.389618, 0.387207, 0.384827, 0.382477, 0.380127, 0.377808, 0.375488, 0.37323, 0.370972, 0.368713, 0.366516, 0.364319, 0.362122, 0.359985, 0.357849, 0.355713, 0.353607, 0.351532, 0.349457, 0.347412, 0.345398, 0.343384, 0.34137, 0.339417, 0.337463, 0.33551, 0.333588, 0.331665, 0.329773, 0.327911, 0.32605, 0.324188, 0.322357, 0.320557, 0.318756, 0.316986, 0.315216, 0.313446, 0.311707, 0.309998, 0.308289, 0.30658, 0.304901, 0.303223, 0.301575, 0.299927, 0.298309, 0.296692, 0.295074, 0.293488, 0.291931, 0.290375, 0.288818, 0.287262, 0.285736, 0.284241, 0.282715, 0.28125, 0.279755, 0.27829, 0.276825, 0.275391, 0.273956, 0.272552, 0.271118, 0.269745, 0.268341, 0.266968, 0.265594, 0.264252, 0.262909, 0.261566, 0.260223, 0.258911, 0.257599, 0.256317, 0.255035, 0.25375 }; class StilsonMoog : public LadderFilterBase { public: StilsonMoog(float sampleRate) : LadderFilterBase(sampleRate) { memset(state, 0, sizeof(state)); SetCutoff(1000.0f); SetResonance(0.10f); } virtual ~StilsonMoog() { } virtual void Process(float * samples, uint32_t n) override { float localState; for (int s = 0; s < n; ++s) { // Scale by arbitrary value on account of our saturation function const float input = samples[s] * 0.65f; // Negative Feedback output = 0.25 * (input - output); for (int pole = 0; pole < 4; ++pole) { localState = state[pole]; output = moog_saturate(output + p * (output - localState)); state[pole] = output; output = moog_saturate(output + localState); } SNAP_TO_ZERO(output); samples[s] = output; output *= Q; // Scale stateful output by Q } } virtual void SetResonance(float r) override { r = moog_min(r, 1); resonance = r; double ix; double ixfrac; int ixint; ix = p * 99; ixint = floor(ix); ixfrac = ix - ixint; Q = r * moog_lerp(ixfrac, S_STILSON_GAINTABLE[ixint + 99], S_STILSON_GAINTABLE[ixint + 100]); } virtual void SetCutoff(float c) override { cutoff = c; // Normalized cutoff between [0, 1] double fc = (cutoff) / sampleRate; double x2 = fc * fc; double x3 = fc * fc * fc; // Frequency & amplitude correction (Cubic Fit) p = -0.69346 * x3 - 0.59515 * x2 + 3.2937 * fc - 1.0072; SetResonance(resonance); } private: double p; double Q; double state[4]; double output; }; #endif ================================================ FILE: lib/MoogLadders/src/Util.h ================================================ #pragma once #ifndef MOOG_UTIL_H #define MOOG_UTIL_H #include #include #define MOOG_E 2.71828182845904523536028747135266250 #define MOOG_LOG2E 1.44269504088896340735992468100189214 #define MOOG_LOG10E 0.434294481903251827651128918916605082 #define MOOG_LN2 0.693147180559945309417232121458176568 #define MOOG_LN10 2.30258509299404568401799145468436421 #define MOOG_PI 3.14159265358979323846264338327950288 #define MOOG_PI_2 1.57079632679489661923132169163975144 #define MOOG_PI_4 0.785398163397448309615660845819875721 #define MOOG_1_PI 0.318309886183790671537767526745028724 #define MOOG_2_PI 0.636619772367581343075535053490057448 #define MOOG_2_SQRTPI 1.12837916709551257389615890312154517 #define MOOG_SQRT2 1.41421356237309504880168872420969808 #define MOOG_SQRT1_2 0.707106781186547524400844362104849039 #define MOOG_INV_PI_2 0.159154943091895 #define NO_COPY(C) C(const C &) = delete; C & operator = (const C &) = delete #define NO_MOVE(C) NO_COPY(C); C(C &&) = delete; C & operator = (const C &&) = delete #define SNAP_TO_ZERO(n) if (! (n < -1.0e-8 || n > 1.0e-8)) n = 0; // Linear interpolation, used to crossfade a gain table inline float moog_lerp(float amount, float a, float b) { return (1.0f - amount) * a + amount * b; } inline float moog_min(float a, float b) { a = b - a; a += fabs(a); a *= 0.5f; a = b - a; return a; } // Clamp without branching // If input - _limit < 0, then it really substracts, and the 0.5 to make it half the 2 inputs. // If > 0 then they just cancel, and keeps input normal. // The easiest way to understand it is check what happends on both cases. inline float moog_saturate(float input) { float x1 = fabs(input + 0.95f); float x2 = fabs(input - 0.95f); return 0.5f * (x1 - x2); } // Imitate the (tanh) clipping function of a transistor pair. // to 4th order, tanh is x - x*x*x/3; this cubic's // plateaus are at +/- 1 so clip to 1 and evaluate the cubic. // This is pretty coarse - for instance if you clip a sinusoid this way you // can sometimes hear the discontinuity in 4th derivative at the clip point inline float clip(float value, float saturation, float saturationinverse) { float v2 = (value * saturationinverse > 1 ? 1 : (value * saturationinverse < -1 ? -1: value * saturationinverse)); return (saturation * (v2 - (1./3.) * v2 * v2 * v2)); } #define HZ_TO_RAD(f) (MOOG_PI_2 * f) #define RAD_TO_HZ(omega) (MOOG_INV_PI_2 * omega) #ifdef __GNUC__ #define ctz(N) __builtin_ctz(N) #else template inline int ctz(T x) { int p, b; for (p = 0, b = 1; !(b & x); b <<= 1, ++p) ; return p; } #endif inline double fast_tanh(double x) { double x2 = x * x; return x * (27.0 + x2) / (27.0 + 9.0 * x2); } #endif ================================================ FILE: lib/SAM/README.md ================================================ https://github.com/s-macke/SAM SAM === Software Automatic Mouth - Tiny Speech Synthesizer What is SAM? ============ Sam is a very small Text-To-Speech (TTS) program written in C, that runs on most popular platforms. It is an adaption to C of the speech software SAM (Software Automatic Mouth) for the Commodore C64 published in the year 1982 by Don't Ask Software (now SoftVoice, Inc.). It includes a Text-To-Phoneme converter called reciter and a Phoneme-To-Speech routine for the final output. It is so small that it will work also on embedded computers. On my computer it takes less than 39KB (much smaller on embedded devices as the executable-overhead is not necessary) of disk space and is a fully stand alone program. For immediate output it uses the SDL-library, otherwise it can save .wav files. An online version and executables for Windows can be found on the web site: http://simulationcorner.net/index.php?page=sam Compile ======= Simply type "make" in your command prompt. In order to compile without SDL remove the SDL statements from the CFLAGS and LFLAGS variables in the file "Makefile". It should compile on every UNIX-like operating system. For Windows you need Cygwin or MinGW( + libsdl). Fork ==== Take a look at https://github.com/vidarh/SAM for a more refactored and cleaner version of the code. Usage ===== type ./sam I am Sam for the first output. If you have disabled SDL try ./sam -wav i_am_sam.wav I am Sam to get a wav file. This file can be played by many media players available for the PC. you can try other options like -pitch number -speed number -throat number -mouth number Some typical values written in the original manual are: DESCRIPTION SPEED PITCH THROAT MOUTH Elf 72 64 110 160 Little Robot 92 60 190 190 Stuffy Guy 82 72 110 105 Little Old Lady 82 32 145 145 Extra-Terrestrial 100 64 150 200 SAM 72 64 128 128 It can even sing look at the file "sing" for a small example. For the phoneme input table look in the Wiki. A description of additional features can be found in the original manual at http://www.retrobits.net/atari/sam.shtml or in the manual of the equivalent Apple II program http://www.apple-iigs.info/newdoc/sam.pdf Adaption To C ============= This program (disassembly at http://hitmen.c02.at/html/tools_sam.html) was converted semi-automatic into C by converting each assembler opcode. e. g. lda 56 => A = mem[56]; jmp 38018 => goto pos38018; inc 38 => mem[38]++; . . . . Then it was manually rewritten to remove most of the jumps and register variables in the code and rename the variables to proper names. Most of the description below is a result of this rewriting process. Unfortunately it is still unreadable. But you should see from where I started :) Short description ================= First of all I will limit myself here to a very coarse description. There are very many exceptions defined in the source code that I will not explain. Also a lot of code is unknown for me e. g. Code47503. For a complete understanding of the code I need more time and especially more eyes have a look on the code. Reciter ------- It changes the english text to phonemes by a ruleset shown in the wiki. The rule " ANT(I)", "AY", means that if he find an "I" with previous letters " ANT", exchange the I by the phoneme "AY". There are some special signs in this rules like # & @ ^ + : % which can mean e. g. that there must be a vocal or a consonant or something else. With the -debug option you will get the corresponding rules and the resulting phonemes. Output ------ Here is the full tree of subroutine calls: SAMMain() Parser1() Parser2() Insert() CopyStress() SetPhonemeLength() Code48619() Code41240() Insert() Code48431() Insert() Code48547 Code47574 Special1 Code47503 Code48227 SAMMain() is the entry routine and calls all further routines. Parser1 transforms the phoneme input and transforms it to three tables phonemeindex[] stress[] phonemelength[] (zero at this moment) This tables are now changed: Parser2 exchanges some phonemes by others and inserts new. CopyStress adds 1 to the stress under some circumstances SetPhonemeLength sets phoneme lengths. Code48619 changes the phoneme lengths Code41240 adds some additional phonemes Code48431 has some extra rules The wiki shows all possible phonemes and some flag fields. The final content of these tables can be seen with the -debug command. In the function PrepareOutput() these tables are partly copied into the small tables: phonemeindexOutput[] stressOutput[] phonemelengthOutput[] for output. Final Output ------------ Except of some special phonemes the output is build by a linear combination: A = A1 * sin ( f1 * t ) + A2 * sin ( f2 * t ) + A3 * rect( f3 * t ) where rect is a rectangular function with the same periodicity like sin. It seems really strange, but this is really enough for most types of phonemes. Therefore the above phonemes are converted with some tables to pitches[] frequency1[] = f1 frequency2[] = f2 frequency3[] = f3 amplitude1[] = A1 amplitude2[] = A2 amplitude3[] = A3 Above formula is calculated in one very good omptimized routine. It only consist of 26 commands: 48087: LDX 43 ; get phase CLC LDA 42240,x ; load sine value (high 4 bits) ORA TabAmpl1,y ; get amplitude (in low 4 bits) TAX LDA 42752,x ; multiplication table STA 56 ; store LDX 42 ; get phase LDA 42240,x ; load sine value (high 4 bits) ORA TabAmpl2,y ; get amplitude (in low 4 bits) TAX LDA 42752,x ; multiplication table ADC Var56 ; add with previous values STA 56 ; and store LDX 41 ; get phase LDA 42496,x ; load rect value (high 4 bits) ORA TabAmpl3,y ; get amplitude (in low 4 bits) TAX LDA 42752,x ; multiplication table ADC 56 ; add with previous values ADC #136 LSR A ; get highest 4 bits LSR A LSR A LSR A STA 54296 ;SID main output command The rest is handled in a special way. At the moment I cannot figure out in which way. But it seems that it uses some noise (e. g. for "s") using a table with random values. License ======= The software is a reverse-engineered version of a software published more than 34 years ago by "Don't ask Software". The company no longer exists. Any attempt to contact the original authors failed. Hence S.A.M. can be best described as Abandonware (http://en.wikipedia.org/wiki/Abandonware) As long this is the case I cannot put my code under any specific open source software license. However the software might be used under the "Fair Use" act (https://en.wikipedia.org/wiki/FAIR_USE_Act) in the USA. Contact ======= If you have questions don' t hesitate to ask me. If you discovered some new knowledge about the code please mail me. Sebastian Macke Email: sebastian@macke.de ================================================ FILE: lib/SAM/ReciterTabs.h ================================================ #ifndef RECITERTABS_H #define RECITERTABS_H //some flags const unsigned char tab36376[] = { 0, 0, 0, 0, 0, 0, 0, 0, // 0-7 0, 0, 0, 0, 0, 0, 0, 0, // 8-15 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 130, // ' ', '!' 0, 0, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 192, 168, 176, 172, 192, 160, 184, // '@', 'A' 160, 192, 188, 160, 172, 168, 172, 192, 160, 160, 172, 180, 164, 192, 168, 168, 176, 192, 188, 0, 0, 0, 2, 0, // 'X', 'Y', 'Z', '[', 32, 32, 155, 32, 192, 185, 32, 205, 163, 76, 138, 142 }; const unsigned char rules[] = { ']','A'|0x80, ' ','(','A','.',')', '=','E','H','4','Y','.',' '|0x80, '(','A',')',' ', '=','A','H'|0x80, ' ','(','A','R','E',')',' ', '=','A','A','R'|0x80, ' ','(','A','R',')','O', '=','A','X','R'|0x80, '(','A','R',')','#', '=','E','H','4','R'|0x80, ' ','^','(','A','S',')','#', '=','E','Y','4','S'|0x80, '(','A',')','W','A', '=','A','X'|0x80, '(','A','W',')', '=','A','O','5'|0x80, ' ',':','(','A','N','Y',')', '=','E','H','4','N','I','Y'|0x80, '(','A',')','^','+','#', '=','E','Y','5'|0x80, '#',':','(','A','L','L','Y',')', '=','U','L','I','Y'|0x80, ' ','(','A','L',')','#', '=','U','L'|0x80, '(','A','G','A','I','N',')', '=','A','X','G','E','H','4','N'|0x80, '#',':','(','A','G',')','E', '=','I','H','J'|0x80, '(','A',')','^','%', '=','E','Y'|0x80, '(','A',')','^','+',':','#', '=','A','E'|0x80, ' ',':','(','A',')','^','+',' ', '=','E','Y','4'|0x80, ' ','(','A','R','R',')', '=','A','X','R'|0x80, '(','A','R','R',')', '=','A','E','4','R'|0x80, ' ','^','(','A','R',')',' ', '=','A','A','5','R'|0x80, '(','A','R',')', '=','A','A','5','R'|0x80, '(','A','I','R',')', '=','E','H','4','R'|0x80, '(','A','I',')', '=','E','Y','4'|0x80, '(','A','Y',')', '=','E','Y','5'|0x80, '(','A','U',')', '=','A','O','4'|0x80, '#',':','(','A','L',')',' ', '=','U','L'|0x80, '#',':','(','A','L','S',')',' ', '=','U','L','Z'|0x80, '(','A','L','K',')', '=','A','O','4','K'|0x80, '(','A','L',')','^', '=','A','O','L'|0x80, ' ',':','(','A','B','L','E',')', '=','E','Y','4','B','U','L'|0x80, '(','A','B','L','E',')', '=','A','X','B','U','L'|0x80, '(','A',')','V','O', '=','E','Y','4'|0x80, '(','A','N','G',')','+', '=','E','Y','4','N','J'|0x80, '(','A','T','A','R','I',')', '=','A','H','T','A','A','4','R','I','Y'|0x80, '(','A',')','T','O','M', '=','A','E'|0x80, '(','A',')','T','T','I', '=','A','E'|0x80, ' ','(','A','T',')',' ', '=','A','E','T'|0x80, ' ','(','A',')','T', '=','A','H'|0x80, '(','A',')', '=','A','E'|0x80, ']','B'|0x80, ' ','(','B',')',' ', '=','B','I','Y','4'|0x80, ' ','(','B','E',')','^','#', '=','B','I','H'|0x80, '(','B','E','I','N','G',')', '=','B','I','Y','4','I','H','N','X'|0x80, ' ','(','B','O','T','H',')',' ', '=','B','O','W','4','T','H'|0x80, ' ','(','B','U','S',')','#', '=','B','I','H','4','Z'|0x80, '(','B','R','E','A','K',')', '=','B','R','E','Y','5','K'|0x80, '(','B','U','I','L',')', '=','B','I','H','4','L'|0x80, '(','B',')', '=','B'|0x80, ']','C'|0x80, ' ','(','C',')',' ', '=','S','I','Y','4'|0x80, ' ','(','C','H',')','^', '=','K'|0x80, '^','E','(','C','H',')', '=','K'|0x80, '(','C','H','A',')','R','#', '=','K','E','H','5'|0x80, '(','C','H',')', '=','C','H'|0x80, ' ','S','(','C','I',')','#', '=','S','A','Y','4'|0x80, '(','C','I',')','A', '=','S','H'|0x80, '(','C','I',')','O', '=','S','H'|0x80, '(','C','I',')','E','N', '=','S','H'|0x80, '(','C','I','T','Y',')', '=','S','I','H','T','I','Y'|0x80, '(','C',')','+', '=','S'|0x80, '(','C','K',')', '=','K'|0x80, '(','C','O','M','M','O','D','O','R','E',')','=','K','A','A','4','M','A','H','D','O','H','R'|0x80, '(','C','O','M',')', '=','K','A','H','M'|0x80, '(','C','U','I','T',')', '=','K','I','H','T'|0x80, '(','C','R','E','A',')', '=','K','R','I','Y','E','Y'|0x80, '(','C',')', '=','K'|0x80, ']','D'|0x80, ' ','(','D',')',' ', '=','D','I','Y','4'|0x80, ' ','(','D','R','.',')',' ', '=','D','A','A','4','K','T','E','R'|0x80, '#',':','(','D','E','D',')',' ', '=','D','I','H','D'|0x80, '.','E','(','D',')',' ', '=','D'|0x80, '#',':','^','E','(','D',')',' ', '=','T'|0x80, ' ','(','D','E',')','^','#', '=','D','I','H'|0x80, ' ','(','D','O',')',' ', '=','D','U','W'|0x80, ' ','(','D','O','E','S',')', '=','D','A','H','Z'|0x80, '(','D','O','N','E',')',' ', '=','D','A','H','5','N'|0x80, '(','D','O','I','N','G',')', '=','D','U','W','4','I','H','N','X'|0x80, ' ','(','D','O','W',')', '=','D','A','W'|0x80, '#','(','D','U',')','A', '=','J','U','W'|0x80, '#','(','D','U',')','^','#', '=','J','A','X'|0x80, '(','D',')', '=','D'|0x80, ']','E'|0x80, ' ','(','E',')',' ', '=','I','Y','I','Y','4'|0x80, '#',':','(','E',')',' ','='|0x80, '\'',':','^','(','E',')',' ','='|0x80, ' ',':','(','E',')',' ', '=','I','Y'|0x80, '#','(','E','D',')',' ', '=','D'|0x80, '#',':','(','E',')','D',' ','='|0x80, '(','E','V',')','E','R', '=','E','H','4','V'|0x80, '(','E',')','^','%', '=','I','Y','4'|0x80, '(','E','R','I',')','#', '=','I','Y','4','R','I','Y'|0x80, '(','E','R','I',')', '=','E','H','4','R','I','H'|0x80, '#',':','(','E','R',')','#', '=','E','R'|0x80, '(','E','R','R','O','R',')', '=','E','H','4','R','O','H','R'|0x80, '(','E','R','A','S','E',')', '=','I','H','R','E','Y','5','S'|0x80, '(','E','R',')','#', '=','E','H','R'|0x80, '(','E','R',')', '=','E','R'|0x80, ' ','(','E','V','E','N',')', '=','I','Y','V','E','H','N'|0x80, '#',':','(','E',')','W','='|0x80, '@','(','E','W',')', '=','U','W'|0x80, '(','E','W',')', '=','Y','U','W'|0x80, '(','E',')','O', '=','I','Y'|0x80, '#',':','&','(','E','S',')',' ', '=','I','H','Z'|0x80, '#',':','(','E',')','S',' ','='|0x80, '#',':','(','E','L','Y',')',' ', '=','L','I','Y'|0x80, '#',':','(','E','M','E','N','T',')', '=','M','E','H','N','T'|0x80, '(','E','F','U','L',')', '=','F','U','H','L'|0x80, '(','E','E',')', '=','I','Y','4'|0x80, '(','E','A','R','N',')', '=','E','R','5','N'|0x80, ' ','(','E','A','R',')','^', '=','E','R','5'|0x80, '(','E','A','D',')', '=','E','H','D'|0x80, '#',':','(','E','A',')',' ', '=','I','Y','A','X'|0x80, '(','E','A',')','S','U', '=','E','H','5'|0x80, '(','E','A',')', '=','I','Y','5'|0x80, '(','E','I','G','H',')', '=','E','Y','4'|0x80, '(','E','I',')', '=','I','Y','4'|0x80, ' ','(','E','Y','E',')', '=','A','Y','4'|0x80, '(','E','Y',')', '=','I','Y'|0x80, '(','E','U',')', '=','Y','U','W','5'|0x80, '(','E','Q','U','A','L',')', '=','I','Y','4','K','W','U','L'|0x80, '(','E',')', '=','E','H'|0x80, ']','F'|0x80, ' ','(','F',')',' ', '=','E','H','4','F'|0x80, '(','F','U','L',')', '=','F','U','H','L'|0x80, '(','F','R','I','E','N','D',')', '=','F','R','E','H','5','N','D'|0x80, '(','F','A','T','H','E','R',')', '=','F','A','A','4','D','H','E','R'|0x80, '(','F',')','F','='|0x80, '(','F',')', '=','F'|0x80, ']','G'|0x80, ' ','(','G',')',' ', '=','J','I','Y','4'|0x80, '(','G','I','V',')', '=','G','I','H','5','V'|0x80, ' ','(','G',')','I','^', '=','G'|0x80, '(','G','E',')','T', '=','G','E','H','5'|0x80, 'S','U','(','G','G','E','S',')', '=','G','J','E','H','4','S'|0x80, '(','G','G',')', '=','G'|0x80, ' ','B','#','(','G',')', '=','G'|0x80, '(','G',')','+', '=','J'|0x80, '(','G','R','E','A','T',')', '=','G','R','E','Y','4','T'|0x80, '(','G','O','N',')','E', '=','G','A','O','5','N'|0x80, '#','(','G','H',')','='|0x80, ' ','(','G','N',')', '=','N'|0x80, '(','G',')', '=','G'|0x80, ']','H'|0x80, ' ','(','H',')',' ', '=','E','Y','4','C','H'|0x80, ' ','(','H','A','V',')', '=','/','H','A','E','6','V'|0x80, ' ','(','H','E','R','E',')', '=','/','H','I','Y','R'|0x80, ' ','(','H','O','U','R',')', '=','A','W','5','E','R'|0x80, '(','H','O','W',')', '=','/','H','A','W'|0x80, '(','H',')','#', '=','/','H'|0x80, '(','H',')','='|0x80, ']','I'|0x80, ' ','(','I','N',')', '=','I','H','N'|0x80, ' ','(','I',')',' ', '=','A','Y','4'|0x80, '(','I',')',' ', '=','A','Y'|0x80, '(','I','N',')','D', '=','A','Y','5','N'|0x80, 'S','E','M','(','I',')', '=','I','Y'|0x80, ' ','A','N','T','(','I',')', '=','A','Y'|0x80, '(','I','E','R',')', '=','I','Y','E','R'|0x80, '#',':','R','(','I','E','D',')',' ', '=','I','Y','D'|0x80, '(','I','E','D',')',' ', '=','A','Y','5','D'|0x80, '(','I','E','N',')', '=','I','Y','E','H','N'|0x80, '(','I','E',')','T', '=','A','Y','4','E','H'|0x80, '(','I','\'',')', '=','A','Y','5'|0x80, ' ',':','(','I',')','^','%', '=','A','Y','5'|0x80, ' ',':','(','I','E',')',' ', '=','A','Y','4'|0x80, '(','I',')','%', '=','I','Y'|0x80, '(','I','E',')', '=','I','Y','4'|0x80, ' ','(','I','D','E','A',')', '=','A','Y','D','I','Y','5','A','H'|0x80, '(','I',')','^','+',':','#', '=','I','H'|0x80, '(','I','R',')','#', '=','A','Y','R'|0x80, '(','I','Z',')','%', '=','A','Y','Z'|0x80, '(','I','S',')','%', '=','A','Y','Z'|0x80, 'I','^','(','I',')','^','#', '=','I','H'|0x80, '+','^','(','I',')','^','+', '=','A','Y'|0x80, '#',':','^','(','I',')','^','+', '=','I','H'|0x80, '(','I',')','^','+', '=','A','Y'|0x80, '(','I','R',')', '=','E','R'|0x80, '(','I','G','H',')', '=','A','Y','4'|0x80, '(','I','L','D',')', '=','A','Y','5','L','D'|0x80, ' ','(','I','G','N',')', '=','I','H','G','N'|0x80, '(','I','G','N',')',' ', '=','A','Y','4','N'|0x80, '(','I','G','N',')','^', '=','A','Y','4','N'|0x80, '(','I','G','N',')','%', '=','A','Y','4','N'|0x80, '(','I','C','R','O',')', '=','A','Y','4','K','R','O','H'|0x80, '(','I','Q','U','E',')', '=','I','Y','4','K'|0x80, '(','I',')', '=','I','H'|0x80, ']','J'|0x80, ' ','(','J',')',' ', '=','J','E','Y','4'|0x80, '(','J',')', '=','J'|0x80, ']','K'|0x80, ' ','(','K',')',' ', '=','K','E','Y','4'|0x80, ' ','(','K',')','N','='|0x80, '(','K',')', '=','K'|0x80, ']','L'|0x80, ' ','(','L',')',' ', '=','E','H','4','L'|0x80, '(','L','O',')','C','#', '=','L','O','W'|0x80, 'L','(','L',')','='|0x80, '#',':','^','(','L',')','%', '=','U','L'|0x80, '(','L','E','A','D',')', '=','L','I','Y','D'|0x80, ' ','(','L','A','U','G','H',')', '=','L','A','E','4','F'|0x80, '(','L',')', '=','L'|0x80, ']','M'|0x80, ' ','(','M',')',' ', '=','E','H','4','M'|0x80, ' ','(','M','R','.',')',' ', '=','M','I','H','4','S','T','E','R'|0x80, ' ','(','M','S','.',')', '=','M','I','H','5','Z'|0x80, ' ','(','M','R','S','.',')',' ', '=','M','I','H','4','S','I','X','Z'|0x80, '(','M','O','V',')', '=','M','U','W','4','V'|0x80, '(','M','A','C','H','I','N',')', '=','M','A','H','S','H','I','Y','5','N'|0x80, 'M','(','M',')','='|0x80, '(','M',')', '=','M'|0x80, ']','N'|0x80, ' ','(','N',')',' ', '=','E','H','4','N'|0x80, 'E','(','N','G',')','+', '=','N','J'|0x80, '(','N','G',')','R', '=','N','X','G'|0x80, '(','N','G',')','#', '=','N','X','G'|0x80, '(','N','G','L',')','%', '=','N','X','G','U','L'|0x80, '(','N','G',')', '=','N','X'|0x80, '(','N','K',')', '=','N','X','K'|0x80, ' ','(','N','O','W',')',' ', '=','N','A','W','4'|0x80, 'N','(','N',')','='|0x80, '(','N','O','N',')','E', '=','N','A','H','4','N'|0x80, '(','N',')', '=','N'|0x80, ']','O'|0x80, ' ','(','O',')',' ', '=','O','H','4','W'|0x80, '(','O','F',')',' ', '=','A','H','V'|0x80, ' ','(','O','H',')',' ', '=','O','W','5'|0x80, '(','O','R','O','U','G','H',')', '=','E','R','4','O','W'|0x80, '#',':','(','O','R',')',' ', '=','E','R'|0x80, '#',':','(','O','R','S',')',' ', '=','E','R','Z'|0x80, '(','O','R',')', '=','A','O','R'|0x80, ' ','(','O','N','E',')', '=','W','A','H','N'|0x80, '#','(','O','N','E',')',' ', '=','W','A','H','N'|0x80, '(','O','W',')', '=','O','W'|0x80, ' ','(','O','V','E','R',')', '=','O','W','5','V','E','R'|0x80, 'P','R','(','O',')','V', '=','U','W','4'|0x80, '(','O','V',')', '=','A','H','4','V'|0x80, '(','O',')','^','%', '=','O','W','5'|0x80, '(','O',')','^','E','N', '=','O','W'|0x80, '(','O',')','^','I','#', '=','O','W','5'|0x80, '(','O','L',')','D', '=','O','W','4','L'|0x80, '(','O','U','G','H','T',')', '=','A','O','5','T'|0x80, '(','O','U','G','H',')', '=','A','H','5','F'|0x80, ' ','(','O','U',')', '=','A','W'|0x80, 'H','(','O','U',')','S','#', '=','A','W','4'|0x80, '(','O','U','S',')', '=','A','X','S'|0x80, '(','O','U','R',')', '=','O','H','R'|0x80, '(','O','U','L','D',')', '=','U','H','5','D'|0x80, '(','O','U',')','^','L', '=','A','H','5'|0x80, '(','O','U','P',')', '=','U','W','5','P'|0x80, '(','O','U',')', '=','A','W'|0x80, '(','O','Y',')', '=','O','Y'|0x80, '(','O','I','N','G',')', '=','O','W','4','I','H','N','X'|0x80, '(','O','I',')', '=','O','Y','5'|0x80, '(','O','O','R',')', '=','O','H','5','R'|0x80, '(','O','O','K',')', '=','U','H','5','K'|0x80, 'F','(','O','O','D',')', '=','U','W','5','D'|0x80, 'L','(','O','O','D',')', '=','A','H','5','D'|0x80, 'M','(','O','O','D',')', '=','U','W','5','D'|0x80, '(','O','O','D',')', '=','U','H','5','D'|0x80, 'F','(','O','O','T',')', '=','U','H','5','T'|0x80, '(','O','O',')', '=','U','W','5'|0x80, '(','O','\'',')', '=','O','H'|0x80, '(','O',')','E', '=','O','W'|0x80, '(','O',')',' ', '=','O','W'|0x80, '(','O','A',')', '=','O','W','4'|0x80, ' ','(','O','N','L','Y',')', '=','O','W','4','N','L','I','Y'|0x80, ' ','(','O','N','C','E',')', '=','W','A','H','4','N','S'|0x80, '(','O','N','\'','T',')', '=','O','W','4','N','T'|0x80, 'C','(','O',')','N', '=','A','A'|0x80, '(','O',')','N','G', '=','A','O'|0x80, ' ',':','^','(','O',')','N', '=','A','H'|0x80, 'I','(','O','N',')', '=','U','N'|0x80, '#',':','(','O','N',')', '=','U','N'|0x80, '#','^','(','O','N',')', '=','U','N'|0x80, '(','O',')','S','T', '=','O','W'|0x80, '(','O','F',')','^', '=','A','O','4','F'|0x80, '(','O','T','H','E','R',')', '=','A','H','5','D','H','E','R'|0x80, 'R','(','O',')','B', '=','R','A','A'|0x80, '^','R','(','O',')',':','#', '=','O','W','5'|0x80, '(','O','S','S',')',' ', '=','A','O','5','S'|0x80, '#',':','^','(','O','M',')', '=','A','H','M'|0x80, '(','O',')', '=','A','A'|0x80, ']','P'|0x80, ' ','(','P',')',' ', '=','P','I','Y','4'|0x80, '(','P','H',')', '=','F'|0x80, '(','P','E','O','P','L',')', '=','P','I','Y','5','P','U','L'|0x80, '(','P','O','W',')', '=','P','A','W','4'|0x80, '(','P','U','T',')',' ', '=','P','U','H','T'|0x80, '(','P',')','P','='|0x80, '(','P',')','S','='|0x80, '(','P',')','N','='|0x80, '(','P','R','O','F','.',')', '=','P','R','O','H','F','E','H','4','S','E','R'|0x80, '(','P',')', '=','P'|0x80, ']','Q'|0x80, ' ','(','Q',')',' ', '=','K','Y','U','W','4'|0x80, '(','Q','U','A','R',')', '=','K','W','O','H','5','R'|0x80, '(','Q','U',')', '=','K','W'|0x80, '(','Q',')', '=','K'|0x80, ']','R'|0x80, ' ','(','R',')',' ', '=','A','A','5','R'|0x80, ' ','(','R','E',')','^','#', '=','R','I','Y'|0x80, '(','R',')','R','='|0x80, '(','R',')', '=','R'|0x80, ']','S'|0x80, ' ','(','S',')',' ', '=','E','H','4','S'|0x80, '(','S','H',')', '=','S','H'|0x80, '#','(','S','I','O','N',')', '=','Z','H','U','N'|0x80, '(','S','O','M','E',')', '=','S','A','H','M'|0x80, '#','(','S','U','R',')','#', '=','Z','H','E','R'|0x80, '(','S','U','R',')','#', '=','S','H','E','R'|0x80, '#','(','S','U',')','#', '=','Z','H','U','W'|0x80, '#','(','S','S','U',')','#', '=','S','H','U','W'|0x80, '#','(','S','E','D',')', '=','Z','D'|0x80, '#','(','S',')','#', '=','Z'|0x80, '(','S','A','I','D',')', '=','S','E','H','D'|0x80, '^','(','S','I','O','N',')', '=','S','H','U','N'|0x80, '(','S',')','S','='|0x80, '.','(','S',')',' ', '=','Z'|0x80, '#',':','.','E','(','S',')',' ', '=','Z'|0x80, '#',':','^','#','(','S',')',' ', '=','S'|0x80, 'U','(','S',')',' ', '=','S'|0x80, ' ',':','#','(','S',')',' ', '=','Z'|0x80, '#','#','(','S',')',' ', '=','Z'|0x80, ' ','(','S','C','H',')', '=','S','K'|0x80, '(','S',')','C','+','='|0x80, '#','(','S','M',')', '=','Z','U','M'|0x80, '#','(','S','N',')','\'', '=','Z','U','M'|0x80, '(','S','T','L','E',')', '=','S','U','L'|0x80, '(','S',')', '=','S'|0x80, ']','T'|0x80, ' ','(','T',')',' ', '=','T','I','Y','4'|0x80, ' ','(','T','H','E',')',' ','#', '=','D','H','I','Y'|0x80, ' ','(','T','H','E',')',' ', '=','D','H','A','X'|0x80, '(','T','O',')',' ', '=','T','U','X'|0x80, ' ','(','T','H','A','T',')', '=','D','H','A','E','T'|0x80, ' ','(','T','H','I','S',')',' ', '=','D','H','I','H','S'|0x80, ' ','(','T','H','E','Y',')', '=','D','H','E','Y'|0x80, ' ','(','T','H','E','R','E',')', '=','D','H','E','H','R'|0x80, '(','T','H','E','R',')', '=','D','H','E','R'|0x80, '(','T','H','E','I','R',')', '=','D','H','E','H','R'|0x80, ' ','(','T','H','A','N',')',' ', '=','D','H','A','E','N'|0x80, ' ','(','T','H','E','M',')',' ', '=','D','H','A','E','N'|0x80, '(','T','H','E','S','E',')',' ', '=','D','H','I','Y','Z'|0x80, ' ','(','T','H','E','N',')', '=','D','H','E','H','N'|0x80, '(','T','H','R','O','U','G','H',')', '=','T','H','R','U','W','4'|0x80, '(','T','H','O','S','E',')', '=','D','H','O','H','Z'|0x80, '(','T','H','O','U','G','H',')',' ', '=','D','H','O','W'|0x80, '(','T','O','D','A','Y',')', '=','T','U','X','D','E','Y'|0x80, '(','T','O','M','O',')','R','R','O','W','=','T','U','M','A','A','5'|0x80, '(','T','O',')','T','A','L', '=','T','O','W','5'|0x80, ' ','(','T','H','U','S',')', '=','D','H','A','H','4','S'|0x80, '(','T','H',')', '=','T','H'|0x80, '#',':','(','T','E','D',')', '=','T','I','X','D'|0x80, 'S','(','T','I',')','#','N', '=','C','H'|0x80, '(','T','I',')','O', '=','S','H'|0x80, '(','T','I',')','A', '=','S','H'|0x80, '(','T','I','E','N',')', '=','S','H','U','N'|0x80, '(','T','U','R',')','#', '=','C','H','E','R'|0x80, '(','T','U',')','A', '=','C','H','U','W'|0x80, ' ','(','T','W','O',')', '=','T','U','W'|0x80, '&','(','T',')','E','N',' ','='|0x80, '(','T',')', '=','T'|0x80, ']','U'|0x80, ' ','(','U',')',' ', '=','Y','U','W','4'|0x80, ' ','(','U','N',')','I', '=','Y','U','W','N'|0x80, ' ','(','U','N',')', '=','A','H','N'|0x80, ' ','(','U','P','O','N',')', '=','A','X','P','A','O','N'|0x80, '@','(','U','R',')','#', '=','U','H','4','R'|0x80, '(','U','R',')','#', '=','Y','U','H','4','R'|0x80, '(','U','R',')', '=','E','R'|0x80, '(','U',')','^',' ', '=','A','H'|0x80, '(','U',')','^','^', '=','A','H','5'|0x80, '(','U','Y',')', '=','A','Y','5'|0x80, ' ','G','(','U',')','#','='|0x80, 'G','(','U',')','%','='|0x80, 'G','(','U',')','#', '=','W'|0x80, '#','N','(','U',')', '=','Y','U','W'|0x80, '@','(','U',')', '=','U','W'|0x80, '(','U',')', '=','Y','U','W'|0x80, ']','V'|0x80, ' ','(','V',')',' ', '=','V','I','Y','4'|0x80, '(','V','I','E','W',')', '=','V','Y','U','W','5'|0x80, '(','V',')', '=','V'|0x80, ']','W'|0x80, ' ','(','W',')',' ', '=','D','A','H','4','B','U','L','Y','U','W'|0x80, ' ','(','W','E','R','E',')', '=','W','E','R'|0x80, '(','W','A',')','S','H', '=','W','A','A'|0x80, '(','W','A',')','S','T', '=','W','E','Y'|0x80, '(','W','A',')','S', '=','W','A','H'|0x80, '(','W','A',')','T', '=','W','A','A'|0x80, '(','W','H','E','R','E',')', '=','W','H','E','H','R'|0x80, '(','W','H','A','T',')', '=','W','H','A','H','T'|0x80, '(','W','H','O','L',')', '=','/','H','O','W','L'|0x80, '(','W','H','O',')', '=','/','H','U','W'|0x80, '(','W','H',')', '=','W','H'|0x80, '(','W','A','R',')','#', '=','W','E','H','R'|0x80, '(','W','A','R',')', '=','W','A','O','R'|0x80, '(','W','O','R',')','^', '=','W','E','R'|0x80, '(','W','R',')', '=','R'|0x80, '(','W','O','M',')','A', '=','W','U','H','M'|0x80, '(','W','O','M',')','E', '=','W','I','H','M'|0x80, '(','W','E','A',')','R', '=','W','E','H'|0x80, '(','W','A','N','T',')', '=','W','A','A','5','N','T'|0x80, 'A','N','S','(','W','E','R',')', '=','E','R'|0x80, '(','W',')', '=','W'|0x80, ']','X'|0x80, ' ','(','X',')',' ', '=','E','H','4','K','R'|0x80, ' ','(','X',')', '=','Z'|0x80, '(','X',')', '=','K','S'|0x80, ']','Y'|0x80, ' ','(','Y',')',' ', '=','W','A','Y','4'|0x80, '(','Y','O','U','N','G',')', '=','Y','A','H','N','X'|0x80, ' ','(','Y','O','U','R',')', '=','Y','O','H','R'|0x80, ' ','(','Y','O','U',')', '=','Y','U','W'|0x80, ' ','(','Y','E','S',')', '=','Y','E','H','S'|0x80, ' ','(','Y',')', '=','Y'|0x80, 'F','(','Y',')', '=','A','Y'|0x80, 'P','S','(','Y','C','H',')', '=','A','Y','K'|0x80, '#',':','^','(','Y',')', '=','I','Y'|0x80, '#',':','^','(','Y',')','I', '=','I','Y'|0x80, ' ',':','(','Y',')',' ', '=','A','Y'|0x80, ' ',':','(','Y',')','#', '=','A','Y'|0x80, ' ',':','(','Y',')','^','+',':','#', '=','I','H'|0x80, ' ',':','(','Y',')','^','#', '=','A','Y'|0x80, '(','Y',')', '=','I','H'|0x80, ']','Z'|0x80, ' ','(','Z',')',' ', '=','Z','I','Y','4'|0x80, '(','Z',')', '=','Z'|0x80, 'j'|0x80 }; const unsigned char rules2[] = { '(','A',')', '='|0x80, '(','!',')', '=','.'|0x80, '(','"',')',' ', '=','-','A','H','5','N','K','W','O','W','T','-'|0x80, '(','"',')', '=','K','W','O','W','4','T','-'|0x80, '(','#',')', '=',' ','N','A','H','4','M','B','E','R'|0x80, '(','$',')', '=',' ','D','A','A','4','L','E','R'|0x80, '(','%',')', '=',' ','P','E','R','S','E','H','4','N','T'|0x80, '(','&',')', '=',' ','A','E','N','D'|0x80, '(','\'',')', '='|0x80, '(','*',')', '=',' ','A','E','4','S','T','E','R','I','H','S','K'|0x80, '(','+',')', '=',' ','P','L','A','H','4','S'|0x80, '(',',',')', '=',','|0x80, ' ','(','-',')',' ', '=','-'|0x80, '(','-',')', '='|0x80, '(','.',')', '=',' ','P','O','Y','N','T'|0x80, '(','/',')', '=',' ','S','L','A','E','4','S','H'|0x80, '(','0',')', '=',' ','Z','I','Y','4','R','O','W'|0x80, ' ','(','1','S','T',')', '=','F','E','R','4','S','T'|0x80, ' ','(','1','0','T','H',')', '=','T','E','H','4','N','T','H'|0x80, '(','1',')', '=',' ','W','A','H','4','N'|0x80, ' ','(','2','N','D',')', '=','S','E','H','4','K','U','N','D'|0x80, '(','2',')', '=',' ','T','U','W','4'|0x80, ' ','(','3','R','D',')', '=','T','H','E','R','4','D'|0x80, '(','3',')', '=',' ','T','H','R','I','Y','4'|0x80, '(','4',')', '=',' ','F','O','H','4','R'|0x80, ' ','(','5','T','H',')', '=','F','I','H','4','F','T','H'|0x80, '(','5',')', '=',' ','F','A','Y','4','V'|0x80, ' ','(','6','4',')',' ', '=','S','I','H','4','K','S','T','I','Y',' ','F','O','H','R'|0x80, '(','6',')', '=',' ','S','I','H','4','K','S'|0x80, '(','7',')', '=',' ','S','E','H','4','V','U','N'|0x80, ' ','(','8','T','H',')', '=','E','Y','4','T','H'|0x80, '(','8',')', '=',' ','E','Y','4','T'|0x80, '(','9',')', '=',' ','N','A','Y','4','N'|0x80, '(',':',')', '=','.'|0x80, '(',';',')', '=','.'|0x80, '(','<',')', '=',' ','L','E','H','4','S',' ','D','H','A','E','N'|0x80, '(','=',')', '=',' ','I','Y','4','K','W','U','L','Z'|0x80, '(','>',')', '=',' ','G','R','E','Y','4','T','E','R',' ','D','H','A','E','N'|0x80, '(','?',')', '=','?'|0x80, '(','@',')', '=',' ','A','E','6','T'|0x80, '(','^',')', '=',' ','K','A','E','4','R','I','X','T'|0x80, ']','A'|0x80 }; //26 items. From 'A' to 'Z' // positions for mem62 and mem63 for each character const unsigned char tab37489[] = { 0, 149, 247, 162, 57, 197, 6, 126, 199, 38, 55, 78, 145, 241, 85, 161, 254, 36, 69, 45, 167, 54, 83, 46, 71, 218 }; const unsigned char tab37515[] = { 125, 126, 126, 127, 128, 129, 130, 130, 130, 132, 132, 132, 132, 132, 133, 135, 135, 136, 136, 137, 138, 139, 139, 140, 140, 140 }; #endif ================================================ FILE: lib/SAM/RenderTabs.h ================================================ #ifndef RENDERTABS_H #define RENDERTABS_H const unsigned char tab48426[5] = { 0x18, 0x1A, 0x17, 0x17, 0x17 }; const unsigned char tab47492[] = { 0 , 0 , 0xE0 , 0xE6 , 0xEC , 0xF3 , 0xF9 , 0 , 6 , 0xC , 6 }; const unsigned char amplitudeRescale[] = { 0 , 1 , 2 , 2 , 2 , 3 , 3 , 4 , 4 , 5 , 6 , 8 , 9 ,0xB ,0xD ,0xF, 0 //17 elements? }; // Used to decide which phoneme's blend lengths. The candidate with the lower score is selected. // tab45856 const unsigned char blendRank[] = { 0 , 0x1F , 0x1F , 0x1F , 0x1F , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 5 , 5 , 2 ,0xA , 2 , 8 , 5 , 5 ,0xB ,0xA , 9 , 8 , 8 , 0xA0 , 8 , 8 , 0x17 , 0x1F , 0x12 , 0x12 , 0x12 , 0x12 , 0x1E , 0x1E , 0x14 , 0x14 , 0x14 , 0x14 , 0x17 , 0x17 , 0x1A , 0x1A , 0x1D , 0x1D , 2 , 2 , 2 , 2 , 2 , 2 , 0x1A , 0x1D , 0x1B , 0x1A , 0x1D , 0x1B , 0x1A , 0x1D , 0x1B , 0x1A , 0x1D , 0x1B , 0x17 , 0x1D , 0x17 , 0x17 , 0x1D , 0x17 , 0x17 , 0x1D , 0x17 , 0x17 , 0x1D , 0x17 , 0x17 , 0x17 }; // Number of frames at the end of a phoneme devoted to interpolating to next phoneme's final value //tab45696 const unsigned char outBlendLength[] = { 0 , 2 , 2 , 2 , 2 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 3 , 2 , 4 , 4 , 2 , 2 , 2 , 2 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 1 , 0 , 1 , 0 , 1 , 0 , 5 , 5 , 5 , 5 , 5 , 4 , 4 , 2 , 0 , 1 , 2 , 0 , 1 , 2 , 0 , 1 , 2 , 0 , 1 , 2 , 0 , 2 , 2 , 0 , 1 , 3 , 0 , 2 , 3 , 0 , 2 , 0xA0 , 0xA0 }; // Number of frames at beginning of a phoneme devoted to interpolating to phoneme's final value // tab45776 const unsigned char inBlendLength[] = { 0 , 2 , 2 , 2 , 2 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 3 , 3 , 4 , 4 , 3 , 3 , 3 , 3 , 3 , 1 , 2 , 3 , 2 , 1 , 3 , 3 , 3 , 3 , 1 , 1 , 3 , 3 , 3 , 2 , 2 , 3 , 2 , 3 , 0 , 0 , 5 , 5 , 5 , 5 , 4 , 4 , 2 , 0 , 2 , 2 , 0 , 3 , 2 , 0 , 4 , 2 , 0 , 3 , 2 , 0 , 2 , 2 , 0 , 2 , 3 , 0 , 3 , 3 , 0 , 3 , 0xB0 , 0xA0 }; // Looks like it's used as bit flags // High bits masked by 248 (11111000) // // 32: S* 241 11110001 // 33: SH 226 11100010 // 34: F* 211 11010011 // 35: TH 187 10111011 // 36: /H 124 01111100 // 37: /X 149 10010101 // 38: Z* 1 00000001 // 39: ZH 2 00000010 // 40: V* 3 00000011 // 41: DH 3 00000011 // 43: ** 114 01110010 // 45: ** 2 00000010 // 67: ** 27 00011011 // 70: ** 25 00011001 // tab45936 const unsigned char sampledConsonantFlags[] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0xF1 , 0xE2 , 0xD3 , 0xBB , 0x7C , 0x95 , 1 , 2 , 3 , 3 , 0 , 0x72 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x1B , 0 , 0 , 0x19 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }; //tab45056 unsigned char freq1data[]= { 0x00 ,0x13 ,0x13 ,0x13 ,0x13 , 0xA , 0xE ,0x12 , 0x18 ,0x1A ,0x16 ,0x14 ,0x10 ,0x14 , 0xE ,0x12 , 0xE ,0x12 ,0x12 ,0x10 , 0xC , 0xE , 0xA ,0x12 , 0xE ,0xA , 8 , 6 , 6 , 6 , 6 ,0x11 , 6 , 6 , 6 , 6 ,0xE , 0x10 , 9 ,0xA , 8 ,0xA , 6 , 6 , 6 , 5 , 6 , 0 , 0x12 , 0x1A , 0x14 , 0x1A , 0x12 ,0xC , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 ,0xA ,0xA , 6 , 6 , 6 , 0x2C , 0x13 }; //tab451356 unsigned char freq2data[]= { 0x00 , 0x43 , 0x43 , 0x43 , 0x43 , 0x54 , 0x48 , 0x42 , 0x3E , 0x28 , 0x2C , 0x1E , 0x24 , 0x2C , 0x48 , 0x30 , 0x24 , 0x1E , 0x32 , 0x24 , 0x1C , 0x44 , 0x18 , 0x32 , 0x1E , 0x18 , 0x52 , 0x2E , 0x36 , 0x56 , 0x36 , 0x43 , 0x49 , 0x4F , 0x1A , 0x42 , 0x49 , 0x25 , 0x33 , 0x42 , 0x28 , 0x2F , 0x4F , 0x4F , 0x42 , 0x4F , 0x6E , 0x00 , 0x48 , 0x26 , 0x1E , 0x2A , 0x1E , 0x22 , 0x1A , 0x1A , 0x1A , 0x42 , 0x42 , 0x42 , 0x6E , 0x6E , 0x6E , 0x54 , 0x54 , 0x54 , 0x1A , 0x1A , 0x1A , 0x42 , 0x42 , 0x42 , 0x6D , 0x56 , 0x6D , 0x54 , 0x54 , 0x54 , 0x7F , 0x7F }; //tab45216 unsigned char freq3data[]= { 0x00 , 0x5B , 0x5B , 0x5B , 0x5B , 0x6E , 0x5D , 0x5B , 0x58 , 0x59 , 0x57 , 0x58 , 0x52 , 0x59 , 0x5D , 0x3E , 0x52 , 0x58 , 0x3E , 0x6E , 0x50 , 0x5D , 0x5A , 0x3C , 0x6E , 0x5A , 0x6E , 0x51 , 0x79 , 0x65 , 0x79 , 0x5B , 0x63 , 0x6A , 0x51 , 0x79 , 0x5D , 0x52 , 0x5D , 0x67 , 0x4C , 0x5D , 0x65 , 0x65 , 0x79 , 0x65 , 0x79 , 0x00 , 0x5A , 0x58 , 0x58 , 0x58 , 0x58 , 0x52 , 0x51 , 0x51 , 0x51 , 0x79 , 0x79 , 0x79 , 0x70 , 0x6E , 0x6E , 0x5E , 0x5E , 0x5E , 0x51 , 0x51 , 0x51 , 0x79 , 0x79 , 0x79 , 0x65 , 0x65 , 0x70 , 0x5E , 0x5E , 0x5E , 0x08 , 0x01 }; const unsigned char ampl1data[] = { 0 , 0 , 0 , 0 , 0 ,0xD ,0xD ,0xE , 0xF ,0xF ,0xF ,0xF ,0xF ,0xC ,0xD ,0xC , 0xF ,0xF ,0xD ,0xD ,0xD ,0xE ,0xD ,0xC , 0xD ,0xD ,0xD ,0xC , 9 , 9 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,0xB ,0xB , 0xB ,0xB , 0 , 0 , 1 ,0xB , 0 , 2 , 0xE ,0xF ,0xF ,0xF ,0xF ,0xD , 2 , 4 , 0 , 2 , 4 , 0 , 1 , 4 , 0 , 1 , 4 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,0xC , 0 , 0 , 0 , 0 ,0xF ,0xF }; const unsigned char ampl2data[] = { 0 , 0 , 0 , 0 , 0 ,0xA ,0xB ,0xD , 0xE ,0xD ,0xC ,0xC ,0xB , 9 ,0xB ,0xB , 0xC ,0xC ,0xC , 8 , 8 ,0xC , 8 ,0xA , 8 , 8 ,0xA , 3 , 9 , 6 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 5 , 3 , 4 , 0 , 0 , 0 , 5 ,0xA , 2 , 0xE ,0xD ,0xC ,0xD ,0xC , 8 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,0xA , 0 , 0 ,0xA , 0 , 0 , 0 }; const unsigned char ampl3data[] = { 0 , 0 , 0 , 0 , 0 , 8 , 7 , 8 , 8 , 1 , 1 , 0 , 1 , 0 , 7 , 5 , 1 , 0 , 6 , 1 , 0 , 7 , 0 , 5 , 1 , 0 , 8 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 1 ,0xE , 1 , 9 , 1 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 7 , 0 , 0 , 5 , 0 , 0x13 , 0x10 }; //tab42240 const signed char sinus[256] = {0,3,6,9,12,16,19,22,25,28,31,34,37,40,43,46,49,51,54,57,60,63,65,68,71,73,76,78,81,83,85,88,90,92,94,96,98,100,102,104,106,107,109,111,112,113,115,116,117,118,120,121,122,122,123,124,125,125,126,126,126,127,127,127,127,127,127,127,126,126,126,125,125,124,123,122,122,121,120,118,117,116,115,113,112,111,109,107,106,104,102,100,98,96,94,92,90,88,85,83,81,78,76,73,71,68,65,63,60,57,54,51,49,46,43,40,37,34,31,28,25,22,19,16,12,9,6,3,0,-3,-6,-9,-12,-16,-19,-22,-25,-28,-31,-34,-37,-40,-43,-46,-49,-51,-54,-57,-60,-63,-65,-68,-71,-73,-76,-78,-81,-83,-85,-88,-90,-92,-94,-96,-98,-100,-102,-104,-106,-107,-109,-111,-112,-113,-115,-116,-117,-118,-120,-121,-122,-122,-123,-124,-125,-125,-126,-126,-126,-127,-127,-127,-127,-127,-127,-127,-126,-126,-126,-125,-125,-124,-123,-122,-122,-121,-120,-118,-117,-116,-115,-113,-112,-111,-109,-107,-106,-104,-102,-100,-98,-96,-94,-92,-90,-88,-85,-83,-81,-78,-76,-73,-71,-68,-65,-63,-60,-57,-54,-51,-49,-46,-43,-40,-37,-34,-31,-28,-25,-22,-19,-16,-12,-9,-6,-3}; //tab42496 const unsigned char rectangle[] = { 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 , 0x70 }; //random data ? const unsigned char sampleTable[0x500] = { //00 0x38 , 0x84 , 0x6B , 0x19 , 0xC6 , 0x63 , 0x18 , 0x86 , 0x73 , 0x98 , 0xC6 , 0xB1 , 0x1C , 0xCA , 0x31 , 0x8C , 0xC7 , 0x31 , 0x88 , 0xC2 , 0x30 , 0x98 , 0x46 , 0x31 , 0x18 , 0xC6 , 0x35 ,0xC , 0xCA , 0x31 ,0xC , 0xC6 //20 , 0x21 , 0x10 , 0x24 , 0x69 , 0x12 , 0xC2 , 0x31 , 0x14 , 0xC4 , 0x71 , 8 , 0x4A , 0x22 , 0x49 , 0xAB , 0x6A , 0xA8 , 0xAC , 0x49 , 0x51 , 0x32 , 0xD5 , 0x52 , 0x88 , 0x93 , 0x6C , 0x94 , 0x22 , 0x15 , 0x54 , 0xD2 , 0x25 //40 , 0x96 , 0xD4 , 0x50 , 0xA5 , 0x46 , 0x21 , 8 , 0x85 , 0x6B , 0x18 , 0xC4 , 0x63 , 0x10 , 0xCE , 0x6B , 0x18 , 0x8C , 0x71 , 0x19 , 0x8C , 0x63 , 0x35 ,0xC , 0xC6 , 0x33 , 0x99 , 0xCC , 0x6C , 0xB5 , 0x4E , 0xA2 , 0x99 //60 , 0x46 , 0x21 , 0x28 , 0x82 , 0x95 , 0x2E , 0xE3 , 0x30 , 0x9C , 0xC5 , 0x30 , 0x9C , 0xA2 , 0xB1 , 0x9C , 0x67 , 0x31 , 0x88 , 0x66 , 0x59 , 0x2C , 0x53 , 0x18 , 0x84 , 0x67 , 0x50 , 0xCA , 0xE3 ,0xA , 0xAC , 0xAB , 0x30 //80 , 0xAC , 0x62 , 0x30 , 0x8C , 0x63 , 0x10 , 0x94 , 0x62 , 0xB1 , 0x8C , 0x82 , 0x28 , 0x96 , 0x33 , 0x98 , 0xD6 , 0xB5 , 0x4C , 0x62 , 0x29 , 0xA5 , 0x4A , 0xB5 , 0x9C , 0xC6 , 0x31 , 0x14 , 0xD6 , 0x38 , 0x9C , 0x4B , 0xB4 //A0 , 0x86 , 0x65 , 0x18 , 0xAE , 0x67 , 0x1C , 0xA6 , 0x63 , 0x19 , 0x96 , 0x23 , 0x19 , 0x84 , 0x13 , 8 , 0xA6 , 0x52 , 0xAC , 0xCA , 0x22 , 0x89 , 0x6E , 0xAB , 0x19 , 0x8C , 0x62 , 0x34 , 0xC4 , 0x62 , 0x19 , 0x86 , 0x63 //C0 , 0x18 , 0xC4 , 0x23 , 0x58 , 0xD6 , 0xA3 , 0x50 , 0x42 , 0x54 , 0x4A , 0xAD , 0x4A , 0x25 , 0x11 , 0x6B , 0x64 , 0x89 , 0x4A , 0x63 , 0x39 , 0x8A , 0x23 , 0x31 , 0x2A , 0xEA , 0xA2 , 0xA9 , 0x44 , 0xC5 , 0x12 , 0xCD , 0x42 //E0 , 0x34 , 0x8C , 0x62 , 0x18 , 0x8C , 0x63 , 0x11 , 0x48 , 0x66 , 0x31 , 0x9D , 0x44 , 0x33 , 0x1D , 0x46 , 0x31 , 0x9C , 0xC6 , 0xB1 ,0xC , 0xCD , 0x32 , 0x88 , 0xC4 , 0x73 , 0x18 , 0x86 , 0x73 , 8 , 0xD6 , 0x63 , 0x58 //100 , 7 , 0x81 , 0xE0 , 0xF0 , 0x3C , 7 , 0x87 , 0x90 , 0x3C , 0x7C ,0xF , 0xC7 , 0xC0 , 0xC0 , 0xF0 , 0x7C , 0x1E , 7 , 0x80 , 0x80 , 0 , 0x1C , 0x78 , 0x70 , 0xF1 , 0xC7 , 0x1F , 0xC0 ,0xC , 0xFE , 0x1C , 0x1F //120 , 0x1F ,0xE ,0xA , 0x7A , 0xC0 , 0x71 , 0xF2 , 0x83 , 0x8F , 3 ,0xF ,0xF ,0xC , 0 , 0x79 , 0xF8 , 0x61 , 0xE0 , 0x43 ,0xF , 0x83 , 0xE7 , 0x18 , 0xF9 , 0xC1 , 0x13 , 0xDA , 0xE9 , 0x63 , 0x8F ,0xF , 0x83 //140 , 0x83 , 0x87 , 0xC3 , 0x1F , 0x3C , 0x70 , 0xF0 , 0xE1 , 0xE1 , 0xE3 , 0x87 , 0xB8 , 0x71 ,0xE , 0x20 , 0xE3 , 0x8D , 0x48 , 0x78 , 0x1C , 0x93 , 0x87 , 0x30 , 0xE1 , 0xC1 , 0xC1 , 0xE4 , 0x78 , 0x21 , 0x83 , 0x83 , 0xC3 //160 , 0x87 , 6 , 0x39 , 0xE5 , 0xC3 , 0x87 , 7 ,0xE , 0x1C , 0x1C , 0x70 , 0xF4 , 0x71 , 0x9C , 0x60 , 0x36 , 0x32 , 0xC3 , 0x1E , 0x3C , 0xF3 , 0x8F ,0xE , 0x3C , 0x70 , 0xE3 , 0xC7 , 0x8F ,0xF ,0xF ,0xE , 0x3C //180 , 0x78 , 0xF0 , 0xE3 , 0x87 , 6 , 0xF0 , 0xE3 , 7 , 0xC1 , 0x99 , 0x87 ,0xF , 0x18 , 0x78 , 0x70 , 0x70 , 0xFC , 0xF3 , 0x10 , 0xB1 , 0x8C , 0x8C , 0x31 , 0x7C , 0x70 , 0xE1 , 0x86 , 0x3C , 0x64 , 0x6C , 0xB0 , 0xE1 //1A0 , 0xE3 ,0xF , 0x23 , 0x8F ,0xF , 0x1E , 0x3E , 0x38 , 0x3C , 0x38 , 0x7B , 0x8F , 7 ,0xE , 0x3C , 0xF4 , 0x17 , 0x1E , 0x3C , 0x78 , 0xF2 , 0x9E , 0x72 , 0x49 , 0xE3 , 0x25 , 0x36 , 0x38 , 0x58 , 0x39 , 0xE2 , 0xDE //1C0 , 0x3C , 0x78 , 0x78 , 0xE1 , 0xC7 , 0x61 , 0xE1 , 0xE1 , 0xB0 , 0xF0 , 0xF0 , 0xC3 , 0xC7 ,0xE , 0x38 , 0xC0 , 0xF0 , 0xCE , 0x73 , 0x73 , 0x18 , 0x34 , 0xB0 , 0xE1 , 0xC7 , 0x8E , 0x1C , 0x3C , 0xF8 , 0x38 , 0xF0 , 0xE1 //1E0 , 0xC1 , 0x8B , 0x86 , 0x8F , 0x1C , 0x78 , 0x70 , 0xF0 , 0x78 , 0xAC , 0xB1 , 0x8F , 0x39 , 0x31 , 0xDB , 0x38 , 0x61 , 0xC3 ,0xE ,0xE , 0x38 , 0x78 , 0x73 , 0x17 , 0x1E , 0x39 , 0x1E , 0x38 , 0x64 , 0xE1 , 0xF1 , 0xC1 //200 , 0x4E ,0xF , 0x40 , 0xA2 , 2 , 0xC5 , 0x8F , 0x81 , 0xA1 , 0xFC , 0x12 , 8 , 0x64 , 0xE0 , 0x3C , 0x22 , 0xE0 , 0x45 , 7 , 0x8E ,0xC , 0x32 , 0x90 , 0xF0 , 0x1F , 0x20 , 0x49 , 0xE0 , 0xF8 ,0xC , 0x60 , 0xF0 //220 , 0x17 , 0x1A , 0x41 , 0xAA , 0xA4 , 0xD0 , 0x8D , 0x12 , 0x82 , 0x1E , 0x1E , 3 , 0xF8 , 0x3E , 3 ,0xC , 0x73 , 0x80 , 0x70 , 0x44 , 0x26 , 3 , 0x24 , 0xE1 , 0x3E , 4 , 0x4E , 4 , 0x1C , 0xC1 , 9 , 0xCC //240 , 0x9E , 0x90 , 0x21 , 7 , 0x90 , 0x43 , 0x64 , 0xC0 , 0xF , 0xC6 , 0x90 , 0x9C , 0xC1 , 0x5B , 3 , 0xE2 , 0x1D , 0x81 , 0xE0 , 0x5E , 0x1D , 3 , 0x84 , 0xB8 , 0x2C ,0xF , 0x80 , 0xB1 , 0x83 , 0xE0 , 0x30 , 0x41 //260 , 0x1E , 0x43 , 0x89 , 0x83 , 0x50 , 0xFC , 0x24 , 0x2E , 0x13 , 0x83 , 0xF1 , 0x7C , 0x4C , 0x2C , 0xC9 ,0xD , 0x83 , 0xB0 , 0xB5 , 0x82 , 0xE4 , 0xE8 , 6 , 0x9C , 7 , 0xA0 , 0x99 , 0x1D , 7 , 0x3E , 0x82 , 0x8F //280 , 0x70 , 0x30 , 0x74 , 0x40 , 0xCA , 0x10 , 0xE4 , 0xE8 , 0xF , 0x92 , 0x14 , 0x3F , 6 , 0xF8 , 0x84 , 0x88 , 0x43 , 0x81 ,0xA , 0x34 , 0x39 , 0x41 , 0xC6 , 0xE3 , 0x1C , 0x47 , 3 , 0xB0 , 0xB8 , 0x13 ,0xA , 0xC2 //2A0 , 0x64 , 0xF8 , 0x18 , 0xF9 , 0x60 , 0xB3 , 0xC0 , 0x65 , 0x20 , 0x60 , 0xA6 , 0x8C , 0xC3 , 0x81 , 0x20 , 0x30 , 0x26 , 0x1E , 0x1C , 0x38 , 0xD3 , 1 , 0xB0 , 0x26 , 0x40 , 0xF4 ,0xB , 0xC3 , 0x42 , 0x1F , 0x85 , 0x32 //2C0 , 0x26 , 0x60 , 0x40 , 0xC9 , 0xCB , 1 , 0xEC , 0x11 , 0x28 , 0x40 , 0xFA , 4 , 0x34 , 0xE0 , 0x70 , 0x4C , 0x8C , 0x1D , 7 , 0x69 , 3 , 0x16 , 0xC8 , 4 , 0x23 , 0xE8 , 0xC6 , 0x9A ,0xB , 0x1A , 3 , 0xE0 //2E0 , 0x76 , 6 , 5 , 0xCF , 0x1E , 0xBC , 0x58 , 0x31 , 0x71 , 0x66 , 0 , 0xF8 , 0x3F , 4 , 0xFC ,0xC , 0x74 , 0x27 , 0x8A , 0x80 , 0x71 , 0xC2 , 0x3A , 0x26 , 6 , 0xC0 , 0x1F , 5 ,0xF , 0x98 , 0x40 , 0xAE //300 , 1 , 0x7F , 0xC0 , 7 , 0xFF , 0 ,0xE , 0xFE , 0 , 3 , 0xDF , 0x80 , 3 , 0xEF , 0x80 , 0x1B , 0xF1 , 0xC2 , 0 , 0xE7 , 0xE0 , 0x18 , 0xFC , 0xE0 , 0x21 , 0xFC , 0x80 , 0x3C , 0xFC , 0x40 ,0xE , 0x7E //320 , 0 , 0x3F , 0x3E , 0 ,0xF , 0xFE , 0 , 0x1F , 0xFF , 0 , 0x3E , 0xF0 , 7 , 0xFC , 0 , 0x7E , 0x10 , 0x3F , 0xFF , 0 , 0x3F , 0x38 ,0xE , 0x7C , 1 , 0x87 ,0xC , 0xFC , 0xC7 , 0 , 0x3E , 4 //340 , 0xF , 0x3E , 0x1F ,0xF ,0xF , 0x1F ,0xF , 2 , 0x83 , 0x87 , 0xCF , 3 , 0x87 ,0xF , 0x3F , 0xC0 , 7 , 0x9E , 0x60 , 0x3F , 0xC0 , 3 , 0xFE , 0 , 0x3F , 0xE0 , 0x77 , 0xE1 , 0xC0 , 0xFE , 0xE0 , 0xC3 //360 , 0xE0 , 1 , 0xDF , 0xF8 , 3 , 7 , 0 , 0x7E , 0x70 , 0 , 0x7C , 0x38 , 0x18 , 0xFE ,0xC , 0x1E , 0x78 , 0x1C , 0x7C , 0x3E ,0xE , 0x1F , 0x1E , 0x1E , 0x3E , 0 , 0x7F , 0x83 , 7 , 0xDB , 0x87 , 0x83 //380 , 7 , 0xC7 , 7 , 0x10 , 0x71 , 0xFF , 0 , 0x3F , 0xE2 , 1 , 0xE0 , 0xC1 , 0xC3 , 0xE1 , 0 , 0x7F , 0xC0 , 5 , 0xF0 , 0x20 , 0xF8 , 0xF0 , 0x70 , 0xFE , 0x78 , 0x79 , 0xF8 , 2 , 0x3F ,0xC , 0x8F , 3 //3a0 , 0xF , 0x9F , 0xE0 , 0xC1 , 0xC7 , 0x87 , 3 , 0xC3 , 0xC3 , 0xB0 , 0xE1 , 0xE1 , 0xC1 , 0xE3 , 0xE0 , 0x71 , 0xF0 , 0 , 0xFC , 0x70 , 0x7C ,0xC , 0x3E , 0x38 , 0xE , 0x1C , 0x70 , 0xC3 , 0xC7 , 3 , 0x81 , 0xC1 //3c0 , 0xC7 , 0xE7 , 0 ,0xF , 0xC7 , 0x87 , 0x19 , 9 , 0xEF , 0xC4 , 0x33 , 0xE0 , 0xC1 , 0xFC , 0xF8 , 0x70 , 0xF0 , 0x78 , 0xF8 , 0xF0 , 0x61 , 0xC7 , 0 , 0x1F , 0xF8 , 1 , 0x7C , 0xF8 , 0xF0 , 0x78 , 0x70 , 0x3C //3e0 , 0x7C , 0xCE ,0xE , 0x21 , 0x83 , 0xCF , 8 , 7 , 0x8F , 8 , 0xC1 , 0x87 , 0x8F , 0x80 , 0xC7 , 0xE3 , 0 , 7 , 0xF8 , 0xE0 , 0xEF , 0 , 0x39 , 0xF7 , 0x80 ,0xE , 0xF8 , 0xE1 , 0xE3 , 0xF8 , 0x21 , 0x9F //400 , 0xC0 , 0xFF , 3 , 0xF8 , 7 , 0xC0 , 0x1F , 0xF8 , 0xC4 , 4 , 0xFC , 0xC4 , 0xC1 , 0xBC , 0x87 , 0xF0 , 0xF , 0xC0 , 0x7F , 5 , 0xE0 , 0x25 , 0xEC , 0xC0 , 0x3E , 0x84 , 0x47 , 0xF0 , 0x8E , 3 , 0xF8 , 3 //420 , 0xFB , 0xC0 , 0x19 , 0xF8 , 7 , 0x9C ,0xC , 0x17 , 0xF8 , 7 , 0xE0 , 0x1F , 0xA1 , 0xFC ,0xF , 0xFC , 1 , 0xF0 , 0x3F , 0 , 0xFE , 3 , 0xF0 , 0x1F , 0 , 0xFD , 0 , 0xFF , 0x88 ,0xD , 0xF9 , 1 //440 , 0xFF , 0 , 0x70 , 7 , 0xC0 , 0x3E , 0x42 , 0xF3 , 0xD , 0xC4 , 0x7F , 0x80 , 0xFC , 7 , 0xF0 , 0x5E , 0xC0 , 0x3F , 0 , 0x78 , 0x3F , 0x81 , 0xFF , 1 , 0xF8 , 1 , 0xC3 , 0xE8 ,0xC , 0xE4 , 0x64 , 0x8F ////460 , 0xE4 ,0xF , 0xF0 , 7 , 0xF0 , 0xC2 , 0x1F , 0 , 0x7F , 0xC0 , 0x6F , 0x80 , 0x7E , 3 , 0xF8 , 7 , 0xF0 , 0x3F , 0xC0 , 0x78 ,0xF , 0x82 , 7 , 0xFE , 0x22 , 0x77 , 0x70 , 2 , 0x76 , 3 , 0xFE , 0 //480 , 0xFE , 0x67 , 0 , 0x7C , 0xC7 , 0xF1 , 0x8E , 0xC6 , 0x3B , 0xE0 , 0x3F , 0x84 , 0xF3 , 0x19 , 0xD8 , 3 , 0x99 , 0xFC , 9 , 0xB8 ,0xF , 0xF8 , 0 , 0x9D , 0x24 , 0x61 , 0xF9 ,0xD , 0 , 0xFD , 3 , 0xF0 //4a0 , 0x1F , 0x90 , 0x3F , 1 , 0xF8 , 0x1F , 0xD0 ,0xF , 0xF8 , 0x37 , 1 , 0xF8 , 7 , 0xF0 ,0xF , 0xC0 , 0x3F , 0 , 0xFE , 3 , 0xF8 ,0xF , 0xC0 , 0x3F , 0 , 0xFA , 3 , 0xF0 ,0xF , 0x80 , 0xFF , 1 //4c0 , 0xB8 , 7 , 0xF0 , 1 , 0xFC , 1 , 0xBC , 0x80 , 0x13 , 0x1E , 0 , 0x7F , 0xE1 , 0x40 , 0x7F , 0xA0 , 0x7F , 0xB0 , 0 , 0x3F , 0xC0 , 0x1F , 0xC0 , 0x38 , 0xF , 0xF0 , 0x1F , 0x80 , 0xFF , 1 , 0xFC , 3 //4e0 , 0xF1 , 0x7E , 1 , 0xFE , 1 , 0xF0 , 0xFF , 0 , 0x7F , 0xC0 , 0x1D , 7 , 0xF0 ,0xF , 0xC0 , 0x7E , 6 , 0xE0 , 7 , 0xE0 ,0xF , 0xF8 , 6 , 0xC1 , 0xFE , 1 , 0xFC , 3 , 0xE0 ,0xF , 0 , 0xFC }; #endif ================================================ FILE: lib/SAM/SamTabs.h ================================================ #ifndef SAMTABS_H #define SAMTABS_H //tab40672 const unsigned char stressInputTable[] = { '*', '1', '2', '3', '4', '5', '6', '7', '8' }; //tab40682 const unsigned char signInputTable1[]={ ' ', '.', '?', ',', '-', 'I', 'I', 'E', 'A', 'A', 'A', 'A', 'U', 'A', 'I', 'E', 'U', 'O', 'R', 'L', 'W', 'Y', 'W', 'R', 'L', 'W', 'Y', 'M', 'N', 'N', 'D', 'Q', 'S', 'S', 'F', 'T', '/', '/', 'Z', 'Z', 'V', 'D', 'C', '*', 'J', '*', '*', '*', 'E', 'A', 'O', 'A', 'O', 'U', 'B', '*', '*', 'D', '*', '*', 'G', '*', '*', 'G', '*', '*', 'P', '*', '*', 'T', '*', '*', 'K', '*', '*', 'K', '*', '*', 'U', 'U', 'U' }; //tab40763 const unsigned char signInputTable2[] = { '*', '*', '*', '*', '*', 'Y', 'H', 'H', 'E', 'A', 'H', 'O', 'H', 'X', 'X', 'R', 'X', 'H', 'X', 'X', 'X', 'X', 'H', '*', '*', '*', '*', '*', '*', 'X', 'X', '*', '*', 'H', '*', 'H', 'H', 'X', '*', 'H', '*', 'H', 'H', '*', '*', '*', '*', '*', 'Y', 'Y', 'Y', 'W', 'W', 'W', '*', '*', '*', '*', '*', '*', '*', '*', '*', 'X', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', 'X', '*', '*', 'L', 'M', 'N' }; //loc_9F8C const unsigned char flags[]={ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xA4 , 0xA4 , 0xA4 , 0xA4 , 0xA4 , 0xA4 , 0x84 , 0x84 , 0xA4 , 0xA4 , 0x84 , 0x84 , 0x84 , 0x84 , 0x84 , 0x84 , 0x84 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x4C , 0x4C , 0x4C , 0x48 , 0x4C , 0x40 , 0x40 , 0x40 , 0x40 , 0x40 , 0x40 , 0x44 , 0x44 , 0x44 , 0x44 , 0x48 , 0x40 , 0x4C , 0x44 , 0x00 , 0x00 , 0xB4 , 0xB4 , 0xB4 , 0x94 , 0x94 , 0x94 , 0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 0x80 , 0xC1 , 0xC1 }; //??? flags overlap flags2 //loc_9FDA const unsigned char flags2[] = { 0x80 , 0xC1 , 0xC1 , 0xC1 , 0xC1 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 , 0x10 , 0x10 , 0x10 , 0x08 , 0x0C , 0x08 , 0x04 , 0x40 , 0x24 , 0x20 , 0x20 , 0x24 , 0x00 , 0x00 , 0x24 , 0x20 , 0x20 , 0x24 , 0x20 , 0x20 , 0x00 , 0x20 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x04 , 0x04 , 0x04 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x04 , 0x04 , 0x04 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 }; //tab45616??? const unsigned char phonemeStressedLengthTable[] = { 0x00 , 0x12 , 0x12 , 0x12 , 8 ,0xB , 9 ,0xB , 0xE ,0xF ,0xB , 0x10 ,0xC , 6 , 6 ,0xE , 0xC ,0xE ,0xC ,0xB , 8 , 8 ,0xB ,0xA , 9 , 8 , 8 , 8 , 8 , 8 , 3 , 5 , 2 , 2 , 2 , 2 , 2 , 2 , 6 , 6 , 8 , 6 , 6 , 2 , 9 , 4 , 2 , 1 , 0xE ,0xF ,0xF ,0xF ,0xE ,0xE , 8 , 2 , 2 , 7 , 2 , 1 , 7 , 2 , 2 , 7 , 2 , 2 , 8 , 2 , 2 , 6 , 2 , 2 , 7 , 2 , 4 , 7 , 1 , 4 , 5 , 5 }; //tab45536??? const unsigned char phonemeLengthTable[] = { 0 , 0x12 , 0x12 , 0x12 , 8 , 8 , 8 , 8 , 8 ,0xB , 6 ,0xC ,0xA , 5 , 5 ,0xB , 0xA ,0xA ,0xA , 9 , 8 , 7 , 9 , 7 , 6 , 8 , 6 , 7 , 7 , 7 , 2 , 5 , 2 , 2 , 2 , 2 , 2 , 2 , 6 , 6 , 7 , 6 , 6 , 2 , 8 , 3 , 1 , 0x1E , 0xD ,0xC ,0xC ,0xC ,0xE , 9 , 6 , 1 , 2 , 5 , 1 , 1 , 6 , 1 , 2 , 6 , 1 , 2 , 8 , 2 , 2 , 4 , 2 , 2 , 6 , 1 , 4 , 6 , 1 , 4 , 0xC7 , 0xFF }; /* Ind | phoneme | flags | -----|---------|----------| 0 | * | 00000000 | 1 | .* | 00000000 | 2 | ?* | 00000000 | 3 | ,* | 00000000 | 4 | -* | 00000000 | VOWELS 5 | IY | 10100100 | 6 | IH | 10100100 | 7 | EH | 10100100 | 8 | AE | 10100100 | 9 | AA | 10100100 | 10 | AH | 10100100 | 11 | AO | 10000100 | 17 | OH | 10000100 | 12 | UH | 10000100 | 16 | UX | 10000100 | 15 | ER | 10000100 | 13 | AX | 10100100 | 14 | IX | 10100100 | DIPHTONGS 48 | EY | 10110100 | 49 | AY | 10110100 | 50 | OY | 10110100 | 51 | AW | 10010100 | 52 | OW | 10010100 | 53 | UW | 10010100 | 21 | YX | 10000100 | 20 | WX | 10000100 | 18 | RX | 10000100 | 19 | LX | 10000100 | 37 | /X | 01000000 | 30 | DX | 01001000 | 22 | WH | 01000100 | VOICED CONSONANTS 23 | R* | 01000100 | 24 | L* | 01000100 | 25 | W* | 01000100 | 26 | Y* | 01000100 | 27 | M* | 01001100 | 28 | N* | 01001100 | 29 | NX | 01001100 | 54 | B* | 01001110 | 57 | D* | 01001110 | 60 | G* | 01001110 | 44 | J* | 01001100 | 38 | Z* | 01000100 | 39 | ZH | 01000100 | 40 | V* | 01000100 | 41 | DH | 01000100 | unvoiced CONSONANTS 32 | S* | 01000000 | 33 | SH | 01000000 | 34 | F* | 01000000 | 35 | TH | 01000000 | 66 | P* | 01001011 | 69 | T* | 01001011 | 72 | K* | 01001011 | 42 | CH | 01001000 | 36 | /H | 01000000 | 43 | ** | 01000000 | 45 | ** | 01000100 | 46 | ** | 00000000 | 47 | ** | 00000000 | 55 | ** | 01001110 | 56 | ** | 01001110 | 58 | ** | 01001110 | 59 | ** | 01001110 | 61 | ** | 01001110 | 62 | ** | 01001110 | 63 | GX | 01001110 | 64 | ** | 01001110 | 65 | ** | 01001110 | 67 | ** | 01001011 | 68 | ** | 01001011 | 70 | ** | 01001011 | 71 | ** | 01001011 | 73 | ** | 01001011 | 74 | ** | 01001011 | 75 | KX | 01001011 | 76 | ** | 01001011 | 77 | ** | 01001011 | SPECIAL 78 | UL | 10000000 | 79 | UM | 11000001 | 80 | UN | 11000001 | 31 | Q* | 01001100 | */ #endif ================================================ FILE: lib/SAM/debug.c ================================================ #include extern const unsigned char signInputTable1[]; extern const unsigned char signInputTable2[]; void PrintPhonemes(unsigned char *phonemeindex, unsigned char *phonemeLength, unsigned char *stress) { int i = 0; printf("===========================================\n"); printf("Internal Phoneme presentation:\n\n"); printf(" idx phoneme length stress\n"); printf("------------------------------\n"); while((phonemeindex[i] != 255) && (i < 255)) { if (phonemeindex[i] < 81) { printf(" %3i %c%c %3i %i\n", phonemeindex[i], signInputTable1[phonemeindex[i]], signInputTable2[phonemeindex[i]], phonemeLength[i], stress[i] ); } else { printf(" %3i ?? %3i %i\n", phonemeindex[i], phonemeLength[i], stress[i]); } i++; } printf("===========================================\n"); printf("\n"); } void PrintOutput( unsigned char *flag, unsigned char *f1, unsigned char *f2, unsigned char *f3, unsigned char *a1, unsigned char *a2, unsigned char *a3, unsigned char *p) { printf("===========================================\n"); printf("Final data for speech output:\n\n"); int i = 0; printf(" flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch\n"); printf("------------------------------------------------\n"); while(i < 255) { printf("%5i %5i %5i %5i %5i %5i %5i %5i\n", flag[i], a1[i], f1[i], a2[i], f2[i], a3[i], f3[i], p[i]); i++; } printf("===========================================\n"); } extern unsigned char GetRuleByte(unsigned short mem62, unsigned char Y); void PrintRule(int offset) { int i = 1; unsigned char A = 0; printf("Applying rule: "); do { A = GetRuleByte(offset, i); if ((A&127) == '=') printf(" -> "); else printf("%c", A&127); i++; } while ((A&128)==0); printf("\n"); } ================================================ FILE: lib/SAM/debug.h ================================================ #ifndef DEBUG_H #define DEBUG_H void PrintPhonemes(unsigned char *phonemeindex, unsigned char *phonemeLength, unsigned char *stress); void PrintOutput( unsigned char *flag, unsigned char *f1, unsigned char *f2, unsigned char *f3, unsigned char *a1, unsigned char *a2, unsigned char *a3, unsigned char *p); void PrintRule(int offset); #endif ================================================ FILE: lib/SAM/reciter.c ================================================ #include #include #include "reciter.h" #include "ReciterTabs.h" #include "debug.h" extern unsigned char A, X, Y; extern int debug; static unsigned char inputtemp[256]; // secure copy of input tab36096 void Code37055(unsigned char mem59) { X = mem59; X--; A = inputtemp[X]; Y = A; A = tab36376[Y]; return; } void Code37066(unsigned char mem58) { X = mem58; X++; A = inputtemp[X]; Y = A; A = tab36376[Y]; } unsigned char GetRuleByte(unsigned short mem62, unsigned char Y) { unsigned int address = mem62; if (mem62 >= 37541) { address -= 37541; return rules2[address+Y]; } address -= 32000; return rules[address+Y]; } int TextToPhonemes(unsigned char *input) // Code36484 { //unsigned char *tab39445 = &mem[39445]; //input and output //unsigned char mem29; unsigned char mem56; //output position for phonemes unsigned char mem57; unsigned char mem58; unsigned char mem59; unsigned char mem60; unsigned char mem61; unsigned short mem62; // memory position of current rule unsigned char mem64; // position of '=' or current character unsigned char mem65; // position of ')' unsigned char mem66; // position of '(' unsigned char mem36653; inputtemp[0] = 32; // secure copy of input // because input will be overwritten by phonemes X = 1; Y = 0; do { //pos36499: A = input[Y] & 127; if ( A >= 112) A = A & 95; else if ( A >= 96) A = A & 79; inputtemp[X] = A; X++; Y++; } while (Y != 255); X = 255; inputtemp[X] = 27; mem61 = 255; pos36550: A = 255; mem56 = 255; pos36554: while(1) { mem61++; X = mem61; A = inputtemp[X]; mem64 = A; if (A == '[') { mem56++; X = mem56; A = 155; input[X] = 155; //goto pos36542; // Code39771(); //Code39777(); return 1; } //pos36579: if (A != '.') break; X++; Y = inputtemp[X]; A = tab36376[Y] & 1; if(A != 0) break; mem56++; X = mem56; A = '.'; input[X] = '.'; } //while //pos36607: A = mem64; Y = A; A = tab36376[A]; mem57 = A; if((A&2) != 0) { mem62 = 37541; goto pos36700; } //pos36630: A = mem57; if(A != 0) goto pos36677; A = 32; inputtemp[X] = ' '; mem56++; X = mem56; if (X > 120) goto pos36654; input[X] = A; goto pos36554; // ----- //36653 is unknown. Contains position pos36654: input[X] = 155; A = mem61; mem36653 = A; // mem29 = A; // not used // Code36538(); das ist eigentlich return 1; //Code39771(); //go on if there is more input ??? mem61 = mem36653; goto pos36550; pos36677: A = mem57 & 128; if(A == 0) { //36683: BRK return 0; } // go to the right rules for this character. X = mem64 - 'A'; mem62 = tab37489[X] | (tab37515[X]<<8); // ------------------------------------- // go to next rule // ------------------------------------- pos36700: // find next rule Y = 0; do { mem62 += 1; A = GetRuleByte(mem62, Y); } while ((A & 128) == 0); Y++; //pos36720: // find '(' while(1) { A = GetRuleByte(mem62, Y); if (A == '(') break; Y++; } mem66 = Y; //pos36732: // find ')' do { Y++; A = GetRuleByte(mem62, Y); } while(A != ')'); mem65 = Y; //pos36741: // find '=' do { Y++; A = GetRuleByte(mem62, Y); A = A & 127; } while (A != '='); mem64 = Y; X = mem61; mem60 = X; // compare the string within the bracket Y = mem66; Y++; //pos36759: while(1) { mem57 = inputtemp[X]; A = GetRuleByte(mem62, Y); if (A != mem57) goto pos36700; Y++; if(Y == mem65) break; X++; mem60 = X; } // the string in the bracket is correct //pos36787: A = mem61; mem59 = mem61; pos36791: while(1) { mem66--; Y = mem66; A = GetRuleByte(mem62, Y); mem57 = A; //36800: BPL 36805 if ((A & 128) != 0) goto pos37180; X = A & 127; A = tab36376[X] & 128; if (A == 0) break; X = mem59-1; A = inputtemp[X]; if (A != mem57) goto pos36700; mem59 = X; } //pos36833: A = mem57; if (A == ' ') goto pos36895; if (A == '#') goto pos36910; if (A == '.') goto pos36920; if (A == '&') goto pos36935; if (A == '@') goto pos36967; if (A == '^') goto pos37004; if (A == '+') goto pos37019; if (A == ':') goto pos37040; // Code42041(); //Error //36894: BRK return 0; // -------------- pos36895: Code37055(mem59); A = A & 128; if(A != 0) goto pos36700; pos36905: mem59 = X; goto pos36791; // -------------- pos36910: Code37055(mem59); A = A & 64; if(A != 0) goto pos36905; goto pos36700; // -------------- pos36920: Code37055(mem59); A = A & 8; if(A == 0) goto pos36700; pos36930: mem59 = X; goto pos36791; // -------------- pos36935: Code37055(mem59); A = A & 16; if(A != 0) goto pos36930; A = inputtemp[X]; if (A != 72) goto pos36700; X--; A = inputtemp[X]; if ((A == 67) || (A == 83)) goto pos36930; goto pos36700; // -------------- pos36967: Code37055(mem59); A = A & 4; if(A != 0) goto pos36930; A = inputtemp[X]; if (A != 72) goto pos36700; if ((A != 84) && (A != 67) && (A != 83)) goto pos36700; mem59 = X; goto pos36791; // -------------- pos37004: Code37055(mem59); A = A & 32; if(A == 0) goto pos36700; pos37014: mem59 = X; goto pos36791; // -------------- pos37019: X = mem59; X--; A = inputtemp[X]; if ((A == 'E') || (A == 'I') || (A == 'Y')) goto pos37014; goto pos36700; // -------------- pos37040: Code37055(mem59); A = A & 32; if(A == 0) goto pos36791; mem59 = X; goto pos37040; //--------------------------------------- pos37077: X = mem58+1; A = inputtemp[X]; if (A != 'E') goto pos37157; X++; Y = inputtemp[X]; X--; A = tab36376[Y] & 128; if(A == 0) goto pos37108; X++; A = inputtemp[X]; if (A != 'R') goto pos37113; pos37108: mem58 = X; goto pos37184; pos37113: if ((A == 83) || (A == 68)) goto pos37108; // 'S' 'D' if (A != 76) goto pos37135; // 'L' X++; A = inputtemp[X]; if (A != 89) goto pos36700; goto pos37108; pos37135: if (A != 70) goto pos36700; X++; A = inputtemp[X]; if (A != 85) goto pos36700; X++; A = inputtemp[X]; if (A == 76) goto pos37108; goto pos36700; pos37157: if (A != 73) goto pos36700; X++; A = inputtemp[X]; if (A != 78) goto pos36700; X++; A = inputtemp[X]; if (A == 71) goto pos37108; //pos37177: goto pos36700; // ----------------------------------------- pos37180: A = mem60; mem58 = A; pos37184: Y = mem65 + 1; //37187: CPY 64 // if(? != 0) goto pos37194; if(Y == mem64) goto pos37455; mem65 = Y; //37196: LDA (62),y A = GetRuleByte(mem62, Y); mem57 = A; X = A; A = tab36376[X] & 128; if(A == 0) goto pos37226; X = mem58+1; A = inputtemp[X]; if (A != mem57) goto pos36700; mem58 = X; goto pos37184; pos37226: A = mem57; if (A == 32) goto pos37295; // ' ' if (A == 35) goto pos37310; // '#' if (A == 46) goto pos37320; // '.' if (A == 38) goto pos37335; // '&' if (A == 64) goto pos37367; // '' if (A == 94) goto pos37404; // '' if (A == 43) goto pos37419; // '+' if (A == 58) goto pos37440; // ':' if (A == 37) goto pos37077; // '%' //pos37291: // Code42041(); //Error //37294: BRK return 0; // -------------- pos37295: Code37066(mem58); A = A & 128; if(A != 0) goto pos36700; pos37305: mem58 = X; goto pos37184; // -------------- pos37310: Code37066(mem58); A = A & 64; if(A != 0) goto pos37305; goto pos36700; // -------------- pos37320: Code37066(mem58); A = A & 8; if(A == 0) goto pos36700; pos37330: mem58 = X; goto pos37184; // -------------- pos37335: Code37066(mem58); A = A & 16; if(A != 0) goto pos37330; A = inputtemp[X]; if (A != 72) goto pos36700; X++; A = inputtemp[X]; if ((A == 67) || (A == 83)) goto pos37330; goto pos36700; // -------------- pos37367: Code37066(mem58); A = A & 4; if(A != 0) goto pos37330; A = inputtemp[X]; if (A != 72) goto pos36700; if ((A != 84) && (A != 67) && (A != 83)) goto pos36700; mem58 = X; goto pos37184; // -------------- pos37404: Code37066(mem58); A = A & 32; if(A == 0) goto pos36700; pos37414: mem58 = X; goto pos37184; // -------------- pos37419: X = mem58; X++; A = inputtemp[X]; if ((A == 69) || (A == 73) || (A == 89)) goto pos37414; goto pos36700; // ---------------------- pos37440: Code37066(mem58); A = A & 32; if(A == 0) goto pos37184; mem58 = X; goto pos37440; pos37455: Y = mem64; mem61 = mem60; #ifdef SAM_DEBUG PrintRule(mem62); #endif pos37461: //37461: LDA (62),y A = GetRuleByte(mem62, Y); mem57 = A; A = A & 127; if (A != '=') { mem56++; X = mem56; input[X] = A; } //37478: BIT 57 //37480: BPL 37485 //not negative flag if ((mem57 & 128) == 0) goto pos37485; //??? goto pos36554; pos37485: Y++; goto pos37461; } ================================================ FILE: lib/SAM/reciter.h ================================================ #ifndef RECITER_C #define RECITER_C //int TextToPhonemes(char *input, char *output); int TextToPhonemes(unsigned char *input); #endif ================================================ FILE: lib/SAM/render.c ================================================ #include #include #include #include "render.h" #include "RenderTabs.h" #include "debug.h" extern int debug; unsigned char wait1 = 7; unsigned char wait2 = 6; extern unsigned char A, X, Y; extern unsigned char mem44; extern unsigned char mem47; extern unsigned char mem49; extern unsigned char mem39; extern unsigned char mem50; extern unsigned char mem51; extern unsigned char mem53; extern unsigned char mem56; extern unsigned char speed; extern unsigned char pitch; extern int singmode; extern unsigned char phonemeIndexOutput[60]; //tab47296 extern unsigned char stressOutput[60]; //tab47365 extern unsigned char phonemeLengthOutput[60]; //tab47416 unsigned char pitches[256]; // tab43008 unsigned char frequency1[256]; unsigned char frequency2[256]; unsigned char frequency3[256]; unsigned char amplitude1[256]; unsigned char amplitude2[256]; unsigned char amplitude3[256]; unsigned char sampledConsonantFlag[256]; // tab44800 void AddInflection(unsigned char mem48, unsigned char phase1); unsigned char trans(unsigned char mem39212, unsigned char mem39213); // contains the final soundbuffer extern int bufferpos; extern void (*SAM_write_buffer)(int pos, char value); //timetable for more accurate c64 simulation int timetable[5][5] = { {162, 167, 167, 127, 128}, {226, 60, 60, 0, 0}, {225, 60, 59, 0, 0}, {200, 0, 0, 54, 55}, {199, 0, 0, 54, 54} }; static unsigned oldtimetableindex = 0; void Output8BitAry(int index, unsigned char ary[5]) { int k; bufferpos += timetable[oldtimetableindex][index]; oldtimetableindex = index; // write a little bit in advance for(k=0; k<5; k++) SAM_write_buffer(bufferpos/50 + k, ary[k]); } void Output8Bit(int index, unsigned char A) { unsigned char ary[5] = {A,A,A,A,A}; Output8BitAry(index, ary); } //written by me because of different table positions. // mem[47] = ... // 168=pitches // 169=frequency1 // 170=frequency2 // 171=frequency3 // 172=amplitude1 // 173=amplitude2 // 174=amplitude3 unsigned char Read(unsigned char p, unsigned char Y) { switch(p) { case 168: return pitches[Y]; case 169: return frequency1[Y]; case 170: return frequency2[Y]; case 171: return frequency3[Y]; case 172: return amplitude1[Y]; case 173: return amplitude2[Y]; case 174: return amplitude3[Y]; } printf("Error reading to tables"); return 0; } void Write(unsigned char p, unsigned char Y, unsigned char value) { switch(p) { case 168: pitches[Y] = value; return; case 169: frequency1[Y] = value; return; case 170: frequency2[Y] = value; return; case 171: frequency3[Y] = value; return; case 172: amplitude1[Y] = value; return; case 173: amplitude2[Y] = value; return; case 174: amplitude3[Y] = value; return; } printf("Error writing to tables\n"); } // ------------------------------------------------------------------------- //Code48227 // Render a sampled sound from the sampleTable. // // Phoneme Sample Start Sample End // 32: S* 15 255 // 33: SH 257 511 // 34: F* 559 767 // 35: TH 583 767 // 36: /H 903 1023 // 37: /X 1135 1279 // 38: Z* 84 119 // 39: ZH 340 375 // 40: V* 596 639 // 41: DH 596 631 // // 42: CH // 43: ** 399 511 // // 44: J* // 45: ** 257 276 // 46: ** // // 66: P* // 67: ** 743 767 // 68: ** // // 69: T* // 70: ** 231 255 // 71: ** // // The SampledPhonemesTable[] holds flags indicating if a phoneme is // voiced or not. If the upper 5 bits are zero, the sample is voiced. // // Samples in the sampleTable are compressed, with bits being converted to // bytes from high bit to low, as follows: // // unvoiced 0 bit -> X // unvoiced 1 bit -> 5 // // voiced 0 bit -> 6 // voiced 1 bit -> 24 // // Where X is a value from the table: // // { 0x18, 0x1A, 0x17, 0x17, 0x17 }; // // The index into this table is determined by masking off the lower // 3 bits from the SampledPhonemesTable: // // index = (SampledPhonemesTable[i] & 7) - 1; // // For voices samples, samples are interleaved between voiced output. // Code48227() void RenderSample(unsigned char *mem66) { int tempA; // current phoneme's index mem49 = Y; // mask low three bits and subtract 1 get value to // convert 0 bits on unvoiced samples. A = mem39&7; X = A-1; // store the result mem56 = X; // determine which offset to use from table { 0x18, 0x1A, 0x17, 0x17, 0x17 } // T, S, Z 0 0x18 // CH, J, SH, ZH 1 0x1A // P, F*, V, TH, DH 2 0x17 // /H 3 0x17 // /X 4 0x17 // get value from the table mem53 = tab48426[X]; mem47 = X; //46016+mem[56]*256 // voiced sample? A = mem39 & 248; if(A == 0) { // voiced phoneme: Z*, ZH, V*, DH Y = mem49; A = pitches[mem49] >> 4; // jump to voiced portion goto pos48315; } Y = A ^ 255; pos48274: // step through the 8 bits in the sample mem56 = 8; // get the next sample from the table // mem47*256 = offset to start of samples A = sampleTable[mem47*256+Y]; pos48280: // left shift to get the high bit tempA = A; A = A << 1; //48281: BCC 48290 // bit not set? if ((tempA & 128) == 0) { // convert the bit to value from table X = mem53; //mem[54296] = X; // output the byte Output8Bit(1, (X&0x0f) * 16); // if X != 0, exit loop if(X != 0) goto pos48296; } // output a 5 for the on bit Output8Bit(2, 5 * 16); //48295: NOP pos48296: X = 0; // decrement counter mem56--; // if not done, jump to top of loop if (mem56 != 0) goto pos48280; // increment position Y++; if (Y != 0) goto pos48274; // restore values and return mem44 = 1; Y = mem49; return; unsigned char phase1; pos48315: // handle voiced samples here // number of samples? phase1 = A ^ 255; Y = *mem66; do { //pos48321: // shift through all 8 bits mem56 = 8; //A = Read(mem47, Y); // fetch value from table A = sampleTable[mem47*256+Y]; // loop 8 times //pos48327: do { //48327: ASL A //48328: BCC 48337 // left shift and check high bit tempA = A; A = A << 1; if ((tempA & 128) != 0) { // if bit set, output 26 X = 26; Output8Bit(3, (X&0xf)*16); } else { //timetable 4 // bit is not set, output a 6 X=6; Output8Bit(4, (X&0xf)*16); } mem56--; } while(mem56 != 0); // move ahead in the table Y++; // continue until counter done phase1++; } while (phase1 != 0); // if (phase1 != 0) goto pos48321; // restore values and return A = 1; mem44 = 1; *mem66 = Y; Y = mem49; return; } // RENDER THE PHONEMES IN THE LIST // // The phoneme list is converted into sound through the steps: // // 1. Copy each phoneme number of times into the frames list, // where each frame represents 10 milliseconds of sound. // // 2. Determine the transitions lengths between phonemes, and linearly // interpolate the values across the frames. // // 3. Offset the pitches by the fundamental frequency. // // 4. Render the each frame. //void Code47574() void Render() { unsigned char phase1 = 0; //mem43 unsigned char phase2=0; unsigned char phase3=0; unsigned char mem66=0; unsigned char mem38=0; unsigned char mem40=0; unsigned char speedcounter=0; //mem45 unsigned char mem48=0; int i; if (phonemeIndexOutput[0] == 255) return; //exit if no data A = 0; X = 0; mem44 = 0; // CREATE FRAMES // // The length parameter in the list corresponds to the number of frames // to expand the phoneme to. Each frame represents 10 milliseconds of time. // So a phoneme with a length of 7 = 7 frames = 70 milliseconds duration. // // The parameters are copied from the phoneme to the frame verbatim. // pos47587: do { // get the index Y = mem44; // get the phoneme at the index A = phonemeIndexOutput[mem44]; mem56 = A; // if terminal phoneme, exit the loop if (A == 255) break; // period phoneme *. if (A == 1) { // add rising inflection A = 1; mem48 = 1; //goto pos48376; AddInflection(mem48, phase1); } /* if (A == 2) goto pos48372; */ // question mark phoneme? if (A == 2) { // create falling inflection mem48 = 255; AddInflection(mem48, phase1); } // pos47615: // get the stress amount (more stress = higher pitch) phase1 = tab47492[stressOutput[Y] + 1]; // get number of frames to write phase2 = phonemeLengthOutput[Y]; Y = mem56; // copy from the source to the frames list do { frequency1[X] = freq1data[Y]; // F1 frequency frequency2[X] = freq2data[Y]; // F2 frequency frequency3[X] = freq3data[Y]; // F3 frequency amplitude1[X] = ampl1data[Y]; // F1 amplitude amplitude2[X] = ampl2data[Y]; // F2 amplitude amplitude3[X] = ampl3data[Y]; // F3 amplitude sampledConsonantFlag[X] = sampledConsonantFlags[Y]; // phoneme data for sampled consonants pitches[X] = pitch + phase1; // pitch X++; phase2--; } while(phase2 != 0); mem44++; } while(mem44 != 0); // ------------------- //pos47694: // CREATE TRANSITIONS // // Linear transitions are now created to smoothly connect the // end of one sustained portion of a phoneme to the following // phoneme. // // To do this, three tables are used: // // Table Purpose // ========= ================================================== // blendRank Determines which phoneme's blend values are used. // // blendOut The number of frames at the end of the phoneme that // will be used to transition to the following phoneme. // // blendIn The number of frames of the following phoneme that // will be used to transition into that phoneme. // // In creating a transition between two phonemes, the phoneme // with the HIGHEST rank is used. Phonemes are ranked on how much // their identity is based on their transitions. For example, // vowels are and diphthongs are identified by their sustained portion, // rather than the transitions, so they are given low values. In contrast, // stop consonants (P, B, T, K) and glides (Y, L) are almost entirely // defined by their transitions, and are given high rank values. // // Here are the rankings used by SAM: // // Rank Type Phonemes // 2 All vowels IY, IH, etc. // 5 Diphthong endings YX, WX, ER // 8 Terminal liquid consonants LX, WX, YX, N, NX // 9 Liquid consonants L, RX, W // 10 Glide R, OH // 11 Glide WH // 18 Voiceless fricatives S, SH, F, TH // 20 Voiced fricatives Z, ZH, V, DH // 23 Plosives, stop consonants P, T, K, KX, DX, CH // 26 Stop consonants J, GX, B, D, G // 27-29 Stop consonants (internal) ** // 30 Unvoiced consonants /H, /X and Q* // 160 Nasal M // // To determine how many frames to use, the two phonemes are // compared using the blendRank[] table. The phoneme with the // higher rank is selected. In case of a tie, a blend of each is used: // // if blendRank[phoneme1] == blendRank[phomneme2] // // use lengths from each phoneme // outBlendFrames = outBlend[phoneme1] // inBlendFrames = outBlend[phoneme2] // else if blendRank[phoneme1] > blendRank[phoneme2] // // use lengths from first phoneme // outBlendFrames = outBlendLength[phoneme1] // inBlendFrames = inBlendLength[phoneme1] // else // // use lengths from the second phoneme // // note that in and out are SWAPPED! // outBlendFrames = inBlendLength[phoneme2] // inBlendFrames = outBlendLength[phoneme2] // // Blend lengths can't be less than zero. // // Transitions are assumed to be symetrical, so if the transition // values for the second phoneme are used, the inBlendLength and // outBlendLength values are SWAPPED. // // For most of the parameters, SAM interpolates over the range of the last // outBlendFrames-1 and the first inBlendFrames. // // The exception to this is the Pitch[] parameter, which is interpolates the // pitch from the CENTER of the current phoneme to the CENTER of the next // phoneme. // // Here are two examples. First, For example, consider the word "SUN" (S AH N) // // Phoneme Duration BlendWeight OutBlendFrames InBlendFrames // S 2 18 1 3 // AH 8 2 4 4 // N 7 8 1 2 // // The formant transitions for the output frames are calculated as follows: // // flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch // ------------------------------------------------ // S // 241 0 6 0 73 0 99 61 Use S (weight 18) for transition instead of AH (weight 2) // 241 0 6 0 73 0 99 61 <-- (OutBlendFrames-1) = (1-1) = 0 frames // AH // 0 2 10 2 66 0 96 59 * <-- InBlendFrames = 3 frames // 0 4 14 3 59 0 93 57 * // 0 8 18 5 52 0 90 55 * // 0 15 22 9 44 1 87 53 // 0 15 22 9 44 1 87 53 // 0 15 22 9 44 1 87 53 Use N (weight 8) for transition instead of AH (weight 2). // 0 15 22 9 44 1 87 53 Since N is second phoneme, reverse the IN and OUT values. // 0 11 17 8 47 1 98 56 * <-- (InBlendFrames-1) = (2-1) = 1 frames // N // 0 8 12 6 50 1 109 58 * <-- OutBlendFrames = 1 // 0 5 6 5 54 0 121 61 // 0 5 6 5 54 0 121 61 // 0 5 6 5 54 0 121 61 // 0 5 6 5 54 0 121 61 // 0 5 6 5 54 0 121 61 // 0 5 6 5 54 0 121 61 // // Now, consider the reverse "NUS" (N AH S): // // flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch // ------------------------------------------------ // N // 0 5 6 5 54 0 121 61 // 0 5 6 5 54 0 121 61 // 0 5 6 5 54 0 121 61 // 0 5 6 5 54 0 121 61 // 0 5 6 5 54 0 121 61 // 0 5 6 5 54 0 121 61 Use N (weight 8) for transition instead of AH (weight 2) // 0 5 6 5 54 0 121 61 <-- (OutBlendFrames-1) = (1-1) = 0 frames // AH // 0 8 11 6 51 0 110 59 * <-- InBlendFrames = 2 // 0 11 16 8 48 0 99 56 * // 0 15 22 9 44 1 87 53 Use S (weight 18) for transition instead of AH (weight 2) // 0 15 22 9 44 1 87 53 Since S is second phoneme, reverse the IN and OUT values. // 0 9 18 5 51 1 90 55 * <-- (InBlendFrames-1) = (3-1) = 2 // 0 4 14 3 58 1 93 57 * // S // 241 2 10 2 65 1 96 59 * <-- OutBlendFrames = 1 // 241 0 6 0 73 0 99 61 A = 0; mem44 = 0; mem49 = 0; // mem49 starts at as 0 X = 0; while(1) //while No. 1 { // get the current and following phoneme Y = phonemeIndexOutput[X]; A = phonemeIndexOutput[X+1]; X++; // exit loop at end token if (A == 255) break;//goto pos47970; // get the ranking of each phoneme X = A; mem56 = blendRank[A]; A = blendRank[Y]; // compare the rank - lower rank value is stronger if (A == mem56) { // same rank, so use out blend lengths from each phoneme phase1 = outBlendLength[Y]; phase2 = outBlendLength[X]; } else if (A < mem56) { // first phoneme is stronger, so us it's blend lengths phase1 = inBlendLength[X]; phase2 = outBlendLength[X]; } else { // second phoneme is stronger, so use it's blend lengths // note the out/in are swapped phase1 = outBlendLength[Y]; phase2 = inBlendLength[Y]; } Y = mem44; A = mem49 + phonemeLengthOutput[mem44]; // A is mem49 + length mem49 = A; // mem49 now holds length + position A = A + phase2; //Maybe Problem because of carry flag //47776: ADC 42 speedcounter = A; mem47 = 168; phase3 = mem49 - phase1; // what is mem49 A = phase1 + phase2; // total transition? mem38 = A; X = A; X -= 2; if ((X & 128) == 0) do //while No. 2 { //pos47810: // mem47 is used to index the tables: // 168 pitches[] // 169 frequency1 // 170 frequency2 // 171 frequency3 // 172 amplitude1 // 173 amplitude2 // 174 amplitude3 mem40 = mem38; if (mem47 == 168) // pitch { // unlike the other values, the pitches[] interpolates from // the middle of the current phoneme to the middle of the // next phoneme unsigned char mem36, mem37; // half the width of the current phoneme mem36 = phonemeLengthOutput[mem44] >> 1; // half the width of the next phoneme mem37 = phonemeLengthOutput[mem44+1] >> 1; // sum the values mem40 = mem36 + mem37; // length of both halves mem37 += mem49; // center of next phoneme mem36 = mem49 - mem36; // center index of current phoneme A = Read(mem47, mem37); // value at center of next phoneme - end interpolation value //A = mem[address]; Y = mem36; // start index of interpolation mem53 = A - Read(mem47, mem36); // value to center of current phoneme } else { // value to interpolate to A = Read(mem47, speedcounter); // position to start interpolation from Y = phase3; // value to interpolate from mem53 = A - Read(mem47, phase3); } //Code47503(mem40); // ML : Code47503 is division with remainder, and mem50 gets the sign // calculate change per frame signed char m53 = (signed char)mem53; mem50 = mem53 & 128; unsigned char m53abs = abs(m53); mem51 = m53abs % mem40; //abs((char)m53) % mem40; mem53 = (unsigned char)((signed char)(m53) / mem40); // interpolation range X = mem40; // number of frames to interpolate over Y = phase3; // starting frame // linearly interpolate values mem56 = 0; //47907: CLC //pos47908: while(1) //while No. 3 { A = Read(mem47, Y) + mem53; //carry alway cleared mem48 = A; Y++; X--; if(X == 0) break; mem56 += mem51; if (mem56 >= mem40) //??? { mem56 -= mem40; //carry? is set //if ((mem56 & 128)==0) if ((mem50 & 128)==0) { //47935: BIT 50 //47937: BMI 47943 if(mem48 != 0) mem48++; } else mem48--; } //pos47945: Write(mem47, Y, mem48); } //while No. 3 //pos47952: mem47++; //if (mem47 != 175) goto pos47810; } while (mem47 != 175); //while No. 2 //pos47963: mem44++; X = mem44; } //while No. 1 //goto pos47701; //pos47970: // add the length of this phoneme mem48 = mem49 + phonemeLengthOutput[mem44]; // ASSIGN PITCH CONTOUR // // This subtracts the F1 frequency from the pitch to create a // pitch contour. Without this, the output would be at a single // pitch level (monotone). // don't adjust pitch if in sing mode if (!singmode) { // iterate through the buffer for(i=0; i<256; i++) { // subtract half the frequency of the formant 1. // this adds variety to the voice pitches[i] -= (frequency1[i] >> 1); } } phase1 = 0; phase2 = 0; phase3 = 0; mem49 = 0; speedcounter = 72; //sam standard speed // RESCALE AMPLITUDE // // Rescale volume from a linear scale to decibels. // //amplitude rescaling for(i=255; i>=0; i--) { amplitude1[i] = amplitudeRescale[amplitude1[i]]; amplitude2[i] = amplitudeRescale[amplitude2[i]]; amplitude3[i] = amplitudeRescale[amplitude3[i]]; } Y = 0; A = pitches[0]; mem44 = A; X = A; mem38 = A - (A>>2); // 3/4*A ??? #ifdef SAM_DEBUG PrintOutput(sampledConsonantFlag, frequency1, frequency2, frequency3, amplitude1, amplitude2, amplitude3, pitches); #endif // PROCESS THE FRAMES // // In traditional vocal synthesis, the glottal pulse drives filters, which // are attenuated to the frequencies of the formants. // // SAM generates these formants directly with sin and rectangular waves. // To simulate them being driven by the glottal pulse, the waveforms are // reset at the beginning of each glottal pulse. //finally the loop for sound output //pos48078: while(1) { // get the sampled information on the phoneme A = sampledConsonantFlag[Y]; mem39 = A; // unvoiced sampled phoneme? A = A & 248; if(A != 0) { // render the sample for the phoneme RenderSample(&mem66); // skip ahead two in the phoneme buffer Y += 2; mem48 -= 2; } else { // simulate the glottal pulse and formants unsigned char ary[5]; unsigned int p1 = phase1 * 256; // Fixed point integers because we need to divide later on unsigned int p2 = phase2 * 256; unsigned int p3 = phase3 * 256; int k; for (k=0; k<5; k++) { signed char sp1 = (signed char)sinus[0xff & (p1>>8)]; signed char sp2 = (signed char)sinus[0xff & (p2>>8)]; signed char rp3 = (signed char)rectangle[0xff & (p3>>8)]; signed int sin1 = sp1 * ((unsigned char)amplitude1[Y] & 0x0f); signed int sin2 = sp2 * ((unsigned char)amplitude2[Y] & 0x0f); signed int rect = rp3 * ((unsigned char)amplitude3[Y] & 0x0f); signed int mux = sin1 + sin2 + rect; mux /= 32; mux += 128; // Go from signed to unsigned amplitude ary[k] = mux; p1 += frequency1[Y] * 256 / 4; // Compromise, this becomes a shift and works well p2 += frequency2[Y] * 256 / 4; p3 += frequency3[Y] * 256 / 4; } // output the accumulated value Output8BitAry(0, ary); speedcounter--; if (speedcounter != 0) goto pos48155; Y++; //go to next amplitude // decrement the frame count mem48--; } // if the frame count is zero, exit the loop if(mem48 == 0) return; speedcounter = speed; pos48155: // decrement the remaining length of the glottal pulse mem44--; // finished with a glottal pulse? if(mem44 == 0) { pos48159: // fetch the next glottal pulse length A = pitches[Y]; mem44 = A; A = A - (A>>2); mem38 = A; // reset the formant wave generators to keep them in // sync with the glottal pulse phase1 = 0; phase2 = 0; phase3 = 0; continue; } // decrement the count mem38--; // is the count non-zero and the sampled flag is zero? if((mem38 != 0) || (mem39 == 0)) { // reset the phase of the formants to match the pulse phase1 += frequency1[Y]; phase2 += frequency2[Y]; phase3 += frequency3[Y]; continue; } // voiced sampled phonemes interleave the sample with the // glottal pulse. The sample flag is non-zero, so render // the sample for the phoneme. RenderSample(&mem66); goto pos48159; } //while // The following code is never reached. It's left over from when // the voiced sample code was part of this loop, instead of part // of RenderSample(); //pos48315: int tempA; phase1 = A ^ 255; Y = mem66; do { //pos48321: mem56 = 8; A = Read(mem47, Y); //pos48327: do { //48327: ASL A //48328: BCC 48337 tempA = A; A = A << 1; if ((tempA & 128) != 0) { X = 26; // mem[54296] = X; bufferpos += 150; SAM_write_buffer(bufferpos/50, (X & 15)*16); } else { //mem[54296] = 6; X=6; bufferpos += 150; SAM_write_buffer(bufferpos/50, (X & 15)*16); } for(X = wait2; X>0; X--); //wait mem56--; } while(mem56 != 0); Y++; phase1++; } while (phase1 != 0); // if (phase1 != 0) goto pos48321; A = 1; mem44 = 1; mem66 = Y; Y = mem49; return; } // Create a rising or falling inflection 30 frames prior to // index X. A rising inflection is used for questions, and // a falling inflection is used for statements. void AddInflection(unsigned char mem48, unsigned char phase1) { //pos48372: // mem48 = 255; //pos48376: // store the location of the punctuation mem49 = X; A = X; int Atemp = A; // backup 30 frames A = A - 30; // if index is before buffer, point to start of buffer if (Atemp <= 30) A=0; X = A; // FIXME: Explain this fix better, it's not obvious // ML : A =, fixes a problem with invalid pitch with '.' while( (A=pitches[X]) == 127) X++; pos48398: //48398: CLC //48399: ADC 48 // add the inflection direction A += mem48; phase1 = A; // set the inflection pitches[X] = A; pos48406: // increment the position X++; // exit if the punctuation has been reached if (X == mem49) return; //goto pos47615; if (pitches[X] == 255) goto pos48406; A = phase1; goto pos48398; } /* SAM's voice can be altered by changing the frequencies of the mouth formant (F1) and the throat formant (F2). Only the voiced phonemes (5-29 and 48-53) are altered. */ void SetMouthThroat(unsigned char mouth, unsigned char throat) { unsigned char initialFrequency; unsigned char newFrequency = 0; //unsigned char mouth; //mem38880 //unsigned char throat; //mem38881 // mouth formants (F1) 5..29 unsigned char mouthFormants5_29[30] = { 0, 0, 0, 0, 0, 10, 14, 19, 24, 27, 23, 21, 16, 20, 14, 18, 14, 18, 18, 16, 13, 15, 11, 18, 14, 11, 9, 6, 6, 6}; // throat formants (F2) 5..29 unsigned char throatFormants5_29[30] = { 255, 255, 255, 255, 255, 84, 73, 67, 63, 40, 44, 31, 37, 45, 73, 49, 36, 30, 51, 37, 29, 69, 24, 50, 30, 24, 83, 46, 54, 86}; // there must be no zeros in this 2 tables // formant 1 frequencies (mouth) 48..53 unsigned char mouthFormants48_53[6] = {19, 27, 21, 27, 18, 13}; // formant 2 frequencies (throat) 48..53 unsigned char throatFormants48_53[6] = {72, 39, 31, 43, 30, 34}; unsigned char pos = 5; //mem39216 //pos38942: // recalculate formant frequencies 5..29 for the mouth (F1) and throat (F2) while(pos != 30) { // recalculate mouth frequency initialFrequency = mouthFormants5_29[pos]; if (initialFrequency != 0) newFrequency = trans(mouth, initialFrequency); freq1data[pos] = newFrequency; // recalculate throat frequency initialFrequency = throatFormants5_29[pos]; if(initialFrequency != 0) newFrequency = trans(throat, initialFrequency); freq2data[pos] = newFrequency; pos++; } //pos39059: // recalculate formant frequencies 48..53 pos = 48; Y = 0; while(pos != 54) { // recalculate F1 (mouth formant) initialFrequency = mouthFormants48_53[Y]; newFrequency = trans(mouth, initialFrequency); freq1data[pos] = newFrequency; // recalculate F2 (throat formant) initialFrequency = throatFormants48_53[Y]; newFrequency = trans(throat, initialFrequency); freq2data[pos] = newFrequency; Y++; pos++; } } //return = (mem39212*mem39213) >> 1 unsigned char trans(unsigned char mem39212, unsigned char mem39213) { //pos39008: unsigned char carry; int temp; unsigned char mem39214, mem39215; A = 0; mem39215 = 0; mem39214 = 0; X = 8; do { carry = mem39212 & 1; mem39212 = mem39212 >> 1; if (carry != 0) { /* 39018: LSR 39212 39021: BCC 39033 */ carry = 0; A = mem39215; temp = (int)A + (int)mem39213; A = A + mem39213; if (temp > 255) carry = 1; mem39215 = A; } temp = mem39215 & 1; mem39215 = (mem39215 >> 1) | (carry?128:0); carry = temp; //39033: ROR 39215 X--; } while (X != 0); temp = mem39214 & 128; mem39214 = (mem39214 << 1) | (carry?1:0); carry = temp; temp = mem39215 & 128; mem39215 = (mem39215 << 1) | (carry?1:0); carry = temp; return mem39215; } ================================================ FILE: lib/SAM/render.h ================================================ #ifndef RENDER_H #define RENDER_H void Render(); void SetMouthThroat(unsigned char mouth, unsigned char throat); #endif ================================================ FILE: lib/SAM/sam.c ================================================ #include #include #include #include "debug.h" #include "sam.h" #include "render.h" #include "SamTabs.h" char input[256]; //tab39445 //standard sam sound unsigned char speed = 72; unsigned char pitch = 64; unsigned char mouth = 128; unsigned char throat = 128; int singmode = 0; int debug = 0; unsigned char mem39; unsigned char mem44; unsigned char mem47; unsigned char mem49; unsigned char mem50; unsigned char mem51; unsigned char mem53; unsigned char mem56; unsigned char mem59=0; unsigned char A, X, Y; unsigned char stress[256]; //numbers from 0 to 8 unsigned char phonemeLength[256]; //tab40160 unsigned char phonemeindex[256]; unsigned char phonemeIndexOutput[60]; //tab47296 unsigned char stressOutput[60]; //tab47365 unsigned char phonemeLengthOutput[60]; //tab47416 // contains the final soundbuffer int bufferpos=0; char *buffer = NULL; void SetInput(char *_input) { int i, l; l = strlen(_input); if (l > 254) l = 254; for(i=0; i 80) { phonemeindex[X] = 255; break; // error: delete all behind it } X++; } while (X != 0); //pos39848: InsertBreath(); //mem[40158] = 255; #ifdef SAM_DEBUG PrintPhonemes(phonemeindex, phonemeLength, stress); #endif PrepareOutput(); return 1; } //void Code48547() void PrepareOutput() { A = 0; X = 0; Y = 0; //pos48551: while(1) { A = phonemeindex[X]; if (A == 255) { A = 255; phonemeIndexOutput[Y] = 255; Render(); return; } if (A == 254) { X++; int temp = X; //mem[48546] = X; phonemeIndexOutput[Y] = 255; Render(); //X = mem[48546]; X=temp; Y = 0; continue; } if (A == 0) { X++; continue; } phonemeIndexOutput[Y] = A; phonemeLengthOutput[Y] = phonemeLength[X]; stressOutput[Y] = stress[X]; X++; Y++; } } //void Code48431() void InsertBreath() { unsigned char mem54; unsigned char mem55; unsigned char index; //variable Y mem54 = 255; X++; mem55 = 0; unsigned char mem66 = 0; while(1) { //pos48440: X = mem66; index = phonemeindex[X]; if (index == 255) return; mem55 += phonemeLength[X]; if (mem55 < 232) { if (index != 254) // ML : Prevents an index out of bounds problem { A = flags2[index]&1; if(A != 0) { X++; mem55 = 0; Insert(X, 254, mem59, 0); mem66++; mem66++; continue; } } if (index == 0) mem54 = X; mem66++; continue; } X = mem54; phonemeindex[X] = 31; // 'Q*' glottal stop phonemeLength[X] = 4; stress[X] = 0; X++; mem55 = 0; Insert(X, 254, mem59, 0); X++; mem66 = X; } } // Iterates through the phoneme buffer, copying the stress value from // the following phoneme under the following circumstance: // 1. The current phoneme is voiced, excluding plosives and fricatives // 2. The following phoneme is voiced, excluding plosives and fricatives, and // 3. The following phoneme is stressed // // In those cases, the stress value+1 from the following phoneme is copied. // // For example, the word LOITER is represented as LOY5TER, with as stress // of 5 on the diphtong OY. This routine will copy the stress value of 6 (5+1) // to the L that precedes it. //void Code41883() void CopyStress() { // loop thought all the phonemes to be output unsigned char pos=0; //mem66 while(1) { // get the phomene Y = phonemeindex[pos]; // exit at end of buffer if (Y == 255) return; // if CONSONANT_FLAG set, skip - only vowels get stress if ((flags[Y] & 64) == 0) {pos++; continue;} // get the next phoneme Y = phonemeindex[pos+1]; if (Y == 255) //prevent buffer overflow { pos++; continue; } else // if the following phoneme is a vowel, skip if ((flags[Y] & 128) == 0) {pos++; continue;} // get the stress value at the next position Y = stress[pos+1]; // if next phoneme is not stressed, skip if (Y == 0) {pos++; continue;} // if next phoneme is not a VOWEL OR ER, skip if ((Y & 128) != 0) {pos++; continue;} // copy stress from prior phoneme to this one stress[pos] = Y+1; // advance pointer pos++; } } //void Code41014() void Insert(unsigned char position/*var57*/, unsigned char mem60, unsigned char mem59, unsigned char mem58) { int i; for(i=253; i >= position; i--) // ML : always keep last safe-guarding 255 { phonemeindex[i+1] = phonemeindex[i]; phonemeLength[i+1] = phonemeLength[i]; stress[i+1] = stress[i]; } phonemeindex[position] = mem60; phonemeLength[position] = mem59; stress[position] = mem58; return; } // The input[] buffer contains a string of phonemes and stress markers along // the lines of: // // DHAX KAET IHZ AH5GLIY. <0x9B> // // The byte 0x9B marks the end of the buffer. Some phonemes are 2 bytes // long, such as "DH" and "AX". Others are 1 byte long, such as "T" and "Z". // There are also stress markers, such as "5" and ".". // // The first character of the phonemes are stored in the table signInputTable1[]. // The second character of the phonemes are stored in the table signInputTable2[]. // The stress characters are arranged in low to high stress order in stressInputTable[]. // // The following process is used to parse the input[] buffer: // // Repeat until the <0x9B> character is reached: // // First, a search is made for a 2 character match for phonemes that do not // end with the '*' (wildcard) character. On a match, the index of the phoneme // is added to phonemeIndex[] and the buffer position is advanced 2 bytes. // // If this fails, a search is made for a 1 character match against all // phoneme names ending with a '*' (wildcard). If this succeeds, the // phoneme is added to phonemeIndex[] and the buffer position is advanced // 1 byte. // // If this fails, search for a 1 character match in the stressInputTable[]. // If this succeeds, the stress value is placed in the last stress[] table // at the same index of the last added phoneme, and the buffer position is // advanced by 1 byte. // // If this fails, return a 0. // // On success: // // 1. phonemeIndex[] will contain the index of all the phonemes. // 2. The last index in phonemeIndex[] will be 255. // 3. stress[] will contain the stress value for each phoneme // input[] holds the string of phonemes, each two bytes wide // signInputTable1[] holds the first character of each phoneme // signInputTable2[] holds te second character of each phoneme // phonemeIndex[] holds the indexes of the phonemes after parsing input[] // // The parser scans through the input[], finding the names of the phonemes // by searching signInputTable1[] and signInputTable2[]. On a match, it // copies the index of the phoneme into the phonemeIndexTable[]. // // The character <0x9B> marks the end of text in input[]. When it is reached, // the index 255 is placed at the end of the phonemeIndexTable[], and the // function returns with a 1 indicating success. int Parser1() { int i; unsigned char sign1; unsigned char sign2; unsigned char position = 0; X = 0; A = 0; Y = 0; // CLEAR THE STRESS TABLE for(i=0; i<256; i++) stress[i] = 0; // THIS CODE MATCHES THE PHONEME LETTERS TO THE TABLE // pos41078: while(1) { // GET THE FIRST CHARACTER FROM THE PHONEME BUFFER sign1 = input[X]; // TEST FOR 155 (�) END OF LINE MARKER if (sign1 == 155) { // MARK ENDPOINT AND RETURN phonemeindex[position] = 255; //mark endpoint // REACHED END OF PHONEMES, SO EXIT return 1; //all ok } // GET THE NEXT CHARACTER FROM THE BUFFER X++; sign2 = input[X]; // NOW sign1 = FIRST CHARACTER OF PHONEME, AND sign2 = SECOND CHARACTER OF PHONEME // TRY TO MATCH PHONEMES ON TWO TWO-CHARACTER NAME // IGNORE PHONEMES IN TABLE ENDING WITH WILDCARDS // SET INDEX TO 0 Y = 0; pos41095: // GET FIRST CHARACTER AT POSITION Y IN signInputTable // --> should change name to PhonemeNameTable1 A = signInputTable1[Y]; // FIRST CHARACTER MATCHES? if (A == sign1) { // GET THE CHARACTER FROM THE PhonemeSecondLetterTable A = signInputTable2[Y]; // NOT A SPECIAL AND MATCHES SECOND CHARACTER? if ((A != '*') && (A == sign2)) { // STORE THE INDEX OF THE PHONEME INTO THE phomeneIndexTable phonemeindex[position] = Y; // ADVANCE THE POINTER TO THE phonemeIndexTable position++; // ADVANCE THE POINTER TO THE phonemeInputBuffer X++; // CONTINUE PARSING continue; } } // NO MATCH, TRY TO MATCH ON FIRST CHARACTER TO WILDCARD NAMES (ENDING WITH '*') // ADVANCE TO THE NEXT POSITION Y++; // IF NOT END OF TABLE, CONTINUE if (Y != 81) goto pos41095; // REACHED END OF TABLE WITHOUT AN EXACT (2 CHARACTER) MATCH. // THIS TIME, SEARCH FOR A 1 CHARACTER MATCH AGAINST THE WILDCARDS // RESET THE INDEX TO POINT TO THE START OF THE PHONEME NAME TABLE Y = 0; pos41134: // DOES THE PHONEME IN THE TABLE END WITH '*'? if (signInputTable2[Y] == '*') { // DOES THE FIRST CHARACTER MATCH THE FIRST LETTER OF THE PHONEME if (signInputTable1[Y] == sign1) { // SAVE THE POSITION AND MOVE AHEAD phonemeindex[position] = Y; // ADVANCE THE POINTER position++; // CONTINUE THROUGH THE LOOP continue; } } Y++; if (Y != 81) goto pos41134; //81 is size of PHONEME NAME table // FAILED TO MATCH WITH A WILDCARD. ASSUME THIS IS A STRESS // CHARACTER. SEARCH THROUGH THE STRESS TABLE // SET INDEX TO POSITION 8 (END OF STRESS TABLE) Y = 8; // WALK BACK THROUGH TABLE LOOKING FOR A MATCH while( (sign1 != stressInputTable[Y]) && (Y>0)) { // DECREMENT INDEX Y--; } // REACHED THE END OF THE SEARCH WITHOUT BREAKING OUT OF LOOP? if (Y == 0) { //mem[39444] = X; //41181: JSR 42043 //Error // FAILED TO MATCH ANYTHING, RETURN 0 ON FAILURE return 0; } // SET THE STRESS FOR THE PRIOR PHONEME stress[position-1] = Y; } //while } //change phonemelength depedendent on stress //void Code41203() void SetPhonemeLength() { unsigned char A; int position = 0; while(phonemeindex[position] != 255 ) { A = stress[position]; //41218: BMI 41229 if ((A == 0) || ((A&128) != 0)) { phonemeLength[position] = phonemeLengthTable[phonemeindex[position]]; } else { phonemeLength[position] = phonemeStressedLengthTable[phonemeindex[position]]; } position++; } } void Code41240() { unsigned char pos=0; while(phonemeindex[pos] != 255) { unsigned char index; //register AC X = pos; index = phonemeindex[pos]; if ((flags[index]&2) == 0) { pos++; continue; } else if ((flags[index]&1) == 0) { Insert(pos+1, index+1, phonemeLengthTable[index+1], stress[pos]); Insert(pos+2, index+2, phonemeLengthTable[index+2], stress[pos]); pos += 3; continue; } do { X++; A = phonemeindex[X]; } while(A==0); if (A != 255) { if ((flags[A] & 8) != 0) {pos++; continue;} if ((A == 36) || (A == 37)) {pos++; continue;} // '/H' '/X' } Insert(pos+1, index+1, phonemeLengthTable[index+1], stress[pos]); Insert(pos+2, index+2, phonemeLengthTable[index+2], stress[pos]); pos += 3; }; } // Rewrites the phonemes using the following rules: // // -> WX // -> YX // UL -> AX L // UM -> AX M // -> Q // T R -> CH R // D R -> J R // R -> RX // L -> LX // G S -> G Z // K -> KX // G -> GX // S P -> S B // S T -> S D // S K -> S G // S KX -> S GX // UW -> UX // CH -> CH CH' (CH requires two phonemes to represent it) // J -> J J' (J requires two phonemes to represent it) // T -> DX // D -> DX //void Code41397() void Parser2() { if (debug) printf("Parser2\n"); unsigned char pos = 0; //mem66; unsigned char mem58 = 0; // Loop through phonemes while(1) { // SET X TO THE CURRENT POSITION X = pos; // GET THE PHONEME AT THE CURRENT POSITION A = phonemeindex[pos]; // DEBUG: Print phoneme and index if (debug && A != 255) printf("%d: %c%c\n", X, signInputTable1[A], signInputTable2[A]); // Is phoneme pause? if (A == 0) { // Move ahead to the pos++; continue; } // If end of phonemes flag reached, exit routine if (A == 255) return; // Copy the current phoneme index to Y Y = A; // RULE: // -> WX // -> YX // Example: OIL, COW // Check for DIPHTONG if ((flags[A] & 16) == 0) goto pos41457; // Not a diphthong. Get the stress mem58 = stress[pos]; // End in IY sound? A = flags[Y] & 32; // If ends with IY, use YX, else use WX if (A == 0) A = 20; else A = 21; // 'WX' = 20 'YX' = 21 //pos41443: // Insert at WX or YX following, copying the stress if (debug) if (A==20) printf("RULE: insert WX following diphtong NOT ending in IY sound\n"); if (debug) if (A==21) printf("RULE: insert YX following diphtong ending in IY sound\n"); Insert(pos+1, A, mem59, mem58); X = pos; // Jump to ??? goto pos41749; pos41457: // RULE: // UL -> AX L // Example: MEDDLE // Get phoneme A = phonemeindex[X]; // Skip this rule if phoneme is not UL if (A != 78) goto pos41487; // 'UL' A = 24; // 'L' //change 'UL' to 'AX L' if (debug) printf("RULE: UL -> AX L\n"); pos41466: // Get current phoneme stress mem58 = stress[X]; // Change UL to AX phonemeindex[X] = 13; // 'AX' // Perform insert. Note code below may jump up here with different values Insert(X+1, A, mem59, mem58); pos++; // Move to next phoneme continue; pos41487: // RULE: // UM -> AX M // Example: ASTRONOMY // Skip rule if phoneme != UM if (A != 79) goto pos41495; // 'UM' // Jump up to branch - replaces current phoneme with AX and continues A = 27; // 'M' //change 'UM' to 'AX M' if (debug) printf("RULE: UM -> AX M\n"); goto pos41466; pos41495: // RULE: // UN -> AX N // Example: FUNCTION // Skip rule if phoneme != UN if (A != 80) goto pos41503; // 'UN' // Jump up to branch - replaces current phoneme with AX and continues A = 28; // 'N' //change UN to 'AX N' if (debug) printf("RULE: UN -> AX N\n"); goto pos41466; pos41503: // RULE: // -> Q // EXAMPLE: AWAY EIGHT Y = A; // VOWEL set? A = flags[A] & 128; // Skip if not a vowel if (A != 0) { // Get the stress A = stress[X]; // If stressed... if (A != 0) { // Get the following phoneme X++; A = phonemeindex[X]; // If following phoneme is a pause if (A == 0) { // Get the phoneme following pause X++; Y = phonemeindex[X]; // Check for end of buffer flag if (Y == 255) //buffer overflow // ??? Not sure about these flags A = 65&128; else // And VOWEL flag to current phoneme's flags A = flags[Y] & 128; // If following phonemes is not a pause if (A != 0) { // If the following phoneme is not stressed A = stress[X]; if (A != 0) { // Insert a glottal stop and move forward if (debug) printf("RULE: Insert glottal stop between two stressed vowels with space between them\n"); // 31 = 'Q' Insert(X, 31, mem59, 0); pos++; continue; } } } } } // RULES FOR PHONEMES BEFORE R // T R -> CH R // Example: TRACK // Get current position and phoneme X = pos; A = phonemeindex[pos]; if (A != 23) goto pos41611; // 'R' // Look at prior phoneme X--; A = phonemeindex[pos-1]; //pos41567: if (A == 69) // 'T' { // Change T to CH if (debug) printf("RULE: T R -> CH R\n"); phonemeindex[pos-1] = 42; goto pos41779; } // RULES FOR PHONEMES BEFORE R // D R -> J R // Example: DRY // Prior phonemes D? if (A == 57) // 'D' { // Change D to J phonemeindex[pos-1] = 44; if (debug) printf("RULE: D R -> J R\n"); goto pos41788; } // RULES FOR PHONEMES BEFORE R // R -> RX // Example: ART // If vowel flag is set change R to RX A = flags[A] & 128; if (debug) printf("RULE: R -> RX\n"); if (A != 0) phonemeindex[pos] = 18; // 'RX' // continue to next phoneme pos++; continue; pos41611: // RULE: // L -> LX // Example: ALL // Is phoneme L? if (A == 24) // 'L' { // If prior phoneme does not have VOWEL flag set, move to next phoneme if ((flags[phonemeindex[pos-1]] & 128) == 0) {pos++; continue;} // Prior phoneme has VOWEL flag set, so change L to LX and move to next phoneme if (debug) printf("RULE: L -> LX\n"); phonemeindex[X] = 19; // 'LX' pos++; continue; } // RULE: // G S -> G Z // // Can't get to fire - // 1. The G -> GX rule intervenes // 2. Reciter already replaces GS -> GZ // Is current phoneme S? if (A == 32) // 'S' { // If prior phoneme is not G, move to next phoneme if (phonemeindex[pos-1] != 60) {pos++; continue;} // Replace S with Z and move on if (debug) printf("RULE: G S -> G Z\n"); phonemeindex[pos] = 38; // 'Z' pos++; continue; } // RULE: // K -> KX // Example: COW // Is current phoneme K? if (A == 72) // 'K' { // Get next phoneme Y = phonemeindex[pos+1]; // If at end, replace current phoneme with KX if (Y == 255) phonemeindex[pos] = 75; // ML : prevents an index out of bounds problem else { // VOWELS AND DIPHTONGS ENDING WITH IY SOUND flag set? A = flags[Y] & 32; if (debug) if (A==0) printf("RULE: K -> KX \n"); // Replace with KX if (A == 0) phonemeindex[pos] = 75; // 'KX' } } else // RULE: // G -> GX // Example: GO // Is character a G? if (A == 60) // 'G' { // Get the following character unsigned char index = phonemeindex[pos+1]; // At end of buffer? if (index == 255) //prevent buffer overflow { pos++; continue; } else // If diphtong ending with YX, move continue processing next phoneme if ((flags[index] & 32) != 0) {pos++; continue;} // replace G with GX and continue processing next phoneme if (debug) printf("RULE: G -> GX \n"); phonemeindex[pos] = 63; // 'GX' pos++; continue; } // RULE: // S P -> S B // S T -> S D // S K -> S G // S KX -> S GX // Examples: SPY, STY, SKY, SCOWL Y = phonemeindex[pos]; //pos41719: // Replace with softer version? A = flags[Y] & 1; if (A == 0) goto pos41749; A = phonemeindex[pos-1]; if (A != 32) // 'S' { A = Y; goto pos41812; } // Replace with softer version if (debug) printf("RULE: S* %c%c -> S* %c%c\n", signInputTable1[Y], signInputTable2[Y],signInputTable1[Y-12], signInputTable2[Y-12]); phonemeindex[pos] = Y-12; pos++; continue; pos41749: // RULE: // UW -> UX // // Example: NEW, DEW, SUE, ZOO, THOO, TOO // UW -> UX A = phonemeindex[X]; if (A == 53) // 'UW' { // ALVEOLAR flag set? Y = phonemeindex[X-1]; A = flags2[Y] & 4; // If not set, continue processing next phoneme if (A == 0) {pos++; continue;} if (debug) printf("RULE: UW -> UX\n"); phonemeindex[X] = 16; pos++; continue; } pos41779: // RULE: // CH -> CH CH' (CH requires two phonemes to represent it) // Example: CHEW if (A == 42) // 'CH' { // pos41783: if (debug) printf("CH -> CH CH+1\n"); Insert(X+1, A+1, mem59, stress[X]); pos++; continue; } pos41788: // RULE: // J -> J J' (J requires two phonemes to represent it) // Example: JAY if (A == 44) // 'J' { if (debug) printf("J -> J J+1\n"); Insert(X+1, A+1, mem59, stress[X]); pos++; continue; } // Jump here to continue pos41812: // RULE: Soften T following vowel // NOTE: This rule fails for cases such as "ODD" // T -> DX // D -> DX // Example: PARTY, TARDY // Past this point, only process if phoneme is T or D if (A != 69) // 'T' if (A != 57) {pos++; continue;} // 'D' //pos41825: // If prior phoneme is not a vowel, continue processing phonemes if ((flags[phonemeindex[X-1]] & 128) == 0) {pos++; continue;} // Get next phoneme X++; A = phonemeindex[X]; //pos41841 // Is the next phoneme a pause? if (A != 0) { // If next phoneme is not a pause, continue processing phonemes if ((flags[A] & 128) == 0) {pos++; continue;} // If next phoneme is stressed, continue processing phonemes // FIXME: How does a pause get stressed? if (stress[X] != 0) {pos++; continue;} //pos41856: // Set phonemes to DX if (debug) printf("RULE: Soften T or D following vowel or ER and preceding a pause -> DX\n"); phonemeindex[pos] = 30; // 'DX' } else { A = phonemeindex[X+1]; if (A == 255) //prevent buffer overflow A = 65 & 128; else // Is next phoneme a vowel or ER? A = flags[A] & 128; if (debug) if (A != 0) printf("RULE: Soften T or D following vowel or ER and preceding a pause -> DX\n"); if (A != 0) phonemeindex[pos] = 30; // 'DX' } pos++; } // while } // Applies various rules that adjust the lengths of phonemes // // Lengthen or between and by 1.5 // - decrease length by 1 // - decrease vowel by 1/8th // - increase vowel by 1/2 + 1 // - set nasal = 5, consonant = 6 // {optional silence} - shorten both to 1/2 + 1 // - decrease by 2 //void Code48619() void AdjustLengths() { // LENGTHEN VOWELS PRECEDING PUNCTUATION // // Search for punctuation. If found, back up to the first vowel, then // process all phonemes between there and up to (but not including) the punctuation. // If any phoneme is found that is a either a fricative or voiced, the duration is // increased by (length * 1.5) + 1 // loop index X = 0; unsigned char index; // iterate through the phoneme list unsigned char loopIndex=0; while(1) { // get a phoneme index = phonemeindex[X]; // exit loop if end on buffer token if (index == 255) break; // not punctuation? if((flags2[index] & 1) == 0) { // skip X++; continue; } // hold index loopIndex = X; // Loop backwards from this point pos48644: // back up one phoneme X--; // stop once the beginning is reached if(X == 0) break; // get the preceding phoneme index = phonemeindex[X]; if (index != 255) //inserted to prevent access overrun if((flags[index] & 128) == 0) goto pos48644; // if not a vowel, continue looping //pos48657: do { // test for vowel index = phonemeindex[X]; if (index != 255)//inserted to prevent access overrun // test for fricative/unvoiced or not voiced if(((flags2[index] & 32) == 0) || ((flags[index] & 4) != 0)) //nochmal �berpr�fen { //A = flags[Y] & 4; //if(A == 0) goto pos48688; // get the phoneme length A = phonemeLength[X]; // change phoneme length to (length * 1.5) + 1 A = (A >> 1) + A + 1; if (debug) printf("RULE: Lengthen or between and by 1.5\n"); if (debug) printf("PRE\n"); if (debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); phonemeLength[X] = A; if (debug) printf("POST\n"); if (debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); } // keep moving forward X++; } while (X != loopIndex); // if (X != loopIndex) goto pos48657; X++; } // while // Similar to the above routine, but shorten vowels under some circumstances // Loop throught all phonemes loopIndex = 0; //pos48697 while(1) { // get a phoneme X = loopIndex; index = phonemeindex[X]; // exit routine at end token if (index == 255) return; // vowel? A = flags[index] & 128; if (A != 0) { // get next phoneme X++; index = phonemeindex[X]; // get flags if (index == 255) mem56 = 65; // use if end marker else mem56 = flags[index]; // not a consonant if ((flags[index] & 64) == 0) { // RX or LX? if ((index == 18) || (index == 19)) // 'RX' & 'LX' { // get the next phoneme X++; index = phonemeindex[X]; // next phoneme a consonant? if ((flags[index] & 64) != 0) { // RULE: RX | LX if (debug) printf("RULE: - decrease length by 1\n"); if (debug) printf("PRE\n"); if (debug) printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable1[phonemeindex[loopIndex]], signInputTable2[phonemeindex[loopIndex]], phonemeLength[loopIndex]); // decrease length of vowel by 1 frame phonemeLength[loopIndex]--; if (debug) printf("POST\n"); if (debug) printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable1[phonemeindex[loopIndex]], signInputTable2[phonemeindex[loopIndex]], phonemeLength[loopIndex]); } // move ahead loopIndex++; continue; } // move ahead loopIndex++; continue; } // Got here if not // not voiced if ((mem56 & 4) == 0) { // Unvoiced // *, .*, ?*, ,*, -*, DX, S*, SH, F*, TH, /H, /X, CH, P*, T*, K*, KX // not an unvoiced plosive? if((mem56 & 1) == 0) { // move ahead loopIndex++; continue; } // P*, T*, K*, KX // RULE: // // move back X--; if (debug) printf("RULE: - decrease vowel by 1/8th\n"); if (debug) printf("PRE\n"); if (debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); // decrease length by 1/8th mem56 = phonemeLength[X] >> 3; phonemeLength[X] -= mem56; if (debug) printf("POST\n"); if (debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); // move ahead loopIndex++; continue; } // RULE: // if (debug) printf("RULE: - increase vowel by 1/2 + 1\n"); if (debug) printf("PRE\n"); if (debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); // decrease length A = phonemeLength[X-1]; phonemeLength[X-1] = (A >> 2) + A + 1; // 5/4*A + 1 if (debug) printf("POST\n"); if (debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); // move ahead loopIndex++; continue; } // WH, R*, L*, W*, Y*, M*, N*, NX, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX //pos48821: // RULE: // Set punctuation length to 6 // Set stop consonant length to 5 // nasal? if((flags2[index] & 8) != 0) { // M*, N*, NX, // get the next phoneme X++; index = phonemeindex[X]; // end of buffer? if (index == 255) A = 65&2; //prevent buffer overflow else A = flags[index] & 2; // check for stop consonant // is next phoneme a stop consonant? if (A != 0) // B*, D*, G*, GX, P*, T*, K*, KX { if (debug) printf("RULE: - set nasal = 5, consonant = 6\n"); if (debug) printf("POST\n"); if (debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); if (debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); // set stop consonant length to 6 phonemeLength[X] = 6; // set nasal length to 5 phonemeLength[X-1] = 5; if (debug) printf("POST\n"); if (debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); if (debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); } // move to next phoneme loopIndex++; continue; } // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX // RULE: {optional silence} // Shorten both to (length/2 + 1) // (voiced) stop consonant? if((flags[index] & 2) != 0) { // B*, D*, G*, GX // move past silence do { // move ahead X++; index = phonemeindex[X]; } while(index == 0); // check for end of buffer if (index == 255) //buffer overflow { // ignore, overflow code if ((65 & 2) == 0) {loopIndex++; continue;} } else if ((flags[index] & 2) == 0) { // if another stop consonant, move ahead loopIndex++; continue; } // RULE: {optional silence} if (debug) printf("RULE: {optional silence} - shorten both to 1/2 + 1\n"); if (debug) printf("PRE\n"); if (debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); if (debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); // X gets overwritten, so hold prior X value for debug statement int debugX = X; // shorten the prior phoneme length to (length/2 + 1) phonemeLength[X] = (phonemeLength[X] >> 1) + 1; X = loopIndex; // also shorten this phoneme length to (length/2 +1) phonemeLength[loopIndex] = (phonemeLength[loopIndex] >> 1) + 1; if (debug) printf("POST\n"); if (debug) printf("phoneme %d (%c%c) length %d\n", debugX, signInputTable1[phonemeindex[debugX]], signInputTable2[phonemeindex[debugX]], phonemeLength[debugX]); if (debug) printf("phoneme %d (%c%c) length %d\n", debugX-1, signInputTable1[phonemeindex[debugX-1]], signInputTable2[phonemeindex[debugX-1]], phonemeLength[debugX-1]); // move ahead loopIndex++; continue; } // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, **, // RULE: // Decrease by 2 // liquic consonant? if ((flags2[index] & 16) != 0) { // R*, L*, W*, Y* // get the prior phoneme index = phonemeindex[X-1]; // prior phoneme a stop consonant> if((flags[index] & 2) != 0) { // Rule: if (debug) printf("RULE: - decrease by 2\n"); if (debug) printf("PRE\n"); if (debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); // decrease the phoneme length by 2 frames (20 ms) phonemeLength[X] -= 2; if (debug) printf("POST\n"); if (debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); } } // move to next phoneme loopIndex++; continue; } // goto pos48701; } // ------------------------------------------------------------------------- // ML : Code47503 is division with remainder, and mem50 gets the sign void Code47503(unsigned char mem52) { Y = 0; if ((mem53 & 128) != 0) { mem53 = -mem53; Y = 128; } mem50 = Y; A = 0; for(X=8; X > 0; X--) { int temp = mem53; mem53 = mem53 << 1; A = A << 1; if (temp >= 128) A++; if (A >= mem52) { A = A - mem52; mem53++; } } mem51 = A; if ((mem50 & 128) != 0) mem53 = -mem53; } ================================================ FILE: lib/SAM/sam.h ================================================ #ifndef SAM_H #define SAM_H void SetInput(char *_input); void SetSpeed(unsigned char _speed); void SetPitch(unsigned char _pitch); void SetMouth(unsigned char _mouth); void SetThroat(unsigned char _throat); void EnableSingmode(); void EnableDebug(); int SAMMain(); extern void (*SAM_write_buffer)(int pos, char value); //Overwrite for own buffer char* GetBuffer(); int GetBufferLength(); //char input[]={"/HAALAOAO MAYN NAAMAEAE IHSTT SAEBAASTTIHAAN \x9b\x9b\0"}; //unsigned char input[]={"/HAALAOAO \x9b\0"}; //unsigned char input[]={"AA \x9b\0"}; //unsigned char input[] = {"GUH5DEHN TAEG\x9b\0"}; //unsigned char input[]={"AY5 AEM EY TAO4LXKIHNX KAX4MPYUX4TAH. GOW4 AH/HEH3D PAHNK.MEYK MAY8 DEY.\x9b\0"}; //unsigned char input[]={"/HEH3LOW2, /HAW AH YUX2 TUXDEY. AY /HOH3P YUX AH FIYLIHNX OW4 KEY.\x9b\0"}; //unsigned char input[]={"/HEY2, DHIHS IH3Z GREY2T. /HAH /HAH /HAH.AYL BIY5 BAEK.\x9b\0"}; //unsigned char input[]={"/HAH /HAH /HAH \x9b\0"}; //unsigned char input[]={"/HAH /HAH /HAH.\x9b\0"}; //unsigned char input[]={".TUW BIY5Y3,, OHR NAA3T - TUW BIY5IYIY., DHAE4T IHZ DHAH KWEH4SCHAHN.\x9b\0"}; //unsigned char input[]={"/HEY2, DHIHS \x9b\0"}; //unsigned char input[]={" IYIHEHAEAAAHAOOHUHUXERAXIX \x9b\0"}; //unsigned char input[]={" RLWWYMNNXBDGJZZHVDH \x9b\0"}; //unsigned char input[]={" SSHFTHPTKCH/H \x9b\0"}; //unsigned char input[]={" EYAYOYAWOWUW ULUMUNQ YXWXRXLX/XDX\x9b\0"}; #endif ================================================ FILE: lib/bbd/LICENSE ================================================ Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: lib/bbd/README.md ================================================ # https://github.com/jpcima/bbd-delay-experimental Testing grounds for newer BBD delay implementation ## Reference - Holters, M., & Parker, J. D. (2018). A combined model for a bucket brigade device and its input and output filters. In *Proc. Int. Conf. Digital Audio Effects (DAFx-18), Aveiro, Portugal*. ================================================ FILE: lib/bbd/bbd_filter.cc ================================================ #include "bbd_filter.h" #include #include #include #include #ifdef M_PI cdouble BBD_Filter_Spec::transfer(cdouble::value_type frequency) const noexcept { cdouble j(0.0, 1.0); cdouble s = j * (cdouble::value_type)(2.0 * M_PI) * frequency; cdouble h = 0.0; for (unsigned i = 0; i < M; ++i) h += R[i] / (s - P[i]); return h; } #endif template static void interpolate_row(cdouble::value_type d, unsigned rows, unsigned cols, const T *src, T *dst) { assert(d >= 0); auto row = d * (rows - 1); unsigned row1 = std::min((unsigned)row, rows - 1); unsigned row2 = std::min(row1 + 1, rows - 1); auto mu = row - (unsigned)row; for (unsigned i = 0; i < cols; ++i) dst[i] = (1 - mu) * src[row1 * cols + i] + mu * src[row2 * cols + i]; } void BBD_Filter_Coef::interpolate_G(cdouble::value_type d, cdouble *g/*[M]*/) const noexcept { interpolate_row(d, N, M, G.get(), g); } BBD_Filter_Coef BBD::compute_filter(float fs, unsigned steps, const BBD_Filter_Spec &spec) { BBD_Filter_Coef coef; cdouble::value_type ts = 1.0 / fs; unsigned M = spec.M; coef.M = M; coef.N = steps; coef.G.reset(new cdouble[M * steps]); coef.P.reset(new cdouble[M]); cdouble *pm = coef.P.get(); for (unsigned m = 0; m < M; ++m) pm[m] = std::exp(ts * spec.P[m]); for (unsigned step = 0; step < steps; ++step) { auto d = (cdouble::value_type)step / (steps - 1); cdouble *gm = &coef.G[step * M]; switch (spec.kind) { case BBD_Filter_Kind::Input: for (unsigned m = 0; m < M; ++m) gm[m] = ts * spec.R[m] * std::pow(pm[m], d); break; case BBD_Filter_Kind::Output: for (unsigned m = 0; m < M; ++m) gm[m] = (spec.R[m] / spec.P[m]) * std::pow(pm[m], 1 - d); break; } } cdouble H = 0; for (unsigned m = 0; m < M; ++m) H -= spec.R[m] / spec.P[m]; coef.H = H.real(); return coef; } namespace j60 { static constexpr unsigned M_in = 5; static constexpr cdouble R_in[M_in] = {{251589, 0}, {-130428, -4165}, {-130428, 4165}, {4634, -22873}, {4634, 22873}}; static constexpr cdouble P_in[M_in] = {{-46580, 0}, {-55482, 25082}, {-55482, -25082}, {-26292, -59437}, {-26292, 59437}}; static constexpr unsigned M_out = 5; static constexpr cdouble R_out[M_out] = {{5092, 0}, {11256, -99566}, {11256, 99566}, {-13802, -24606}, {-13802, 24606}}; static constexpr cdouble P_out[M_out] = {{-176261, 0}, {-51468, 21437}, {-51468, -21437}, {-26276, -59699}, {-26276, 59699}}; } // namespace j60 const BBD_Filter_Spec bbd_fin_j60 = {BBD_Filter_Kind::Input, j60::M_in, j60::R_in, j60::P_in}; const BBD_Filter_Spec bbd_fout_j60 = {BBD_Filter_Kind::Output, j60::M_out, j60::R_out, j60::P_out}; ================================================ FILE: lib/bbd/bbd_filter.h ================================================ #pragma once #include #include typedef std::complex cdouble; enum class BBD_Filter_Kind { Input, Output, }; /* Analog specifications of BBD filters, input and output. M=order R=numerator P=denominator Analog transfer: H(s)=sum(m:1→M) (R[m]/(s-P[m])) */ struct BBD_Filter_Spec { BBD_Filter_Kind kind; unsigned M; const cdouble* R;/*[M]*/ const cdouble* P;/*[M]*/ // cdouble transfer(cdouble::value_type frequency) const noexcept; }; /* Discretized matrix of filters coefficients. M=order, N=interpolation steps, H=feedback factor */ struct BBD_Filter_Coef { unsigned M; unsigned N; std::unique_ptr G;/*[M*N]*/ std::unique_ptr P;/*[M]*/ cdouble::value_type H; // void interpolate_G(cdouble::value_type d, cdouble *g/*[M]*/) const noexcept; }; namespace BBD { BBD_Filter_Coef compute_filter(float fs, unsigned steps, const BBD_Filter_Spec &spec); } // namespace BBD /* The model of BBD input and output filters from Juno 60. */ extern const BBD_Filter_Spec bbd_fin_j60; extern const BBD_Filter_Spec bbd_fout_j60; ================================================ FILE: lib/bbd/bbd_line.cc ================================================ #include "bbd_line.h" #include #include void BBD_Line::setup(unsigned ns, const BBD_Filter_Coef &fin, const BBD_Filter_Coef &fout) { //[eh2k] mem_.reserve(8192); fin_ = &fin; fout_ = &fout; unsigned Min = fin.M; unsigned Mout = fout.M; Xin_.reset(new cdouble[Min]); Xout_.reset(new cdouble[Mout]); Xout_mem_.reset(new cdouble[Mout]); Gin_.reset(new cdouble[Min]); Gout_.reset(new cdouble[Mout]); set_delay_size(ns); clear(); } void BBD_Line::set_delay_size(unsigned ns) { mem_.clear(); mem_.resize(ns); imem_ = 0; ns_ = ns; } void BBD_Line::clear() { std::fill(mem_.begin(), mem_.end(), 0); imem_ = 0; pclk_ = 0; ptick_ = 0; ybbd_old_ = 0; unsigned Min = fin_->M; unsigned Mout = fout_->M; std::fill(&Xin_[0], &Xin_[Min], 0); std::fill(&Xout_[0], &Xout_[Mout], 0); std::fill(&Xout_mem_[0], &Xout_mem_[Mout], 0); } void BBD_Line::process(unsigned n, const float *input, float *output, const float *clock) { unsigned ns = ns_; float *mem = mem_.data(); unsigned imem = imem_; auto pclk = pclk_; unsigned ptick = ptick_; auto ybbd_old = ybbd_old_; const BBD_Filter_Coef &fin = *fin_, &fout = *fout_; unsigned Min = fin.M, Mout = fout.M; cdouble *Xin = Xin_.get(), *Xout = Xout_.get(); cdouble *Xout_mem = Xout_mem_.get(); cdouble *Gin = Gin_.get(), *Gout = Gout_.get(); const cdouble *Pin = fin.P.get(), *Pout = fout.P.get(); for (unsigned i = 0; i < n; ++i) { double fclk = clock[i]; for (unsigned m = 0; m < Mout; ++m) Xout[m] = 0; if (fclk > 0) { auto pclk_old = pclk; pclk += fclk; unsigned tick_count = (unsigned)pclk; pclk -= tick_count; for (unsigned tick = 0; tick < tick_count; ++tick) { auto d = (1 - pclk_old + tick) * (1 / fclk); d -= (unsigned)d; if ((ptick & 1) == 0) { fin.interpolate_G(d, Gin); cdouble s = 0; for (unsigned m = 0; m < Min; ++m) s += Gin[m] * Xin[m]; mem[imem] = s.real(); imem = ((imem + 1) < ns) ? (imem + 1) : 0; } else { fout.interpolate_G(d, Gout); auto ybbd = mem[imem]; auto delta = ybbd - ybbd_old; ybbd_old = ybbd; for (unsigned m = 0; m < Mout; ++m) Xout[m] += Gout[m] * delta; } ++ptick; } } for (unsigned m = 0; m < Min; ++m) Xin[m] = Pin[m] * Xin[m] + cdouble(input[i]); cdouble y = fout.H * ybbd_old; for (unsigned m = 0; m < Mout; ++m) { cdouble xout = Pout[m] * Xout_mem[m] + Xout[m]; Xout_mem[m] = xout; y += xout; } output[i] = y.real(); } imem_ = imem; pclk_ = pclk; ptick_ = ptick; ybbd_old_ = ybbd_old; } ================================================ FILE: lib/bbd/bbd_line.h ================================================ #pragma once #include "bbd_filter.h" #include #include #include #include class BBD_Line { public: /** * Initialize a delay line with the specified parameters. (non-RT) * @param fs audio sampling rate * @param ns number of stages / length of the virtual capacitor array * @param fsin analog specification of the input filter * @param fsout analog specification of the output filter */ void setup(unsigned ns, const BBD_Filter_Coef &fin, const BBD_Filter_Coef &fout); /** * Change the number of stages. (RT?) * @note It guarantees not to reallocate the buffer for \f$ns \leq 8192\f$. * @param ns number of stages / length of the virtual capacitor array */ void set_delay_size(unsigned ns); /** * Reinitialize all the internal state to zero. (RT) */ void clear(); /** * Process a block of audio signal. (RT) * @note The clock input is defined as \f$F_{clk}/F_{s}\f$, where * \f$F_{clk}\f$ is the desired BBD instantaneous clock rate. It is * valid to have \f$F_{clk}>F_{s}/2\f$. * @param n number of frames to process * @param input input buffer of size @p n * @param output output buffer of size @p n * @param clock clock input buffer of size @p n */ void process(unsigned n, const float *input, float *output, const float *clock); /** * Get the discretization of the input filter. (RT) * @return digital filter model */ const BBD_Filter_Coef &filter_in() const noexcept { return *fin_; } /** * Get the discretization of the output filter. (RT) * @return digital filter model */ const BBD_Filter_Coef &filter_out() const noexcept { return *fout_; } /** * Determine the BBD clock rate \f$F_{clk}\f$ which obtains a given delay. (RT) * @param delay delay in seconds * @param ns number of stages / length of the virtual capacitor array * @return BBD clock rate in Hz */ static inline float hz_rate_for_delay(float delay, unsigned ns) { return 2 * ns / delay; } /** * Determine the delay obtained for a given BBD clock rate \f$F_{clk}\f$. (RT) * @param rate BBD clock rate in Hz * @param ns number of stages / length of the virtual capacitor array * @return delay in seconds */ static inline cdouble::value_type delay_for_hz_rate(cdouble::value_type rate, unsigned ns) { return 2 * ns / rate; } private: unsigned ns_; // delay size std::vector mem_; // delay memory unsigned imem_; // delay memory index cdouble::value_type pclk_; // clock phase unsigned ptick_; // clock tick counter cdouble::value_type ybbd_old_; const BBD_Filter_Coef *fin_; const BBD_Filter_Coef *fout_; std::unique_ptr Xin_; std::unique_ptr Xout_; std::unique_ptr Xout_mem_; // sample memory of output filter std::unique_ptr Gin_; std::unique_ptr Gout_; }; ================================================ FILE: lib/braids/README.md ================================================ # Synthesis Models ## Classic Analog Waveforms | # | Model | Description | Timbre | Color | |----|-------------|-------------------------------|--------------------|---------------------| | 0 | `CSAW` | CS-80 imperfect saw | Notch width | Notch polarity | | 1 | `/\/\|-_-_` | Variable waveshape | Waveshape | Distortion/filter | | 2 | `/\|/\|-_-_`| Classic saw-tooth/square | Pulse width | Saw to square | | 3 | `FOLD` | Sine/triangle into wavefolder | Wavefolder amount | Sine to triangle | --- ## Digital Synthesis | # | Model | Description | Timbre | Color | |----|-------------|--------------------------------------|--------------------------|-------------------------| | 4 | `_\|_\|_\|_`| 2 detuned harmonic combs | Smoothness | Detune | | 5 | `SUB-_` | | | | | 6 | `SUB/_` | | | | | 7 | `SYN-_` | 2 VCOs with hardsync | VCO frequency ratio | VCO balance | | 8 | `SYN/\|` | 2 VCOs with hardsync | VCO frequency ratio | VCO balance | | 9 | `/\|/\| x3` | Triple saw waves | Osc. 2 detune | Osc. 3 detune | | 10 | `-_ x3` | Triple square waves | Osc. 2 detune | Osc. 3 detune | | 11 | `/\ x3` | Triple triangle waves | Osc. 2 detune | Osc. 3 detune | | 12 | `SI x3` | Triple sine waves | Osc. 2 detune | Osc. 3 detune | | 13 | `RING` | 3 ring-modulated sine waves | 2/1 frequency ratio | 3/1 frequency ratio | | 14 | `/\|/\|/\|/\|` | Swarm of 7 sawtooth waves | Detune | High-pass filter | | 15 | `/\|/\|_\|_\|` | Comb filtered sawtooth | Delay time | Neg./pos. feedback | | 16 | `TOY*` | Low-fi circuitbent sounds | Sample reduction | Bit toggling | | 17 | `ZLPF` | Direct synthesis of LP waveform | Cutoff frequency | Waveshape | | 18 | `ZPKF` | Direct synthesis of Peaking waveform | Cutoff frequency | Waveshape | | 19 | `ZBPF` | Direct synthesis of BP waveform | Cutoff frequency | Waveshape | | 20 | `ZHPF` | Direct synthesis of HP waveform | Cutoff frequency | Waveshape | | 21 | `VOSM` | Sawtooth with 2 formants | Formant 1 frequency | Formant 2 frequency | --- ## Vocal Synthesis | # | Model | Description | Timbre | Color | |----|-------------|----------------------------------|---------------|--------------------| | 22 | `VOWL` | Vowel synthesis (a, e, i, o, u) | Vowel shape | Gender | | 23 | `VFOF` | Hi-fi vowel synthesis | Air pressure | Instrument shape | --- ## Additive Synthesis | # | Model | Description | Timbre | Color | |----|-------------|----------------------------|-----------------|---------------------| | 24 | `HARM` | Additive synth, 14 harmonics | Harmonic # | Spectral peakedness | --- ## Frequency Modulation (FM) | # | Model | Description | Timbre | Color | |----|-------------|----------------------------------------|-----------------------|----------------------| | 25 | `FM` | Plain 2-operator FM | Modulation index | Frequency ratio | | 26 | `FBFM` | Feedback 2-operator FM | Modulation index | Frequency ratio | | 27 | `WTFM` | Chaotic 2-operator FM | Modulation index | Frequency ratio | --- ## Physical Simulations | # | Model | Description | Timbre | Color | |----|-------------|-----------------------------|-----------------------|---------------------| | 28 | `PLUK` | Plucked strings | Decay | Plucking position | | 29 | `BOWD` | Bowed string | Friction | Bowing position | | 30 | `BLOW` | Reed simulation | Air pressure | Instrument geometry | | 31 | `FLUT` | Flute simulation | Air pressure | Instrument geometry | --- ## Percussions | # | Model | Description | Timbre | Color | |----|-------------|-----------------------------|-----------------------|---------------------| | 32 | `BELL` | Bell sound | Decay | Harmonicity | | 33 | `DRUM` | Metallic drum sound | Decay | Harmonicity | | 34 | `KICK` | 808 bass drum | Decay | Brightness | | 35 | `CYMB` | Cymbal noise | Cutoff | Noisiness | | 36 | `SNAR` | 808 snare drum | Tone | Noisiness/decay | --- ## Wavetables | # | Model | Description | Timbre | Color | |----|-------------|-------------------------------|-----------------------|---------------------| | 37 | `WTBL` | 21 wavetables | Smooth wavetable position | Quantized selection | | 38 | `WMAP` | 16x16 waves | X position | Y position | | 39 | `WLIN` | Linear wavetable scanning | Wavetable position | Interpolation quality | | 40 | `WTx4` | Polyphonic wavetable | Wavetable position | Chord type | --- ## Noise | # | Model | Description | Timbre | Color | |----|-------------|-----------------------------|-----------------------|---------------------| | 41 | `NOIS` | Tuned noise (2-pole filter) | Filter resonance | Response (LP to HP) | | 42 | `TWNQ` | Noise sent to 2 resonators | Resonance | Resonators freq. ratio | | 43 | `CLKN` | Clocked digital noise | Cycle length | Quantization | | 44 | `CLOU` | Sinusoidal granular synthesis | Grain density | Frequency dispersion | | 45 | `PRTC` | Droplets granular synthesis | Grain density | Frequency dispersion | | 46 | `QPSK` | Modem noises | Bit-rate | Modulated data | ## EASTER EGG | # | Model | Description | Timbre | Color | |----|-------------|-----------------------------|-----------------------|---------------------| | 47 | `****` | | | | ## Braids Renaissance Chords (https://burns.ca/eurorack.html) | # | Model | Description | Timbre | Color | |----|-------------|-----------------------------|-----------------------|---------------------| | 48 | `//CH` | | | | | 49 | `-_CH` | | | | | 50 | `/\\CH` | | | | | 51 | `SICH` | | | | | 52 | `WTCH` | | | | | 53 | `//x6` | | | | | 54 | `-_x6` | | | | | 55 | `/\\x6` | | | | | 56 | `SIx6` | | | | | 57 | `WTx6` | | | | ================================================ FILE: lib/braids/analog_oscillator.cc ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Oscillator - analog style waveforms. #include "braids/analog_oscillator.h" #include "stmlib/utils/dsp.h" #include "braids/resources.h" #include "braids/parameter_interpolation.h" namespace braids { using namespace stmlib; static const size_t kNumZones = 15; static const uint16_t kHighestNote = 128 * 128; static const uint16_t kPitchTableStart = 128 * 128; static const uint16_t kOctave = 12 * 128; uint32_t AnalogOscillator::ComputePhaseIncrement(int16_t midi_pitch) { if (midi_pitch >= kHighestNote) { midi_pitch = kHighestNote - 1; } int32_t ref_pitch = midi_pitch; ref_pitch -= kPitchTableStart; size_t num_shifts = 0; while (ref_pitch < 0) { ref_pitch += kOctave; ++num_shifts; } uint32_t a = lut_oscillator_increments[ref_pitch >> 4]; uint32_t b = lut_oscillator_increments[(ref_pitch >> 4) + 1]; uint32_t phase_increment = a + \ (static_cast(b - a) * (ref_pitch & 0xf) >> 4); phase_increment >>= num_shifts; return phase_increment; } void AnalogOscillator::Render( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { RenderFn fn = fn_table_[shape_]; if (shape_ != previous_shape_) { Init(); previous_shape_ = shape_; } phase_increment_ = ComputePhaseIncrement(pitch_); if (pitch_ > kHighestNote) { pitch_ = kHighestNote; } else if (pitch_ < 0) { pitch_ = 0; } (this->*fn)(sync_in, buffer, sync_out, size); } void AnalogOscillator::RenderCSaw( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { BEGIN_INTERPOLATE_PHASE_INCREMENT int32_t next_sample = next_sample_; while (size--) { bool sync_reset = false; bool self_reset = false; bool transition_during_reset = false; uint32_t reset_time = 0; INTERPOLATE_PHASE_INCREMENT uint32_t pw = static_cast(parameter_) * 49152; if (pw < 8 * phase_increment) { pw = 8 * phase_increment; } int32_t this_sample = next_sample; next_sample = 0; if (*sync_in) { // sync_in contain the fractional reset time. reset_time = static_cast(*sync_in - 1) << 9; uint32_t phase_at_reset = phase_ + \ (65535 - reset_time) * (phase_increment >> 16); sync_reset = true; transition_during_reset = false; if (phase_at_reset < phase_ || (!high_ && phase_at_reset >= pw)) { transition_during_reset = true; } if (phase_ >= pw) { discontinuity_depth_ = -2048 + (aux_parameter_ >> 2); int32_t before = (phase_at_reset >> 18); int16_t after = discontinuity_depth_; int32_t discontinuity = after - before; this_sample += discontinuity * ThisBlepSample(reset_time) >> 15; next_sample += discontinuity * NextBlepSample(reset_time) >> 15; } } sync_in++; phase_ += phase_increment; if (phase_ < phase_increment) { self_reset = true; } if (sync_out) { if (phase_ < phase_increment) { *sync_out++ = phase_ / (phase_increment >> 7) + 1; } else { *sync_out++ = 0; } } while (transition_during_reset || !sync_reset) { if (!high_) { if (phase_ < pw) { break; } uint32_t t = (phase_ - pw) / (phase_increment >> 16); int16_t before = discontinuity_depth_; int16_t after = phase_ >> 18; int16_t discontinuity = after - before; this_sample += discontinuity * ThisBlepSample(t) >> 15; next_sample += discontinuity * NextBlepSample(t) >> 15; high_ = true; } if (high_) { if (!self_reset) { break; } self_reset = false; discontinuity_depth_ = -2048 + (aux_parameter_ >> 2); uint32_t t = phase_ / (phase_increment >> 16); int16_t before = 16383; int16_t after = discontinuity_depth_; int16_t discontinuity = after - before; this_sample += discontinuity * ThisBlepSample(t) >> 15; next_sample += discontinuity * NextBlepSample(t) >> 15; high_ = false; } } if (sync_reset) { phase_ = reset_time * (phase_increment >> 16); high_ = false; } next_sample += phase_ < pw ? discontinuity_depth_ : phase_ >> 18; *buffer++ = (this_sample - 8192) << 1; } next_sample_ = next_sample; END_INTERPOLATE_PHASE_INCREMENT } void AnalogOscillator::RenderSquare( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { BEGIN_INTERPOLATE_PHASE_INCREMENT if (parameter_ > 32000) { parameter_ = 32000; } int32_t next_sample = next_sample_; while (size--) { bool sync_reset = false; bool self_reset = false; bool transition_during_reset = false; uint32_t reset_time = 0; INTERPOLATE_PHASE_INCREMENT uint32_t pw = static_cast(32768 - parameter_) << 16; int32_t this_sample = next_sample; next_sample = 0; if (*sync_in) { // sync_in contain the fractional reset time. reset_time = static_cast(*sync_in - 1) << 9; uint32_t phase_at_reset = phase_ + \ (65535 - reset_time) * (phase_increment >> 16); sync_reset = true; if (phase_at_reset < phase_ || (!high_ && phase_at_reset >= pw)) { transition_during_reset = true; } if (phase_at_reset >= pw) { this_sample -= ThisBlepSample(reset_time); next_sample -= NextBlepSample(reset_time); } } sync_in++; phase_ += phase_increment; if (phase_ < phase_increment) { self_reset = true; } if (sync_out) { if (phase_ < phase_increment) { *sync_out++ = phase_ / (phase_increment >> 7) + 1; } else { *sync_out++ = 0; } } while (transition_during_reset || !sync_reset) { if (!high_) { if (phase_ < pw) { break; } uint32_t t = (phase_ - pw) / (phase_increment >> 16); this_sample += ThisBlepSample(t); next_sample += NextBlepSample(t); high_ = true; } if (high_) { if (!self_reset) { break; } self_reset = false; uint32_t t = phase_ / (phase_increment >> 16); this_sample -= ThisBlepSample(t); next_sample -= NextBlepSample(t); high_ = false; } } if (sync_reset) { phase_ = reset_time * (phase_increment >> 16); high_ = false; } next_sample += phase_ < pw ? 0 : 32767; *buffer++ = (this_sample - 16384) << 1; } next_sample_ = next_sample; END_INTERPOLATE_PHASE_INCREMENT } void AnalogOscillator::RenderSaw( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { BEGIN_INTERPOLATE_PHASE_INCREMENT int32_t next_sample = next_sample_; while (size--) { bool sync_reset = false; bool self_reset = false; bool transition_during_reset = false; uint32_t reset_time = 0; INTERPOLATE_PHASE_INCREMENT int32_t this_sample = next_sample; next_sample = 0; if (*sync_in) { // sync_in contain the fractional reset time. reset_time = static_cast(*sync_in - 1) << 9; uint32_t phase_at_reset = phase_ + \ (65535 - reset_time) * (phase_increment >> 16); sync_reset = true; if (phase_at_reset < phase_) { transition_during_reset = true; } int32_t discontinuity = phase_at_reset >> 17; this_sample -= discontinuity * ThisBlepSample(reset_time) >> 15; next_sample -= discontinuity * NextBlepSample(reset_time) >> 15; } sync_in++; phase_ += phase_increment; if (phase_ < phase_increment) { self_reset = true; } if (sync_out) { if (phase_ < phase_increment) { *sync_out++ = phase_ / (phase_increment >> 7) + 1; } else { *sync_out++ = 0; } } if ((transition_during_reset || !sync_reset) && self_reset) { uint32_t t = phase_ / (phase_increment >> 16); this_sample -= ThisBlepSample(t); next_sample -= NextBlepSample(t); } if (sync_reset) { phase_ = reset_time * (phase_increment >> 16); high_ = false; } next_sample += phase_ >> 17; *buffer++ = (this_sample - 16384) << 1; } next_sample_ = next_sample; END_INTERPOLATE_PHASE_INCREMENT } void AnalogOscillator::RenderVariableSaw( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { BEGIN_INTERPOLATE_PHASE_INCREMENT int32_t next_sample = next_sample_; if (parameter_ < 1024) { parameter_ = 1024; } while (size--) { bool sync_reset = false; bool self_reset = false; bool transition_during_reset = false; uint32_t reset_time = 0; INTERPOLATE_PHASE_INCREMENT uint32_t pw = static_cast(parameter_) << 16; int32_t this_sample = next_sample; next_sample = 0; if (*sync_in) { // sync_in contain the fractional reset time. reset_time = static_cast(*sync_in - 1) << 9; uint32_t phase_at_reset = phase_ + \ (65535 - reset_time) * (phase_increment >> 16); sync_reset = true; if (phase_at_reset < phase_ || (!high_ && phase_at_reset >= pw)) { transition_during_reset = true; } int32_t before = (phase_at_reset >> 18) + ((phase_at_reset - pw) >> 18); int32_t after = (0 >> 18) + ((0 - pw) >> 18); int32_t discontinuity = after - before; this_sample += discontinuity * ThisBlepSample(reset_time) >> 15; next_sample += discontinuity * NextBlepSample(reset_time) >> 15; } sync_in++; phase_ += phase_increment; if (phase_ < phase_increment) { self_reset = true; } if (sync_out) { if (phase_ < phase_increment) { *sync_out++ = phase_ / (phase_increment >> 7) + 1; } else { *sync_out++ = 0; } } while (transition_during_reset || !sync_reset) { if (!high_) { if (phase_ < pw) { break; } uint32_t t = (phase_ - pw) / (phase_increment >> 16); this_sample -= ThisBlepSample(t) >> 1; next_sample -= NextBlepSample(t) >> 1; high_ = true; } if (high_) { if (!self_reset) { break; } self_reset = false; uint32_t t = phase_ / (phase_increment >> 16); this_sample -= ThisBlepSample(t) >> 1; next_sample -= NextBlepSample(t) >> 1; high_ = false; } } if (sync_reset) { phase_ = reset_time * (phase_increment >> 16); high_ = false; } next_sample += phase_ >> 18; next_sample += (phase_ - pw) >> 18; *buffer++ = (this_sample - 16384) << 1; } next_sample_ = next_sample; END_INTERPOLATE_PHASE_INCREMENT } void AnalogOscillator::RenderTriangle( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { BEGIN_INTERPOLATE_PHASE_INCREMENT uint32_t phase = phase_; while (size--) { INTERPOLATE_PHASE_INCREMENT int16_t triangle; uint16_t phase_16; if (*sync_in++) { phase = 0; } phase += phase_increment >> 1; phase_16 = phase >> 16; triangle = (phase_16 << 1) ^ (phase_16 & 0x8000 ? 0xffff : 0x0000); triangle += 32768; *buffer = triangle >> 1; phase += phase_increment >> 1; phase_16 = phase >> 16; triangle = (phase_16 << 1) ^ (phase_16 & 0x8000 ? 0xffff : 0x0000); triangle += 32768; *buffer++ += triangle >> 1; } phase_ = phase; END_INTERPOLATE_PHASE_INCREMENT } void AnalogOscillator::RenderSine( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { uint32_t phase = phase_; BEGIN_INTERPOLATE_PHASE_INCREMENT while (size--) { INTERPOLATE_PHASE_INCREMENT phase += phase_increment; if (*sync_in++) { phase = 0; } *buffer++ = Interpolate824(wav_sine, phase); } END_INTERPOLATE_PHASE_INCREMENT phase_ = phase; } void AnalogOscillator::RenderTriangleFold( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { uint32_t phase = phase_; BEGIN_INTERPOLATE_PHASE_INCREMENT BEGIN_INTERPOLATE_PARAMETER while (size--) { INTERPOLATE_PARAMETER INTERPOLATE_PHASE_INCREMENT uint16_t phase_16; int16_t triangle; int16_t gain = 2048 + (parameter * 30720 >> 15); if (*sync_in++) { phase = 0; } // 2x oversampled WF. phase += phase_increment >> 1; phase_16 = phase >> 16; triangle = (phase_16 << 1) ^ (phase_16 & 0x8000 ? 0xffff : 0x0000); triangle += 32768; triangle = triangle * gain >> 15; triangle = Interpolate88(ws_tri_fold, triangle + 32768); *buffer = triangle >> 1; phase += phase_increment >> 1; phase_16 = phase >> 16; triangle = (phase_16 << 1) ^ (phase_16 & 0x8000 ? 0xffff : 0x0000); triangle += 32768; triangle = triangle * gain >> 15; triangle = Interpolate88(ws_tri_fold, triangle + 32768); *buffer++ += triangle >> 1; } END_INTERPOLATE_PARAMETER END_INTERPOLATE_PHASE_INCREMENT phase_ = phase; } void AnalogOscillator::RenderSineFold( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { uint32_t phase = phase_; BEGIN_INTERPOLATE_PHASE_INCREMENT BEGIN_INTERPOLATE_PARAMETER while (size--) { INTERPOLATE_PARAMETER INTERPOLATE_PHASE_INCREMENT int16_t sine; int16_t gain = 2048 + (parameter * 30720 >> 15); if (*sync_in++) { phase = 0; } // 2x oversampled WF. phase += phase_increment >> 1; sine = Interpolate824(wav_sine, phase); sine = sine * gain >> 15; sine = Interpolate88(ws_sine_fold, sine + 32768); *buffer = sine >> 1; phase += phase_increment >> 1; sine = Interpolate824(wav_sine, phase); sine = sine * gain >> 15; sine = Interpolate88(ws_sine_fold, sine + 32768); *buffer++ += sine >> 1; } END_INTERPOLATE_PARAMETER END_INTERPOLATE_PHASE_INCREMENT phase_ = phase; } void AnalogOscillator::RenderBuzz( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { int32_t shifted_pitch = pitch_ + ((32767 - parameter_) >> 1); uint16_t crossfade = shifted_pitch << 6; size_t index = (shifted_pitch >> 10); if (index >= kNumZones) { index = kNumZones - 1; } const int16_t* wave_1 = waveform_table[WAV_BANDLIMITED_COMB_0 + index]; index += 1; if (index >= kNumZones) { index = kNumZones - 1; } const int16_t* wave_2 = waveform_table[WAV_BANDLIMITED_COMB_0 + index]; while (size--) { phase_ += phase_increment_; if (*sync_in++) { phase_ = 0; } *buffer++ = Crossfade(wave_1, wave_2, phase_, crossfade); } } /* static */ AnalogOscillator::RenderFn AnalogOscillator::fn_table_[] = { &AnalogOscillator::RenderSaw, &AnalogOscillator::RenderVariableSaw, &AnalogOscillator::RenderCSaw, &AnalogOscillator::RenderSquare, &AnalogOscillator::RenderTriangle, &AnalogOscillator::RenderSine, &AnalogOscillator::RenderTriangleFold, &AnalogOscillator::RenderSineFold, &AnalogOscillator::RenderBuzz, }; } // namespace braids ================================================ FILE: lib/braids/analog_oscillator.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Oscillator - analog style waveforms. #ifndef BRAIDS_ANALOG_OSCILLATOR_H_ #define BRAIDS_ANALOG_OSCILLATOR_H_ #include "stmlib/stmlib.h" #include #include #include "braids/resources.h" namespace braids { enum AnalogOscillatorShape { OSC_SHAPE_SAW, OSC_SHAPE_VARIABLE_SAW, OSC_SHAPE_CSAW, OSC_SHAPE_SQUARE, OSC_SHAPE_TRIANGLE, OSC_SHAPE_SINE, OSC_SHAPE_TRIANGLE_FOLD, OSC_SHAPE_SINE_FOLD, OSC_SHAPE_BUZZ }; enum SyncMode { OSCILLATOR_SYNC_MODE_OFF, OSCILLATOR_SYNC_MODE_MASTER, OSCILLATOR_SYNC_MODE_SLAVE }; class AnalogOscillator { public: typedef void (AnalogOscillator::*RenderFn)( const uint8_t*, int16_t*, uint8_t*, size_t); AnalogOscillator() { } ~AnalogOscillator() { } inline void Init() { phase_ = 0; phase_increment_ = 1; high_ = false; parameter_ = previous_parameter_ = 0; aux_parameter_ = 0; discontinuity_depth_ = -16383; pitch_ = 60 << 7; next_sample_ = 0; } inline void set_shape(AnalogOscillatorShape shape) { shape_ = shape; } inline void set_pitch(int16_t pitch) { pitch_ = pitch; } inline void set_parameter(int16_t parameter) { parameter_ = parameter; } inline void set_aux_parameter(int16_t parameter) { aux_parameter_ = parameter; } inline uint32_t phase_increment() const { return phase_increment_; } inline void Reset() { phase_ = -phase_increment_; } void Render( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size); private: void RenderSquare(const uint8_t*, int16_t*, uint8_t*, size_t); void RenderSaw(const uint8_t*, int16_t*, uint8_t*, size_t); void RenderVariableSaw(const uint8_t*, int16_t*, uint8_t*, size_t); void RenderCSaw(const uint8_t*, int16_t*, uint8_t*, size_t); void RenderTriangle(const uint8_t*, int16_t*, uint8_t*, size_t); void RenderSine(const uint8_t*, int16_t*, uint8_t*, size_t); void RenderTriangleFold(const uint8_t*, int16_t*, uint8_t*, size_t); void RenderSineFold(const uint8_t*, int16_t*, uint8_t*, size_t); void RenderBuzz(const uint8_t*, int16_t*, uint8_t*, size_t); uint32_t ComputePhaseIncrement(int16_t midi_pitch); inline int32_t ThisBlepSample(uint32_t t) { if (t > 65535) { t = 65535; } return t * t >> 18; } inline int32_t NextBlepSample(uint32_t t) { if (t > 65535) { t = 65535; } t = 65535 - t; return -static_cast(t * t >> 18); } uint32_t phase_; uint32_t phase_increment_; uint32_t previous_phase_increment_; bool high_; int16_t parameter_; int16_t previous_parameter_; int16_t aux_parameter_; int16_t discontinuity_depth_; int16_t pitch_; int32_t next_sample_; AnalogOscillatorShape shape_; AnalogOscillatorShape previous_shape_; static RenderFn fn_table_[]; DISALLOW_COPY_AND_ASSIGN(AnalogOscillator); }; } // namespace braids #endif // BRAIDS_ANALOG_OSCILLATOR_H_ ================================================ FILE: lib/braids/chords_stack.cc ================================================ //https://github.com/boourns/eurorack/blob/master/braids/stack.cc #include "braids/digital_oscillator.h" #include #include #include "stmlib/utils/dsp.h" #include "stmlib/utils/random.h" #include "braids/parameter_interpolation.h" #include "braids/resources.h" #include "braids/quantizer.h" extern braids::Quantizer quantizer; namespace braids { using namespace stmlib; const int kStackSize = 6; #define CALC_SINE(phase) Interpolate88(ws_sine_fold, (Interpolate824(wav_sine, phase) * gain >> 15) + 32768); inline void renderChordSine( DigitalOscillatorState& state_, int16_t parameter_[2], const uint8_t *sync, int16_t *buffer, size_t size, uint32_t *phase_increment, uint8_t noteCount) { uint32_t phase_0, phase_1, phase_2, phase_3, phase_4; int16_t gain = 2048 + (parameter_[0] * 30720 >> 15); phase_0 = state_.stack.phase[0]; phase_1 = state_.stack.phase[1]; phase_2 = state_.stack.phase[2]; phase_3 = state_.stack.phase[3]; phase_4 = state_.stack.phase[4]; while (size) { int32_t sample = 0; phase_0 += phase_increment[0]; phase_1 += phase_increment[1]; phase_2 += phase_increment[2]; phase_3 += phase_increment[3]; phase_4 += phase_increment[4]; sample = CALC_SINE(phase_0); sample += CALC_SINE(phase_1); sample += CALC_SINE(phase_2); sample += CALC_SINE(phase_3); if (noteCount > 4) { sample += CALC_SINE(phase_4); } sample = (sample >> 3) + (sample >> 5); CLIP(sample) *buffer++ = sample; phase_0 += phase_increment[0]; phase_1 += phase_increment[1]; phase_2 += phase_increment[2]; phase_3 += phase_increment[3]; phase_4 += phase_increment[4]; sample = CALC_SINE(phase_0); sample += CALC_SINE(phase_1); sample += CALC_SINE(phase_2); sample += CALC_SINE(phase_3); if (noteCount > 4) { sample += CALC_SINE(phase_4); } sample = (sample >> 3) + (sample >> 5); CLIP(sample) *buffer++ = sample; size -= 2; } state_.stack.phase[0] = phase_0; state_.stack.phase[1] = phase_1; state_.stack.phase[2] = phase_2; state_.stack.phase[3] = phase_3; state_.stack.phase[4] = phase_4; } inline void renderChordSaw( DigitalOscillatorState& state_, int16_t parameter_[2], const uint8_t *sync, int16_t *buffer, size_t size, uint32_t *phase_increment, uint8_t noteCount) { uint32_t phase_0, phase_1, phase_2, phase_3, phase_4, phase_5; uint32_t detune = 0; for (int i = 0; i < 2; i++) { phase_0 = state_.stack.phase[(i*6)+0]; phase_1 = state_.stack.phase[(i*6)+1]; phase_2 = state_.stack.phase[(i*6)+2]; phase_3 = state_.stack.phase[(i*6)+3]; phase_4 = state_.stack.phase[(i*6)+4]; phase_5 = state_.stack.phase[(i*6)+5]; if (i == 1) { detune = parameter_[0]<<3; } int16_t *b = buffer; size_t s = size; while (s) { int32_t sample = 0; phase_0 += phase_increment[0] + detune; phase_1 += phase_increment[1] - detune; phase_2 += phase_increment[2] + detune; phase_3 += phase_increment[3] - detune; phase_4 += phase_increment[4] + detune; phase_5 += phase_increment[5] - detune; sample += (1 << 15) - (phase_0 >> 16); sample += (1 << 15) - (phase_1 >> 16); sample += (1 << 15) - (phase_2 >> 16); sample += (1 << 15) - (phase_3 >> 16); if (noteCount > 4) { sample += (1 << 15) - (phase_4 >> 16); } if (noteCount > 5) { sample += (1 << 15) - (phase_5 >> 16); } sample = (sample >> 2) + (sample >> 5); CLIP(sample) if (i == 0) { *b++ = sample >> 1; } else { *b += sample >> 1; b++; } phase_0 += phase_increment[0] + detune; phase_1 += phase_increment[1] - detune; phase_2 += phase_increment[2] + detune; phase_3 += phase_increment[3] - detune; phase_4 += phase_increment[4] + detune; phase_5 += phase_increment[5] - detune; sample = (1 << 15) - (phase_0 >> 16); sample += (1 << 15) - (phase_1 >> 16); sample += (1 << 15) - (phase_2 >> 16); sample += (1 << 15) - (phase_3 >> 16); if (noteCount > 4) { sample += (1 << 15) - (phase_4 >> 16); } if (noteCount > 5) { sample += (1 << 15) - (phase_5 >> 16); } sample = (sample >> 2) + (sample >> 5); CLIP(sample) if (i == 0) { *b++ = sample >> 1; } else { *b += sample >> 1; b++; } s -= 2; } state_.stack.phase[(i*6)+0] = phase_0; state_.stack.phase[(i*6)+1] = phase_1; state_.stack.phase[(i*6)+2] = phase_2; state_.stack.phase[(i*6)+3] = phase_3; state_.stack.phase[(i*6)+4] = phase_4; state_.stack.phase[(i*6)+5] = phase_5; } } // #define CALC_TRIANGLE_RAW(x) ((int16_t) ((((x >> 16) << 1) ^ (x & 0x80000000 ? 0xffff : 0x0000))) + 32768) #define CALC_TRIANGLE(x) Interpolate88(ws_tri_fold, (calc_triangle_raw(x) * gain >> 15) + 32768) inline int16_t calc_triangle_raw(uint32_t phase) { uint16_t phase_16 = phase >> 16; int16_t triangle = (phase_16 << 1) ^ (phase_16 & 0x8000 ? 0xffff : 0x0000); return triangle + 32768; } inline void renderChordTriangle( DigitalOscillatorState& state_, int16_t parameter_[2], const uint8_t *sync, int16_t *buffer, size_t size, uint32_t *phase_increment, uint8_t noteCount) { uint32_t phase_0, phase_1, phase_2, phase_3, phase_4, phase_5; phase_0 = state_.stack.phase[0]; phase_1 = state_.stack.phase[1]; phase_2 = state_.stack.phase[2]; phase_3 = state_.stack.phase[3]; phase_4 = state_.stack.phase[4]; phase_5 = state_.stack.phase[5]; int16_t gain = 2048 + (parameter_[0] * 30720 >> 15); while (size) { int32_t sample = 0; phase_0 += phase_increment[0]; phase_1 += phase_increment[1]; phase_2 += phase_increment[2]; phase_3 += phase_increment[3]; phase_4 += phase_increment[4]; phase_5 += phase_increment[5]; sample = CALC_TRIANGLE(phase_0); sample += CALC_TRIANGLE(phase_1); sample += CALC_TRIANGLE(phase_2); sample += CALC_TRIANGLE(phase_3); if (noteCount > 4) { sample += CALC_TRIANGLE(phase_4); } if (noteCount > 5) { sample += CALC_TRIANGLE(phase_5); } sample = (sample >> 3) + (sample >> 5); CLIP(sample) *buffer++ = sample; phase_0 += phase_increment[0]; phase_1 += phase_increment[1]; phase_2 += phase_increment[2]; phase_3 += phase_increment[3]; phase_4 += phase_increment[4]; phase_5 += phase_increment[5]; sample = CALC_TRIANGLE(phase_0); sample += CALC_TRIANGLE(phase_1); sample += CALC_TRIANGLE(phase_2); sample += CALC_TRIANGLE(phase_3); if (noteCount > 4) { sample += CALC_TRIANGLE(phase_4); } if (noteCount > 5) { sample += CALC_TRIANGLE(phase_5); } sample = (sample >> 3) + (sample >> 5); CLIP(sample) *buffer++ = sample; size -= 2; } state_.stack.phase[0] = phase_0; state_.stack.phase[1] = phase_1; state_.stack.phase[2] = phase_2; state_.stack.phase[3] = phase_3; state_.stack.phase[4] = phase_4; state_.stack.phase[5] = phase_5; } #define CALC_SQUARE(x, width) ((x > width) ? 5400 : -5400) inline void renderChordSquare( DigitalOscillatorState& state_, int16_t parameter_[2], const uint8_t *sync, int16_t *buffer, size_t size, uint32_t *phase_increment, uint8_t noteCount) { uint32_t phase_0, phase_1, phase_2, phase_3, phase_4, phase_5; uint32_t pw = parameter_[0] << 16; phase_0 = state_.stack.phase[0]; phase_1 = state_.stack.phase[1]; phase_2 = state_.stack.phase[2]; phase_3 = state_.stack.phase[3]; phase_4 = state_.stack.phase[4]; phase_5 = state_.stack.phase[5]; while (size) { int32_t sample = 0; phase_0 += phase_increment[0]; phase_1 += phase_increment[1]; phase_2 += phase_increment[2]; phase_3 += phase_increment[3]; sample = CALC_SQUARE(phase_0, pw); sample += CALC_SQUARE(phase_1, pw); sample += CALC_SQUARE(phase_2, pw); sample += CALC_SQUARE(phase_3, pw); if (noteCount > 4) { sample += CALC_SQUARE(phase_4, pw); } if (noteCount > 5) { sample += CALC_SQUARE(phase_5, pw); } CLIP(sample) *buffer++ = sample; phase_0 += phase_increment[0]; phase_1 += phase_increment[1]; phase_2 += phase_increment[2]; phase_3 += phase_increment[3]; sample = CALC_SQUARE(phase_0, pw); sample += CALC_SQUARE(phase_1, pw); sample += CALC_SQUARE(phase_2, pw); sample += CALC_SQUARE(phase_3, pw); if (noteCount > 4) { sample += CALC_SQUARE(phase_4, pw); } if (noteCount > 5) { sample += CALC_SQUARE(phase_5, pw); } CLIP(sample) *buffer++ = sample; size -= 2; } state_.stack.phase[0] = phase_0; state_.stack.phase[1] = phase_1; state_.stack.phase[2] = phase_2; state_.stack.phase[3] = phase_3; state_.stack.phase[4] = phase_4; state_.stack.phase[5] = phase_5; } const uint8_t mini_wave_line[] = { 157, 161, 171, 188, 189, 191, 192, 193, 196, 198, 201, 234, 232, 229, 226, 224, 1, 2, 3, 4, 5, 8, 12, 32, 36, 42, 47, 252, 254, 141, 139, 135, 174 }; #define SEMI * 128 const uint16_t chords[17][3] = { { 2, 4, 6 }, { 16, 32, 48 }, { 2 SEMI, 7 SEMI, 12 SEMI }, { 3 SEMI, 7 SEMI, 10 SEMI }, { 3 SEMI, 7 SEMI, 12 SEMI }, { 3 SEMI, 7 SEMI, 14 SEMI }, { 3 SEMI, 7 SEMI, 17 SEMI }, { 7 SEMI, 12 SEMI, 19 SEMI }, { 7 SEMI, 3 + 12 SEMI, 5 + 19 SEMI }, { 4 SEMI, 7 SEMI, 17 SEMI }, { 4 SEMI, 7 SEMI, 14 SEMI }, { 4 SEMI, 7 SEMI, 12 SEMI }, { 4 SEMI, 7 SEMI, 11 SEMI }, { 5 SEMI, 7 SEMI, 12 SEMI }, { 4, 7 SEMI, 12 SEMI }, { 4, 4 + 12 SEMI, 12 SEMI }, { 4, 4 + 12 SEMI, 12 SEMI }, }; inline void renderChordWavetable( DigitalOscillatorState& state_, int16_t parameter_[2], const uint8_t *sync, int16_t *buffer, size_t size, uint32_t *phase_increment, uint8_t noteCount) { const uint8_t* wave_1 = wt_waves + mini_wave_line[parameter_[0] >> 10] * 129; const uint8_t* wave_2 = wt_waves + mini_wave_line[(parameter_[0] >> 10) + 1] * 129; uint16_t wave_xfade = parameter_[0] << 6; uint32_t phase_0, phase_1, phase_2, phase_3, phase_4; phase_0 = state_.stack.phase[0]; phase_1 = state_.stack.phase[1]; phase_2 = state_.stack.phase[2]; phase_3 = state_.stack.phase[3]; phase_4 = state_.stack.phase[4]; while (size) { int32_t sample = 0; phase_0 += phase_increment[0]; phase_1 += phase_increment[1]; phase_2 += phase_increment[2]; phase_3 += phase_increment[3]; phase_4 += phase_increment[4]; sample = Crossfade(wave_1, wave_2, phase_0 >> 1, wave_xfade); sample += Crossfade(wave_1, wave_2, phase_1 >> 1, wave_xfade); sample += Crossfade(wave_1, wave_2, phase_2 >> 1, wave_xfade); sample += Crossfade(wave_1, wave_2, phase_3 >> 1, wave_xfade); if (noteCount > 4) { sample += Crossfade(wave_1, wave_2, phase_4 >> 1, wave_xfade); } sample = (sample >> 2); CLIP(sample) *buffer++ = sample; phase_0 += phase_increment[0]; phase_1 += phase_increment[1]; phase_2 += phase_increment[2]; phase_3 += phase_increment[3]; phase_4 += phase_increment[4]; sample = Crossfade(wave_1, wave_2, phase_0 >> 1, wave_xfade); sample += Crossfade(wave_1, wave_2, phase_1 >> 1, wave_xfade); sample += Crossfade(wave_1, wave_2, phase_2 >> 1, wave_xfade); sample += Crossfade(wave_1, wave_2, phase_3 >> 1, wave_xfade); if (noteCount > 4) { sample += Crossfade(wave_1, wave_2, phase_4 >> 1, wave_xfade); } sample = (sample >> 2); CLIP(sample) *buffer++ = sample; size -= 2; } state_.stack.phase[0] = phase_0; state_.stack.phase[1] = phase_1; state_.stack.phase[2] = phase_2; state_.stack.phase[3] = phase_3; state_.stack.phase[4] = phase_4; } // without the attribute this gets build as-is AND inlined into RenderStack :/ void DigitalOscillator::renderChord( const uint8_t *sync, int16_t *buffer, size_t size, const uint8_t* noteOffset, uint8_t noteCount) { int32_t fm = 0; if (strike_) { for (size_t i = 0; i < kStackSize; ++i) { state_.stack.phase[i] = Random::GetWord(); } strike_ = false; } // Do not use an array here to allow these to be kept in arbitrary registers. uint32_t phase_increment[6]; if (quantizer.enabled()) { int8_t index = 0; int8_t root = 0; quantizer.Process(pitch_, 0, &root); fm = pitch_ - quantizer.Lookup(root); phase_increment[0] = phase_increment_; for (size_t i = 1; i < noteCount; i++) { if(custom_chord != nullptr) phase_increment[i] = DigitalOscillator::ComputePhaseIncrement(quantizer.Process(pitch_ + (noteOffset[i-1]<<7))); else { index = (root + noteOffset[i-1]); phase_increment[i] = DigitalOscillator::ComputePhaseIncrement(quantizer.Lookup(index) + fm); } } } else { noteCount = 4; uint16_t chord_integral = parameter_[1] >> 11; uint16_t chord_fractional = parameter_[1] << 5; if (chord_fractional < 30720) { chord_fractional = 0; } else if (chord_fractional >= 34816) { chord_fractional = 65535; } else { chord_fractional = (chord_fractional - 30720) * 16; } phase_increment[0] = phase_increment_; for (size_t i = 0; i < 3; ++i) { uint16_t detune_1 = chords[chord_integral][i]; uint16_t detune_2 = chords[chord_integral + 1][i]; uint16_t detune = detune_1 + ((detune_2 - detune_1) * chord_fractional >> 16); phase_increment[i+1] = DigitalOscillator::ComputePhaseIncrement(pitch_ + detune); } } if (shape_ == OSC_SHAPE_STACK_SAW || shape_ == OSC_SHAPE_CHORD_SAW) { renderChordSaw(state_, parameter_, sync, buffer, size, phase_increment, noteCount); } else if (shape_ == OSC_SHAPE_STACK_WAVETABLE || shape_ == OSC_SHAPE_CHORD_WAVETABLE) { renderChordWavetable(state_, parameter_, sync, buffer, size, phase_increment, noteCount); } else if (shape_ == OSC_SHAPE_STACK_TRIANGLE || shape_ == OSC_SHAPE_CHORD_TRIANGLE) { renderChordTriangle(state_, parameter_, sync, buffer, size, phase_increment, noteCount); } else if (shape_ == OSC_SHAPE_STACK_SQUARE || shape_ == OSC_SHAPE_CHORD_SQUARE) { renderChordSquare(state_, parameter_, sync, buffer, size, phase_increment, noteCount); } else { renderChordSine(state_, parameter_, sync, buffer, size, phase_increment, noteCount); } } //number of notes, followed by offsets const uint8_t diatonic_chords[8][6] = { {0, 2, 4, 7, 0, 0}, // octave {0, 2, 4, 5, 7, 0}, // octave add6 {0, 2, 4, 6, 0, 0}, // 7th {0, 2, 4, 5, 6, 0}, // 7th add6 {0, 2, 4, 6, 8, 0}, // 9th {0, 2, 4, 6, 8, 10}, // 11th {0, 2, 4, 5, 7, 10}, // 11th add6 {0, 2, 4, 8, 0, 0}, // add9 }; const uint8_t* custom_chord = nullptr; void DigitalOscillator::RenderDiatonicChord( const uint8_t* sync, int16_t* buffer, size_t size) { const uint8_t* offsets = custom_chord; if(offsets == nullptr) offsets = diatonic_chords[(parameter_[1] >> 12) & 0x7]; uint8_t len = 4; for (size_t i = 4; i < 6; i++) { if(offsets[i] > 0) len ++; } renderChord(sync, buffer, size, &offsets[1], len); } void DigitalOscillator::RenderStack( const uint8_t* sync, int16_t* buffer, size_t size) { uint8_t span = 1 + (parameter_[1] >> 11); uint8_t offsets[kStackSize]; uint8_t acc = 0; uint8_t count = kStackSize-1; uint8_t i = 0; for (; i < count; i++) { acc += span; offsets[i] = acc; } // don't pass in kStackSize or gcc will render a second, optimized version of renderChord that // knows noteCount is static. renderChord(sync, buffer, size, offsets, i); } } ================================================ FILE: lib/braids/digital_oscillator.cc ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Oscillator - digital style waveforms. #include "braids/digital_oscillator.h" #include #include #include "stmlib/utils/dsp.h" #include "stmlib/utils/random.h" #include "braids/parameter_interpolation.h" #include "braids/resources.h" namespace braids { using namespace stmlib; static const uint16_t kHighestNote = 140 * 128; static const uint16_t kPitchTableStart = 128 * 128; static const uint16_t kOctave = 12 * 128; static const uint32_t kFIR4Coefficients[4] = { 10530, 14751, 16384, 14751 }; static const uint32_t kFIR4DcOffset = 28208; uint32_t DigitalOscillator::ComputePhaseIncrement(int16_t midi_pitch) { if (midi_pitch >= kPitchTableStart) { midi_pitch = kPitchTableStart - 1; } int32_t ref_pitch = midi_pitch; ref_pitch -= kPitchTableStart; size_t num_shifts = 0; while (ref_pitch < 0) { ref_pitch += kOctave; ++num_shifts; } uint32_t a = lut_oscillator_increments[ref_pitch >> 4]; uint32_t b = lut_oscillator_increments[(ref_pitch >> 4) + 1]; uint32_t phase_increment = a + \ (static_cast(b - a) * (ref_pitch & 0xf) >> 4); phase_increment >>= num_shifts; return phase_increment; } uint32_t DigitalOscillator::ComputeDelay(int16_t midi_pitch) { if (midi_pitch >= kHighestNote - kOctave) { midi_pitch = kHighestNote - kOctave; } int32_t ref_pitch = midi_pitch; ref_pitch -= kPitchTableStart; size_t num_shifts = 0; while (ref_pitch < 0) { ref_pitch += kOctave; ++num_shifts; } uint32_t a = lut_oscillator_delays[ref_pitch >> 4]; uint32_t b = lut_oscillator_delays[(ref_pitch >> 4) + 1]; uint32_t delay = a + (static_cast(b - a) * (ref_pitch & 0xf) >> 4); delay >>= 12 - num_shifts; return delay; } void DigitalOscillator::Render( const uint8_t* sync, int16_t* buffer, size_t size) { // Quantize parameter for FM. if (shape_ >= OSC_SHAPE_FM && shape_ <= OSC_SHAPE_CHAOTIC_FEEDBACK_FM) { uint16_t integral = parameter_[1] >> 8; uint16_t fractional = parameter_[1] & 255; int16_t a = lut_fm_frequency_quantizer[integral]; int16_t b = lut_fm_frequency_quantizer[integral + 1]; parameter_[1] = a + ((b - a) * fractional >> 8); } RenderFn fn = fn_table_[shape_]; if (shape_ != previous_shape_) { Init(); previous_shape_ = shape_; init_ = true; } phase_increment_ = ComputePhaseIncrement(pitch_); delay_ = ComputeDelay(pitch_); if (pitch_ > kHighestNote) { pitch_ = kHighestNote; } else if (pitch_ < 0) { pitch_ = 0; } (this->*fn)(sync, buffer, size); } void DigitalOscillator::RenderTripleRingMod( const uint8_t* sync, int16_t* buffer, size_t size) { uint32_t phase = phase_ + (1L << 30); uint32_t increment = phase_increment_; uint32_t modulator_phase = state_.vow.formant_phase[0]; uint32_t modulator_phase_2 = state_.vow.formant_phase[1]; uint32_t modulator_phase_increment = ComputePhaseIncrement( pitch_ + ((parameter_[0] - 16384) >> 2) ); uint32_t modulator_phase_increment_2 = ComputePhaseIncrement( pitch_ + ((parameter_[1] - 16384) >> 2) ); while (size--) { phase += increment; if (*sync++) { phase = 0; modulator_phase = 0; modulator_phase_2 = 0; } modulator_phase += modulator_phase_increment; modulator_phase_2 += modulator_phase_increment_2; int16_t result = Interpolate824(wav_sine, phase); result = result * Interpolate824(wav_sine, modulator_phase) >> 16; result = result * Interpolate824(wav_sine, modulator_phase_2) >> 16; result = Interpolate88(ws_moderate_overdrive, result + 32768); *buffer++ = result; } phase_ = phase - (1L << 30); state_.vow.formant_phase[0] = modulator_phase; state_.vow.formant_phase[1] = modulator_phase_2; } void DigitalOscillator::RenderSawSwarm( const uint8_t* sync, int16_t* buffer, size_t size) { int32_t detune = parameter_[0] + 1024; detune = (detune * detune) >> 9; uint32_t increments[7]; for (int16_t i = 0; i < 7; ++i) { int32_t saw_detune = detune * (i - 3); int32_t detune_integral = saw_detune >> 16; int32_t detune_fractional = saw_detune & 0xffff; int32_t increment_a = ComputePhaseIncrement(pitch_ + detune_integral); int32_t increment_b = ComputePhaseIncrement(pitch_ + detune_integral + 1); increments[i] = increment_a + \ (((increment_b - increment_a) * detune_fractional) >> 16); } if (strike_) { for (size_t i = 0; i < 6; ++i) { state_.saw.phase[i] = Random::GetWord(); } strike_ = false; } int32_t hp_cutoff = pitch_; if (parameter_[1] < 10922) { hp_cutoff += ((parameter_[1] - 10922) * 24) >> 5; } else { hp_cutoff += ((parameter_[1] - 10922) * 12) >> 5; } if (hp_cutoff < 0) { hp_cutoff = 0; } else if (hp_cutoff > 32767) { hp_cutoff = 32767; } int32_t f = Interpolate824(lut_svf_cutoff, hp_cutoff << 17); int32_t damp = lut_svf_damp[0]; int32_t bp = state_.saw.bp; int32_t lp = state_.saw.lp; while (size--) { if (*sync++) { for (size_t i = 0; i < 6; ++i) { state_.saw.phase[i] = 0; } } int32_t notch, hp, sample; phase_ += increments[0]; state_.saw.phase[0] += increments[1]; state_.saw.phase[1] += increments[2]; state_.saw.phase[2] += increments[3]; state_.saw.phase[3] += increments[4]; state_.saw.phase[4] += increments[5]; state_.saw.phase[5] += increments[6]; // Compute a sample. sample = -28672; sample += phase_ >> 19; sample += state_.saw.phase[0] >> 19; sample += state_.saw.phase[1] >> 19; sample += state_.saw.phase[2] >> 19; sample += state_.saw.phase[3] >> 19; sample += state_.saw.phase[4] >> 19; sample += state_.saw.phase[5] >> 19; sample = Interpolate88(ws_moderate_overdrive, sample + 32768); notch = sample - (bp * damp >> 15); lp += f * bp >> 15; CLIP(lp) hp = notch - lp; bp += f * hp >> 15; int32_t result = hp; CLIP(result) *buffer++ = result; } state_.saw.lp = lp; state_.saw.bp = bp; } void DigitalOscillator::RenderComb( const uint8_t* sync, int16_t* buffer, size_t size) { // Filter the delay time to avoid clicks/glitches. int32_t pitch = pitch_ + ((parameter_[0] - 16384) >> 1); int32_t filtered_pitch = state_.ffm.previous_sample; filtered_pitch = (15 * filtered_pitch + pitch) >> 4; state_.ffm.previous_sample = filtered_pitch; int16_t* dl = delay_lines_.comb; uint32_t delay = ComputeDelay(filtered_pitch); if (delay > (kCombDelayLength << 16)) { delay = kCombDelayLength << 16; } uint32_t delay_integral = delay >> 16; int32_t delay_fractional = delay & 0xffff; // Warp the resonance curve to have a more precise adjustment in the extrema. int16_t resonance = (parameter_[1] << 1) - 32768; resonance = Interpolate88(ws_moderate_overdrive, resonance + 32768); uint32_t delay_ptr = phase_; delay_ptr = delay_ptr % kCombDelayLength; while (size--) { int32_t in = *buffer; uint32_t offset = delay_ptr + 2 * kCombDelayLength - delay_integral; int32_t a = dl[offset % kCombDelayLength]; int32_t b = dl[(offset - 1) % kCombDelayLength]; int32_t delayed_sample = a + (((b - a) * (delay_fractional >> 1)) >> 15); int32_t feedback = (delayed_sample * resonance >> 15) + (in >> 1); CLIP(feedback) dl[delay_ptr] = feedback; int32_t out = (in + (delayed_sample << 1)) >> 1; CLIP(out) *buffer++ = out; delay_ptr = (delay_ptr + 1) % kCombDelayLength; } phase_ = delay_ptr; } void DigitalOscillator::RenderToy( const uint8_t* sync, int16_t* buffer, size_t size) { // 4 times oversampling. phase_increment_ >>= 2; uint32_t phase_increment = phase_increment_; uint32_t phase = phase_; uint16_t decimation_counter = state_.toy.decimation_counter; uint16_t decimation_count = 512 - (parameter_[0] >> 6); uint8_t held_sample = state_.toy.held_sample; while (size--) { int32_t filtered_sample = 0; if (*sync++) { phase = 0; } for (size_t tap = 0; tap < 4; ++tap) { phase += phase_increment; if (decimation_counter >= decimation_count) { uint8_t x = parameter_[1] >> 8; held_sample = (((phase >> 24) ^ (x << 1)) & (~x)) + (x >> 1); decimation_counter = 0; } filtered_sample += kFIR4Coefficients[tap] * held_sample; ++decimation_counter; } *buffer++ = (filtered_sample >> 8) - kFIR4DcOffset; } state_.toy.held_sample = held_sample; state_.toy.decimation_counter = decimation_counter; phase_ = phase; } const uint32_t kPhaseReset[] = { 0, 0x80000000, 0x40000000, 0x80000000 }; void DigitalOscillator::RenderDigitalFilter( const uint8_t* sync, int16_t* buffer, size_t size) { int16_t shifted_pitch = pitch_ + ((parameter_[0] - 2048) >> 1); if (shifted_pitch > 16383) { shifted_pitch = 16383; } uint32_t modulator_phase = state_.res.modulator_phase; uint32_t square_modulator_phase = state_.res.square_modulator_phase; int32_t square_integrator = state_.res.integrator; uint8_t filter_type = shape_ - OSC_SHAPE_DIGITAL_FILTER_LP; uint32_t modulator_phase_increment = state_.res.modulator_phase_increment; uint32_t target_increment = ComputePhaseIncrement(shifted_pitch); uint32_t modulator_phase_increment_increment = modulator_phase_increment < target_increment ? (target_increment - modulator_phase_increment) / size : ~((modulator_phase_increment - target_increment) / size); while (size--) { phase_ += phase_increment_; modulator_phase_increment += modulator_phase_increment_increment; modulator_phase += modulator_phase_increment; uint16_t integrator_gain = (modulator_phase_increment >> 14); if (*sync++) { state_.res.polarity = 1; phase_ = 0; modulator_phase = 0; square_modulator_phase = 0; square_integrator = 0; } square_modulator_phase += modulator_phase_increment; if (phase_ < phase_increment_) { modulator_phase = kPhaseReset[filter_type]; } if ((phase_ << 1) < (phase_increment_ << 1)) { state_.res.polarity = !state_.res.polarity; square_modulator_phase = kPhaseReset[(filter_type & 1) + 2]; } int32_t carrier = Interpolate824(wav_sine, modulator_phase); int32_t square_carrier = Interpolate824(wav_sine, square_modulator_phase); uint16_t saw = ~(phase_ >> 16); uint16_t double_saw = ~(phase_ >> 15); uint16_t triangle = (phase_ >> 15) ^ (phase_ & 0x80000000 ? 0xffff : 0x0000); uint16_t window = parameter_[1] < 16384 ? saw : triangle; int32_t pulse = (square_carrier * double_saw) >> 16; if (state_.res.polarity) { pulse = -pulse; } square_integrator += (pulse * integrator_gain) >> 16; CLIP(square_integrator) int16_t saw_tri_signal; int16_t square_signal; if (filter_type & 2) { saw_tri_signal = (carrier * window) >> 16; square_signal = pulse; } else { saw_tri_signal = (window * (carrier + 32768) >> 16) - 32768; square_signal = square_integrator; if (filter_type == 1) { square_signal = (pulse + square_integrator) >> 1; } } uint16_t balance = (parameter_[1] < 16384 ? parameter_[1] : ~parameter_[1]) << 2; *buffer++ = Mix(saw_tri_signal, square_signal, balance); } state_.res.modulator_phase = modulator_phase; state_.res.square_modulator_phase = square_modulator_phase; state_.res.integrator = square_integrator; state_.res.modulator_phase_increment = modulator_phase_increment; } void DigitalOscillator::RenderVosim( const uint8_t* sync, int16_t* buffer, size_t size) { for (size_t i = 0; i < 2; ++i) { state_.vow.formant_increment[i] = ComputePhaseIncrement(parameter_[i] >> 1); } while (size--) { phase_ += phase_increment_; if (*sync++) { phase_ = 0; } int32_t sample = 16384 + 8192; state_.vow.formant_phase[0] += state_.vow.formant_increment[0]; sample += Interpolate824(wav_sine, state_.vow.formant_phase[0]) >> 1; state_.vow.formant_phase[1] += state_.vow.formant_increment[1]; sample += Interpolate824(wav_sine, state_.vow.formant_phase[1]) >> 2; sample = sample * (Interpolate824(lut_bell, phase_) >> 1) >> 15; if (phase_ < phase_increment_) { state_.vow.formant_phase[0] = 0; state_.vow.formant_phase[1] = 0; sample = 0; } sample -= 16384 + 8192; *buffer++ = sample; } } struct PhonemeDefinition { uint8_t formant_frequency[3]; uint8_t formant_amplitude[3]; }; static const PhonemeDefinition vowels_data[9] = { { { 27, 40, 89 }, { 15, 13, 1 } }, { { 18, 51, 62 }, { 13, 12, 6 } }, { { 15, 69, 93 }, { 14, 12, 7 } }, { { 10, 84, 110 }, { 13, 10, 8 } }, { { 23, 44, 87 }, { 15, 12, 1 } }, { { 13, 29, 80 }, { 13, 8, 0 } }, { { 6, 46, 81 }, { 12, 3, 0 } }, { { 9, 51, 95 }, { 15, 3, 0 } }, { { 6, 73, 99 }, { 7, 3, 14 } } }; static const PhonemeDefinition consonant_data[8] = { { { 6, 54, 121 }, { 9, 9, 0 } }, { { 18, 50, 51 }, { 12, 10, 5 } }, { { 11, 24, 70 }, { 13, 8, 0 } }, { { 15, 69, 74 }, { 14, 12, 7 } }, { { 16, 37, 111 }, { 14, 8, 1 } }, { { 18, 51, 62 }, { 14, 12, 6 } }, { { 6, 26, 81 }, { 5, 5, 5 } }, { { 6, 73, 99 }, { 7, 10, 14 } }, }; void DigitalOscillator::RenderVowel( const uint8_t* sync, int16_t* buffer, size_t size) { size_t vowel_index = parameter_[0] >> 12; uint16_t balance = parameter_[0] & 0x0fff; uint16_t formant_shift = (200 + (parameter_[1] >> 6)); if (strike_) { strike_ = false; state_.vow.consonant_frames = 160; uint16_t index = (Random::GetSample() + 1) & 7; for (size_t i = 0; i < 3; ++i) { state_.vow.formant_increment[i] = \ static_cast(consonant_data[index].formant_frequency[i]) * \ 0x1000 * formant_shift; state_.vow.formant_amplitude[i] = consonant_data[index].formant_amplitude[i]; } state_.vow.noise = index >= 6 ? 4095 : 0; } if (state_.vow.consonant_frames) { --state_.vow.consonant_frames; } else { for (size_t i = 0; i < 3; ++i) { state_.vow.formant_increment[i] = (vowels_data[vowel_index].formant_frequency[i] * (0x1000 - balance) + \ vowels_data[vowel_index + 1].formant_frequency[i] * balance) * \ formant_shift; state_.vow.formant_amplitude[i] = (vowels_data[vowel_index].formant_amplitude[i] * (0x1000 - balance) + \ vowels_data[vowel_index + 1].formant_amplitude[i] * balance) >> 12; } state_.vow.noise = 0; } int32_t noise = state_.vow.noise; while (size--) { phase_ += phase_increment_; size_t phaselet; int16_t sample = 0; state_.vow.formant_phase[0] += state_.vow.formant_increment[0]; phaselet = (state_.vow.formant_phase[0] >> 24) & 0xf0; sample += wav_formant_sine[phaselet | state_.vow.formant_amplitude[0]]; state_.vow.formant_phase[1] += state_.vow.formant_increment[1]; phaselet = (state_.vow.formant_phase[1] >> 24) & 0xf0; sample += wav_formant_sine[phaselet | state_.vow.formant_amplitude[1]]; state_.vow.formant_phase[2] += state_.vow.formant_increment[2]; phaselet = (state_.vow.formant_phase[2] >> 24) & 0xf0; sample += wav_formant_square[phaselet | state_.vow.formant_amplitude[2]]; sample *= 255 - (phase_ >> 24); int32_t phase_noise = Random::GetSample() * noise; if ((phase_ + phase_noise) < phase_increment_) { state_.vow.formant_phase[0] = 0; state_.vow.formant_phase[1] = 0; state_.vow.formant_phase[2] = 0; sample = 0; } sample = Interpolate88(ws_moderate_overdrive, sample + 32768); *buffer++ = sample; } } static const int16_t formant_f_data[kNumFormants][kNumFormants][kNumFormants] = { // bass { { 9519, 10738, 12448, 12636, 12892 }, // a { 8620, 11720, 12591, 12932, 13158 }, // e { 7579, 11891, 12768, 13122, 13323 }, // i { 8620, 10013, 12591, 12768, 13010 }, // o { 8324, 9519, 12591, 12831, 13048 } // u }, // tenor { { 9696, 10821, 12810, 13010, 13263 }, // a { 8620, 11827, 12768, 13228, 13477 }, // e { 7908, 12038, 12932, 13263, 13452 }, // i { 8620, 10156, 12768, 12932, 13085 }, // o { 8324, 9519, 12852, 13010, 13296 } // u }, // countertenor { { 9730, 10902, 12892, 13085, 13330 }, // a { 8832, 11953, 12852, 13085, 13296 }, // e { 7749, 12014, 13010, 13330, 13483 }, // i { 8781, 10211, 12852, 13085, 13296 }, // o { 8448, 9627, 12892, 13085, 13363 } // u }, // alto { { 10156, 10960, 12932, 13427, 14195 }, // a { 8620, 11692, 12852, 13296, 14195 }, // e { 8324, 11827, 12852, 13550, 14195 }, // i { 8881, 10156, 12956, 13427, 14195 }, // o { 8160, 9860, 12708, 13427, 14195 } // u }, // soprano { { 10156, 10960, 13010, 13667, 14195 }, // a { 8324, 12187, 12932, 13489, 14195 }, // e { 7749, 12337, 13048, 13667, 14195 }, // i { 8881, 10156, 12956, 13609, 14195 }, // o { 8160, 9860, 12852, 13609, 14195 } // u } }; static const int16_t formant_a_data[kNumFormants][kNumFormants][kNumFormants] = { // bass { { 16384, 7318, 5813, 5813, 1638 }, // a { 16384, 4115, 5813, 4115, 2062 }, // e { 16384, 518, 2596, 1301, 652 }, // i { 16384, 4617, 1460, 1638, 163 }, // o { 16384, 1638, 411, 652, 259 } // u }, // tenor { { 16384, 8211, 7318, 6522, 1301 }, // a { 16384, 3269, 4115, 3269, 1638 }, // e { 16384, 2913, 2062, 1638, 518 }, // i { 16384, 5181, 4115, 4115, 821 }, // o { 16384, 1638, 2314, 3269, 821 } // u }, // countertenor { { 16384, 8211, 1159, 1033, 206 }, // a { 16384, 3269, 2062, 1638, 1638 }, // e { 16384, 1033, 1033, 259, 259 }, // i { 16384, 5181, 821, 1301, 326 }, // o { 16384, 1638, 1159, 518, 326 } // u }, // alto { { 16384, 10337, 1638, 259, 16 }, // a { 16384, 1033, 518, 291, 16 }, // e { 16384, 1638, 518, 259, 16 }, // i { 16384, 5813, 2596, 652, 29 }, // o { 16384, 4115, 518, 163, 10 } // u }, // soprano { { 16384, 8211, 411, 1638, 51 }, // a { 16384, 1638, 2913, 163, 25 }, // e { 16384, 4115, 821, 821, 103 }, // i { 16384, 4617, 1301, 1301, 51 }, // o { 16384, 2596, 291, 163, 16 } // u } }; int16_t DigitalOscillator::InterpolateFormantParameter( const int16_t table[][kNumFormants][kNumFormants], int16_t x, int16_t y, uint8_t formant) { uint16_t x_index = x >> 13; uint16_t x_mix = x << 3; uint16_t y_index = y >> 13; uint16_t y_mix = y << 3; int16_t a = table[x_index][y_index][formant]; int16_t b = table[x_index + 1][y_index][formant]; int16_t c = table[x_index][y_index + 1][formant]; int16_t d = table[x_index + 1][y_index + 1][formant]; a = a + ((b - a) * x_mix >> 16); c = c + ((d - c) * x_mix >> 16); return a + ((c - a) * y_mix >> 16); } void DigitalOscillator::RenderVowelFof( const uint8_t* sync, int16_t* buffer, size_t size) { // The original implementation used FOF but we live in the future and it's // less computationally expensive to render a proper bank of 5 SVF. int16_t amplitudes[kNumFormants]; int32_t svf_lp[kNumFormants]; int32_t svf_bp[kNumFormants]; int16_t svf_f[kNumFormants]; for (size_t i = 0; i < kNumFormants; ++i) { int32_t frequency = InterpolateFormantParameter( formant_f_data, parameter_[1], parameter_[0], i) + (12 << 7); svf_f[i] = Interpolate824(lut_svf_cutoff, frequency << 17); amplitudes[i] = InterpolateFormantParameter( formant_a_data, parameter_[1], parameter_[0], i); if (init_) { svf_lp[i] = 0; svf_bp[i] = 0; } else { svf_lp[i] = state_.fof.svf_lp[i]; svf_bp[i] = state_.fof.svf_bp[i]; } } if (init_) { init_ = false; } uint32_t phase = phase_; int32_t previous_sample = state_.fof.previous_sample; int32_t next_saw_sample = state_.fof.next_saw_sample; uint32_t increment = phase_increment_ << 1; while (size) { int32_t this_saw_sample = next_saw_sample; next_saw_sample = 0; phase += increment; if (phase < increment) { uint32_t t = phase / (increment >> 16); if (t > 65535) { t = 65535; } this_saw_sample -= static_cast(t * t >> 18); t = 65535 - t; next_saw_sample -= -static_cast(t * t >> 18); } next_saw_sample += phase >> 17; int32_t in = this_saw_sample; int32_t out = 0; for (int32_t i = 0; i < 5; ++i) { int32_t notch = in - (svf_bp[i] >> 6); svf_lp[i] += svf_f[i] * svf_bp[i] >> 15; CLIP(svf_lp[i]) int32_t hp = notch - svf_lp[i]; svf_bp[i] += svf_f[i] * hp >> 15; CLIP(svf_bp[i]) out += svf_bp[i] * amplitudes[0] >> 17; } CLIP(out); *buffer++ = (out + previous_sample) >> 1; *buffer++ = out; previous_sample = out; size -= 2; } phase_ = phase; state_.fof.next_saw_sample = next_saw_sample; state_.fof.previous_sample = previous_sample; for (size_t i = 0; i < kNumFormants; ++i) { state_.fof.svf_lp[i] = svf_lp[i]; state_.fof.svf_bp[i] = svf_bp[i]; } } void DigitalOscillator::RenderFm( const uint8_t* sync, int16_t* buffer, size_t size) { uint32_t modulator_phase = state_.modulator_phase; uint32_t modulator_phase_increment = ComputePhaseIncrement( (12 << 7) + pitch_ + ((parameter_[1] - 16384) >> 1)) >> 1; BEGIN_INTERPOLATE_PARAMETER_0 while (size--) { INTERPOLATE_PARAMETER_0 phase_ += phase_increment_; if (*sync++) { phase_ = modulator_phase = 0; } modulator_phase += modulator_phase_increment; uint32_t pm = ( Interpolate824(wav_sine, modulator_phase) * parameter_0) << 2; *buffer++ = Interpolate824(wav_sine, phase_ + pm); } END_INTERPOLATE_PARAMETER_0 previous_parameter_[0] = parameter_[0]; state_.modulator_phase = modulator_phase; } void DigitalOscillator::RenderFeedbackFm( const uint8_t* sync, int16_t* buffer, size_t size) { int16_t previous_sample = state_.ffm.previous_sample; uint32_t modulator_phase = state_.ffm.modulator_phase; int32_t attenuation = pitch_ - (72 << 7) + ((parameter_[1] - 16384) >> 1); attenuation = 32767 - attenuation * 4; if (attenuation < 0) attenuation = 0; if (attenuation > 32767) attenuation = 32767; uint32_t modulator_phase_increment = ComputePhaseIncrement( (12 << 7) + pitch_ + ((parameter_[1] - 16384) >> 1)) >> 1; BEGIN_INTERPOLATE_PARAMETER_0 while (size--) { INTERPOLATE_PARAMETER_0 phase_ += phase_increment_; if (*sync++) { phase_ = modulator_phase = 0; } modulator_phase += modulator_phase_increment; int32_t pm; int32_t p = parameter_0 * attenuation >> 15; pm = previous_sample << 14; pm = ( Interpolate824(wav_sine, modulator_phase + pm) * p) << 1; previous_sample = Interpolate824(wav_sine, phase_ + pm); *buffer++ = previous_sample; } END_INTERPOLATE_PARAMETER_0 state_.ffm.previous_sample = previous_sample; state_.ffm.modulator_phase = modulator_phase; } void DigitalOscillator::RenderChaoticFeedbackFm( const uint8_t* sync, int16_t* buffer, size_t size) { uint32_t modulator_phase_increment = ComputePhaseIncrement( (12 << 7) + pitch_ + ((parameter_[1] - 16384) >> 1)) >> 1; int16_t previous_sample = state_.ffm.previous_sample; uint32_t modulator_phase = state_.ffm.modulator_phase; BEGIN_INTERPOLATE_PARAMETER_0 while (size--) { INTERPOLATE_PARAMETER_0 phase_ += phase_increment_; if (*sync++) { phase_ = modulator_phase = 0; } int32_t pm; pm = (Interpolate824(wav_sine, modulator_phase) * parameter_0) << 1; previous_sample = Interpolate824(wav_sine, phase_ + pm); *buffer++ = previous_sample; modulator_phase += (modulator_phase_increment >> 8) * \ (129 + (previous_sample >> 9)); } END_INTERPOLATE_PARAMETER_0 state_.ffm.previous_sample = previous_sample; state_.ffm.modulator_phase = modulator_phase; } static const int16_t kBellPartials[] = { -1284, -1283, -184, -183, 385, 1175, 1536, 2233, 2434, 2934, 3110 }; static const int16_t kBellPartialAmplitudes[] = { 8192, 5488, 8192, 14745, 21872, 13680, 11960, 10895, 10895, 6144, 10895 }; static const uint16_t kBellPartialDecayLong[] = { 65533, 65533, 65533, 65532, 65531, 65531, 65530, 65529, 65527, 65523, 65519 }; static const uint16_t kBellPartialDecayShort[] = { 65308, 65283, 65186, 65123, 64839, 64889, 64632, 64409, 64038, 63302, 62575 }; static const int16_t kDrumPartials[] = { 0, 0, 1041, 1747, 1846, 3072 }; static const int16_t kDrumPartialAmplitude[] = { 16986, 2654, 3981, 5308, 3981, 2985 }; static const uint16_t kDrumPartialDecayLong[] = { 65533, 65531, 65531, 65531, 65531, 65516 }; static const uint16_t kDrumPartialDecayShort[] = { 65083, 64715, 64715, 64715, 64715, 62312 }; void DigitalOscillator::RenderStruckBell( const uint8_t* sync, int16_t* buffer, size_t size) { // To save some CPU cycles, do not refresh the frequency of all partials at // the same time. This create a kind of "arpeggiation" with high frequency // CV though... size_t first_partial = state_.add.current_partial; size_t last_partial = std::min( state_.add.current_partial + 3, kNumBellPartials); state_.add.current_partial = (first_partial + 3) % kNumBellPartials; if (strike_) { for (size_t i = 0; i < kNumBellPartials; ++i) { state_.add.partial_amplitude[i] = kBellPartialAmplitudes[i]; state_.add.partial_phase[i] = (1L << 30); } strike_ = false; first_partial = 0; last_partial = kNumBellPartials; } for (size_t i = first_partial; i < last_partial; ++i) { int16_t partial_pitch = pitch_ + kBellPartials[i]; if (i & 1) { partial_pitch += parameter_[1] >> 7; } else { partial_pitch -= parameter_[1] >> 7; } state_.add.partial_phase_increment[i] = \ ComputePhaseIncrement(partial_pitch) << 1; } // Allow a "droning" bell with no energy loss when the parameter is set to // its maximum value if (parameter_[0] < 32000) { for (size_t i = 0; i < kNumBellPartials; ++i) { int32_t decay_long = kBellPartialDecayLong[i]; int32_t decay_short = kBellPartialDecayShort[i]; int16_t balance = (32767 - parameter_[0]) >> 8; balance = balance * balance >> 7; int32_t decay = decay_long - ((decay_long - decay_short) * balance >> 7); state_.add.partial_amplitude[i] = \ state_.add.partial_amplitude[i] * decay >> 16; } } int16_t previous_sample = state_.add.previous_sample; while (size--) { int32_t out = 0; for (size_t i = 0; i < kNumBellPartials; ++i) { state_.add.partial_phase[i] += state_.add.partial_phase_increment[i]; int32_t partial = Interpolate824(wav_sine, state_.add.partial_phase[i]); out += partial * state_.add.partial_amplitude[i] >> 17; } CLIP(out) *buffer++ = (out + previous_sample) >> 1; *buffer++ = out; size--; previous_sample = out; } state_.add.previous_sample = previous_sample; } void DigitalOscillator::RenderHarmonics( const uint8_t* sync, int16_t* buffer, size_t size) { uint32_t phase = phase_; int16_t previous_sample = state_.add.previous_sample; uint32_t phase_increment = phase_increment_ << 1; int32_t target_amplitude[kNumAdditiveHarmonics]; int32_t amplitude[kNumAdditiveHarmonics]; int32_t peak = (kNumAdditiveHarmonics * parameter_[0]) >> 7; int32_t second_peak = (peak >> 1) + kNumAdditiveHarmonics * 128; int32_t second_peak_amount = parameter_[1] * parameter_[1] >> 15; int32_t sqrtsqrt_width = parameter_[1] < 16384 ? parameter_[1] >> 6 : 511 - (parameter_[1] >> 6); int32_t sqrt_width = sqrtsqrt_width * sqrtsqrt_width >> 10; int32_t width = sqrt_width * sqrt_width + 4; int32_t total = 0; for (size_t i = 0; i < kNumAdditiveHarmonics; ++i) { int32_t x = i << 8; int32_t d, g; d = (x - peak); g = 32768 * 128 / (128 + d * d / width); d = (x - second_peak); g += second_peak_amount * 128 / (128 + d * d / width); total += g; target_amplitude[i] = g; } int32_t attenuation = 2147483647 / total; for (size_t i = 0; i < kNumAdditiveHarmonics; ++i) { if ((phase_increment >> 16) * (i + 1) > 0x4000) { target_amplitude[i] = 0; } else { target_amplitude[i] = target_amplitude[i] * attenuation >> 16; } amplitude[i] = state_.hrm.amplitude[i]; } while (size) { int32_t out; phase += phase_increment; if (*sync++ || *sync++) { phase = 0; } out = 0; for (size_t i = 0; i < kNumAdditiveHarmonics; ++i) { out += Interpolate824(wav_sine, phase * (i + 1)) * amplitude[i] >> 15; amplitude[i] += (target_amplitude[i] - amplitude[i]) >> 8; } CLIP(out) *buffer++ = (out + previous_sample) >> 1; *buffer++ = out; previous_sample = out; size -= 2; } state_.add.previous_sample = previous_sample; phase_ = phase; for (size_t i = 0; i < kNumAdditiveHarmonics; ++i) { state_.hrm.amplitude[i] = amplitude[i]; } } void DigitalOscillator::RenderStruckDrum( const uint8_t* sync, int16_t* buffer, size_t size) { if (strike_) { bool reset_phase = state_.add.partial_amplitude[0] < 1024; for (size_t i = 0; i < kNumDrumPartials; ++i) { state_.add.target_partial_amplitude[i] = kDrumPartialAmplitude[i]; if (reset_phase) { state_.add.partial_phase[i] = (1L << 30); } } strike_ = false; } else { if (parameter_[0] < 32000) { for (size_t i = 0; i < kNumDrumPartials; ++i) { int32_t decay_long = kDrumPartialDecayLong[i]; int32_t decay_short = kDrumPartialDecayShort[i]; int16_t balance = (32767 - parameter_[0]) >> 8; balance = balance * balance >> 7; int32_t decay = decay_long - ((decay_long - decay_short) * balance >> 7); state_.add.target_partial_amplitude[i] = \ state_.add.partial_amplitude[i] * decay >> 16; } } } for (size_t i = 0; i < kNumDrumPartials; ++i) { int16_t partial_pitch = pitch_ + kDrumPartials[i]; state_.add.partial_phase_increment[i] = ComputePhaseIncrement(partial_pitch) << 1; } int16_t previous_sample = state_.add.previous_sample; int32_t cutoff = (pitch_ - 12 * 128) + (parameter_[1] >> 2); if (cutoff < 0) { cutoff = 0; } else if (cutoff > 32767) { cutoff = 32767; } int32_t f = Interpolate824(lut_svf_cutoff, cutoff << 16); int32_t lp_state_0 = state_.add.lp_noise[0]; int32_t lp_state_1 = state_.add.lp_noise[1]; int32_t lp_state_2 = state_.add.lp_noise[2]; int32_t harmonics_gain = parameter_[1] < 12888 ? (parameter_[1] + 4096) : 16384; int32_t noise_mode_gain = parameter_[1] < 16384 ? 0 : parameter_[1] - 16384; noise_mode_gain = noise_mode_gain * 12888 >> 14; int32_t fade_increment = 65536 / size; int32_t fade = 0; while (size--) { fade += fade_increment; int32_t harmonics = 0; int32_t noise = Random::GetSample(); if (noise > 16384) { noise = 16384; } if (noise < -16384) { noise = -16384; } lp_state_0 += (noise - lp_state_0) * f >> 15; lp_state_1 += (lp_state_0 - lp_state_1) * f >> 15; lp_state_2 += (lp_state_1 - lp_state_2) * f >> 15; int32_t partials[kNumDrumPartials]; for (size_t i = 0; i < kNumDrumPartials; ++i) { AdditiveState* a = &state_.add; a->partial_phase[i] += a->partial_phase_increment[i]; int32_t partial = Interpolate824(wav_sine, a->partial_phase[i]); int32_t amplitude = a->partial_amplitude[i] + \ (((a->target_partial_amplitude[i] - a->partial_amplitude[i]) * fade) >> 15); partial = partial * amplitude >> 16; harmonics += partial; partials[i] = partial; } int32_t sample = partials[0]; int32_t noise_mode_1 = partials[1] * lp_state_2 >> 8; int32_t noise_mode_2 = partials[3] * lp_state_2 >> 9; sample += noise_mode_1 * (12288 - noise_mode_gain) >> 14; sample += noise_mode_2 * noise_mode_gain >> 14; sample += harmonics * harmonics_gain >> 14; CLIP(sample) //sample = Interpolate88(ws_moderate_overdrive, sample + 32768); *buffer++ = (sample + previous_sample) >> 1; *buffer++ = sample; size--; previous_sample = sample; } state_.add.previous_sample = previous_sample; state_.add.lp_noise[0] = lp_state_0; state_.add.lp_noise[1] = lp_state_1; state_.add.lp_noise[2] = lp_state_2; for (size_t i = 0; i < kNumBellPartials; ++i) { AdditiveState* a = &state_.add; a->partial_amplitude[i] = a->target_partial_amplitude[i]; } } void DigitalOscillator::RenderPlucked( const uint8_t* sync, int16_t* buffer, size_t size) { phase_increment_ <<= 1; if (strike_) { ++active_voice_; if (active_voice_ >= kNumPluckVoices) { active_voice_ = 0; } // Find the optimal oversampling rate. PluckState* p = &state_.plk[active_voice_]; int32_t increment = phase_increment_; p->shift = 0; while (increment > (2 << 22)) { increment >>= 1; ++p->shift; } p->size = 1024 >> p->shift; p->mask = p->size - 1; p->write_ptr = 0; p->max_phase_increment = phase_increment_ << 1; p->phase_increment = phase_increment_; int32_t width = parameter_[1]; width = (3 * width) >> 1; p->initialization_ptr = p->size * (8192 + width) >> 16; strike_ = false; } PluckState* current_string = &state_.plk[active_voice_]; // Update the phase increment of the latest note, but do not transpose too // high above the original pitch. current_string->phase_increment = std::min( phase_increment_, current_string->max_phase_increment); // Compute loss and stretching factors. uint32_t update_probability = parameter_[0] < 16384 ? 65535 : 131072 - (parameter_[0] >> 3) * 31; int16_t loss = 4096 - (phase_increment_ >> 14); if (loss < 256) { loss = 256; } if (parameter_[0] < 16384) { loss = loss * (16384 - parameter_[0]) >> 14; } else { loss = 0; } int16_t previous_sample = state_.plk[0].previous_sample; while (size) { int32_t sample = 0; for (size_t i = 0; i < kNumPluckVoices; ++i) { PluckState* p = &state_.plk[i]; int16_t* dl = delay_lines_.ks + i * 1025; // Initialization: Just use a white noise sample and fill the delay // line. if (p->initialization_ptr) { --p->initialization_ptr; int32_t excitation_sample = (dl[p->initialization_ptr] + \ 3 * Random::GetSample()) >> 2; dl[p->initialization_ptr] = excitation_sample; sample += excitation_sample; } else { p->phase += p->phase_increment; size_t read_ptr = ((p->phase >> (22 + p->shift)) + 2) & p->mask; size_t write_ptr = p->write_ptr; size_t num_loops = 0; while (write_ptr != read_ptr) { ++num_loops; size_t next = (write_ptr + 1) & p->mask; int32_t a = dl[write_ptr]; int32_t b = dl[next]; uint32_t probability = Random::GetWord(); if ((probability & 0xffff) <= update_probability) { int32_t sum = (a + b); sum = sum < 0 ? -(-sum >> 1) : (sum >> 1); if (loss) { sum = sum * (32768 - loss) >> 15; } dl[write_ptr] = sum; } if (write_ptr == 0) { dl[p->size] = dl[0]; } write_ptr = next; } p->write_ptr = write_ptr; sample += Interpolate1022(dl, p->phase >> p->shift); } } CLIP(sample); *buffer++ = (previous_sample + sample) >> 1; *buffer++ = sample; previous_sample = sample; size -= 2; } state_.plk[0].previous_sample = previous_sample; } static const int32_t kBridgeLPGain = 14008; static const int32_t kBridgeLPPole1 = 18022; static const int32_t kBiquadGain = 6553; static const int32_t kBiquadPole1 = 6948; static const int32_t kBiquadPole2 = -2959; void DigitalOscillator::RenderBowed( const uint8_t* sync, int16_t* buffer, size_t size) { int8_t* dl_b = delay_lines_.bowed.bridge; int8_t* dl_n = delay_lines_.bowed.neck; if (strike_) { memset(dl_b, 0, sizeof(delay_lines_.bowed.bridge)); memset(dl_n, 0, sizeof(delay_lines_.bowed.neck)); memset(&state_, 0, sizeof(state_)); strike_ = false; } int16_t parameter_0 = 172 - (parameter_[0] >> 8); int16_t parameter_1 = 6 + (parameter_[1] >> 9); uint16_t delay_ptr = state_.phy.delay_ptr; uint16_t excitation_ptr = state_.phy.excitation_ptr; int32_t lp_state = state_.phy.lp_state; int32_t biquad_y0 = state_.phy.filter_state[0]; int32_t biquad_y1 = state_.phy.filter_state[1]; // Setup delay times and interpolation coefficients. uint32_t delay = (delay_ >> 1) - (2 << 16); // Compensation for 1-pole delay uint32_t bridge_delay = (delay >> 8) * parameter_1; // Transpose one octave up when the note is too low to fit in the delays. while ((delay - bridge_delay) > ((kWGNeckLength - 1) << 16) || bridge_delay > ((kWGBridgeLength - 1) << 16)) { delay >>= 1; bridge_delay >>= 1; } uint16_t bridge_delay_integral = bridge_delay >> 16; uint16_t bridge_delay_fractional = bridge_delay & 0xffff; uint32_t neck_delay = delay - bridge_delay; uint32_t neck_delay_integral = neck_delay >> 16; uint16_t neck_delay_fractional = neck_delay & 0xffff; int16_t previous_sample = state_.phy.previous_sample; // Rendered at half the sample rate (for avoiding big rounding error in // coefficients of body IIR filter). while (size) { phase_ += phase_increment_; int32_t new_velocity, friction; uint16_t bridge_delay_ptr = delay_ptr + 2 * kWGBridgeLength \ - bridge_delay_integral; uint16_t neck_delay_ptr = delay_ptr + 2 * kWGNeckLength \ - neck_delay_integral; int16_t bridge_dl_a = dl_b[bridge_delay_ptr % kWGBridgeLength]; int16_t bridge_dl_b = dl_b[(bridge_delay_ptr - 1) % kWGBridgeLength]; int16_t nut_dl_a = dl_n[neck_delay_ptr % kWGNeckLength]; int16_t nut_dl_b = dl_n[(neck_delay_ptr - 1) % kWGNeckLength]; int32_t bridge_value = Mix( bridge_dl_a, bridge_dl_b, bridge_delay_fractional) << 8; int32_t nut_value = Mix(nut_dl_a, nut_dl_b, neck_delay_fractional) << 8; lp_state = (bridge_value * kBridgeLPGain + lp_state * kBridgeLPPole1) >> 15; int32_t bridge_reflection = -lp_state; int32_t nut_reflection = -nut_value; int32_t string_velocity = bridge_reflection + nut_reflection; int32_t bow_velocity = lut_bowing_envelope[excitation_ptr >> 1]; bow_velocity += lut_bowing_envelope[(excitation_ptr + 1) >> 1]; bow_velocity >>= 1; int32_t velocity_delta = bow_velocity - string_velocity; friction = velocity_delta * parameter_0 >> 5; if (friction < 0) { friction = -friction; } if (friction >= (1 << 17)) { friction = (1 << 17) - 1; } //friction = Interpolate824(lut_bowing_friction, friction << 15); friction = lut_bowing_friction[friction >> 9]; new_velocity = friction * velocity_delta >> 15; dl_n[delay_ptr % kWGNeckLength] = (bridge_reflection + new_velocity) >> 8; dl_b[delay_ptr % kWGBridgeLength] = (nut_reflection + new_velocity) >> 8; ++delay_ptr; int32_t temp = bridge_value * kBiquadGain >> 15; temp += biquad_y0 * kBiquadPole1 >> 12; temp += biquad_y1 * kBiquadPole2 >> 12; int32_t out = temp - biquad_y1; biquad_y1 = biquad_y0; biquad_y0 = temp; CLIP(out) *buffer++ = (out + previous_sample) >> 1; *buffer++ = out; previous_sample = out; ++excitation_ptr; size -= 2; } if ((excitation_ptr >> 1) >= LUT_BOWING_ENVELOPE_SIZE - 32) { excitation_ptr = (LUT_BOWING_ENVELOPE_SIZE - 32) << 1; } state_.phy.delay_ptr = delay_ptr % kWGNeckLength; state_.phy.excitation_ptr = excitation_ptr; state_.phy.lp_state = lp_state; state_.phy.filter_state[0] = biquad_y0; state_.phy.filter_state[1] = biquad_y1; state_.phy.previous_sample = previous_sample; } static const uint16_t kBreathPressure = 26214; static const int16_t kReflectionCoefficient = -3891; static const int16_t kReedSlope = -1229; static const int16_t kReedOffset = 22938; void DigitalOscillator::RenderBlown( const uint8_t* sync, int16_t* buffer, size_t size) { uint16_t delay_ptr = state_.phy.delay_ptr; int32_t lp_state = state_.phy.lp_state; int16_t* dl = delay_lines_.bore; if (strike_) { memset(dl, 0, sizeof(delay_lines_.bore)); strike_ = false; } uint32_t delay = (delay_ >> 1) - (1 << 16); while (delay > ((kWGBoreLength - 1) << 16)) { delay >>= 1; } uint16_t bore_delay_integral = delay >> 16; uint16_t bore_delay_fractional = delay & 0xffff; uint16_t parameter = 28000 - (parameter_[0] >> 1); int16_t filter_state = state_.phy.filter_state[0]; int16_t normalized_pitch = (pitch_ - 8192 + (parameter_[1] >> 1)) >> 7; if (normalized_pitch < 0) { normalized_pitch = 0; } else if (normalized_pitch > 127) { normalized_pitch = 127; } uint16_t filter_coefficient = lut_flute_body_filter[normalized_pitch]; while (size--) { phase_ += phase_increment_; int32_t breath_pressure = Random::GetSample() * parameter >> 15; breath_pressure = breath_pressure * kBreathPressure >> 15; breath_pressure += kBreathPressure; uint16_t bore_delay_ptr = delay_ptr + 2 * kWGBoreLength \ - bore_delay_integral; int16_t dl_a = dl[bore_delay_ptr % kWGBoreLength]; int16_t dl_b = dl[(bore_delay_ptr - 1) % kWGBoreLength]; int32_t dl_value = Mix(dl_a, dl_b, bore_delay_fractional); int32_t pressure_delta = (dl_value >> 1) + lp_state; lp_state = dl_value >> 1; pressure_delta = kReflectionCoefficient * pressure_delta >> 12; pressure_delta -= breath_pressure; int32_t reed = (pressure_delta * kReedSlope >> 12) + kReedOffset; CLIP(reed) int32_t out = pressure_delta * reed >> 15; out += breath_pressure; CLIP(out) dl[delay_ptr++ % kWGBoreLength] = out; filter_state = (filter_coefficient * out + \ (4096 - filter_coefficient) * filter_state) >> 12; *buffer++ = filter_state; } state_.phy.filter_state[0] = filter_state; state_.phy.delay_ptr = delay_ptr % kWGBoreLength; state_.phy.lp_state = lp_state; } static const uint16_t kRandomPressure = 0.22 * 4096; static const uint16_t kDCBlockingPole = 0.99 * 4096; void DigitalOscillator::RenderFluted( const uint8_t* sync, int16_t* buffer, size_t size) { uint16_t delay_ptr = state_.phy.delay_ptr; uint16_t excitation_ptr = state_.phy.excitation_ptr; int32_t lp_state = state_.phy.lp_state; int32_t dc_blocking_x0 = state_.phy.filter_state[0]; int32_t dc_blocking_y0 = state_.phy.filter_state[1]; int8_t* dl_b = delay_lines_.fluted.bore; int8_t* dl_j = delay_lines_.fluted.jet; if (strike_) { excitation_ptr = 0; memset(dl_b, 0, sizeof(delay_lines_.fluted.bore)); memset(dl_j, 0, sizeof(delay_lines_.fluted.jet)); lp_state = 0; strike_ = false; } // Setup delay times and interpolation coefficients. uint32_t bore_delay = (delay_ << 1) - (2 << 16); uint32_t jet_delay = (bore_delay >> 8) * (48 + (parameter_[1] >> 10)); bore_delay -= jet_delay; while (bore_delay > ((kWGFBoreLength - 1) << 16) || jet_delay > ((kWGJetLength - 1) << 16)) { bore_delay >>= 1; jet_delay >>= 1; } uint16_t bore_delay_integral = bore_delay >> 16; uint16_t bore_delay_fractional = bore_delay & 0xffff; uint32_t jet_delay_integral = jet_delay >> 16; uint16_t jet_delay_fractional = jet_delay & 0xffff; uint16_t breath_intensity = 2100 - (parameter_[0] >> 4); uint16_t filter_coefficient = lut_flute_body_filter[pitch_ >> 7]; while (size--) { phase_ += phase_increment_; uint16_t bore_delay_ptr = delay_ptr + 2 * kWGFBoreLength \ - bore_delay_integral; uint16_t jet_delay_ptr = delay_ptr + 2 * kWGJetLength \ - jet_delay_integral; int16_t bore_dl_a = dl_b[bore_delay_ptr % kWGFBoreLength]; int16_t bore_dl_b = dl_b[(bore_delay_ptr - 1) % kWGFBoreLength]; int16_t jet_dl_a = dl_j[jet_delay_ptr % kWGJetLength]; int16_t jet_dl_b = dl_j[(jet_delay_ptr - 1) % kWGJetLength]; int32_t bore_value = Mix(bore_dl_a, bore_dl_b, bore_delay_fractional) << 9; int32_t jet_value = Mix(jet_dl_a, jet_dl_b, jet_delay_fractional) << 9; int32_t breath_pressure = lut_blowing_envelope[excitation_ptr]; breath_pressure <<= 1; int32_t random_pressure = Random::GetSample() * breath_intensity >> 12; random_pressure = random_pressure * breath_pressure >> 15; breath_pressure += random_pressure; lp_state = (-filter_coefficient * bore_value + \ (4096 - filter_coefficient) * lp_state) >> 12; int32_t reflection = lp_state; dc_blocking_y0 = (kDCBlockingPole * dc_blocking_y0 >> 12); dc_blocking_y0 += reflection - dc_blocking_x0; dc_blocking_x0 = reflection; reflection = dc_blocking_y0; int32_t pressure_delta = breath_pressure - (reflection >> 1); dl_j[delay_ptr % kWGJetLength] = pressure_delta >> 9; pressure_delta = jet_value; int32_t jet_table_index = pressure_delta; if (jet_table_index < 0) { jet_table_index = 0; } if (jet_table_index > 65535) { jet_table_index = 65535; } pressure_delta = static_cast( lut_blowing_jet[jet_table_index >> 8]) + (reflection >> 1); dl_b[delay_ptr % kWGFBoreLength] = pressure_delta >> 9; ++delay_ptr; int32_t out = bore_value >> 1; CLIP(out) *buffer++ = out; if (size & 3) { ++excitation_ptr; } } if (excitation_ptr >= LUT_BLOWING_ENVELOPE_SIZE - 32) { excitation_ptr = LUT_BLOWING_ENVELOPE_SIZE - 32; } state_.phy.delay_ptr = delay_ptr; state_.phy.excitation_ptr = excitation_ptr; state_.phy.lp_state = lp_state; state_.phy.filter_state[0] = dc_blocking_x0; state_.phy.filter_state[1] = dc_blocking_y0; } struct WavetableDefinition { uint8_t num_steps; uint8_t wave_index[17]; }; static const WavetableDefinition wavetable_definitions[] = { // 01 male { 16 , { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15 } }, // 02 female { 16 , { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 31 } }, // 03 choir { 16 , { 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 47 } }, // 04 space_voice { 16 , { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 63 } }, // 05 tampura { 16 , { 64, 65, 66, 67, 68, 68, 69, 70, 71, 72, 73, 73, 74, 75, 75, 76, 76 } }, // 06 shamus { 16 , { 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 92 } }, // 07 swept_string { 16 , { 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 108 } }, // 08 bowed { 16 , { 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 124 } }, // 09 cello { 16 , { 125, 126, 127, 128, 129, 130, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132 } }, // 10 vibes { 16 , { 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 144, 145, 145, 145 } }, // 11 slap { 16 , { 146, 147, 148, 149, 150, 151, 151, 151, 152, 152, 152, 152, 153, 153, 153, 153, 153 } }, // 12 piano { 8 , { 154, 154, 154, 154, 154, 154, 155, 156, 156 } }, // 13 organ! { 16 , { 176, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171 } }, // 14 waves! { 16 , { 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 187 } }, // 15 digital { 16 , { 176, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202 } }, // 16 drone 1 { 16 , { 203, 205, 204, 205, 212, 206, 207, 208, 208, 209, 210, 210, 211, 211, 212, 212, 212 } }, // 17 drone 2 { 8 , { 213, 213, 213, 214, 215, 216, 217, 218, 219 } }, // 18 metallic { 16 , { 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 235 } }, // 19 fantasy { 16 , { 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 251 } }, // 20 bell { 4 , { 252, 253, 254, 255, 254 } }, }; void DigitalOscillator::RenderWavetables( const uint8_t* sync, int16_t* buffer, size_t size) { // Add some hysteresis to the second parameter to prevent a single DAC bit // error to cause a sharp and glitchy wavetable transition. if ((parameter_[1] > previous_parameter_[1] + 64) || (parameter_[1] < previous_parameter_[1] - 64)) { previous_parameter_[1] = parameter_[1]; } uint32_t wavetable_index = static_cast(previous_parameter_[1]) * 20; wavetable_index >>= 15; uint32_t wave_pointer; const uint8_t* wave[2]; const WavetableDefinition& wt = wavetable_definitions[wavetable_index]; wave_pointer = (parameter_[0] << 1) * wt.num_steps; for (size_t i = 0; i < 2; ++i) { size_t wave_index = wt.wave_index[(wave_pointer >> 16) + i]; wave[i] = wt_waves + wave_index * 129; } uint32_t phase_increment = phase_increment_ >> 1; while (size--) { int16_t sample; // 2x naive oversampling. phase_ += phase_increment; if (*sync++) { phase_ = 0; } sample = Crossfade(wave[0], wave[1], phase_ >> 1, wave_pointer) >> 1; phase_ += phase_increment; sample += Crossfade(wave[0], wave[1], phase_ >> 1, wave_pointer) >> 1; *buffer++ = sample; } } void DigitalOscillator::RenderWaveMap( const uint8_t* sync, int16_t* buffer, size_t size) { // The grid is 16x16; so there are 15 interpolation squares. uint16_t p[2]; uint16_t wave_xfade[2]; uint16_t wave_coordinate[2]; p[0] = parameter_[0] * 15 >> 4; p[1] = parameter_[1] * 15 >> 4; wave_xfade[0] = p[0] << 5; wave_xfade[1] = p[1] << 5; wave_coordinate[0] = p[0] >> 11; wave_coordinate[1] = p[1] >> 11; const uint8_t* wave[2][2]; for (size_t i = 0; i < 2; ++i) { for (size_t j = 0; j < 2; ++j) { uint16_t wave_index = \ (wave_coordinate[0] + i) * 16 + (wave_coordinate[1] + j); wave[i][j] = wt_waves + wt_map[wave_index] * 129; } } uint32_t phase_increment = phase_increment_ >> 1; while (size--) { int16_t sample; // 2x naive oversampling. phase_ += phase_increment; if (*sync++) { phase_ = 0; } sample = Mix( Crossfade(wave[0][0], wave[0][1], phase_ >> 1, wave_xfade[1]), Crossfade(wave[1][0], wave[1][1], phase_ >> 1, wave_xfade[1]), wave_xfade[0]) >> 1; phase_ += phase_increment; sample += Mix( Crossfade(wave[0][0], wave[0][1], phase_ >> 1, wave_xfade[1]), Crossfade(wave[1][0], wave[1][1], phase_ >> 1, wave_xfade[1]), wave_xfade[0]) >> 1; *buffer++ = sample; } } static const uint8_t wave_line[] = { 187, 179, 154, 155, 135, 134, 137, 19, 24, 3, 8, 66, 79, 25, 180, 174, 64, 127, 198, 15, 10, 7, 11, 0, 191, 192, 115, 238, 237, 236, 241, 47, 70, 76, 235, 26, 133, 208, 34, 175, 183, 146, 147, 148, 150, 151, 152, 153, 117, 138, 32, 33, 35, 125, 199, 201, 30, 31, 193, 27, 29, 21, 18, 182 }; static const uint8_t mini_wave_line[] = { 157, 161, 171, 188, 189, 191, 192, 193, 196, 198, 201, 234, 232, 229, 226, 224, 1, 2, 3, 4, 5, 8, 12, 32, 36, 42, 47, 252, 254, 141, 139, 135, 174 }; void DigitalOscillator::RenderWaveLine( const uint8_t* sync, int16_t* buffer, size_t size) { smoothed_parameter_ = (3 * smoothed_parameter_ + (parameter_[0] << 1)) >> 2; uint16_t scan = smoothed_parameter_; const uint8_t* wave_0 = wt_waves + wave_line[previous_parameter_[0] >> 9] * 129; const uint8_t* wave_1 = wt_waves + wave_line[scan >> 10] * 129; const uint8_t* wave_2 = wt_waves + wave_line[(scan >> 10) + 1] * 129; uint16_t smooth_xfade = scan << 6; uint16_t rough_xfade = 0; uint16_t rough_xfade_increment = 32768 / size; uint32_t balance = parameter_[1] << 3; uint32_t phase = phase_; uint32_t phase_increment = phase_increment_ >> 1; int16_t rough, smooth; if (parameter_[1] < 8192) { while (size--) { if (*sync++) { phase = 0; } int32_t sample = 0; rough = Crossfade(wave_0, wave_1, (phase >> 1) & 0xfe000000, rough_xfade); smooth = Crossfade(wave_0, wave_1, phase >> 1, rough_xfade); sample += Mix(rough, smooth, balance); phase += phase_increment; rough_xfade += rough_xfade_increment; rough = Crossfade(wave_0, wave_1, (phase >> 1) & 0xfe000000, rough_xfade); smooth = Crossfade(wave_0, wave_1, phase >> 1, rough_xfade); sample += Mix(rough, smooth, balance); phase += phase_increment; rough_xfade += rough_xfade_increment; *buffer++ = sample >> 1; } } else if (parameter_[1] < 16384) { while (size--) { if (*sync++) { phase = 0; } int32_t sample = 0; rough = Crossfade(wave_0, wave_1, phase >> 1, rough_xfade); smooth = Crossfade(wave_1, wave_2, phase >> 1, smooth_xfade); sample += Mix(rough, smooth, balance); phase += phase_increment; rough_xfade += rough_xfade_increment; rough = Crossfade(wave_0, wave_1, phase >> 1, rough_xfade); smooth = Crossfade(wave_1, wave_2, phase >> 1, smooth_xfade); sample += Mix(rough, smooth, balance); phase += phase_increment; rough_xfade += rough_xfade_increment; *buffer++ = sample >> 1; } } else if (parameter_[1] < 24576) { while (size--) { if (*sync++) { phase = 0; } int32_t sample = 0; smooth = Crossfade(wave_1, wave_2, phase >> 1, smooth_xfade); rough = Crossfade(wave_1, wave_2, (phase >> 1) & 0xfe000000, smooth_xfade); sample += Mix(smooth, rough, balance); phase += phase_increment; smooth = Crossfade(wave_1, wave_2, phase >> 1, smooth_xfade); rough = Crossfade(wave_1, wave_2, (phase >> 1) & 0xfe000000, smooth_xfade); sample += Mix(smooth, rough, balance); phase += phase_increment; *buffer++ = sample >> 1; } } else { while (size--) { if (*sync++) { phase = 0; } int32_t sample = 0; smooth = Crossfade(wave_1, wave_2, (phase >> 1) & 0xfe000000, smooth_xfade); rough = Crossfade(wave_1, wave_2, (phase >> 1) & 0xf8000000, smooth_xfade); sample += Mix(smooth, rough, balance); phase += phase_increment; smooth = Crossfade(wave_1, wave_2, (phase >> 1) & 0xfe000000, smooth_xfade); rough = Crossfade(wave_1, wave_2, (phase >> 1) & 0xf8000000, smooth_xfade); sample += Mix(smooth, rough, balance); phase += phase_increment; *buffer++ = sample >> 1; } } phase_ = phase; previous_parameter_[0] = smoothed_parameter_ >> 1; } #define SEMI * 128 static const uint16_t chords[17][3] = { { 2, 4, 6 }, { 16, 32, 48 }, { 2 SEMI, 7 SEMI, 12 SEMI }, { 3 SEMI, 7 SEMI, 10 SEMI }, { 3 SEMI, 7 SEMI, 12 SEMI }, { 3 SEMI, 7 SEMI, 14 SEMI }, { 3 SEMI, 7 SEMI, 17 SEMI }, { 7 SEMI, 12 SEMI, 19 SEMI }, { 7 SEMI, 3 + 12 SEMI, 5 + 19 SEMI }, { 4 SEMI, 7 SEMI, 17 SEMI }, { 4 SEMI, 7 SEMI, 14 SEMI }, { 4 SEMI, 7 SEMI, 12 SEMI }, { 4 SEMI, 7 SEMI, 11 SEMI }, { 5 SEMI, 7 SEMI, 12 SEMI }, { 4, 7 SEMI, 12 SEMI }, { 4, 4 + 12 SEMI, 12 SEMI }, { 4, 4 + 12 SEMI, 12 SEMI }, }; void DigitalOscillator::RenderWaveParaphonic( const uint8_t* sync, int16_t* buffer, size_t size) { if (strike_) { for (size_t i = 0; i < 4; ++i) { state_.saw.phase[i] = Random::GetWord(); } strike_ = false; } // Do not use an array here to allow these to be kept in arbitrary registers. uint32_t phase_0, phase_1, phase_2, phase_3; uint32_t phase_increment[3]; uint32_t phase_increment_0; phase_increment_0 = phase_increment_; phase_0 = state_.saw.phase[0]; phase_1 = state_.saw.phase[1]; phase_2 = state_.saw.phase[2]; phase_3 = state_.saw.phase[3]; uint16_t chord_integral = parameter_[1] >> 11; uint16_t chord_fractional = parameter_[1] << 5; if (chord_fractional < 30720) { chord_fractional = 0; } else if (chord_fractional >= 34816) { chord_fractional = 65535; } else { chord_fractional = (chord_fractional - 30720) * 16; } for (size_t i = 0; i < 3; ++i) { uint16_t detune_1 = chords[chord_integral][i]; uint16_t detune_2 = chords[chord_integral + 1][i]; uint16_t detune = detune_1 + ((detune_2 - detune_1) * chord_fractional >> 16); phase_increment[i] = ComputePhaseIncrement(pitch_ + detune); } const uint8_t* wave_1 = wt_waves + mini_wave_line[parameter_[0] >> 10] * 129; const uint8_t* wave_2 = wt_waves + mini_wave_line[(parameter_[0] >> 10) + 1] * 129; uint16_t wave_xfade = parameter_[0] << 6; while (size) { int32_t sample = 0; phase_0 += phase_increment_0; phase_1 += phase_increment[0]; phase_2 += phase_increment[1]; phase_3 += phase_increment[2]; sample += Crossfade(wave_1, wave_2, phase_0 >> 1, wave_xfade); sample += Crossfade(wave_1, wave_2, phase_1 >> 1, wave_xfade); sample += Crossfade(wave_1, wave_2, phase_2 >> 1, wave_xfade); sample += Crossfade(wave_1, wave_2, phase_3 >> 1, wave_xfade); *buffer++ = sample >> 2; phase_0 += phase_increment_0; phase_1 += phase_increment[0]; phase_2 += phase_increment[1]; phase_3 += phase_increment[2]; sample = 0; sample += Crossfade(wave_1, wave_2, phase_0 >> 1, wave_xfade); sample += Crossfade(wave_1, wave_2, phase_1 >> 1, wave_xfade); sample += Crossfade(wave_1, wave_2, phase_2 >> 1, wave_xfade); sample += Crossfade(wave_1, wave_2, phase_3 >> 1, wave_xfade); *buffer++ = sample >> 2; size -= 2; } state_.saw.phase[0] = phase_0; state_.saw.phase[1] = phase_1; state_.saw.phase[2] = phase_2; state_.saw.phase[3] = phase_3; } void DigitalOscillator::RenderFilteredNoise( const uint8_t* sync, int16_t* buffer, size_t size) { int32_t f = Interpolate824(lut_svf_cutoff, pitch_ << 17); int32_t damp = Interpolate824(lut_svf_damp, parameter_[0] << 17); int32_t scale = Interpolate824(lut_svf_scale, parameter_[0] << 17); int32_t bp = state_.svf.bp; int32_t lp = state_.svf.lp; int32_t bp_gain, lp_gain, hp_gain; // Morph between LP, BP, HP. if (parameter_[1] < 16384) { bp_gain = parameter_[1]; lp_gain = 16384 - bp_gain; hp_gain = 0; } else { bp_gain = 32767 - parameter_[1]; hp_gain = parameter_[1] - 16384; lp_gain = 0; } int32_t gain_correction = f > scale ? scale * 32767 / f : 32767; while (size--) { int32_t notch, hp, in; in = Random::GetSample() >> 1; notch = in - (bp * damp >> 15); lp += f * bp >> 15; CLIP(lp) hp = notch - lp; bp += f * hp >> 15; int32_t result = 0; result += (lp_gain * lp) >> 14; result += (bp_gain * bp) >> 14; result += (hp_gain * hp) >> 14; CLIP(result) result = result * gain_correction >> 15; *buffer++ = Interpolate88(ws_moderate_overdrive, result + 32768); } state_.svf.lp = lp; state_.svf.bp = bp; } void DigitalOscillator::RenderTwinPeaksNoise( const uint8_t* sync, int16_t* buffer, size_t size) { int32_t sample; int32_t y10, y20; int32_t y11 = state_.pno.filter_state[0][0]; int32_t y12 = state_.pno.filter_state[0][1]; int32_t y21 = state_.pno.filter_state[1][0]; int32_t y22 = state_.pno.filter_state[1][1]; uint32_t q = 65240 + (parameter_[0] >> 7); int32_t q_squared = q * q >> 17; int16_t p1 = pitch_; CONSTRAIN(p1, 0, 16383) int32_t c1 = Interpolate824(lut_resonator_coefficient, p1 << 17); int32_t s1 = Interpolate824(lut_resonator_scale, p1 << 17); int16_t p2 = pitch_ + ((parameter_[1] - 16384) >> 1); CONSTRAIN(p2, 0, 16383) int32_t c2 = Interpolate824(lut_resonator_coefficient, p2 << 17); int32_t s2 = Interpolate824(lut_resonator_scale, p2 << 17); c1 = c1 * q >> 16; c2 = c2 * q >> 16; int32_t makeup_gain = 8191 - (parameter_[0] >> 2); while (size) { sample = Random::GetSample() >> 1; if (sample > 0) { y10 = sample * s1 >> 16; y20 = sample * s2 >> 16; } else { y10 = -((-sample) * s1 >> 16); y20 = -((-sample) * s2 >> 16); } y10 += y11 * c1 >> 15; y10 -= y12 * q_squared >> 15; CLIP(y10) y12 = y11; y11 = y10; y20 += y21 * c2 >> 15; y20 -= y22 * q_squared >> 15; CLIP(y20) y22 = y21; y21 = y20; y10 += y20; y10 += (y10 * makeup_gain >> 13); CLIP(y10) sample = y10; sample = Interpolate88(ws_moderate_overdrive, sample + 32768); *buffer++ = sample; *buffer++ = sample; size -= 2; } state_.pno.filter_state[0][0] = y11; state_.pno.filter_state[0][1] = y12; state_.pno.filter_state[1][0] = y21; state_.pno.filter_state[1][1] = y22; } void DigitalOscillator::RenderClockedNoise( const uint8_t* sync, int16_t* buffer, size_t size) { ClockedNoiseState* state = &state_.clk; if ((parameter_[1] > previous_parameter_[1] + 64) || (parameter_[1] < previous_parameter_[1] - 64)) { previous_parameter_[1] = parameter_[1]; } if ((parameter_[0] > previous_parameter_[0] + 16) || (parameter_[0] < previous_parameter_[0] - 16)) { previous_parameter_[0] = parameter_[0]; } if (strike_) { state->seed = Random::GetWord(); strike_ = false; } // Shift the range of the Coarse knob to reach higher clock rates, close // to the sample rate. uint32_t phase = phase_; uint32_t phase_increment = phase_increment_; for (size_t i = 0; i < 3; ++i) { if (phase_increment < (1UL << 31)) { phase_increment <<= 1; } } // Compute the period of the random generator. state->cycle_phase_increment = ComputePhaseIncrement( previous_parameter_[0] - 16384) << 1; // Compute the number of quantization steps uint32_t num_steps = 1 + (previous_parameter_[1] >> 10); if (num_steps == 1) { num_steps = 2; } uint32_t quantizer_divider = 65536 / num_steps; while (size--) { phase += phase_increment; if (*sync++) { phase = 0; } // Clock. if (phase < phase_increment) { state->rng_state = state->rng_state * 1664525L + 1013904223L; state->cycle_phase += state->cycle_phase_increment; // Enforce period if (state->cycle_phase < state->cycle_phase_increment) { state->rng_state = state->seed; // Make the period an integer. state->cycle_phase = state->cycle_phase_increment; } uint16_t sample = state->rng_state; sample -= sample % quantizer_divider; sample += quantizer_divider >> 1; state->sample = sample; // Make the clock rate an exact divisor of the sample rate. phase = phase_increment; } *buffer++ = state->sample; } phase_ = phase; } void DigitalOscillator::RenderGranularCloud( const uint8_t* sync, int16_t* buffer, size_t size) { for (size_t i = 0; i < 4; ++i) { Grain* g = &state_.grain[i]; // If a grain has reached the end of its envelope, reset it. if (g->envelope_phase > (1 << 24) || g->envelope_phase_increment == 0) { g->envelope_phase_increment = 0; if ((Random::GetWord() & 0xffff) < 0x4000) { g->envelope_phase_increment = \ lut_granular_envelope_rate[parameter_[0] >> 7] << 3; g->envelope_phase = 0; g->phase_increment = phase_increment_; int32_t pitch_mod = Random::GetSample() * parameter_[1] >> 16; int32_t phi = phase_increment_ >> 8; if (pitch_mod < 0) { g->phase_increment += phi * (pitch_mod >> 8); } else { g->phase_increment += phi * (pitch_mod >> 7); } } } } // TODO(pichenettes): Check if it's possible to interpolate envelope // increment too! while (size--) { int32_t sample = 0; state_.grain[0].phase += state_.grain[0].phase_increment; state_.grain[0].envelope_phase += state_.grain[0].envelope_phase_increment; sample += Interpolate824(wav_sine, state_.grain[0].phase) * \ lut_granular_envelope[state_.grain[0].envelope_phase >> 16] >> 17; state_.grain[1].phase += state_.grain[1].phase_increment; state_.grain[1].envelope_phase += state_.grain[1].envelope_phase_increment; sample += Interpolate824(wav_sine, state_.grain[1].phase) * \ lut_granular_envelope[state_.grain[1].envelope_phase >> 16] >> 17; state_.grain[2].phase += state_.grain[2].phase_increment; state_.grain[2].envelope_phase += state_.grain[2].envelope_phase_increment; sample += Interpolate824(wav_sine, state_.grain[2].phase) * \ lut_granular_envelope[state_.grain[2].envelope_phase >> 16] >> 17; state_.grain[3].phase += state_.grain[3].phase_increment; state_.grain[3].envelope_phase += state_.grain[3].envelope_phase_increment; sample += Interpolate824(wav_sine, state_.grain[3].phase) * \ lut_granular_envelope[state_.grain[3].envelope_phase >> 16] >> 17; if (sample < -32768) { sample = -32768; } if (sample > 32767) { sample = 32767; } *buffer++ = sample; } } static const uint16_t kParticleNoiseDecay = 64763; static const int32_t kResonanceSquared = 32768 * 0.996 * 0.996; static const int32_t kResonanceFactor = 32768 * 0.996; void DigitalOscillator::RenderParticleNoise( const uint8_t* sync, int16_t* buffer, size_t size) { uint16_t amplitude = state_.pno.amplitude; uint32_t density = 1024 + parameter_[0]; int32_t sample; int32_t y10, y20, y30; int32_t y11 = state_.pno.filter_state[0][0]; int32_t y12 = state_.pno.filter_state[0][1]; int32_t s1 = state_.pno.filter_scale[0]; int32_t c1 = state_.pno.filter_coefficient[0]; int32_t y21 = state_.pno.filter_state[1][0]; int32_t y22 = state_.pno.filter_state[1][1]; int32_t s2 = state_.pno.filter_scale[1]; int32_t c2 = state_.pno.filter_coefficient[1]; int32_t y31 = state_.pno.filter_state[2][0]; int32_t y32 = state_.pno.filter_state[2][1]; int32_t s3 = state_.pno.filter_scale[2]; int32_t c3 = state_.pno.filter_coefficient[2]; while (size) { uint32_t noise = Random::GetWord(); if ((noise & 0x7fffff) < density) { amplitude = 65535; int16_t noise_a = (noise & 0x0fff) - 0x800; int16_t noise_b = ((noise >> 15) & 0x1fff) - 0x1000; int16_t p1 = pitch_ + (3 * noise_a * parameter_[1] >> 17) + 0x600; CONSTRAIN(p1, 0, 16383) c1 = Interpolate824(lut_resonator_coefficient, p1 << 17); s1 = Interpolate824(lut_resonator_scale, p1 << 17); int16_t p2 = pitch_ + (noise_a * parameter_[1] >> 15) + 0x980; CONSTRAIN(p2, 0, 16383) c2 = Interpolate824(lut_resonator_coefficient, p2 << 17); s2 = Interpolate824(lut_resonator_scale, p2 << 17); int16_t p3 = pitch_ + (noise_b * parameter_[1] >> 16) + 0x790; CONSTRAIN(p3, 0, 16383) c3 = Interpolate824(lut_resonator_coefficient, p3 << 17); s3 = Interpolate824(lut_resonator_scale, p3 << 17); c1 = c1 * kResonanceFactor >> 15; c2 = c2 * kResonanceFactor >> 15; c3 = c3 * kResonanceFactor >> 15; } sample = (static_cast(noise) * amplitude) >> 16; amplitude = (amplitude * kParticleNoiseDecay) >> 16; if (sample > 0) { y10 = sample * s1 >> 16; y20 = sample * s2 >> 16; y30 = sample * s3 >> 16; } else { y10 = -((-sample) * s1 >> 16); y20 = -((-sample) * s2 >> 16); y30 = -((-sample) * s3 >> 16); } y10 += y11 * c1 >> 15; y10 -= y12 * kResonanceSquared >> 15; CLIP(y10); y12 = y11; y11 = y10; y20 += y21 * c2 >> 15; y20 -= y22 * kResonanceSquared >> 15; CLIP(y20); y22 = y21; y21 = y20; y30 += y31 * c3 >> 15; y30 -= y32 * kResonanceSquared >> 15; CLIP(y30); y32 = y31; y31 = y30; y10 += y20 + y30; CLIP(y10) *buffer++ = y10; *buffer++ = y10; size -= 2; } state_.pno.amplitude = amplitude; state_.pno.filter_state[0][0] = y11; state_.pno.filter_state[0][1] = y12; state_.pno.filter_scale[0] = s1; state_.pno.filter_coefficient[0] = c1; state_.pno.filter_state[1][0] = y21; state_.pno.filter_state[1][1] = y22; state_.pno.filter_scale[1] = s2; state_.pno.filter_coefficient[1] = c2; state_.pno.filter_state[2][0] = y31; state_.pno.filter_state[2][1] = y32; state_.pno.filter_scale[2] = s3; state_.pno.filter_coefficient[2] = c3; } static const int32_t kConstellationQ[] = { 23100, -23100, -23100, 23100 }; static const int32_t kConstellationI[] = { 23100, 23100, -23100, -23100 }; void DigitalOscillator::RenderDigitalModulation( const uint8_t* sync, int16_t* buffer, size_t size) { uint32_t phase = phase_; uint32_t increment = phase_increment_; uint32_t symbol_stream_phase = state_.dmd.symbol_phase; uint32_t symbol_stream_phase_increment = ComputePhaseIncrement( pitch_ - 1536 + ((parameter_[0] - 32767) >> 3)); uint8_t data_byte = state_.dmd.data_byte; if (strike_) { state_.dmd.symbol_count = 0; strike_ = false; } while (size--) { phase += increment; symbol_stream_phase += symbol_stream_phase_increment; if (symbol_stream_phase < symbol_stream_phase_increment) { ++state_.dmd.symbol_count; if (!(state_.dmd.symbol_count & 3)) { if (state_.dmd.symbol_count >= (64 + 4 * 256)) { state_.dmd.symbol_count = 0; } if (state_.dmd.symbol_count < 32) { data_byte = 0x00; } else if (state_.dmd.symbol_count < 48) { data_byte = 0x99; } else if (state_.dmd.symbol_count < 64) { data_byte = 0xcc; } else { state_.dmd.filter_state = (state_.dmd.filter_state * 3 + \ static_cast(parameter_[1])) >> 2; data_byte = state_.dmd.filter_state >> 7; } } else { data_byte >>= 2; } } int16_t i = Interpolate824(wav_sine, phase); int16_t q = Interpolate824(wav_sine, phase + (1 << 30)); *buffer++ = (kConstellationQ[data_byte & 3] * q >> 15) + \ (kConstellationI[data_byte & 3] * i >> 15); } phase_ = phase; state_.dmd.symbol_phase = symbol_stream_phase; state_.dmd.data_byte = data_byte; } void DigitalOscillator::RenderQuestionMark( const uint8_t* sync, int16_t* buffer, size_t size) { ClockedNoiseState* state = &state_.clk; if (strike_) { state->rng_state = 0; state->cycle_phase = 0; state->sample = 10; state->cycle_phase_increment = -1; state->seed = 32767; strike_ = false; } uint32_t phase = phase_; uint32_t increment = phase_increment_; uint32_t dit_duration = 3600 + ((32767 - parameter_[0]) >> 2); int32_t noise_threshold = 1024 + (parameter_[1] >> 3); while (size--) { phase += increment; int32_t sample; if (state->rng_state) { sample = (Interpolate824(wav_sine, phase) * 3) >> 2; } else { sample = 0; } if (++state->cycle_phase > dit_duration) { --state->sample; if (state->sample == 0) { ++state->cycle_phase_increment; state->rng_state = !state->rng_state; size_t address = state->cycle_phase_increment >> 2; size_t shift = (state->cycle_phase_increment & 0x3) << 1; state->sample = (2 << ((wt_code[address] >> shift) & 3)) - 1; if (state->sample == 15) { state->sample = 100; state->rng_state = 0; state->cycle_phase_increment = - 1; } phase = 1L << 30; } state->cycle_phase = 0; } state->seed += Random::GetSample() >> 2; int32_t noise_intensity = state->seed >> 8; if (noise_intensity < 0) { noise_intensity = -noise_intensity; } if (noise_intensity < noise_threshold) { noise_intensity = noise_threshold; } if (noise_intensity > 16000) { noise_intensity = 16000; } int32_t noise = (Random::GetSample() * noise_intensity >> 15); noise = noise * wav_sine[(phase >> 22) & 0xff] >> 15; sample += noise; CLIP(sample); int32_t distorted = sample * sample >> 14; sample += distorted * parameter_[1] >> 15; CLIP(sample); *buffer++ = sample; } phase_ = phase; } void DigitalOscillator::RenderKick( const uint8_t* sync, int16_t* buffer, size_t size) { if (init_) { pulse_[0].Init(); pulse_[0].set_delay(0); pulse_[0].set_decay(3340); pulse_[1].Init(); pulse_[1].set_delay(1.0e-3 * 48000); pulse_[1].set_decay(3072); pulse_[2].Init(); pulse_[2].set_delay(4.0e-3 * 48000); pulse_[2].set_decay(4093); svf_[0].Init(); svf_[0].set_punch(32768); svf_[0].set_mode(SVF_MODE_BP); init_ = false; } if (strike_) { strike_ = false; pulse_[0].Trigger(12 * 32768 * 0.7); pulse_[1].Trigger(-19662 * 0.7); pulse_[2].Trigger(18000); svf_[0].set_punch(24000); } uint32_t decay = parameter_[0]; uint32_t scaled = 65535 - (decay << 1); uint32_t squared = scaled * scaled >> 16; scaled = squared * scaled >> 18; svf_[0].set_resonance(32768 - 128 - scaled); uint32_t coefficient = parameter_[1]; coefficient = coefficient * coefficient >> 15; coefficient = coefficient * coefficient >> 15; int32_t lp_coefficient = 128 + (coefficient >> 1) * 3; int32_t lp_state = state_.svf.lp; while (size) { int32_t excitation = 0; excitation += pulse_[0].Process(); excitation += !pulse_[1].done() ? 16384 : 0; excitation += pulse_[1].Process(); pulse_[2].Process(); svf_[0].set_frequency(pitch_ + (pulse_[2].done() ? 0 : 17 << 7)); for (int32_t j = 0; j < 2; ++j) { int32_t resonator_output, output; resonator_output = (excitation >> 4) + svf_[0].Process(excitation); lp_state += (resonator_output - lp_state) * lp_coefficient >> 15; CLIP(lp_state); output = lp_state; *buffer++ = output; } size -= 2; } state_.svf.lp = lp_state; } void DigitalOscillator::RenderSnare( const uint8_t* sync, int16_t* buffer, size_t size) { if (init_) { pulse_[0].Init(); pulse_[0].set_delay(0); pulse_[0].set_decay(1536); pulse_[1].Init(); pulse_[1].set_delay(1e-3 * 48000); pulse_[1].set_decay(3072); pulse_[2].Init(); pulse_[2].set_delay(1e-3 * 48000); pulse_[2].set_decay(1200); pulse_[3].Init(); pulse_[3].set_delay(0); svf_[0].Init(); svf_[1].Init(); svf_[2].Init(); svf_[2].set_resonance(2000); svf_[2].set_mode(SVF_MODE_BP); init_ = false; } if (strike_) { int32_t decay = 49152 - pitch_; decay += parameter_[1] < 16384 ? 0 : parameter_[1] - 16384; if (decay > 65535) { decay = 65535; } svf_[0].set_resonance(29000 + (decay >> 5)); svf_[1].set_resonance(26500 + (decay >> 5)); pulse_[3].set_decay(4092 + (decay >> 14)); pulse_[0].Trigger(15 * 32768); pulse_[1].Trigger(-1 * 32768); pulse_[2].Trigger(13107); int32_t snappy = parameter_[1]; if (snappy >= 14336) { snappy = 14336; } pulse_[3].Trigger(512 + (snappy << 1)); strike_ = false; } svf_[0].set_frequency(pitch_ + (12 << 7)); svf_[1].set_frequency(pitch_ + (24 << 7)); svf_[2].set_frequency(pitch_ + (60 << 7)); int32_t g_1 = 22000 - (parameter_[0] >> 1); int32_t g_2 = 22000 + (parameter_[0] >> 1); while (size) { int32_t excitation_1 = 0; excitation_1 += pulse_[0].Process(); excitation_1 += pulse_[1].Process(); excitation_1 += !pulse_[1].done() ? 2621 : 0; int32_t excitation_2 = 0; excitation_2 += pulse_[2].Process(); excitation_2 += !pulse_[2].done() ? 13107 : 0; int32_t noise_sample = Random::GetSample() * pulse_[3].Process() >> 15; int32_t sd = 0; sd += (svf_[0].Process(excitation_1) + (excitation_1 >> 4)) * g_1 >> 15; sd += (svf_[1].Process(excitation_2) + (excitation_2 >> 4)) * g_2 >> 15; sd += svf_[2].Process(noise_sample); CLIP(sd); *buffer++ = sd; *buffer++ = sd; size -= 2; } } void DigitalOscillator::RenderCymbal( const uint8_t* sync, int16_t* buffer, size_t size) { if (init_) { svf_[0].Init(); svf_[0].set_mode(SVF_MODE_BP); svf_[0].set_resonance(12000); svf_[1].Init(); svf_[1].set_mode(SVF_MODE_HP); svf_[1].set_resonance(2000); init_ = false; } HatState* hat = &state_.hat; uint32_t increments[7]; int32_t note = (40 << 7) + (pitch_ >> 1); increments[0] = ComputePhaseIncrement(note); uint32_t root = increments[0] >> 10; increments[1] = root * 24273 >> 4; increments[2] = root * 12561 >> 4; increments[3] = root * 18417 >> 4; increments[4] = root * 22452 >> 4; increments[5] = root * 31858 >> 4; increments[6] = increments[0] * 24; int32_t xfade = parameter_[1]; svf_[0].set_frequency(parameter_[0] >> 1); svf_[1].set_frequency(parameter_[0] >> 1); while (size--) { phase_ += increments[6]; if (phase_ < increments[6]) { hat->rng_state = hat->rng_state * 1664525L + 1013904223L; } hat->phase[0] += increments[0]; hat->phase[1] += increments[1]; hat->phase[2] += increments[2]; hat->phase[3] += increments[3]; hat->phase[4] += increments[4]; hat->phase[5] += increments[5]; int32_t hat_noise = 0; hat_noise += hat->phase[0] >> 31; hat_noise += hat->phase[1] >> 31; hat_noise += hat->phase[2] >> 31; hat_noise += hat->phase[3] >> 31; hat_noise += hat->phase[4] >> 31; hat_noise += hat->phase[5] >> 31; hat_noise -= 3; hat_noise *= 5461; hat_noise = svf_[0].Process(hat_noise); CLIP(hat_noise) int32_t noise = (hat->rng_state >> 16) - 32768; noise = svf_[1].Process(noise >> 1); CLIP(noise) *buffer++ = hat_noise + ((noise - hat_noise) * xfade >> 15); } } /* void DigitalOscillator::RenderYourAlgo( const uint8_t* sync, int16_t* buffer, size_t size) { while (size--) { *buffer++ = 0; } } */ /* static */ DigitalOscillator::RenderFn DigitalOscillator::fn_table_[] = { &DigitalOscillator::RenderTripleRingMod, &DigitalOscillator::RenderSawSwarm, &DigitalOscillator::RenderComb, &DigitalOscillator::RenderToy, &DigitalOscillator::RenderDigitalFilter, &DigitalOscillator::RenderDigitalFilter, &DigitalOscillator::RenderDigitalFilter, &DigitalOscillator::RenderDigitalFilter, &DigitalOscillator::RenderVosim, &DigitalOscillator::RenderVowel, &DigitalOscillator::RenderVowelFof, &DigitalOscillator::RenderHarmonics, &DigitalOscillator::RenderFm, &DigitalOscillator::RenderFeedbackFm, &DigitalOscillator::RenderChaoticFeedbackFm, &DigitalOscillator::RenderPlucked, &DigitalOscillator::RenderBowed, &DigitalOscillator::RenderBlown, &DigitalOscillator::RenderFluted, &DigitalOscillator::RenderStruckBell, &DigitalOscillator::RenderStruckDrum, &DigitalOscillator::RenderKick, &DigitalOscillator::RenderCymbal, &DigitalOscillator::RenderSnare, &DigitalOscillator::RenderWavetables, &DigitalOscillator::RenderWaveMap, &DigitalOscillator::RenderWaveLine, &DigitalOscillator::RenderWaveParaphonic, &DigitalOscillator::RenderFilteredNoise, &DigitalOscillator::RenderTwinPeaksNoise, &DigitalOscillator::RenderClockedNoise, &DigitalOscillator::RenderGranularCloud, &DigitalOscillator::RenderParticleNoise, &DigitalOscillator::RenderDigitalModulation, // &DigitalOscillator::RenderYourAlgo, &DigitalOscillator::RenderQuestionMark, &DigitalOscillator::RenderDiatonicChord, &DigitalOscillator::RenderDiatonicChord, &DigitalOscillator::RenderDiatonicChord, &DigitalOscillator::RenderDiatonicChord, &DigitalOscillator::RenderDiatonicChord, &DigitalOscillator::RenderStack, &DigitalOscillator::RenderStack, &DigitalOscillator::RenderStack, &DigitalOscillator::RenderStack, &DigitalOscillator::RenderStack, }; } // namespace braids ================================================ FILE: lib/braids/digital_oscillator.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Oscillator - digital style waveforms. #ifndef BRAIDS_DIGITAL_OSCILLATOR_H_ #define BRAIDS_DIGITAL_OSCILLATOR_H_ #include "stmlib/stmlib.h" #include "braids/excitation.h" #include "braids/svf.h" #include namespace braids { static const size_t kWGBridgeLength = 1024; static const size_t kWGNeckLength = 4096; static const size_t kWGBoreLength = 2048; static const size_t kWGJetLength = 1024; static const size_t kWGFBoreLength = 4096; static const size_t kCombDelayLength = 8192; static const size_t kNumFormants = 5; static const size_t kNumPluckVoices = 3; static const size_t kNumOverlappingFof = 3; static const size_t kNumBellPartials = 11; static const size_t kNumDrumPartials = 6; static const size_t kNumAdditiveHarmonics = 12; enum DigitalOscillatorShape { OSC_SHAPE_TRIPLE_RING_MOD, OSC_SHAPE_SAW_SWARM, OSC_SHAPE_COMB_FILTER, OSC_SHAPE_TOY, OSC_SHAPE_DIGITAL_FILTER_LP, OSC_SHAPE_DIGITAL_FILTER_PK, OSC_SHAPE_DIGITAL_FILTER_BP, OSC_SHAPE_DIGITAL_FILTER_HP, OSC_SHAPE_VOSIM, OSC_SHAPE_VOWEL, OSC_SHAPE_VOWEL_FOF, OSC_SHAPE_HARMONICS, OSC_SHAPE_FM, OSC_SHAPE_FEEDBACK_FM, OSC_SHAPE_CHAOTIC_FEEDBACK_FM, OSC_SHAPE_STRUCK_BELL, OSC_SHAPE_STRUCK_DRUM, OSC_SHAPE_KICK, OSC_SHAPE_HAT, OSC_SHAPE_SNARE, OSC_SHAPE_PLUCKED, OSC_SHAPE_BOWED, OSC_SHAPE_BLOWN, OSC_SHAPE_FLUTED, OSC_SHAPE_WAVETABLES, OSC_SHAPE_WAVE_MAP, OSC_SHAPE_WAVE_LINE, OSC_SHAPE_WAVE_PARAPHONIC, OSC_SHAPE_FILTERED_NOISE, OSC_SHAPE_TWIN_PEAKS_NOISE, OSC_SHAPE_CLOCKED_NOISE, OSC_SHAPE_GRANULAR_CLOUD, OSC_SHAPE_PARTICLE_NOISE, OSC_SHAPE_DIGITAL_MODULATION, OSC_SHAPE_QUESTION_MARK_LAST, // Braids Renaissance https://burns.ca/eurorack.html OSC_SHAPE_CHORD_SAW, OSC_SHAPE_CHORD_SQUARE, OSC_SHAPE_CHORD_TRIANGLE, OSC_SHAPE_CHORD_SINE, OSC_SHAPE_CHORD_WAVETABLE, OSC_SHAPE_STACK_SAW, OSC_SHAPE_STACK_SQUARE, OSC_SHAPE_STACK_TRIANGLE, OSC_SHAPE_STACK_SINE, OSC_SHAPE_STACK_WAVETABLE, }; struct ResoSquareState { uint32_t modulator_phase_increment; uint32_t modulator_phase; uint32_t square_modulator_phase; int32_t integrator; bool polarity; }; struct VowelSynthesizerState { uint32_t formant_increment[3]; uint32_t formant_phase[3]; uint32_t formant_amplitude[3]; uint16_t consonant_frames; uint16_t noise; }; struct SawSwarmState { uint32_t phase[6]; int32_t filter_state[2][2]; int32_t dc_blocked; int32_t lp; int32_t bp; }; struct HarmonicsState { int32_t amplitude[kNumAdditiveHarmonics]; }; struct AdditiveState { uint32_t partial_phase[kNumBellPartials]; uint32_t partial_phase_increment[kNumBellPartials]; int32_t partial_amplitude[kNumBellPartials]; int32_t target_partial_amplitude[kNumBellPartials]; int16_t previous_sample; size_t current_partial; int32_t lp_noise[3]; }; struct PluckState { size_t size; size_t write_ptr; size_t shift; size_t mask; size_t pluck_position; size_t initialization_ptr; uint32_t phase; uint32_t phase_increment; uint32_t max_phase_increment; int16_t previous_sample; uint8_t polyphony_assigner; }; struct FeedbackFmState { uint32_t modulator_phase; int16_t previous_sample; }; struct ParticleNoiseState { uint16_t amplitude; int32_t filter_state[3][2]; int32_t filter_scale[3]; int32_t filter_coefficient[3]; }; struct PhysicalModellingState { uint16_t delay_ptr; uint16_t excitation_ptr; int32_t lp_state; int32_t filter_state[2]; int16_t previous_sample; }; struct Grain { uint32_t phase; uint32_t phase_increment; uint32_t envelope_phase; uint32_t envelope_phase_increment; }; struct FofState { int32_t next_saw_sample; int16_t previous_sample; int32_t svf_lp[kNumFormants]; int32_t svf_bp[kNumFormants]; }; struct ToyState { uint8_t held_sample; uint16_t decimation_counter; }; struct SvfState { int32_t bp; int32_t lp; }; struct DigitalModulationState { uint32_t symbol_phase; uint16_t symbol_count; int32_t filter_state; uint8_t data_byte; }; struct ClockedNoiseState { uint32_t cycle_phase; uint32_t cycle_phase_increment; uint32_t rng_state; int32_t seed; int16_t sample; }; struct HatState { uint32_t phase[6]; uint32_t rng_state; }; struct StackState { uint32_t phase[12]; int16_t previous_sample; }; union DigitalOscillatorState { ResoSquareState res; VowelSynthesizerState vow; SawSwarmState saw; PluckState plk[4]; FeedbackFmState ffm; ParticleNoiseState pno; PhysicalModellingState phy; Grain grain[4]; FofState fof; ToyState toy; SvfState svf; AdditiveState add; DigitalModulationState dmd; ClockedNoiseState clk; HatState hat; HarmonicsState hrm; StackState stack; uint32_t modulator_phase; }; class DigitalOscillator { public: typedef void (DigitalOscillator::*RenderFn)(const uint8_t*, int16_t*, size_t); DigitalOscillator() { } ~DigitalOscillator() { } inline void Init() { memset(&state_, 0, sizeof(state_)); pulse_[0].Init(); pulse_[1].Init(); pulse_[2].Init(); pulse_[3].Init(); svf_[0].Init(); svf_[1].Init(); svf_[2].Init(); phase_ = 0; strike_ = true; init_ = true; } inline void set_shape(DigitalOscillatorShape shape) { shape_ = shape; } inline void set_pitch(int16_t pitch) { // Smooth HF noise when the pitch CV is noisy. if (pitch_ > (90 << 7) && pitch > (90 << 7)) { pitch_ = (static_cast(pitch_) + pitch) >> 1; } else { pitch_ = pitch; } } inline void set_parameters( int16_t parameter_1, int16_t parameter_2) { parameter_[0] = parameter_1; parameter_[1] = parameter_2; } inline uint32_t phase_increment() const { return phase_increment_; } inline void Strike() { strike_ = true; } void Render(const uint8_t* sync, int16_t* buffer, size_t size); private: void RenderTripleRingMod(const uint8_t*, int16_t*, size_t); void RenderSawSwarm(const uint8_t*, int16_t*, size_t); void RenderComb(const uint8_t*, int16_t*, size_t); void RenderToy(const uint8_t*, int16_t*, size_t); void RenderDigitalFilter(const uint8_t*, int16_t*, size_t); void RenderVosim(const uint8_t*, int16_t*, size_t); void RenderVowel(const uint8_t*, int16_t*, size_t); void RenderVowelFof(const uint8_t*, int16_t*, size_t); void RenderHarmonics(const uint8_t*, int16_t*, size_t); void RenderFm(const uint8_t*, int16_t*, size_t); void RenderFeedbackFm(const uint8_t*, int16_t*, size_t); void RenderChaoticFeedbackFm(const uint8_t*, int16_t*, size_t); void RenderStruckBell(const uint8_t*, int16_t*, size_t); void RenderStruckDrum(const uint8_t*, int16_t*, size_t); void RenderPlucked(const uint8_t*, int16_t*, size_t); void RenderBowed(const uint8_t*, int16_t*, size_t); void RenderBlown(const uint8_t*, int16_t*, size_t); void RenderFluted(const uint8_t*, int16_t*, size_t); void RenderWavetables(const uint8_t*, int16_t*, size_t); void RenderWaveMap(const uint8_t*, int16_t*, size_t); void RenderWaveLine(const uint8_t*, int16_t*, size_t); void RenderWaveParaphonic(const uint8_t*, int16_t*, size_t); void RenderTwinPeaksNoise(const uint8_t*, int16_t*, size_t); void RenderFilteredNoise(const uint8_t*, int16_t*, size_t); void RenderClockedNoise(const uint8_t*, int16_t*, size_t); void RenderGranularCloud(const uint8_t*, int16_t*, size_t); void RenderParticleNoise(const uint8_t*, int16_t*, size_t); void RenderDigitalModulation(const uint8_t*, int16_t*, size_t); void RenderKick(const uint8_t*, int16_t*, size_t); void RenderSnare(const uint8_t*, int16_t*, size_t); void RenderCymbal(const uint8_t*, int16_t*, size_t); void RenderQuestionMark(const uint8_t*, int16_t*, size_t); // void RenderYourAlgo(const uint8_t*, int16_t*, size_t); void renderChord( const uint8_t *sync, int16_t *buffer, size_t size, const uint8_t* noteOffset, uint8_t noteCount); void RenderStack(const uint8_t*, int16_t*, size_t); void RenderDiatonicChord(const uint8_t*, int16_t*, size_t); public: static uint32_t ComputePhaseIncrement(int16_t midi_pitch); static uint32_t ComputeDelay(int16_t midi_pitch); static int16_t InterpolateFormantParameter( const int16_t table[][kNumFormants][kNumFormants], int16_t x, int16_t y, uint8_t formant); private: uint32_t phase_; uint32_t phase_increment_; uint32_t delay_; int16_t parameter_[2]; int16_t previous_parameter_[2]; int32_t smoothed_parameter_; int16_t pitch_; uint8_t active_voice_; bool init_; bool strike_; DigitalOscillatorShape shape_; DigitalOscillatorShape previous_shape_; DigitalOscillatorState state_; Excitation pulse_[4]; Svf svf_[3]; union { int16_t comb[kCombDelayLength]; int16_t ks[1025 * 4]; struct { int8_t bridge[kWGBridgeLength]; int8_t neck[kWGNeckLength]; } bowed; int16_t bore[kWGBoreLength]; struct { int8_t jet[kWGJetLength]; int8_t bore[kWGFBoreLength]; } fluted; } delay_lines_; static RenderFn fn_table_[]; DISALLOW_COPY_AND_ASSIGN(DigitalOscillator); }; } // namespace braids #endif // BRAIDS_DIGITAL_OSCILLATOR_H_ ================================================ FILE: lib/braids/envelope.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. #ifndef BRAIDS_ENVELOPE_H_ #define BRAIDS_ENVELOPE_H_ #include "stmlib/stmlib.h" #include "stmlib/utils/dsp.h" #include "braids/resources.h" namespace braids { using namespace stmlib; enum EnvelopeSegment { ENV_SEGMENT_ATTACK = 0, ENV_SEGMENT_DECAY = 1, ENV_SEGMENT_DEAD = 2, ENV_NUM_SEGMENTS, }; class Envelope { public: Envelope() { } ~Envelope() { } void Init() { target_[ENV_SEGMENT_ATTACK] = 65535; target_[ENV_SEGMENT_DECAY] = 0; target_[ENV_SEGMENT_DEAD] = 0; increment_[ENV_SEGMENT_DEAD] = 0; } inline EnvelopeSegment segment() const { return static_cast(segment_); } inline void Update(int32_t a, int32_t d) { increment_[ENV_SEGMENT_ATTACK] = lut_env_portamento_increments[a]; increment_[ENV_SEGMENT_DECAY] = lut_env_portamento_increments[d]; } inline void Trigger(EnvelopeSegment segment) { if (segment == ENV_SEGMENT_DEAD) { value_ = 0; } a_ = value_; b_ = target_[segment]; segment_ = segment; phase_ = 0; } inline uint16_t Render() { uint32_t increment = increment_[segment_]; phase_ += increment; if (phase_ < increment) { value_ = Mix(a_, b_, 65535); Trigger(static_cast(segment_ + 1)); } if (increment_[segment_]) { value_ = Mix(a_, b_, Interpolate824(lut_env_expo, phase_)); } return value_; } inline uint16_t value() const { return value_; } private: // Phase increments for each segment. uint32_t increment_[ENV_NUM_SEGMENTS]; // Value that needs to be reached at the end of each segment. uint16_t target_[ENV_NUM_SEGMENTS]; // Current segment. size_t segment_; // Start and end value of the current segment. uint16_t a_; uint16_t b_; uint16_t value_; uint32_t phase_; DISALLOW_COPY_AND_ASSIGN(Envelope); }; } // namespace braids #endif // BRAIDS_ENVELOPE_H_ ================================================ FILE: lib/braids/excitation.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Exponential decay excitation. #ifndef BRAIDS_EXCITATION_H_ #define BRAIDS_EXCITATION_H_ #include "stmlib/stmlib.h" namespace braids { class Excitation { public: Excitation() { } ~Excitation() { } void Init() { delay_ = 0; decay_ = 4093; counter_ = 0; state_ = 0; } void set_delay(uint16_t delay) { delay_ = delay; } void set_decay(uint16_t decay) { decay_ = decay; } void Trigger(int32_t level) { level_ = level; counter_ = delay_ + 1; } bool done() { return counter_ == 0; } inline int32_t Process() { state_ = (state_ * decay_ >> 12); if (counter_ > 0) { --counter_; if (counter_ == 0) { state_ += level_ < 0 ? -level_ : level_; } } return level_ < 0 ? -state_ : state_; } private: uint32_t delay_; uint32_t decay_; int32_t counter_; int32_t state_; int32_t level_; DISALLOW_COPY_AND_ASSIGN(Excitation); }; } // namespace braids #endif // BRAIDS_EXCITATION_H_ ================================================ FILE: lib/braids/macro_oscillator.cc ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Macro-oscillator. #include "braids/macro_oscillator.h" #include #include "stmlib/utils/dsp.h" #include "braids/parameter_interpolation.h" #include "braids/resources.h" namespace braids { using namespace stmlib; void MacroOscillator::Render( const uint8_t* sync, int16_t* buffer, size_t size) { RenderFn fn = fn_table_[shape_]; (this->*fn)(sync, buffer, size); } void MacroOscillator::RenderCSaw( const uint8_t* sync, int16_t* buffer, size_t size) { analog_oscillator_[0].set_pitch(pitch_); analog_oscillator_[0].set_shape(OSC_SHAPE_CSAW); analog_oscillator_[0].set_parameter(parameter_[0]); analog_oscillator_[0].set_aux_parameter(parameter_[1]); analog_oscillator_[0].Render(sync, buffer, NULL, size); int16_t shift = -(parameter_[1] - 32767) >> 4; while (size--) { int32_t s = *buffer + shift; *buffer++ = (s * 13) >> 3; } } void MacroOscillator::RenderMorph( const uint8_t* sync, int16_t* buffer, size_t size) { analog_oscillator_[0].set_pitch(pitch_); analog_oscillator_[1].set_pitch(pitch_); uint16_t balance; if (parameter_[0] <= 10922) { analog_oscillator_[0].set_parameter(0); analog_oscillator_[1].set_parameter(0); analog_oscillator_[0].set_shape(OSC_SHAPE_TRIANGLE); analog_oscillator_[1].set_shape(OSC_SHAPE_SAW); balance = parameter_[0] * 6; } else if (parameter_[0] <= 21845) { analog_oscillator_[0].set_parameter(0); analog_oscillator_[1].set_parameter(0); analog_oscillator_[0].set_shape(OSC_SHAPE_SQUARE); analog_oscillator_[1].set_shape(OSC_SHAPE_SAW); balance = 65535 - (parameter_[0] - 10923) * 6; } else { analog_oscillator_[0].set_parameter((parameter_[0] - 21846) * 3); analog_oscillator_[1].set_parameter(0); analog_oscillator_[0].set_shape(OSC_SHAPE_SQUARE); analog_oscillator_[1].set_shape(OSC_SHAPE_SINE); balance = 0; } int16_t* shape_1 = buffer; int16_t* shape_2 = temp_buffer_; analog_oscillator_[0].Render(sync, shape_1, NULL, size); analog_oscillator_[1].Render(sync, shape_2, NULL, size); int32_t lp_cutoff = pitch_ - (parameter_[1] >> 1) + 128 * 128; if (lp_cutoff < 0) { lp_cutoff = 0; } else if (lp_cutoff > 32767) { lp_cutoff = 32767; } int32_t f = Interpolate824(lut_svf_cutoff, lp_cutoff << 17); int32_t lp_state = lp_state_; int32_t fuzz_amount = parameter_[1] << 1; if (pitch_ > (80 << 7)) { fuzz_amount -= (pitch_ - (80 << 7)) << 4; if (fuzz_amount < 0) { fuzz_amount = 0; } } while (size--) { int16_t sample = Mix(*shape_1++, *shape_2++, balance); int32_t shifted_sample = sample; shifted_sample += (parameter_[1] >> 2) + (parameter_[0] >> 4); lp_state += (sample - lp_state) * f >> 15; CLIP(lp_state) shifted_sample = lp_state + 32768; int16_t fuzzed = Interpolate88(ws_violent_overdrive, shifted_sample); *buffer++ = Mix(sample, fuzzed, fuzz_amount); } lp_state_ = lp_state; } void MacroOscillator::RenderSawSquare( const uint8_t* sync, int16_t* buffer, size_t size) { analog_oscillator_[0].set_parameter(parameter_[0]); analog_oscillator_[1].set_parameter(parameter_[0]); analog_oscillator_[0].set_pitch(pitch_); analog_oscillator_[1].set_pitch(pitch_); analog_oscillator_[0].set_shape(OSC_SHAPE_VARIABLE_SAW); analog_oscillator_[1].set_shape(OSC_SHAPE_SQUARE); int16_t* saw_buffer = buffer; int16_t* square_buffer = temp_buffer_; analog_oscillator_[0].Render(sync, saw_buffer, NULL, size); analog_oscillator_[1].Render(sync, square_buffer, NULL, size); BEGIN_INTERPOLATE_PARAMETER_1 while (size--) { INTERPOLATE_PARAMETER_1 uint16_t balance = parameter_1 << 1; int16_t attenuated_square = static_cast( *square_buffer++) * 148 >> 8; *buffer++ = Mix(*saw_buffer++, attenuated_square, balance); } END_INTERPOLATE_PARAMETER_1 } #define SEMI * 128 const int16_t intervals[65] = { -24 SEMI, -24 SEMI, -24 SEMI + 4, -23 SEMI, -22 SEMI, -21 SEMI, -20 SEMI, -19 SEMI, -18 SEMI, -17 SEMI - 4, -17 SEMI, -16 SEMI, -15 SEMI, -14 SEMI, -13 SEMI, -12 SEMI - 4, -12 SEMI, -11 SEMI, -10 SEMI, -9 SEMI, -8 SEMI, -7 SEMI - 4, -7 SEMI, -6 SEMI, -5 SEMI, -4 SEMI, -3 SEMI, -2 SEMI, -1 SEMI, -24, -8, -4, 0, 4, 8, 24, 1 SEMI, 2 SEMI, 3 SEMI, 4 SEMI, 5 SEMI, 6 SEMI, 7 SEMI, 7 SEMI + 4, 8 SEMI, 9 SEMI, 10 SEMI, 11 SEMI, 12 SEMI, 12 SEMI + 4, 13 SEMI, 14 SEMI, 15 SEMI, 16 SEMI, 17 SEMI, 17 SEMI + 4, 18 SEMI, 19 SEMI, 20 SEMI, 21 SEMI, 22 SEMI, 23 SEMI, 24 SEMI - 4, 24 SEMI, 24 SEMI }; void MacroOscillator::RenderTriple( const uint8_t* sync, int16_t* buffer, size_t size) { AnalogOscillatorShape base_shape; switch (shape_) { case MACRO_OSC_SHAPE_TRIPLE_SAW: base_shape = OSC_SHAPE_SAW; break; case MACRO_OSC_SHAPE_TRIPLE_TRIANGLE: base_shape = OSC_SHAPE_TRIANGLE; break; case MACRO_OSC_SHAPE_TRIPLE_SQUARE: base_shape = OSC_SHAPE_SQUARE; break; default: base_shape = OSC_SHAPE_SINE; break; } analog_oscillator_[0].set_parameter(0); analog_oscillator_[1].set_parameter(0); analog_oscillator_[2].set_parameter(0); analog_oscillator_[0].set_pitch(pitch_); for (size_t i = 0; i < 2; ++i) { int16_t detune_1 = intervals[parameter_[i] >> 9]; int16_t detune_2 = intervals[((parameter_[i] >> 8) + 1) >> 1]; uint16_t xfade = parameter_[i] << 8; int16_t detune = detune_1 + ((detune_2 - detune_1) * xfade >> 16); analog_oscillator_[i + 1].set_pitch(pitch_ + detune); } analog_oscillator_[0].set_shape(base_shape); analog_oscillator_[1].set_shape(base_shape); analog_oscillator_[2].set_shape(base_shape); std::fill(&buffer[0], &buffer[size], 0); for (size_t i = 0; i < 3; ++i) { analog_oscillator_[i].Render(sync, temp_buffer_, NULL, size); for (size_t j = 0; j < size; ++j) { buffer[j] += temp_buffer_[j] * 21 >> 6; } } } void MacroOscillator::RenderSub( const uint8_t* sync, int16_t* buffer, size_t size) { AnalogOscillatorShape base_shape = shape_ == MACRO_OSC_SHAPE_SQUARE_SUB ? OSC_SHAPE_SQUARE : OSC_SHAPE_VARIABLE_SAW; analog_oscillator_[0].set_parameter(parameter_[0]); analog_oscillator_[0].set_shape(base_shape); analog_oscillator_[0].set_pitch(pitch_); analog_oscillator_[1].set_parameter(0); analog_oscillator_[1].set_shape(OSC_SHAPE_SQUARE); int16_t octave = parameter_[1] < 16384 ? (24 << 7) : (12 << 7); analog_oscillator_[1].set_pitch(pitch_ - octave); analog_oscillator_[0].Render(sync, buffer, NULL, size); analog_oscillator_[1].Render(sync, temp_buffer_, NULL, size); BEGIN_INTERPOLATE_PARAMETER_1 int16_t* temp_buffer = temp_buffer_; while (size--) { INTERPOLATE_PARAMETER_1 uint16_t sub_gain = (parameter_1 < 16384 ? (16383 - parameter_1) : (parameter_1 - 16384)) << 1; *buffer = Mix(*buffer, *temp_buffer, sub_gain); buffer++; temp_buffer++; } END_INTERPOLATE_PARAMETER_1 } void MacroOscillator::RenderDualSync( const uint8_t* sync, int16_t* buffer, size_t size) { AnalogOscillatorShape base_shape = shape_ == MACRO_OSC_SHAPE_SQUARE_SYNC ? OSC_SHAPE_SQUARE : OSC_SHAPE_SAW; analog_oscillator_[0].set_parameter(0); analog_oscillator_[0].set_shape(base_shape); analog_oscillator_[0].set_pitch(pitch_); analog_oscillator_[1].set_parameter(0); analog_oscillator_[1].set_shape(base_shape); analog_oscillator_[1].set_pitch(pitch_ + (parameter_[0] >> 2)); analog_oscillator_[0].Render(sync, buffer, sync_buffer_, size); analog_oscillator_[1].Render(sync_buffer_, temp_buffer_, NULL, size); BEGIN_INTERPOLATE_PARAMETER_1 int16_t* temp_buffer = temp_buffer_; while (size--) { INTERPOLATE_PARAMETER_1 uint16_t balance = parameter_1 << 1; *buffer = (Mix(*buffer, *temp_buffer, balance) >> 2) * 3; buffer++; temp_buffer++; } END_INTERPOLATE_PARAMETER_1 } void MacroOscillator::RenderSineTriangle( const uint8_t* sync, int16_t* buffer, size_t size) { int32_t attenuation_sine = 32767 - 6 * (pitch_ - (92 << 7)); int32_t attenuation_tri = 32767 - 7 * (pitch_ - (80 << 7)); if (attenuation_tri < 0) attenuation_tri = 0; if (attenuation_sine < 0) attenuation_sine = 0; if (attenuation_tri > 32767) attenuation_tri = 32767; if (attenuation_sine > 32767) attenuation_sine = 32767; int32_t timbre = parameter_[0]; analog_oscillator_[0].set_parameter(timbre * attenuation_sine >> 15); analog_oscillator_[1].set_parameter(timbre * attenuation_tri >> 15); analog_oscillator_[0].set_pitch(pitch_); analog_oscillator_[1].set_pitch(pitch_); analog_oscillator_[0].set_shape(OSC_SHAPE_SINE_FOLD); analog_oscillator_[1].set_shape(OSC_SHAPE_TRIANGLE_FOLD); analog_oscillator_[0].Render(sync, buffer, NULL, size); analog_oscillator_[1].Render(sync, temp_buffer_, NULL, size); int16_t* temp_buffer = temp_buffer_; BEGIN_INTERPOLATE_PARAMETER_1 while (size--) { INTERPOLATE_PARAMETER_1 uint16_t balance = parameter_1 << 1; *buffer = Mix(*buffer, *temp_buffer, balance); buffer++; temp_buffer++; } END_INTERPOLATE_PARAMETER_1 } void MacroOscillator::RenderBuzz( const uint8_t* sync, int16_t* buffer, size_t size) { analog_oscillator_[0].set_parameter(parameter_[0]); analog_oscillator_[0].set_shape(OSC_SHAPE_BUZZ); analog_oscillator_[0].set_pitch(pitch_); analog_oscillator_[1].set_parameter(parameter_[0]); analog_oscillator_[1].set_shape(OSC_SHAPE_BUZZ); analog_oscillator_[1].set_pitch(pitch_ + (parameter_[1] >> 8)); analog_oscillator_[0].Render(sync, buffer, NULL, size); analog_oscillator_[1].Render(sync, temp_buffer_, NULL, size); int16_t* temp_buffer = temp_buffer_; while (size--) { *buffer >>= 1; *buffer += *temp_buffer >> 1; buffer++; temp_buffer++; } } void MacroOscillator::RenderDigital( const uint8_t* sync, int16_t* buffer, size_t size) { digital_oscillator_.set_parameters(parameter_[0], parameter_[1]); digital_oscillator_.set_pitch(pitch_); digital_oscillator_.set_shape(static_cast( shape_ - MACRO_OSC_SHAPE_TRIPLE_RING_MOD)); digital_oscillator_.Render(sync, buffer, size); } void MacroOscillator::RenderSawComb( const uint8_t* sync, int16_t* buffer, size_t size) { analog_oscillator_[0].set_parameter(0); analog_oscillator_[0].set_pitch(pitch_); analog_oscillator_[0].set_shape(OSC_SHAPE_SAW); analog_oscillator_[0].Render(sync, buffer, NULL, size); digital_oscillator_.set_parameters(parameter_[0], parameter_[1]); digital_oscillator_.set_pitch(pitch_); digital_oscillator_.set_shape(OSC_SHAPE_COMB_FILTER); digital_oscillator_.Render(sync, buffer, size); } /* static */ MacroOscillator::RenderFn MacroOscillator::fn_table_[] = { &MacroOscillator::RenderCSaw, &MacroOscillator::RenderMorph, &MacroOscillator::RenderSawSquare, &MacroOscillator::RenderSineTriangle, &MacroOscillator::RenderBuzz, &MacroOscillator::RenderSub, &MacroOscillator::RenderSub, &MacroOscillator::RenderDualSync, &MacroOscillator::RenderDualSync, &MacroOscillator::RenderTriple, &MacroOscillator::RenderTriple, &MacroOscillator::RenderTriple, &MacroOscillator::RenderTriple, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, // Diatonic Chord 1-5 &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, // Stacks 1-5 &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderSawComb, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, &MacroOscillator::RenderDigital, // &MacroOscillator::RenderDigital }; } // namespace braids ================================================ FILE: lib/braids/macro_oscillator.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Macro-oscillator entry point. #ifndef BRAIDS_MACRO_OSCILLATOR_H_ #define BRAIDS_MACRO_OSCILLATOR_H_ #include "stmlib/stmlib.h" #include #include "braids/analog_oscillator.h" #include "braids/digital_oscillator.h" #include "braids/resources.h" #include "braids/settings.h" namespace braids { class MacroOscillator { public: typedef void (MacroOscillator::*RenderFn)(const uint8_t*, int16_t*, size_t); MacroOscillator() { } ~MacroOscillator() { } inline void Init() { analog_oscillator_[0].Init(); analog_oscillator_[1].Init(); analog_oscillator_[2].Init(); digital_oscillator_.Init(); lp_state_ = 0; previous_parameter_[0] = 0; previous_parameter_[1] = 0; } inline void set_shape(MacroOscillatorShape shape) { if (shape != shape_) { Strike(); } shape_ = shape; } inline void set_pitch(int16_t pitch) { pitch_ = pitch; } inline int16_t pitch() const { return pitch_; } inline void set_parameters( int16_t parameter_1, int16_t parameter_2) { parameter_[0] = parameter_1; parameter_[1] = parameter_2; } inline void Strike() { digital_oscillator_.Strike(); } void Render(const uint8_t* sync_buffer, int16_t* buffer, size_t size); private: void RenderCSaw(const uint8_t*, int16_t*, size_t); void RenderMorph(const uint8_t*, int16_t*, size_t); void RenderSawSquare(const uint8_t*, int16_t*, size_t); void RenderSub(const uint8_t*, int16_t*, size_t); void RenderDualSync(const uint8_t*, int16_t*, size_t); void RenderSineTriangle(const uint8_t*, int16_t*, size_t); void RenderBuzz(const uint8_t*, int16_t*, size_t); void RenderDigital(const uint8_t*, int16_t*, size_t); void RenderSawComb(const uint8_t*, int16_t*, size_t); void RenderTriple(const uint8_t*, int16_t*, size_t); void ConfigureTriple(AnalogOscillatorShape shape); int16_t parameter_[2]; int16_t previous_parameter_[2]; int16_t pitch_; uint8_t sync_buffer_[24]; int16_t temp_buffer_[24]; int32_t lp_state_; AnalogOscillator analog_oscillator_[3]; DigitalOscillator digital_oscillator_; MacroOscillatorShape shape_; static RenderFn fn_table_[]; DISALLOW_COPY_AND_ASSIGN(MacroOscillator); }; } // namespace braids #endif // BRAIDS_MACRO_OSCILLATOR_H_ ================================================ FILE: lib/braids/parameter_interpolation.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Macros for linearly interpolating parameters - used when the modulated signal // is a sine or triangle - which makes the 4kHz quantization obvious. #ifndef BRAIDS_PARAMETER_INTERPOLATION_H_ #define BRAIDS_PARAMETER_INTERPOLATION_H_ // Macro for linear interpolation of parameters. #define BEGIN_INTERPOLATE_PARAMETERS \ int32_t parameter_0_start = previous_parameter_[0]; \ int32_t parameter_1_start = previous_parameter_[1]; \ int32_t parameter_0_delta = parameter_[0] - previous_parameter_[0]; \ int32_t parameter_1_end = parameter_[1] - previous_parameter_[1]; \ int32_t parameter_increment = 32767 / size; \ int32_t parameter_xfade = 0; #define INTERPOLATE_PARAMETERS \ parameter_xfade += parameter_increment; \ int32_t parameter_0 = parameter_0_start + \ (parameter_0_delta * parameter_xfade >> 15); \ int32_t parameter_1 = parameter_0_start + \ (parameter_0_delta * parameter_xfade >> 15); #define END_INTERPOLATE_PARAMETERS \ previous_parameter_[0] = parameter_[0]; \ previous_parameter_[1] = parameter_[1]; #define BEGIN_INTERPOLATE_PARAMETER_0 \ int32_t parameter_0_start = previous_parameter_[0]; \ int32_t parameter_0_delta = parameter_[0] - previous_parameter_[0]; \ int32_t parameter_increment = 32767 / size; \ int32_t parameter_xfade = 0; #define INTERPOLATE_PARAMETER_0 \ parameter_xfade += parameter_increment; \ int32_t parameter_0 = parameter_0_start + \ (parameter_0_delta * parameter_xfade >> 15); #define END_INTERPOLATE_PARAMETER_0 \ previous_parameter_[0] = parameter_[0]; #define BEGIN_INTERPOLATE_PARAMETER_1 \ int32_t parameter_1_start = previous_parameter_[1]; \ int32_t parameter_1_delta = parameter_[1] - previous_parameter_[1]; \ int32_t parameter_increment = 32767 / size; \ int32_t parameter_xfade = 0; #define INTERPOLATE_PARAMETER_1 \ parameter_xfade += parameter_increment; \ int32_t parameter_1 = parameter_1_start + \ (parameter_1_delta * parameter_xfade >> 15); #define END_INTERPOLATE_PARAMETER_1 \ previous_parameter_[1] = parameter_[1]; #define BEGIN_INTERPOLATE_PARAMETER \ int32_t parameter_start = previous_parameter_; \ int32_t parameter_delta = parameter_ - previous_parameter_; \ int32_t parameter_increment = 32767 / size; \ int32_t parameter_xfade = 0; #define INTERPOLATE_PARAMETER \ parameter_xfade += parameter_increment; \ int32_t parameter = parameter_start + \ (parameter_delta * parameter_xfade >> 15); #define END_INTERPOLATE_PARAMETER \ previous_parameter_ = parameter_; #define BEGIN_INTERPOLATE_PHASE_INCREMENT \ uint32_t phase_increment = previous_phase_increment_; \ uint32_t phase_increment_increment = \ previous_phase_increment_ < phase_increment_ \ ? (phase_increment_ - previous_phase_increment_) / size \ : ~((previous_phase_increment_ - phase_increment_) / size); #define INTERPOLATE_PHASE_INCREMENT \ phase_increment += phase_increment_increment; #define END_INTERPOLATE_PHASE_INCREMENT \ previous_phase_increment_ = phase_increment; #endif // BRAIDS_PARAMETER_INTERPOLATION_H_ ================================================ FILE: lib/braids/quantizer.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Note quantizer #include #include "braids/quantizer.h" #include #include namespace braids { void Quantizer::Init() { enabled_ = false; codeword_ = 0; previous_boundary_ = 0; next_boundary_ = 0; last_note = 64; num_notes_ = 12; for (int16_t i = 0; i < 128; ++i) { codebook_[i] = (i - 64) << 7; } } int16_t Quantizer::Lookup(uint8_t index) { return codebook_[index]; } bool Quantizer::enabled() { return enabled_; } void Quantizer::Configure( const int16_t* notes, int16_t span, size_t num_notes) { enabled_ = notes != NULL && num_notes != 0 && span != 0; num_notes_ = num_notes; if (enabled_) { codeword_ = 0; previous_boundary_ = 0; next_boundary_ = 0; last_note = 64; int32_t octave = 0; size_t note = 0; int16_t root = 0; for (int32_t i = 0; i < 64; ++i) { int32_t up = root + notes[note] + span * octave; int32_t down = root + notes[num_notes - 1 - note] + (-octave - 1) * span; CLIP(up) CLIP(down) codebook_[64 + i] = up; codebook_[64 - i - 1] = down; ++note; if (note >= num_notes) { note = 0; ++octave; } } } else { Init(); } } int32_t Quantizer::Process(int32_t pitch, int32_t root, int8_t* note) { pitch -= root; if (pitch >= previous_boundary_ && pitch <= next_boundary_) { // We're still in the voronoi cell for the active codeword. } else { // Search for the nearest neighbour in the codebook. int16_t upper_bound_index = std::upper_bound( &codebook_[3], &codebook_[126], static_cast(pitch)) - &codebook_[0]; int16_t lower_bound_index = upper_bound_index - 2; int16_t best_distance = 16384; int16_t q = -1; for (int16_t i = lower_bound_index; i <= upper_bound_index; ++i) { int16_t distance = abs(pitch - codebook_[i]); if (distance < best_distance) { best_distance = distance; q = i; } } codeword_ = codebook_[q]; last_note = q; // Enlarge the current voronoi cell a bit for hysteresis. previous_boundary_ = (9 * codebook_[q - 1] + 7 * codeword_) >> 4; next_boundary_ = (9 * codebook_[q + 1] + 7 * codeword_) >> 4; if (enabled_) pitch = codeword_; } if (enabled_) pitch = codeword_; if(note != nullptr) *note = last_note; pitch += root; return pitch; } } // namespace braids ================================================ FILE: lib/braids/quantizer.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Note quantizer #ifndef BRAIDS_QUANTIZER_H_ #define BRAIDS_QUANTIZER_H_ #include "stmlib/stmlib.h" namespace braids { struct Scale { int16_t span; size_t num_notes; int16_t notes[16]; }; class Quantizer { public: Quantizer() { } ~Quantizer() { } void Init(); int32_t Process(int32_t pitch) { return Process(pitch, 0, nullptr); } int32_t Process(int32_t pitch, int32_t root, int8_t* note); void Configure(const Scale& scale) { Configure(scale.notes, scale.span, scale.num_notes); } int16_t Lookup(uint8_t index); void Configure(const int16_t* notes, int16_t span, size_t num_notes); bool enabled(); size_t NumNotes() { return num_notes_; } private: int8_t last_note; bool enabled_; int16_t codebook_[128]; int32_t codeword_; int32_t previous_boundary_; int32_t next_boundary_; size_t num_notes_; DISALLOW_COPY_AND_ASSIGN(Quantizer); }; } // namespace braids #endif // BRAIDS_QUANTIZER_H_ ================================================ FILE: lib/braids/quantizer_scales.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Quantizer scales #ifndef BRAIDS_QUANTIZER_SCALES_H_ #define BRAIDS_QUANTIZER_SCALES_H_ #include "quantizer.h" namespace braids { const Scale scales[] = { // Off { 0, 0, { } }, // Semitones { 12 << 7, 12, { 0, 128, 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1408} }, // Ionian (From midipal/BitT source code) { 12 << 7, 7, { 0, 256, 512, 640, 896, 1152, 1408} }, // Dorian (From midipal/BitT source code) { 12 << 7, 7, { 0, 256, 384, 640, 896, 1152, 1280} }, // Phrygian (From midipal/BitT source code) { 12 << 7, 7, { 0, 128, 384, 640, 896, 1024, 1280} }, // Lydian (From midipal/BitT source code) { 12 << 7, 7, { 0, 256, 512, 768, 896, 1152, 1408} }, // Mixolydian (From midipal/BitT source code) { 12 << 7, 7, { 0, 256, 512, 640, 896, 1152, 1280} }, // Aeolian (From midipal/BitT source code) { 12 << 7, 7, { 0, 256, 384, 640, 896, 1024, 1280} }, // Locrian (From midipal/BitT source code) { 12 << 7, 7, { 0, 128, 384, 640, 768, 1024, 1280} }, // Blues major (From midipal/BitT source code) { 12 << 7, 6, { 0, 384, 512, 896, 1152, 1280} }, // Blues minor (From midipal/BitT source code) { 12 << 7, 6, { 0, 384, 640, 768, 896, 1280} }, // Pentatonic major (From midipal/BitT source code) { 12 << 7, 5, { 0, 256, 512, 896, 1152} }, // Pentatonic minor (From midipal/BitT source code) { 12 << 7, 5, { 0, 384, 640, 896, 1280} }, // Folk (From midipal/BitT source code) { 12 << 7, 8, { 0, 128, 384, 512, 640, 896, 1024, 1280} }, // Japanese (From midipal/BitT source code) { 12 << 7, 5, { 0, 128, 640, 896, 1024} }, // Gamelan (From midipal/BitT source code) { 12 << 7, 5, { 0, 128, 384, 896, 1024} }, // Gypsy { 12 << 7, 7, { 0, 256, 384, 768, 896, 1024, 1408} }, // Arabian { 12 << 7, 7, { 0, 128, 512, 640, 896, 1024, 1408} }, // Flamenco { 12 << 7, 7, { 0, 128, 512, 640, 896, 1024, 1280} }, // Whole tone (From midipal/BitT source code) { 12 << 7, 6, { 0, 256, 512, 768, 1024, 1280} }, // pythagorean (From yarns source code) { 12 << 7, 12, { 0, 115, 261, 376, 522, 637, 783, 899, 1014, 1160, 1275, 1421} }, // 1_4_eb (From yarns source code) { 12 << 7, 12, { 0, 128, 256, 384, 448, 640, 768, 896, 1024, 1152, 1280, 1344} }, // 1_4_e (From yarns source code) { 12 << 7, 12, { 0, 128, 256, 384, 448, 640, 768, 896, 1024, 1152, 1280, 1408} }, // 1_4_ea (From yarns source code) { 12 << 7, 12, { 0, 128, 256, 384, 448, 640, 768, 896, 1024, 1088, 1280, 1408} }, // bhairav (From yarns source code) { 12 << 7, 7, { 0, 115, 494, 637, 899, 1014, 1393} }, // gunakri (From yarns source code) { 12 << 7, 5, { 0, 143, 637, 899, 1042} }, // marwa (From yarns source code) { 12 << 7, 6, { 0, 143, 494, 755, 1132, 1393} }, // shree (From yarns source code) { 12 << 7, 7, { 0, 115, 494, 755, 899, 1014, 1393} }, // purvi (From yarns source code) { 12 << 7, 7, { 0, 143, 494, 755, 899, 1042, 1393} }, // bilawal (From yarns source code) { 12 << 7, 7, { 0, 261, 494, 637, 899, 1160, 1393} }, // yaman (From yarns source code) { 12 << 7, 7, { 0, 261, 522, 783, 899, 1160, 1421} }, // kafi (From yarns source code) { 12 << 7, 7, { 0, 233, 376, 637, 899, 1132, 1275} }, // bhimpalasree (From yarns source code) { 12 << 7, 7, { 0, 261, 404, 637, 899, 1160, 1303} }, // darbari (From yarns source code) { 12 << 7, 7, { 0, 261, 376, 637, 899, 1014, 1275} }, // rageshree (From yarns source code) { 12 << 7, 7, { 0, 261, 494, 637, 899, 1132, 1275} }, // khamaj (From yarns source code) { 12 << 7, 8, { 0, 261, 494, 637, 899, 1160, 1275, 1421} }, // mimal (From yarns source code) { 12 << 7, 8, { 0, 261, 376, 637, 899, 1132, 1275, 1393} }, // parameshwari (From yarns source code) { 12 << 7, 6, { 0, 115, 376, 637, 1132, 1275} }, // rangeshwari (From yarns source code) { 12 << 7, 6, { 0, 261, 376, 637, 899, 1393} }, // gangeshwari (From yarns source code) { 12 << 7, 6, { 0, 494, 637, 899, 1014, 1275} }, // kameshwari (From yarns source code) { 12 << 7, 6, { 0, 261, 755, 899, 1132, 1275} }, // pa__kafi (From yarns source code) { 12 << 7, 7, { 0, 261, 376, 637, 899, 1160, 1275} }, // natbhairav (From yarns source code) { 12 << 7, 7, { 0, 261, 494, 637, 899, 1014, 1393} }, // m_kauns (From yarns source code) { 12 << 7, 6, { 0, 261, 522, 637, 1014, 1275} }, // bairagi (From yarns source code) { 12 << 7, 5, { 0, 115, 637, 899, 1275} }, // b_todi (From yarns source code) { 12 << 7, 5, { 0, 115, 376, 899, 1275} }, // chandradeep (From yarns source code) { 12 << 7, 5, { 0, 376, 637, 899, 1275} }, // kaushik_todi (From yarns source code) { 12 << 7, 5, { 0, 376, 637, 755, 1014} }, // jogeshwari (From yarns source code) { 12 << 7, 6, { 0, 376, 494, 637, 1132, 1275} }, }; } // namespace braids #endif // BRAIDS_QUANTIZER_SCALES_H_ ================================================ FILE: lib/braids/resources.cc ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resources definitions. // // Automatically generated with: // make resources #include "braids/resources.h" #ifndef FLASHMEM #define FLASHMEM #endif namespace braids { static const char str_dummy[] = "dummy"; const char* string_table[] = { str_dummy, }; const uint16_t FLASHMEM lut_resonator_coefficient[] = { 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65534, 65534, 65534, 65534, 65534, 65534, 65533, 65533, 65533, 65532, 65532, 65532, 65531, 65531, 65530, 65529, 65529, 65528, 65527, 65526, 65525, 65523, 65522, 65520, 65518, 65516, 65514, 65511, 65508, 65505, 65501, 65497, 65492, 65487, 65481, 65475, 65467, 65459, 65449, 65439, 65427, 65414, 65399, 65382, 65363, 65342, 65318, 65292, 65262, 65228, 65191, 65149, 65101, 65048, 64988, 64922, 64847, 64762, 64668, 64562, 64443, 64310, 64160, 63992, 63804, 63593, 63356, 63091, 62794, 62461, 62088, 61670, 61202, 60677, 60091, 59435, 58701, 57881, 56964, 55941, 54799, 53526, 52107, 50528, 48773, 46824, 44662, 42268, 39623, 36704, 33492, 29966, 26107, 21898, 17325, 12380, 7061, 1374, 0, 0, }; const uint16_t FLASHMEM lut_resonator_scale[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 20, 22, 24, 27, 29, 32, 35, 38, 41, 45, 49, 54, 58, 64, 70, 76, 83, 90, 98, 107, 117, 128, 139, 152, 166, 181, 197, 215, 234, 255, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, }; const uint16_t FLASHMEM lut_svf_cutoff[] = { 17, 18, 19, 20, 22, 23, 24, 26, 27, 29, 31, 33, 35, 37, 39, 41, 44, 46, 49, 52, 55, 58, 62, 66, 70, 74, 78, 83, 88, 93, 99, 105, 111, 117, 124, 132, 140, 148, 157, 166, 176, 187, 198, 210, 222, 235, 249, 264, 280, 297, 314, 333, 353, 374, 396, 420, 445, 471, 499, 529, 561, 594, 629, 667, 706, 748, 793, 840, 890, 943, 999, 1059, 1122, 1188, 1259, 1334, 1413, 1497, 1586, 1681, 1781, 1886, 1999, 2117, 2243, 2377, 2518, 2668, 2826, 2994, 3172, 3361, 3560, 3772, 3996, 4233, 4485, 4751, 5033, 5332, 5648, 5983, 6337, 6713, 7111, 7532, 7978, 8449, 8949, 9477, 10037, 10628, 11254, 11916, 12616, 13356, 14138, 14964, 15837, 16758, 17730, 18756, 19837, 20975, 22174, 23435, 24761, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, }; const uint16_t FLASHMEM lut_svf_damp[] = { 65534, 49213, 46125, 44055, 42453, 41129, 39991, 38988, 38086, 37266, 36512, 35812, 35158, 34544, 33965, 33416, 32893, 32395, 31918, 31460, 31021, 30597, 30188, 29793, 29411, 29041, 28681, 28332, 27992, 27661, 27339, 27024, 26717, 26418, 26125, 25838, 25558, 25283, 25014, 24750, 24491, 24236, 23987, 23742, 23501, 23264, 23031, 22802, 22577, 22355, 22136, 21921, 21708, 21499, 21293, 21089, 20889, 20691, 20495, 20302, 20112, 19924, 19738, 19555, 19373, 19194, 19017, 18842, 18668, 18497, 18327, 18160, 17994, 17830, 17667, 17506, 17347, 17189, 17033, 16878, 16725, 16573, 16423, 16274, 16126, 15980, 15834, 15691, 15548, 15407, 15266, 15127, 14989, 14853, 14717, 14582, 14449, 14316, 14185, 14054, 13925, 13796, 13669, 13542, 13416, 13291, 13167, 13044, 12922, 12801, 12680, 12561, 12442, 12324, 12206, 12090, 11974, 11859, 11744, 11631, 11518, 11406, 11294, 11183, 11073, 10964, 10855, 10747, 10639, 10532, 10426, 10321, 10215, 10111, 10007, 9904, 9801, 9699, 9597, 9496, 9396, 9296, 9196, 9097, 8999, 8901, 8804, 8707, 8610, 8514, 8419, 8324, 8230, 8136, 8042, 7949, 7856, 7764, 7672, 7581, 7490, 7400, 7309, 7220, 7131, 7042, 6953, 6865, 6778, 6690, 6604, 6517, 6431, 6345, 6260, 6175, 6090, 6006, 5922, 5839, 5755, 5673, 5590, 5508, 5426, 5345, 5263, 5183, 5102, 5022, 4942, 4862, 4783, 4704, 4626, 4547, 4469, 4391, 4314, 4237, 4160, 4083, 4007, 3931, 3855, 3780, 3705, 3630, 3555, 3481, 3407, 3333, 3259, 3186, 3113, 3040, 2968, 2895, 2823, 2752, 2680, 2609, 2538, 2467, 2396, 2326, 2256, 2186, 2116, 2047, 1978, 1909, 1840, 1771, 1703, 1635, 1567, 1500, 1432, 1365, 1298, 1231, 1164, 1098, 1032, 966, 900, 834, 769, 704, 639, 574, 510, 445, 381, 317, 253, }; const uint16_t FLASHMEM lut_svf_scale[] = { 32767, 28395, 27490, 26866, 26373, 25958, 25596, 25273, 24979, 24709, 24458, 24222, 24000, 23790, 23589, 23398, 23214, 23037, 22867, 22703, 22544, 22389, 22239, 22093, 21951, 21812, 21677, 21544, 21415, 21288, 21163, 21041, 20922, 20804, 20688, 20574, 20462, 20352, 20243, 20136, 20031, 19927, 19824, 19722, 19622, 19523, 19425, 19328, 19232, 19137, 19043, 18951, 18859, 18768, 18677, 18588, 18499, 18411, 18324, 18238, 18152, 18067, 17983, 17899, 17815, 17733, 17651, 17569, 17488, 17408, 17328, 17249, 17170, 17091, 17013, 16935, 16858, 16781, 16705, 16629, 16553, 16478, 16403, 16328, 16254, 16180, 16106, 16033, 15960, 15887, 15815, 15743, 15671, 15599, 15528, 15456, 15386, 15315, 15244, 15174, 15104, 15034, 14964, 14895, 14826, 14756, 14687, 14619, 14550, 14482, 14413, 14345, 14277, 14209, 14141, 14074, 14006, 13939, 13871, 13804, 13737, 13670, 13603, 13536, 13469, 13402, 13336, 13269, 13202, 13136, 13070, 13003, 12937, 12870, 12804, 12738, 12672, 12605, 12539, 12473, 12407, 12341, 12274, 12208, 12142, 12076, 12010, 11943, 11877, 11811, 11744, 11678, 11611, 11545, 11478, 11412, 11345, 11278, 11211, 11144, 11077, 11010, 10943, 10876, 10808, 10741, 10673, 10605, 10538, 10470, 10401, 10333, 10265, 10196, 10127, 10058, 9989, 9920, 9850, 9780, 9710, 9640, 9570, 9499, 9429, 9357, 9286, 9215, 9143, 9071, 8998, 8925, 8852, 8779, 8705, 8631, 8557, 8482, 8407, 8332, 8256, 8179, 8103, 8025, 7948, 7870, 7791, 7712, 7632, 7552, 7471, 7390, 7308, 7225, 7142, 7058, 6973, 6888, 6801, 6714, 6626, 6538, 6448, 6358, 6266, 6173, 6080, 5985, 5889, 5791, 5692, 5592, 5491, 5388, 5283, 5176, 5067, 4957, 4844, 4729, 4612, 4491, 4368, 4242, 4112, 3979, 3841, 3698, 3550, 3397, 3236, 3068, 2890, 2701, 2499, 2280, 2038, }; const uint16_t FLASHMEM lut_granular_envelope[] = { 0, 4, 19, 44, 78, 123, 177, 241, 314, 398, 490, 593, 705, 826, 957, 1097, 1247, 1405, 1572, 1749, 1934, 2128, 2330, 2541, 2761, 2988, 3224, 3467, 3718, 3977, 4244, 4517, 4798, 5086, 5381, 5682, 5989, 6303, 6623, 6949, 7281, 7618, 7960, 8308, 8660, 9017, 9378, 9744, 10113, 10487, 10864, 11244, 11627, 12013, 12402, 12793, 13187, 13582, 13979, 14377, 14777, 15178, 15579, 15981, 16383, 16785, 17187, 17588, 17989, 18389, 18787, 19184, 19579, 19973, 20364, 20753, 21139, 21522, 21902, 22279, 22653, 23022, 23388, 23749, 24106, 24458, 24806, 25148, 25485, 25817, 26143, 26463, 26777, 27084, 27385, 27680, 27968, 28249, 28522, 28789, 29048, 29299, 29542, 29778, 30005, 30225, 30436, 30638, 30832, 31017, 31194, 31361, 31519, 31669, 31809, 31940, 32061, 32173, 32276, 32368, 32452, 32525, 32589, 32643, 32688, 32722, 32747, 32762, 32767, 32762, 32747, 32722, 32688, 32643, 32589, 32525, 32452, 32368, 32276, 32173, 32061, 31940, 31809, 31669, 31519, 31361, 31194, 31017, 30832, 30638, 30436, 30225, 30005, 29778, 29542, 29299, 29048, 28789, 28522, 28249, 27968, 27680, 27385, 27084, 26777, 26463, 26143, 25817, 25485, 25148, 24806, 24458, 24106, 23749, 23388, 23022, 22653, 22279, 21902, 21522, 21139, 20753, 20364, 19973, 19579, 19184, 18787, 18389, 17989, 17588, 17187, 16785, 16383, 15981, 15579, 15178, 14777, 14377, 13979, 13582, 13187, 12793, 12402, 12013, 11627, 11244, 10864, 10487, 10113, 9744, 9378, 9017, 8660, 8308, 7960, 7618, 7281, 6949, 6623, 6303, 5989, 5682, 5381, 5086, 4798, 4517, 4244, 3977, 3718, 3467, 3224, 2988, 2761, 2541, 2330, 2128, 1934, 1749, 1572, 1405, 1247, 1097, 957, 826, 705, 593, 490, 398, 314, 241, 177, 123, 78, 44, 19, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; const uint16_t FLASHMEM lut_granular_envelope_rate[] = { 2048, 2070, 2092, 2115, 2138, 2161, 2185, 2209, 2233, 2257, 2282, 2307, 2332, 2357, 2383, 2409, 2435, 2462, 2488, 2515, 2543, 2571, 2599, 2627, 2655, 2684, 2714, 2743, 2773, 2803, 2834, 2865, 2896, 2927, 2959, 2991, 3024, 3057, 3090, 3124, 3158, 3192, 3227, 3262, 3298, 3334, 3370, 3407, 3444, 3481, 3519, 3558, 3596, 3635, 3675, 3715, 3756, 3796, 3838, 3880, 3922, 3965, 4008, 4051, 4096, 4140, 4185, 4231, 4277, 4323, 4371, 4418, 4466, 4515, 4564, 4614, 4664, 4715, 4766, 4818, 4870, 4924, 4977, 5031, 5086, 5142, 5198, 5254, 5311, 5369, 5428, 5487, 5547, 5607, 5668, 5730, 5792, 5855, 5919, 5983, 6049, 6114, 6181, 6248, 6316, 6385, 6455, 6525, 6596, 6668, 6741, 6814, 6888, 6963, 7039, 7116, 7193, 7271, 7351, 7431, 7512, 7593, 7676, 7760, 7844, 7930, 8016, 8103, 8192, 8281, 8371, 8462, 8554, 8647, 8742, 8837, 8933, 9030, 9129, 9228, 9328, 9430, 9533, 9637, 9741, 9848, 9955, 10063, 10173, 10284, 10396, 10509, 10623, 10739, 10856, 10974, 11094, 11214, 11336, 11460, 11585, 11711, 11838, 11967, 12098, 12229, 12363, 12497, 12633, 12771, 12910, 13051, 13193, 13336, 13482, 13628, 13777, 13927, 14078, 14232, 14387, 14543, 14702, 14862, 15024, 15187, 15353, 15520, 15689, 15860, 16032, 16207, 16384, 16562, 16742, 16925, 17109, 17295, 17484, 17674, 17866, 18061, 18258, 18456, 18657, 18861, 19066, 19274, 19483, 19696, 19910, 20127, 20346, 20568, 20792, 21018, 21247, 21478, 21712, 21949, 22188, 22429, 22673, 22920, 23170, 23422, 23677, 23935, 24196, 24459, 24726, 24995, 25267, 25542, 25820, 26102, 26386, 26673, 26964, 27257, 27554, 27854, 28157, 28464, 28774, 29087, 29404, 29724, 30048, 30375, 30706, 31040, 31378, 31720, 32065, 32415, 32768, }; const uint16_t FLASHMEM lut_bowing_envelope[] = { 0, 10, 21, 32, 43, 54, 65, 76, 87, 98, 109, 120, 131, 142, 153, 164, 175, 185, 196, 207, 218, 229, 240, 251, 262, 273, 284, 295, 306, 317, 328, 339, 350, 361, 371, 382, 393, 404, 415, 426, 437, 448, 459, 470, 481, 492, 503, 514, 525, 536, 547, 557, 568, 579, 590, 601, 612, 623, 634, 645, 656, 667, 678, 689, 700, 711, 722, 733, 743, 754, 765, 776, 787, 798, 809, 820, 831, 842, 853, 864, 875, 886, 897, 908, 919, 929, 940, 951, 962, 973, 984, 995, 1006, 1017, 1028, 1039, 1050, 1061, 1072, 1083, 1094, 1105, 1115, 1126, 1137, 1148, 1159, 1170, 1181, 1192, 1203, 1214, 1225, 1236, 1247, 1258, 1269, 1280, 1291, 1301, 1312, 1323, 1334, 1345, 1356, 1367, 1378, 1389, 1400, 1411, 1422, 1433, 1444, 1455, 1466, 1477, 1487, 1498, 1509, 1520, 1531, 1542, 1553, 1564, 1575, 1586, 1597, 1608, 1619, 1630, 1641, 1652, 1663, 1673, 1684, 1695, 1706, 1717, 1728, 1739, 1750, 1761, 1772, 1783, 1794, 1805, 1816, 1827, 1838, 1849, 1859, 1870, 1881, 1892, 1903, 1914, 1925, 1936, 1947, 1958, 1969, 1980, 1991, 2002, 2013, 2024, 2035, 2045, 2056, 2067, 2078, 2089, 2100, 2111, 2122, 2133, 2144, 2155, 2166, 2177, 2188, 2199, 2210, 2221, 2231, 2242, 2253, 2264, 2275, 2286, 2297, 2308, 2319, 2330, 2341, 2352, 2363, 2374, 2385, 2396, 2406, 2417, 2428, 2439, 2450, 2461, 2472, 2483, 2494, 2505, 2516, 2527, 2538, 2549, 2560, 2571, 2582, 2592, 2603, 2614, 2625, 2636, 2647, 2658, 2669, 2680, 2691, 2702, 2713, 2724, 2735, 2746, 2757, 2768, 2778, 2789, 2800, 2811, 2822, 2833, 2844, 2855, 2866, 2877, 2888, 2899, 2910, 2921, 2932, 2943, 2954, 2964, 2975, 2986, 2997, 3008, 3019, 3030, 3041, 3052, 3063, 3074, 3085, 3096, 3107, 3118, 3129, 3140, 3150, 3161, 3172, 3183, 3194, 3205, 3216, 3227, 3238, 3249, 3260, 3271, 3282, 3293, 3304, 3315, 3326, 3336, 3347, 3358, 3369, 3380, 3391, 3402, 3413, 3424, 3435, 3446, 3457, 3468, 3479, 3490, 3501, 3512, 3522, 3533, 3544, 3555, 3566, 3577, 3588, 3599, 3610, 3621, 3632, 3643, 3654, 3665, 3676, 3687, 3698, 3708, 3719, 3730, 3741, 3752, 3763, 3774, 3785, 3796, 3807, 3818, 3829, 3840, 3851, 3862, 3873, 3884, 3894, 3905, 3916, 3927, 3938, 3949, 3960, 3971, 3982, 3993, 4004, 4015, 4026, 4037, 4048, 4059, 4070, 4080, 4091, 4102, 4113, 4124, 4135, 4146, 4157, 4168, 4179, 4190, 4201, 4212, 4223, 4234, 4245, 4256, 4266, 4277, 4288, 4299, 4310, 4321, 4332, 4343, 4354, 4365, 4376, 4387, 4398, 4409, 4420, 4431, 4442, 4452, 4463, 4474, 4485, 4496, 4507, 4518, 4529, 4540, 4551, 4562, 4573, 4584, 4595, 4606, 4617, 4628, 4638, 4649, 4660, 4671, 4682, 4693, 4704, 4715, 4726, 4737, 4748, 4759, 4770, 4781, 4792, 4803, 4813, 4824, 4835, 4846, 4857, 4868, 4879, 4890, 4901, 4912, 4923, 4934, 4945, 4956, 4967, 4978, 4989, 4999, 5010, 5021, 5032, 5043, 5054, 5065, 5076, 5087, 5098, 5109, 5120, 5131, 5142, 5153, 5164, 5175, 5185, 5196, 5207, 5218, 5229, 5240, 5251, 5262, 5273, 5284, 5295, 5306, 5317, 5328, 5339, 5350, 5361, 5371, 5382, 5393, 5404, 5415, 5426, 5437, 5448, 5459, 5470, 5481, 5492, 5503, 5514, 5525, 5536, 5547, 5557, 5568, 5579, 5590, 5601, 5612, 5623, 5634, 5645, 5656, 5667, 5678, 5689, 5700, 5711, 5722, 5733, 5743, 5754, 5765, 5776, 5787, 5798, 5809, 5820, 5831, 5842, 5853, 5864, 5875, 5886, 5897, 5908, 5919, 5929, 5940, 5951, 5962, 5973, 5984, 5995, 6006, 6017, 6028, 6039, 6050, 6061, 6072, 6083, 6094, 6105, 6115, 6126, 6137, 6148, 6159, 6170, 6181, 6192, 6203, 6214, 6225, 6236, 6247, 6258, 6269, 6280, 6291, 6301, 6312, 6323, 6334, 6345, 6356, 6367, 6378, 6389, 6400, 6411, 6422, 6433, 6444, 6455, 6466, 6477, 6487, 6498, 6509, 6520, 6531, 6542, 6553, 6553, 6542, 6531, 6520, 6509, 6498, 6487, 6476, 6465, 6454, 6443, 6432, 6421, 6410, 6399, 6388, 6377, 6366, 6355, 6344, 6333, 6322, 6311, 6300, 6289, 6278, 6267, 6256, 6245, 6234, 6223, 6212, 6201, 6190, 6179, 6168, 6157, 6146, 6135, 6124, 6113, 6102, 6090, 6079, 6068, 6057, 6046, 6035, 6024, 6013, 6002, 5991, 5980, 5969, 5958, 5947, 5936, 5925, 5914, 5903, 5892, 5881, 5870, 5859, 5848, 5837, 5826, 5815, 5804, 5793, 5782, 5771, 5760, 5749, 5738, 5727, 5716, 5705, 5694, 5683, 5672, 5661, 5650, 5639, 5628, 5617, 5606, 5595, 5584, 5573, 5562, 5551, 5540, 5529, 5518, 5507, 5496, 5485, 5474, 5463, 5452, 5441, 5430, 5419, 5408, 5397, 5386, 5375, 5364, 5353, 5342, 5330, 5319, 5308, 5297, 5286, 5275, 5264, 5253, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, 5242, }; const uint16_t FLASHMEM lut_bowing_friction[] = { 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 30797, 28973, 27281, 25711, 24253, 22896, 21633, 20456, 19358, 18333, 17374, 16478, 15638, 14852, 14114, 13421, 12771, 12159, 11583, 11042, 10531, 10050, 9596, 9167, 8762, 8379, 8016, 7673, 7349, 7041, 6749, 6472, 6209, 5960, 5723, 5497, 5283, 5078, 4884, 4699, 4522, 4354, 4194, 4040, 3894, 3754, 3621, 3493, 3371, 3254, 3143, 3036, 2933, 2835, 2741, 2651, 2564, 2481, 2401, 2325, 2251, 2181, 2113, 2048, 1985, 1924, 1866, 1810, 1756, 1705, 1655, 1606, 1560, 1515, 1472, 1431, 1390, 1352, 1314, 1278, 1243, 1209, 1177, 1145, 1115, 1085, 1057, 1029, 1003, 977, 952, 928, 904, 882, 860, 838, 818, 798, 778, 759, 741, 723, 706, 690, 673, 658, 642, 628, 613, 599, 586, 572, 560, 547, 535, 523, 512, 501, 490, 479, 469, 459, 449, 440, 430, 421, 413, 404, 396, 388, 380, 372, 365, 357, 350, 343, 336, 330, 323, 317, 311, 305, 299, 293, 288, 282, 277, 272, 267, 262, 257, 252, 247, 243, 238, 234, 230, 226, 222, 218, 214, 210, 207, 203, 199, 196, 193, 189, 186, 183, 180, 177, 174, 171, 168, 165, 162, 160, 157, 155, 152, 150, 147, 145, 143, 140, 138, 136, 134, 132, 130, 128, 126, 124, 122, 120, 118, 116, 114, 113, 111, 109, 108, 106, 104, 103, 101, 100, 98, 97, 96, 94, 93, 92, 90, 89, 88, 86, 85, 84, 83, 82, 81, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 66, 65, 64, }; const uint16_t FLASHMEM lut_blowing_envelope[] = { 0, 178, 357, 536, 715, 894, 1073, 1252, 1431, 1610, 1789, 1968, 2147, 2326, 2505, 2684, 2863, 3042, 3221, 3400, 3579, 3758, 3937, 4116, 4295, 4474, 4653, 4832, 5011, 5190, 5369, 5548, 5727, 5906, 6085, 6264, 6443, 6622, 6801, 6980, 7159, 7338, 7517, 7696, 7875, 8054, 8233, 8412, 8591, 8770, 8949, 9128, 9307, 9486, 9665, 9844, 10023, 10202, 10381, 10560, 10739, 10918, 11097, 11276, 11455, 11634, 11813, 11991, 12170, 12349, 12528, 12707, 12886, 13065, 13244, 13423, 13602, 13781, 13960, 14139, 14318, 14497, 14676, 14855, 15034, 15213, 15392, 15571, 15750, 15929, 16108, 16287, 16466, 16645, 16824, 17003, 17182, 17361, 17540, 17719, 17898, 18077, 18256, 18435, 18614, 18793, 18972, 19151, 19330, 19509, 19688, 19867, 20046, 20225, 20404, 20583, 20762, 20941, 21120, 21299, 21299, 21281, 21263, 21245, 21227, 21210, 21192, 21174, 21156, 21138, 21120, 21103, 21085, 21067, 21049, 21031, 21014, 20996, 20978, 20960, 20942, 20924, 20907, 20889, 20871, 20853, 20835, 20817, 20800, 20782, 20764, 20746, 20728, 20711, 20693, 20675, 20657, 20639, 20621, 20604, 20586, 20568, 20550, 20532, 20514, 20497, 20479, 20461, 20443, 20425, 20408, 20390, 20372, 20354, 20336, 20318, 20301, 20283, 20265, 20247, 20229, 20211, 20194, 20176, 20158, 20140, 20122, 20105, 20087, 20069, 20051, 20033, 20015, 19998, 19980, 19962, 19944, 19926, 19908, 19891, 19873, 19855, 19837, 19819, 19802, 19784, 19766, 19748, 19730, 19712, 19695, 19677, 19659, 19641, 19623, 19605, 19588, 19570, 19552, 19534, 19516, 19499, 19481, 19463, 19445, 19427, 19409, 19392, 19374, 19356, 19338, 19320, 19302, 19285, 19267, 19249, 19231, 19213, 19196, 19178, 19160, 19142, 19124, 19106, 19089, 19071, 19053, 19035, 19017, 18999, 18982, 18964, 18946, 18928, 18910, 18893, 18875, 18857, 18839, 18821, 18803, 18786, 18768, 18750, 18732, 18714, 18696, 18679, 18661, 18643, 18625, 18607, 18590, 18572, 18554, 18536, 18518, 18500, 18483, 18465, 18447, 18429, 18411, 18393, 18376, 18358, 18340, 18322, 18304, 18287, 18269, 18251, 18233, 18215, 18197, 18180, 18162, 18144, 18126, 18108, 18090, 18073, 18055, 18037, 18019, 18001, 17984, 17966, 17948, 17930, 17912, 17894, 17877, 17859, 17841, 17823, 17805, 17787, 17770, 17752, 17734, 17716, 17698, 17681, 17663, 17645, 17627, 17609, 17591, 17574, 17556, 17538, 17520, 17502, 17484, 17467, 17449, 17431, 17413, 17395, 17378, 17360, 17342, 17324, 17306, 17288, 17271, 17253, 17235, 17217, 17199, 17181, 17164, 17146, 17128, 17110, 17092, 17075, 17057, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, 17039, }; const uint16_t FLASHMEM lut_flute_body_filter[] = { 30, 32, 34, 36, 38, 40, 43, 45, 48, 51, 54, 57, 60, 64, 68, 72, 76, 81, 86, 91, 96, 102, 108, 114, 121, 129, 136, 144, 153, 162, 172, 182, 193, 204, 216, 229, 243, 258, 273, 289, 306, 325, 344, 364, 386, 409, 433, 459, 487, 516, 546, 579, 613, 650, 688, 729, 773, 819, 867, 919, 974, 1032, 1093, 1158, 1227, 1300, 1377, 1459, 1546, 1638, 1735, 1839, 1948, 2064, 2187, 2317, 2454, 2600, 2755, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867, }; const uint16_t FLASHMEM lut_fm_frequency_quantizer[] = { 7168, 7168, 7168, 7360, 7552, 7744, 7936, 8128, 8320, 8512, 8704, 8896, 9088, 9280, 9472, 9664, 9856, 10048, 10240, 10240, 10240, 10432, 10624, 10816, 11008, 11200, 11392, 11584, 11776, 11968, 12160, 12352, 12544, 12736, 12928, 13312, 13312, 13312, 13352, 13352, 13352, 13726, 14100, 14474, 14848, 14848, 14848, 15080, 15313, 15313, 15313, 15581, 15848, 16116, 16384, 16384, 16384, 16424, 16424, 16424, 16798, 17172, 17546, 17920, 17920, 17920, 18152, 18385, 18385, 18385, 18624, 18864, 18864, 18864, 19160, 19456, 19456, 19456, 19496, 19496, 19496, 19737, 19978, 19978, 19978, 20200, 20422, 20645, 20867, 20867, 20867, 20992, 20992, 20992, 21253, 21253, 21253, 21457, 21457, 21457, 21673, 21890, 21890, 21890, 22209, 22528, 22528, 22528, 22789, 22789, 22789, 23021, 23254, 23254, 23254, 23516, 23516, 23516, 23790, 24064, 24064, 24064, 24448, 24832, 25216, 25600, 25600, 25600, 25600, }; const uint16_t FLASHMEM lut_vco_detune[] = { 10, 10, 10, 47, 116, 184, 252, 321, 389, 456, 524, 592, 659, 727, 794, 862, 929, 996, 1063, 1130, 1196, 1263, 1330, 1396, 1463, 1529, 1595, 1662, 1728, 1794, 1860, 1926, 1992, 2058, 2124, 2189, 2255, 2321, 2386, 2452, 2517, 2583, 2648, 2714, 2779, 2844, 2910, 2975, 3040, 3105, 3170, 3235, 3301, 3366, 3431, 3496, 3560, 3625, 3690, 3755, 3820, 3885, 3950, 4014, 4079, 4144, 4208, 4273, 4338, 4402, 4467, 4532, 4596, 4661, 4725, 4790, 4854, 4919, 4983, 5048, 5112, 5176, 5241, 5305, 5370, 5434, 5498, 5563, 5627, 5691, 5755, 5820, 5884, 5948, 6013, 6077, 6141, 6205, 6269, 6334, 6398, 6462, 6526, 6590, 6654, 6719, 6783, 6847, 6911, 6975, 7039, 7103, 7167, 7231, 7295, 7359, 7423, 7487, 7551, 7615, 7680, 7743, 7807, 7871, 7935, 7999, 8063, 8127, 8191, 8255, 8319, 8383, 8447, 8511, 8575, 8638, 8702, 8766, 8830, 8894, 8958, 9021, 9085, 9149, 9213, 9277, 9340, 9404, 9468, 9532, 9595, 9659, 9723, 9786, 9850, 9914, 9977, 10041, 10105, 10168, 10232, 10295, 10359, 10422, 10486, 10549, 10613, 10676, 10740, 10803, 10867, 10930, 10993, 11057, 11120, 11183, 11247, 11310, 11373, 11436, 11500, 11563, 11626, 11689, 11752, 11815, 11878, 11941, 12004, 12067, 12130, 12193, 12256, 12319, 12381, 12444, 12507, 12570, 12632, 12695, 12757, 12820, 12882, 12945, 13007, 13069, 13132, 13194, 13256, 13318, 13380, 13442, 13504, 13566, 13628, 13690, 13752, 13813, 13875, 13936, 13998, 14059, 14120, 14182, 14243, 14304, 14365, 14426, 14487, 14547, 14608, 14668, 14729, 14789, 14849, 14910, 14970, 15030, 15089, 15149, 15209, 15268, 15327, 15387, 15446, 15505, 15564, 15622, 15681, 15739, 15797, 15855, 15913, 15971, 16029, 16086, 16143, }; const uint16_t FLASHMEM lut_bell[] = { 0, 670, 2655, 5873, 10191, 15434, 21387, 27805, 34427, 40980, 47198, 52824, 57630, 61417, 64032, 65366, 65534, 65528, 65517, 65500, 65477, 65449, 65415, 65376, 65331, 65280, 65224, 65162, 65095, 65022, 64944, 64860, 64770, 64675, 64574, 64468, 64357, 64240, 64118, 63990, 63857, 63718, 63575, 63426, 63271, 63112, 62947, 62777, 62602, 62421, 62236, 62046, 61850, 61650, 61444, 61234, 61018, 60798, 60573, 60343, 60109, 59870, 59626, 59377, 59124, 58866, 58604, 58338, 58067, 57791, 57512, 57228, 56940, 56648, 56351, 56051, 55746, 55438, 55126, 54810, 54490, 54166, 53839, 53508, 53173, 52835, 52494, 52149, 51801, 51449, 51094, 50736, 50375, 50011, 49645, 49275, 48902, 48526, 48148, 47767, 47384, 46998, 46610, 46219, 45826, 45431, 45033, 44633, 44232, 43828, 43423, 43015, 42606, 42195, 41783, 41369, 40953, 40537, 40118, 39699, 39278, 38856, 38433, 38010, 37585, 37159, 36733, 36306, 35879, 35450, 35022, 34593, 34163, 33734, 33304, 32874, 32445, 32015, 31585, 31156, 30727, 30298, 29869, 29442, 29014, 28588, 28162, 27737, 27312, 26889, 26467, 26045, 25625, 25206, 24789, 24373, 23958, 23545, 23133, 22723, 22315, 21908, 21504, 21101, 20700, 20302, 19905, 19511, 19119, 18730, 18343, 17958, 17576, 17196, 16819, 16445, 16074, 15706, 15340, 14978, 14618, 14262, 13909, 13559, 13212, 12869, 12529, 12193, 11860, 11531, 11206, 10884, 10566, 10252, 9941, 9635, 9332, 9034, 8740, 8450, 8164, 7882, 7604, 7331, 7062, 6798, 6538, 6283, 6032, 5786, 5544, 5307, 5075, 4848, 4625, 4407, 4195, 3987, 3784, 3586, 3393, 3205, 3022, 2844, 2671, 2504, 2342, 2185, 2033, 1887, 1746, 1610, 1479, 1354, 1235, 1121, 1012, 909, 811, 719, 632, 550, 475, 405, 340, 281, 228, 180, 138, 101, 70, 45, 25, 11, 2, 0, 0, }; const uint16_t FLASHMEM lut_env_expo[] = { 0, 1034, 2053, 3057, 4044, 5016, 5974, 6916, 7844, 8757, 9656, 10542, 11413, 12271, 13116, 13948, 14766, 15572, 16366, 17147, 17916, 18673, 19419, 20153, 20875, 21587, 22287, 22976, 23655, 24323, 24981, 25629, 26267, 26894, 27512, 28121, 28720, 29310, 29890, 30462, 31024, 31578, 32124, 32661, 33189, 33710, 34222, 34727, 35223, 35712, 36193, 36667, 37134, 37593, 38045, 38490, 38928, 39360, 39785, 40203, 40615, 41020, 41419, 41812, 42198, 42579, 42954, 43323, 43686, 44044, 44396, 44743, 45084, 45420, 45751, 46077, 46397, 46713, 47024, 47330, 47631, 47927, 48219, 48507, 48790, 49068, 49342, 49612, 49878, 50140, 50398, 50651, 50901, 51147, 51389, 51627, 51862, 52092, 52320, 52544, 52764, 52981, 53195, 53405, 53612, 53816, 54016, 54214, 54408, 54600, 54788, 54974, 55156, 55336, 55513, 55688, 55859, 56028, 56195, 56358, 56520, 56678, 56835, 56988, 57140, 57289, 57436, 57580, 57723, 57863, 58001, 58136, 58270, 58402, 58531, 58659, 58784, 58908, 59029, 59149, 59267, 59383, 59498, 59610, 59721, 59830, 59937, 60043, 60147, 60250, 60351, 60450, 60548, 60644, 60739, 60832, 60924, 61014, 61103, 61191, 61277, 61362, 61446, 61528, 61609, 61689, 61768, 61845, 61921, 61996, 62070, 62143, 62214, 62285, 62354, 62422, 62490, 62556, 62621, 62685, 62748, 62810, 62871, 62932, 62991, 63049, 63107, 63163, 63219, 63274, 63328, 63381, 63434, 63485, 63536, 63586, 63635, 63683, 63731, 63778, 63824, 63870, 63914, 63958, 64002, 64045, 64087, 64128, 64169, 64209, 64248, 64287, 64326, 64363, 64400, 64437, 64473, 64508, 64543, 64577, 64611, 64645, 64677, 64710, 64741, 64773, 64803, 64834, 64863, 64893, 64922, 64950, 64978, 65006, 65033, 65060, 65086, 65112, 65137, 65162, 65187, 65212, 65236, 65259, 65282, 65305, 65328, 65350, 65372, 65393, 65414, 65435, 65456, 65476, 65496, 65515, 65535, }; const uint16_t* lookup_table_table[] = { lut_resonator_coefficient, lut_resonator_scale, lut_svf_cutoff, lut_svf_damp, lut_svf_scale, lut_granular_envelope, lut_granular_envelope_rate, lut_bowing_envelope, lut_bowing_friction, lut_blowing_envelope, lut_flute_body_filter, lut_fm_frequency_quantizer, lut_vco_detune, lut_bell, lut_env_expo, }; const int16_t FLASHMEM lut_blowing_jet[] = { 0, -255, -511, -767, -1022, -1278, -1532, -1786, -2039, -2292, -2544, -2795, -3044, -3293, -3541, -3787, -4031, -4275, -4516, -4756, -4994, -5231, -5465, -5697, -5927, -6155, -6381, -6604, -6824, -7042, -7257, -7470, -7679, -7886, -8089, -8289, -8486, -8680, -8870, -9056, -9239, -9418, -9594, -9765, -9932, -10095, -10254, -10409, -10559, -10705, -10846, -10982, -11114, -11241, -11363, -11480, -11591, -11698, -11799, -11894, -11984, -12069, -12147, -12220, -12287, -12348, -12403, -12452, -12494, -12530, -12560, -12583, -12599, -12609, -12611, -12607, -12596, -12578, -12552, -12519, -12479, -12431, -12376, -12313, -12242, -12163, -12077, -11982, -11879, -11768, -11649, -11521, -11384, -11239, -11085, -10923, -10751, -10571, -10381, -10182, -9974, -9757, -9530, -9293, -9047, -8791, -8526, -8250, -7964, -7668, -7362, -7046, -6719, -6382, -6034, -5676, -5306, -4926, -4535, -4133, -3719, -3295, -2859, -2411, -1952, -1482, -1000, -506, 0, 517, 1048, 1590, 2144, 2711, 3291, 3883, 4487, 5105, 5735, 6378, 7034, 7704, 8386, 9082, 9791, 10514, 11250, 12000, 12764, 13542, 14333, 15139, 15959, 16793, 17642, 18504, 19382, 20274, 21181, 22102, 23039, 23990, 24957, 25939, 26936, 27948, 28976, 30019, 31079, 32153, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, }; const int16_t* lookup_table_signed_table[] = { lut_blowing_jet, }; const uint32_t FLASHMEM lut_oscillator_increments[] = { 594573364, 598881888, 603221633, 607592826, 611995694, 616430467, 620897376, 625396654, 629928536, 634493258, 639091058, 643722175, 648386851, 653085330, 657817855, 662584675, 667386036, 672222191, 677093390, 681999888, 686941940, 691919804, 696933740, 701984010, 707070875, 712194602, 717355458, 722553711, 727789633, 733063497, 738375577, 743726151, 749115497, 754543897, 760011633, 765518991, 771066257, 776653721, 782281674, 787950409, 793660223, 799411412, 805204277, 811039119, 816916243, 822835954, 828798563, 834804379, 840853716, 846946888, 853084215, 859266014, 865492610, 871764326, 878081490, 884444431, 890853479, 897308971, 903811242, 910360631, 916957479, 923602131, 930294933, 937036233, 943826384, 950665739, 957554655, 964493491, 971482608, 978522372, 985613148, 992755307, 999949221, 1007195266, 1014493818, 1021845258, 1029249970, 1036708340, 1044220756, 1051787610, 1059409296, 1067086213, 1074818759, 1082607339, 1090452358, 1098354226, 1106313353, 1114330156, 1122405051, 1130538461, 1138730809, 1146982522, 1155294030, 1163665767, 1172098168, 1180591675, 1189146729, }; const uint32_t FLASHMEM lut_oscillator_delays[] = { 1939073583, 1925123345, 1911273470, 1897523234, 1883871922, 1870318821, 1856863224, 1843504431, 1830241745, 1817074474, 1804001933, 1791023438, 1778138315, 1765345891, 1752645499, 1740036478, 1727518169, 1715089920, 1702751084, 1690501017, 1678339080, 1666264640, 1654277066, 1642375735, 1630560024, 1618829320, 1607183009, 1595620485, 1584141146, 1572744391, 1561429629, 1550196268, 1539043722, 1527971412, 1516978758, 1506065189, 1495230135, 1484473032, 1473793318, 1463190437, 1452663836, 1442212966, 1431837283, 1421536245, 1411309316, 1401155962, 1391075655, 1381067868, 1371132079, 1361267772, 1351474431, 1341751546, 1332098611, 1322515121, 1313000577, 1303554484, 1294176349, 1284865683, 1275622000, 1266444818, 1257333660, 1248288051, 1239307518, 1230391593, 1221539812, 1212751713, 1204026838, 1195364733, 1186764945, 1178227026, 1169750531, 1161335019, 1152980050, 1144685189, 1136450004, 1128274065, 1120156946, 1112098224, 1104097479, 1096154293, 1088268252, 1080438946, 1072665967, 1064948908, 1057287368, 1049680947, 1042129249, 1034631880, 1027188449, 1019798568, 1012461852, 1005177918, 997946388, 990766882, 983639028, 976562454, 969536791, }; const uint32_t FLASHMEM lut_env_portamento_increments[] = { 1431655765, 1208633567, 1025339217, 873854034, 747996982, 642910145, 554750639, 480459775, 417588783, 364166300, 318596895, 279582889, 246063710, 217168604, 192179528, 170501890, 151641346, 135185326, 120788231, 108159539, 97054201, 87264844, 78615425, 70956050, 64158714, 58113796, 52727166, 47917783, 43615697, 39760385, 36299356, 33186980, 30383504, 27854220, 25568762, 23500507, 21626072, 19924877, 18378778, 16971748, 15689604, 14519780, 13451115, 12473688, 11578663, 10758156, 10005128, 9313280, 8676970, 8091136, 7551232, 7053169, 6593263, 6168194, 5774964, 5410864, 5073442, 4760475, 4469950, 4200037, 3949073, 3715547, 3498079, 3295415, 3106409, 2930012, 2765269, 2611303, 2467313, 2332562, 2206377, 2088136, 1977272, 1873260, 1775618, 1683902, 1597702, 1516641, 1440370, 1368566, 1300932, 1237191, 1177088, 1120388, 1066869, 1016330, 968580, 923445, 880761, 840376, 802150, 765951, 731657, 699152, 668331, 639094, 611349, 585008, 559991, 536221, 513628, 492146, 471711, 452267, 433757, 416131, 399341, 383341, 368089, 353545, 339672, 326434, 313798, 301733, 290209, 279199, 268677, 258617, 248997, 239795, 230990, 222562, 214494, 206767, 199365, 192272, 185474, 178956, }; const uint32_t* lookup_table_hr_table[] = { lut_oscillator_increments, lut_oscillator_delays, lut_env_portamento_increments, }; const int16_t FLASHMEM wav_formant_sine[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 3, 3, 4, 5, 6, 7, 8, 10, 12, 14, 17, 20, 24, 0, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31, 37, 45, 0, 4, 5, 6, 8, 9, 11, 13, 16, 19, 23, 28, 34, 40, 49, 58, 0, 5, 6, 7, 8, 10, 12, 15, 17, 21, 25, 30, 36, 44, 53, 63, 0, 4, 5, 6, 8, 9, 11, 13, 16, 19, 23, 28, 34, 40, 49, 58, 0, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31, 37, 45, 0, 2, 2, 3, 3, 4, 5, 6, 7, 8, 10, 12, 14, 17, 20, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -3, -3, -4, -5, -6, -7, -8, -10, -12, -14, -17, -20, -24, 0, -3, -4, -5, -6, -7, -9, -10, -12, -15, -18, -21, -26, -31, -37, -45, 0, -4, -5, -6, -8, -9, -11, -13, -16, -19, -23, -28, -34, -40, -49, -58, 0, -5, -6, -7, -8, -10, -12, -15, -17, -21, -25, -30, -36, -44, -53, -63, 0, -4, -5, -6, -8, -9, -11, -13, -16, -19, -23, -28, -34, -40, -49, -58, 0, -3, -4, -5, -6, -7, -9, -10, -12, -15, -18, -21, -26, -31, -37, -45, 0, -2, -2, -3, -3, -4, -5, -6, -7, -8, -10, -12, -14, -17, -20, -24, }; const int16_t FLASHMEM wav_formant_square[] = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 8, 9, 11, 13, 16, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 8, 9, 11, 13, 16, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 8, 9, 11, 13, 16, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 8, 9, 11, 13, 16, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 8, 9, 11, 13, 16, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 8, 9, 11, 13, 16, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 8, 9, 11, 13, 16, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 8, 9, 11, 13, 16, 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -6, -8, -9, -11, -13, -16, 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -6, -8, -9, -11, -13, -16, 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -6, -8, -9, -11, -13, -16, 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -6, -8, -9, -11, -13, -16, 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -6, -8, -9, -11, -13, -16, 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -6, -8, -9, -11, -13, -16, 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -6, -8, -9, -11, -13, -16, 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -6, -8, -9, -11, -13, -16, }; const int16_t FLASHMEM wav_sine[] = { -32512, -32502, -32473, -32423, -32356, -32265, -32160, -32031, -31885, -31719, -31533, -31331, -31106, -30864, -30605, -30324, -30028, -29712, -29379, -29026, -28658, -28272, -27868, -27449, -27011, -26558, -26089, -25604, -25103, -24588, -24056, -23512, -22953, -22378, -21793, -21191, -20579, -19954, -19316, -18667, -18006, -17334, -16654, -15960, -15259, -14548, -13828, -13100, -12363, -11620, -10868, -10112, -9347, -8578, -7805, -7023, -6241, -5453, -4662, -3868, -3073, -2274, -1474, -674, 126, 929, 1729, 2527, 3326, 4123, 4916, 5707, 6495, 7278, 8057, 8833, 9601, 10366, 11122, 11874, 12618, 13353, 14082, 14802, 15512, 16216, 16906, 17589, 18260, 18922, 19569, 20207, 20834, 21446, 22045, 22634, 23206, 23765, 24311, 24842, 25357, 25858, 26343, 26812, 27266, 27701, 28123, 28526, 28912, 29281, 29632, 29966, 30281, 30579, 30859, 31118, 31361, 31583, 31788, 31973, 32139, 32286, 32412, 32521, 32608, 32679, 32725, 32757, 32766, 32757, 32725, 32679, 32608, 32521, 32412, 32286, 32139, 31973, 31788, 31583, 31361, 31118, 30859, 30579, 30281, 29966, 29632, 29281, 28912, 28526, 28123, 27701, 27266, 26812, 26343, 25858, 25357, 24842, 24311, 23765, 23206, 22634, 22045, 21446, 20834, 20207, 19569, 18922, 18260, 17589, 16906, 16216, 15512, 14802, 14082, 13353, 12618, 11874, 11122, 10366, 9601, 8833, 8057, 7278, 6495, 5707, 4916, 4123, 3326, 2527, 1729, 929, 126, -674, -1474, -2274, -3073, -3868, -4662, -5453, -6241, -7023, -7805, -8578, -9347, -10112, -10868, -11620, -12363, -13100, -13828, -14548, -15259, -15960, -16654, -17334, -18006, -18667, -19316, -19954, -20579, -21191, -21793, -22378, -22953, -23512, -24056, -24588, -25103, -25604, -26089, -26558, -27011, -27449, -27868, -28272, -28658, -29026, -29379, -29712, -30028, -30324, -30605, -30864, -31106, -31331, -31533, -31719, -31885, -32031, -32160, -32265, -32356, -32423, -32473, -32502, -32512, }; const int16_t FLASHMEM wav_bandlimited_comb_0[] = { -142, -146, -143, -139, -129, -125, -122, -125, -133, -142, -146, -146, -141, -133, -124, -120, -123, -129, -140, -147, -149, -145, -136, -125, -117, -119, -126, -136, -148, -154, -150, -139, -127, -115, -113, -119, -133, -148, -159, -158, -147, -129, -112, -103, -108, -126, -148, -168, -175, -161, -136, -104, -82, -80, -105, -150, -196, -226, -220, -164, -65, 60, 180, 270, 32765, 271, 180, 59, -65, -163, -220, -227, -196, -149, -106, -79, -83, -104, -135, -162, -174, -168, -150, -124, -109, -102, -113, -128, -147, -159, -158, -149, -132, -120, -113, -114, -127, -140, -150, -153, -148, -138, -124, -119, -118, -125, -135, -145, -150, -147, -139, -130, -122, -121, -124, -132, -141, -147, -146, -141, -133, -126, -122, -124, -130, -138, -144, -145, -143, -135, -128, -124, -125, -128, -135, -142, -145, -142, -137, -131, -126, -125, -126, -135, -138, -144, -143, -139, -133, -127, -125, -127, -131, -138, -142, -142, -141, -135, -128, -127, -126, -130, -135, -141, -143, -141, -136, -131, -127, -126, -128, -135, -139, -141, -143, -137, -133, -128, -126, -128, -132, -137, -142, -142, -139, -135, -128, -127, -128, -129, -137, -140, -143, -139, -137, -130, -127, -127, -129, -134, -140, -142, -140, -139, -131, -129, -125, -129, -132, -138, -142, -142, -138, -135, -129, -125, -128, -130, -137, -140, -144, -140, -135, -131, -126, -125, -130, -135, -140, -142, -143, -137, -131, -128, -124, -128, -132, -140, -143, -142, -140, -134, -127, -125, -125, -131, -137, -143, -144, -142, -136, -128, -124, -124, -129, -135, -142, }; const int16_t FLASHMEM wav_bandlimited_comb_1[] = { -150, -157, -152, -144, -132, -121, -119, -125, -135, -149, -157, -157, -149, -135, -123, -114, -120, -131, -146, -158, -162, -156, -139, -123, -112, -113, -124, -142, -160, -167, -164, -147, -125, -108, -104, -113, -136, -161, -177, -175, -159, -129, -102, -89, -96, -124, -161, -192, -201, -182, -140, -89, -55, -53, -92, -161, -237, -285, -272, -185, -29, 170, 362, 503, 32766, 503, 362, 170, -28, -186, -272, -285, -237, -161, -92, -52, -56, -89, -140, -182, -201, -192, -160, -125, -96, -89, -101, -130, -159, -175, -177, -161, -135, -115, -102, -109, -125, -147, -163, -168, -160, -142, -124, -113, -111, -124, -140, -154, -163, -158, -146, -131, -119, -116, -122, -134, -150, -156, -158, -149, -136, -123, -120, -121, -132, -143, -154, -155, -151, -140, -128, -122, -121, -130, -139, -150, -154, -151, -144, -131, -125, -122, -128, -136, -146, -153, -151, -145, -136, -128, -122, -127, -133, -143, -151, -151, -147, -139, -130, -124, -126, -131, -140, -148, -152, -148, -141, -132, -127, -125, -130, -136, -146, -151, -149, -144, -135, -128, -125, -128, -135, -143, -149, -150, -146, -138, -130, -125, -127, -133, -139, -149, -150, -147, -142, -131, -127, -125, -131, -137, -147, -149, -150, -143, -134, -128, -126, -127, -136, -143, -150, -150, -146, -137, -130, -124, -127, -132, -142, -148, -151, -149, -139, -132, -125, -124, -131, -138, -147, -152, -150, -143, -134, -126, -123, -128, -135, -145, -152, -152, -147, -136, -127, -122, -125, -132, -143, -152, -153, -150, -140, -129, -122, -121, -129, -140, -150, }; const int16_t FLASHMEM wav_bandlimited_comb_2[] = { -159, -164, -128, -110, -139, -167, -154, -114, -116, -153, -171, -138, -105, -127, -170, -163, -119, -105, -147, -176, -149, -104, -114, -165, -178, -127, -94, -134, -183, -164, -104, -97, -159, -193, -140, -83, -115, -187, -188, -108, -72, -146, -214, -164, -70, -79, -192, -228, -120, -29, -114, -254, -220, -41, 3, -194, -342, -165, 119, 24, -441, -578, 190, 1453, 32767, 1453, 191, -579, -442, 26, 118, -165, -341, -195, 3, -41, -220, -254, -114, -29, -120, -227, -193, -80, -68, -165, -214, -145, -74, -107, -187, -188, -115, -82, -142, -191, -160, -97, -103, -165, -184, -132, -95, -128, -176, -166, -114, -104, -148, -178, -145, -106, -118, -165, -168, -128, -106, -137, -170, -154, -116, -114, -153, -169, -137, -111, -128, -164, -159, -123, -115, -143, -166, -146, -116, -122, -157, -161, -133, -114, -135, -163, -152, -122, -119, -149, -161, -141, -117, -129, -157, -156, -130, -117, -140, -162, -147, -120, -125, -150, -161, -134, -118, -135, -158, -152, -125, -121, -146, -159, -143, -119, -128, -155, -156, -131, -120, -138, -159, -148, -123, -125, -148, -159, -136, -121, -132, -157, -152, -128, -121, -143, -159, -144, -121, -127, -153, -157, -132, -120, -137, -158, -150, -123, -124, -147, -159, -140, -118, -132, -156, -154, -128, -121, -141, -160, -145, -121, -126, -152, -158, -134, -119, -134, -160, -151, -125, -120, -146, -162, -141, -117, -129, -157, -157, -129, -117, -139, -164, -147, -120, -121, -153, -162, -136, -114, -132, -163, -155, -122, -117, -145, -167, -144, -112, -125, -159, }; const int16_t FLASHMEM wav_bandlimited_comb_3[] = { -190, -184, -179, -172, -166, -156, -150, -143, -133, -128, -121, -114, -110, -106, -103, -102, -103, -102, -107, -111, -116, -124, -132, -141, -152, -161, -174, -185, -197, -206, -218, -226, -235, -241, -246, -249, -249, -248, -243, -238, -226, -217, -199, -185, -164, -143, -120, -93, -68, -40, -12, 17, 47, 73, 101, 128, 151, 176, 194, 213, 227, 239, 248, 253, 32767, 252, 248, 239, 228, 212, 195, 175, 151, 129, 100, 74, 46, 17, -11, -41, -67, -94, -120, -142, -165, -184, -200, -216, -228, -236, -243, -249, -248, -250, -245, -242, -235, -225, -219, -206, -197, -184, -174, -162, -152, -141, -131, -125, -116, -110, -107, -104, -101, -102, -104, -105, -111, -114, -121, -127, -134, -142, -150, -158, -164, -173, -178, -185, -189, -195, -197, -199, -200, -201, -199, -198, -193, -191, -186, -180, -175, -170, -161, -158, -150, -145, -139, -135, -131, -127, -124, -123, -123, -122, -123, -126, -127, -132, -134, -141, -145, -150, -155, -161, -167, -170, -177, -179, -184, -187, -189, -189, -192, -190, -189, -187, -186, -181, -178, -174, -168, -165, -158, -153, -150, -143, -141, -135, -132, -131, -127, -126, -128, -125, -129, -129, -133, -136, -139, -144, -149, -154, -159, -163, -169, -174, -178, -181, -185, -188, -189, -190, -192, -189, -189, -187, -183, -180, -177, -170, -167, -160, -156, -151, -144, -140, -135, -131, -129, -124, -124, -123, -121, -123, -125, -128, -129, -136, -139, -145, -150, -157, -163, -168, -176, -180, -186, -190, -195, -196, -200, -201, -200, -199, -197, -194, -190, }; const int16_t FLASHMEM wav_bandlimited_comb_4[] = { -201, -92, -117, -221, -162, -74, -164, -225, -112, -86, -211, -197, -73, -128, -236, -148, -61, -183, -232, -91, -84, -235, -191, -50, -140, -260, -125, -44, -211, -243, -57, -83, -272, -181, -12, -162, -296, -89, -15, -261, -261, 7, -84, -343, -160, 66, -212, -372, -7, 52, -383, -304, 173, -81, -563, -88, 341, -408, -711, 424, 462, -1367, -794, 3905, 32766, 3905, -795, -1366, 462, 423, -710, -408, 341, -89, -562, -81, 172, -303, -383, 51, -6, -372, -212, 66, -160, -344, -83, 6, -260, -261, -15, -90, -295, -162, -12, -181, -273, -83, -56, -243, -211, -44, -126, -259, -141, -48, -193, -234, -85, -90, -232, -183, -62, -146, -238, -127, -73, -198, -210, -86, -113, -224, -164, -75, -161, -220, -119, -91, -202, -191, -88, -130, -217, -151, -84, -172, -208, -111, -107, -202, -177, -92, -142, -211, -140, -93, -180, -197, -107, -118, -204, -165, -93, -155, -205, -129, -103, -187, -185, -105, -129, -203, -155, -96, -164, -200, -121, -111, -192, -176, -102, -140, -202, -144, -102, -171, -193, -116, -119, -195, -168, -100, -149, -201, -136, -104, -181, -186, -109, -128, -198, -159, -100, -158, -199, -126, -111, -186, -180, -104, -137, -200, -149, -101, -167, -196, -119, -115, -193, -172, -101, -144, -203, -139, -103, -176, -191, -111, -122, -199, -164, -97, -154, -203, -130, -104, -186, -187, -101, -131, -205, -154, -94, -164, -204, -119, -106, -198, -179, -94, -139, -211, -143, -91, -177, -203, -106, -111, -209, -171, -85, -150, -218, -129, -88, -193, -200, }; const int16_t FLASHMEM wav_bandlimited_comb_5[] = { 0, -130, -195, -104, 21, 14, -125, -204, -116, 24, 26, -117, -214, -130, 25, 42, -108, -225, -147, 26, 61, -98, -237, -168, 28, 83, -84, -254, -191, 28, 111, -68, -273, -222, 29, 146, -45, -299, -263, 29, 195, -14, -333, -325, 31, 266, 35, -387, -421, 31, 387, 118, -484, -599, 31, 636, 304, -714, -1072, 31, 1501, 1103, -2083, -6238, 32766, -6238, -2084, 1105, 1500, 31, -1072, -715, 305, 636, 32, -601, -483, 119, 385, 32, -421, -386, 34, 266, 30, -324, -333, -14, 195, 29, -263, -299, -45, 146, 29, -222, -273, -68, 111, 28, -191, -254, -84, 83, 27, -166, -239, -97, 61, 26, -147, -225, -108, 42, 25, -130, -214, -117, 26, 24, -116, -204, -125, 13, 23, -105, -195, -130, 0, 20, -93, -187, -135, -11, 18, -83, -180, -139, -21, 15, -74, -172, -143, -32, 15, -67, -165, -147, -40, 12, -60, -157, -150, -49, 10, -54, -150, -152, -58, 8, -47, -145, -154, -64, 3, -40, -138, -157, -71, 1, -35, -133, -156, -80, -2, -30, -125, -159, -86, -5, -26, -119, -159, -93, -9, -21, -112, -160, -99, -14, -16, -106, -160, -106, -17, -12, -100, -160, -112, -21, -9, -93, -160, -118, -25, -7, -85, -159, -124, -32, -1, -79, -158, -132, -35, 2, -73, -156, -138, -40, 3, -64, -154, -145, -47, 7, -56, -153, -151, -52, 8, -47, -151, -157, -60, 11, -39, -147, -165, -67, 15, -32, -143, -172, -74, 15, -21, -139, -180, -83, 18, -11, -135, -187, -94, 21, 0, }; const int16_t FLASHMEM wav_bandlimited_comb_6[] = { 0, -260, 12, -272, 24, -285, 38, -298, 50, -310, 62, -322, 74, -334, 85, -344, 96, -356, 108, -368, 120, -380, 131, -390, 142, -401, 151, -410, 161, -419, 169, -428, 180, -439, 189, -447, 196, -453, 203, -461, 211, -469, 218, -475, 225, -482, 230, -486, 234, -491, 240, -496, 244, -500, 247, -502, 250, -505, 251, -506, 253, -507, 253, -507, 32765, -507, 253, -507, 252, -505, 251, -505, 250, -502, 246, -498, 242, -494, 238, -490, 234, -486, 229, -480, 224, -476, 219, -469, 211, -461, 203, -453, 195, -446, 189, -439, 181, -430, 170, -419, 161, -411, 152, -400, 140, -389, 131, -380, 120, -369, 110, -358, 98, -346, 86, -334, 74, -322, 61, -308, 48, -296, 36, -284, 24, -273, 14, -262, 1, -248, -12, -236, -24, -224, -36, -212, -48, -200, -61, -186, -74, -174, -86, -162, -98, -150, -110, -139, -120, -128, -131, -119, -140, -108, -152, -97, -161, -89, -170, -78, -181, -69, -189, -62, -195, -55, -203, -47, -211, -39, -219, -32, -224, -28, -229, -22, -234, -18, -238, -14, -242, -10, -246, -6, -250, -3, -251, -3, -252, -1, -253, -1, -253, -1, -253, -1, -253, -2, -251, -3, -250, -6, -247, -8, -244, -12, -240, -17, -234, -22, -230, -26, -225, -33, -218, -39, -211, -47, -203, -55, -196, -61, -189, -69, -180, -80, -169, -89, -161, -98, -151, -107, -142, -118, -131, -128, -120, -140, -108, -152, -96, -164, -85, -174, -74, -186, -62, -198, -50, -210, -38, -223, -24, -236, -12, -248, 0, }; const int16_t FLASHMEM wav_bandlimited_comb_7[] = { 0, -101, -495, -60, -22, -500, -136, 49, -484, -223, 106, -442, -317, 142, -375, -412, 155, -288, -501, 141, -184, -574, 94, -66, -628, 18, 57, -656, -87, 177, -648, -222, 287, -602, -378, 375, -512, -553, 433, -374, -740, 450, -183, -932, 414, 63, -1119, 310, 374, -1294, 114, 772, -1448, -222, 1310, -1578, -801, 2133, -1672, -2002, 3876, -1734, -6442, 14783, 32766, 14782, -6443, -1732, 3875, -2001, -1674, 2135, -802, -1577, 1308, -220, -1449, 773, 112, -1292, 373, 310, -1118, 62, 414, -931, -184, 450, -740, -374, 434, -555, -510, 374, -378, -601, 285, -220, -649, 177, -87, -655, 56, 19, -629, -66, 94, -574, -183, 139, -499, -289, 156, -413, -375, 142, -317, -441, 105, -223, -483, 47, -134, -500, -24, -59, -494, -102, 0, -466, -183, 40, -422, -257, 57, -361, -327, 57, -294, -380, 34, -223, -418, -3, -155, -437, -55, -92, -439, -115, -42, -420, -180, -6, -387, -243, 14, -341, -301, 16, -285, -350, 3, -226, -387, -25, -166, -408, -68, -110, -411, -121, -62, -400, -177, -27, -373, -235, -5, -333, -291, 3, -286, -336, -8, -230, -374, -31, -174, -396, -70, -118, -405, -117, -71, -396, -173, -33, -373, -229, -9, -336, -285, 1, -289, -334, -5, -234, -374, -27, -176, -401, -62, -120, -412, -110, -68, -408, -165, -26, -387, -226, 4, -351, -286, 18, -302, -341, 15, -244, -387, -6, -179, -421, -42, -115, -438, -93, -55, -436, -156, -3, -418, -223, 34, -379, -295, 57, -326, -363, 59, -258, -422, 40, -182, -467, 0, }; const int16_t FLASHMEM wav_bandlimited_comb_8[] = { -640, -727, -239, 149, -114, -674, -747, -215, 185, -116, -715, -769, -188, 228, -118, -761, -800, -155, 282, -120, -820, -836, -115, 349, -122, -894, -881, -65, 433, -123, -988, -942, 2, 543, -123, -1115, -1025, 92, 697, -123, -1295, -1144, 223, 925, -124, -1569, -1329, 429, 1296, -125, -2036, -1659, 807, 2004, -126, -3025, -2397, 1722, 3890, -126, -6482, -5603, 7218, 24634, 32766, 24634, 7218, -5602, -6483, -126, 3889, 1724, -2399, -3023, -127, 2004, 807, -1658, -2037, -125, 1296, 429, -1329, -1569, -124, 925, 223, -1143, -1296, -124, 698, 93, -1026, -1115, -123, 543, 3, -943, -988, -123, 432, -63, -882, -894, -121, 347, -114, -836, -820, -120, 282, -155, -799, -762, -118, 228, -187, -771, -714, -116, 186, -216, -747, -674, -114, 149, -239, -727, -639, -113, 118, -259, -711, -611, -109, 92, -278, -697, -585, -107, 70, -295, -686, -561, -105, 50, -309, -676, -542, -101, 32, -323, -667, -524, -97, 16, -336, -661, -506, -93, 1, -347, -656, -490, -91, -9, -360, -650, -477, -85, -22, -370, -647, -464, -80, -30, -384, -643, -451, -74, -41, -394, -641, -439, -69, -48, -405, -640, -428, -62, -56, -416, -640, -416, -56, -62, -428, -640, -404, -49, -70, -438, -641, -394, -40, -76, -450, -643, -383, -31, -81, -463, -646, -372, -21, -84, -478, -650, -360, -10, -89, -492, -654, -349, 3, -94, -506, -661, -336, 16, -97, -524, -667, -323, 32, -101, -542, -676, -309, 50, -105, -561, -686, -295, 70, -107, -585, -697, -278, 92, -109, -611, -711, -259, 118, -112, -640, }; const int16_t FLASHMEM wav_bandlimited_comb_9[] = { 0, -521, -1050, -1263, -1024, -465, 82, 279, 1, -602, -1168, -1350, -1024, -374, 216, 378, -1, -706, -1320, -1462, -1024, -252, 391, 508, 0, -848, -1529, -1615, -1025, -83, 643, 694, 1, -1056, -1839, -1848, -1023, 177, 1038, 994, -1, -1398, -2363, -2246, -1025, 651, 1768, 1559, 1, -2094, -3463, -3124, -1024, 1791, 3640, 3114, 0, -4354, -7452, -6767, -1024, 8955, 20343, 29349, 32765, 29349, 20344, 8954, -1024, -6766, -7453, -4354, 0, 3115, 3639, 1791, -1024, -3124, -3462, -2094, -1, 1561, 1767, 651, -1024, -2248, -2361, -1399, 0, 993, 1038, 178, -1024, -1848, -1839, -1055, 0, 694, 643, -83, -1024, -1616, -1529, -848, 1, 507, 392, -253, -1024, -1462, -1319, -708, 1, 378, 214, -373, -1023, -1351, -1167, -603, 0, 281, 81, -464, -1025, -1263, -1049, -522, 0, 204, -25, -538, -1024, -1193, -955, -453, -1, 140, -113, -598, -1024, -1136, -872, -398, -1, 86, -187, -652, -1024, -1084, -803, -348, -1, 38, -254, -697, -1025, -1039, -739, -305, 0, -6, -314, -739, -1024, -999, -681, -264, -1, -44, -371, -778, -1024, -961, -626, -227, 1, -84, -422, -816, -1024, -923, -576, -189, -1, -118, -474, -853, -1023, -887, -525, -154, -1, -154, -524, -888, -1023, -852, -475, -118, 0, -191, -574, -924, -1024, -815, -423, -83, 0, -227, -626, -961, -1023, -779, -371, -44, 0, -265, -681, -999, -1023, -740, -314, -6, 1, -306, -739, -1039, -1024, -698, -254, 38, 0, -349, -802, -1085, -1025, -650, -187, 84, 1, -398, -874, -1134, -1025, -598, -113, 140, 0, -454, -954, -1194, -1024, -538, -24, 203, 0, }; const int16_t FLASHMEM wav_bandlimited_comb_10[] = { 0, -492, -1080, -1617, -1967, -2040, -1807, -1322, -691, -79, 371, 533, 359, -114, -784, -1487, -2044, -2316, -2219, -1765, -1053, -252, 439, 843, 844, 423, -334, -1250, -2106, -2679, -2811, -2442, -1639, -575, 491, 1293, 1610, 1325, 467, -785, -2150, -3284, -3882, -3741, -2828, -1296, 526, 2207, 3300, 3446, 2485, 496, -2177, -4961, -7173, -8126, -7279, -4364, 544, 7005, 14274, 21393, 27381, 31367, 32767, 31367, 27381, 21394, 14273, 7005, 545, -4365, -7279, -8126, -7172, -4963, -2175, 495, 2485, 3447, 3298, 2208, 527, -1297, -2828, -3740, -3883, -3284, -2149, -787, 469, 1324, 1610, 1293, 492, -576, -1639, -2442, -2810, -2680, -2106, -1250, -334, 424, 843, 843, 439, -252, -1053, -1765, -2218, -2316, -2046, -1485, -785, -115, 361, 533, 369, -77, -692, -1321, -1808, -2040, -1968, -1615, -1081, -492, 1, 279, 285, 18, -447, -992, -1486, -1802, -1874, -1684, -1287, -781, -294, 53, 183, 62, -271, -736, -1212, -1584, -1765, -1707, -1435, -1012, -550, -158, 64, 68, -147, -527, -972, -1376, -1639, -1695, -1538, -1202, -776, -365, -69, 41, -65, -354, -756, -1173, -1496, -1655, -1601, -1359, -982, -567, -218, -16, -17, -212, -561, -970, -1341, -1583, -1634, -1485, -1169, -769, -381, -102, 1, -102, -381, -768, -1170, -1485, -1634, -1582, -1342, -970, -560, -214, -15, -18, -216, -568, -982, -1358, -1602, -1654, -1498, -1171, -757, -354, -64, 39, -67, -366, -776, -1202, -1537, -1697, -1637, -1377, -972, -526, -148, 68, 65, -159, -550, -1012, -1435, -1707, -1764, -1585, -1212, -736, -271, 62, 183, 54, -295, -781, -1286, -1685, -1874, -1802, -1485, -994, -446, 19, 284, 280, 0, }; const int16_t FLASHMEM wav_bandlimited_comb_11[] = { 0, -465, -1027, -1635, -2234, -2768, -3185, -3439, -3506, -3375, -3045, -2548, -1922, -1222, -513, 144, 677, 1040, 1185, 1096, 768, 223, -497, -1330, -2206, -3042, -3759, -4284, -4553, -4537, -4211, -3596, -2730, -1681, -535, 609, 1637, 2450, 2955, 3078, 2784, 2057, 936, -514, -2189, -3958, -5661, -7140, -8230, -8778, -8665, -7805, -6147, -3711, -543, 3233, 7471, 11973, 16521, 20884, 24832, 28154, 30667, 32235, 32765, 32234, 30668, 28153, 24833, 20883, 16522, 11972, 7471, 3235, -546, -3708, -6149, -7804, -8666, -8778, -8229, -7140, -5662, -3957, -2189, -515, 936, 2058, 2783, 3079, 2954, 2451, 1637, 608, -534, -1681, -2731, -3595, -4213, -4534, -4555, -4283, -3760, -3041, -2207, -1329, -498, 224, 767, 1096, 1186, 1040, 677, 143, -512, -1223, -1921, -2549, -3045, -3373, -3508, -3439, -3184, -2768, -2235, -1634, -1028, -464, -1, 329, 491, 482, 300, -30, -476, -996, -1539, -2054, -2496, -2826, -3014, -3046, -2924, -2658, -2277, -1819, -1325, -845, -416, -85, 125, 193, 116, -97, -425, -836, -1291, -1748, -2164, -2502, -2731, -2829, -2794, -2623, -2340, -1966, -1541, -1103, -693, -347, -101, 29, 27, -105, -351, -692, -1094, -1519, -1926, -2282, -2548, -2706, -2738, -2640, -2426, -2112, -1731, -1314, -906, -537, -249, -64, 0, -63, -249, -538, -905, -1315, -1730, -2113, -2425, -2641, -2737, -2706, -2549, -2281, -1927, -1518, -1094, -693, -351, -104, 26, 29, -99, -349, -692, -1103, -1542, -1966, -2339, -2624, -2793, -2830, -2730, -2503, -2163, -1748, -1292, -836, -424, -97, 115, 194, 124, -84, -417, -844, -1325, -1820, -2276, -2659, -2923, -3047, -3013, -2826, -2497, -2054, -1538, -996, -477, -30, 301, 481, 492, 328, 0, }; const int16_t FLASHMEM wav_bandlimited_comb_12[] = { 0, -449, -979, -1569, -2199, -2835, -3457, -4036, -4543, -4957, -5256, -5424, -5448, -5325, -5052, -4639, -4096, -3442, -2703, -1903, -1081, -263, 507, 1203, 1783, 2222, 2496, 2578, 2462, 2138, 1613, 892, 1, -1039, -2188, -3405, -4648, -5859, -6991, -7989, -8798, -9374, -9669, -9645, -9277, -8542, -7429, -5944, -4096, -1911, 578, 3319, 6267, 9351, 12509, 15664, 18744, 21676, 24384, 26806, 28877, 30544, 31768, 32514, 32767, 32515, 31768, 30544, 28877, 26805, 24385, 21676, 18744, 15664, 12508, 9352, 6266, 3321, 576, -1911, -4095, -5944, -7429, -8542, -9277, -9646, -9668, -9374, -8798, -7989, -6992, -5859, -4646, -3407, -2187, -1039, 0, 893, 1613, 2137, 2463, 2579, 2494, 2222, 1785, 1201, 508, -263, -1081, -1904, -2702, -3443, -4095, -4639, -5052, -5325, -5449, -5423, -5256, -4957, -4544, -4034, -3459, -2835, -2197, -1571, -978, -449, -1, 351, 591, 711, 713, 595, 369, 41, -368, -839, -1355, -1890, -2423, -2927, -3389, -3782, -4095, -4317, -4436, -4452, -4363, -4179, -3903, -3552, -3144, -2689, -2218, -1740, -1285, -867, -502, -212, 1, 120, 147, 77, -81, -325, -639, -1012, -1426, -1866, -2307, -2737, -3134, -3480, -3764, -3971, -4097, -4130, -4076, -3934, -3710, -3417, -3066, -2669, -2250, -1821, -1404, -1015, -671, -387, -174, -46, 1, -44, -176, -386, -672, -1014, -1404, -1821, -2250, -2670, -3065, -3417, -3710, -3934, -4077, -4129, -4097, -3971, -3765, -3480, -3132, -2738, -2308, -1865, -1426, -1012, -640, -324, -82, 79, 145, 121, 0, -210, -504, -866, -1285, -1741, -2217, -2690, -3142, -3554, -3902, -4179, -4364, -4451, -4436, -4317, -4095, -3783, -3388, -2928, -2422, -1890, -1355, -840, -367, 42, 367, 596, 712, 712, 591, 350, 0, }; const int16_t FLASHMEM wav_bandlimited_comb_13[] = { 0, 457, 858, 1194, 1456, 1640, 1738, 1748, 1666, 1490, 1224, 864, 416, -111, -718, -1393, -2126, -2908, -3728, -4569, -5424, -6274, -7104, -7901, -8651, -9333, -9938, -10453, -10856, -11145, -11301, -11319, -11186, -10901, -10454, -9844, -9071, -8133, -7036, -5783, -4384, -2842, -1178, 607, 2489, 4457, 6490, 8576, 10689, 12809, 14923, 17000, 19028, 20980, 22840, 24588, 26205, 27675, 28982, 30111, 31054, 31798, 32332, 32658, 32766, 32658, 32332, 31798, 31053, 30113, 28981, 27675, 26204, 24589, 22840, 20981, 19026, 17002, 14921, 12811, 10688, 8575, 6491, 4457, 2490, 605, -1176, -2844, -4383, -5783, -7036, -8134, -9069, -9845, -10454, -10901, -11186, -11319, -11302, -11143, -10858, -10451, -9939, -9334, -8650, -7901, -7104, -6274, -5423, -4571, -3727, -2908, -2126, -1393, -718, -111, 416, 864, 1223, 1491, 1666, 1748, 1739, 1639, 1456, 1194, 857, 458, 0, -504, -1048, -1615, -2202, -2795, -3383, -3956, -4508, -5024, -5500, -5927, -6300, -6610, -6856, -7034, -7143, -7177, -7144, -7043, -6873, -6643, -6355, -6017, -5634, -5212, -4764, -4292, -3809, -3320, -2838, -2368, -1919, -1501, -1115, -774, -483, -240, -57, 67, 132, 131, 74, -46, -223, -454, -734, -1058, -1420, -1815, -2234, -2669, -3113, -3561, -4000, -4426, -4828, -5203, -5542, -5839, -6092, -6289, -6436, -6523, -6554, -6523, -6436, -6290, -6090, -5840, -5542, -5203, -4829, -4425, -4000, -3560, -3114, -2670, -2233, -1815, -1420, -1058, -734, -454, -222, -47, 73, 132, 132, 67, -57, -241, -481, -775, -1116, -1499, -1920, -2368, -2838, -3321, -3808, -4292, -4763, -5214, -5632, -6018, -6355, -6644, -6872, -7043, -7143, -7179, -7142, -7034, -6856, -6610, -6300, -5927, -5500, -5024, -4508, -3956, -3384, -2793, -2203, -1616, -1046, -505, 0, }; const int16_t FLASHMEM wav_bandlimited_comb_14[] = { 0, 804, 1608, 2410, 3212, 4011, 4808, 5601, 6393, 7178, 7963, 8738, 9512, 10278, 11038, 11793, 12539, 13277, 14011, 14731, 15446, 16150, 16845, 17530, 18204, 18867, 19518, 20159, 20787, 21402, 22003, 22595, 23168, 23731, 24278, 24811, 25328, 25831, 26319, 26788, 27244, 27682, 28105, 28509, 28897, 29268, 29619, 29956, 30271, 30571, 30851, 31112, 31354, 31580, 31784, 31970, 32136, 32284, 32412, 32518, 32609, 32678, 32726, 32755, 32767, 32756, 32727, 32677, 32608, 32520, 32410, 32285, 32136, 31970, 31784, 31579, 31355, 31112, 30851, 30571, 30271, 29955, 29620, 29268, 28897, 28509, 28104, 27683, 27244, 26789, 26317, 25832, 25328, 24811, 24278, 23730, 23170, 22593, 22004, 21402, 20787, 20158, 19519, 18867, 18204, 17530, 16844, 16151, 15446, 14732, 14009, 13278, 12539, 11792, 11039, 10278, 9512, 8738, 7962, 7180, 6391, 5602, 4808, 4011, 3212, 2410, 1608, 803, 1, -804, -1608, -2410, -3213, -4010, -4807, -5603, -6392, -7178, -7963, -8738, -9512, -10278, -11039, -11792, -12539, -13278, -14009, -14732, -15446, -16151, -16844, -17530, -18204, -18867, -19519, -20158, -20787, -21402, -22004, -22593, -23170, -23730, -24278, -24811, -25328, -25832, -26317, -26789, -27244, -27683, -28104, -28509, -28898, -29266, -29621, -29955, -30271, -30571, -30851, -31112, -31355, -31579, -31784, -31970, -32137, -32283, -32411, -32520, -32608, -32678, -32726, -32756, -32766, -32756, -32727, -32677, -32608, -32520, -32411, -32283, -32138, -31969, -31784, -31579, -31355, -31112, -30852, -30569, -30273, -29954, -29620, -29268, -28897, -28509, -28105, -27682, -27244, -26789, -26318, -25830, -25330, -24809, -24279, -23731, -23169, -22593, -22004, -21403, -20786, -20158, -19519, -18867, -18204, -17530, -16845, -16150, -15446, -14732, -14009, -13278, -12539, -11793, -11038, -10278, -9512, -8739, -7961, -7179, -6393, -5601, -4808, -4012, -3210, -2411, -1608, -804, 0, }; const int16_t* waveform_table[] = { wav_formant_sine, wav_formant_square, wav_sine, wav_bandlimited_comb_0, wav_bandlimited_comb_1, wav_bandlimited_comb_2, wav_bandlimited_comb_3, wav_bandlimited_comb_4, wav_bandlimited_comb_5, wav_bandlimited_comb_6, wav_bandlimited_comb_7, wav_bandlimited_comb_8, wav_bandlimited_comb_9, wav_bandlimited_comb_10, wav_bandlimited_comb_11, wav_bandlimited_comb_12, wav_bandlimited_comb_13, wav_bandlimited_comb_14, }; const int16_t FLASHMEM ws_moderate_overdrive[] = { -32766, -32728, -32689, -32648, -32607, -32564, -32519, -32474, -32427, -32378, -32328, -32277, -32224, -32170, -32113, -32056, -31996, -31935, -31872, -31807, -31740, -31671, -31600, -31527, -31451, -31374, -31294, -31212, -31128, -31041, -30951, -30859, -30765, -30667, -30567, -30464, -30358, -30250, -30138, -30022, -29904, -29782, -29657, -29529, -29397, -29261, -29122, -28979, -28832, -28681, -28526, -28367, -28204, -28036, -27864, -27688, -27507, -27321, -27131, -26936, -26736, -26531, -26321, -26106, -25886, -25660, -25429, -25192, -24950, -24702, -24449, -24190, -23925, -23654, -23377, -23094, -22805, -22510, -22209, -21902, -21588, -21268, -20942, -20609, -20270, -19924, -19573, -19215, -18850, -18479, -18102, -17718, -17328, -16932, -16530, -16121, -15707, -15286, -14859, -14427, -13989, -13545, -13095, -12640, -12180, -11715, -11244, -10769, -10289, -9804, -9315, -8822, -8324, -7823, -7319, -6810, -6299, -5785, -5268, -4748, -4226, -3703, -3177, -2650, -2121, -1592, -1062, -531, 0, 531, 1062, 1592, 2122, 2650, 3177, 3703, 4227, 4749, 5268, 5785, 6299, 6811, 7319, 7824, 8325, 8822, 9315, 9804, 10289, 10769, 11244, 11715, 12180, 12641, 13095, 13545, 13989, 14427, 14860, 15286, 15707, 16122, 16530, 16933, 17329, 17719, 18102, 18479, 18850, 19215, 19573, 19925, 20270, 20609, 20942, 21268, 21588, 21902, 22209, 22510, 22806, 23094, 23377, 23654, 23925, 24190, 24449, 24703, 24950, 25192, 25429, 25660, 25886, 26106, 26321, 26531, 26736, 26936, 27131, 27322, 27507, 27688, 27865, 28037, 28204, 28367, 28526, 28681, 28832, 28979, 29122, 29262, 29397, 29529, 29658, 29783, 29904, 30023, 30138, 30250, 30359, 30465, 30568, 30668, 30765, 30860, 30952, 31041, 31128, 31212, 31294, 31374, 31452, 31527, 31600, 31671, 31740, 31807, 31872, 31935, 31996, 32056, 32114, 32170, 32224, 32277, 32329, 32379, 32427, 32474, 32520, 32564, 32607, 32648, 32689, 32728, 32728, }; const int16_t FLASHMEM ws_violent_overdrive[] = { -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32765, -32765, -32765, -32765, -32765, -32765, -32765, -32765, -32765, -32764, -32764, -32764, -32764, -32763, -32763, -32763, -32762, -32762, -32761, -32760, -32760, -32759, -32758, -32757, -32756, -32754, -32753, -32751, -32749, -32747, -32744, -32741, -32738, -32734, -32730, -32725, -32720, -32713, -32706, -32698, -32689, -32679, -32668, -32655, -32640, -32623, -32604, -32582, -32558, -32531, -32499, -32464, -32424, -32379, -32327, -32269, -32204, -32130, -32046, -31951, -31844, -31724, -31587, -31434, -31260, -31065, -30845, -30598, -30320, -30008, -29658, -29266, -28828, -28340, -27795, -27189, -26518, -25774, -24954, -24053, -23064, -21985, -20811, -19541, -18172, -16705, -15142, -13486, -11742, -9919, -8025, -6073, -4075, -2045, 0, 2045, 4075, 6073, 8025, 9919, 11742, 13486, 15142, 16705, 18172, 19541, 20811, 21985, 23064, 24053, 24954, 25774, 26518, 27189, 27795, 28340, 28828, 29266, 29658, 30008, 30320, 30598, 30845, 31065, 31260, 31434, 31587, 31724, 31844, 31951, 32046, 32130, 32204, 32269, 32327, 32379, 32424, 32464, 32499, 32531, 32558, 32582, 32604, 32623, 32640, 32655, 32668, 32679, 32689, 32698, 32706, 32713, 32720, 32725, 32730, 32734, 32738, 32741, 32744, 32747, 32749, 32751, 32753, 32754, 32756, 32757, 32758, 32759, 32760, 32760, 32761, 32762, 32762, 32763, 32763, 32763, 32764, 32764, 32764, 32764, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, }; const int16_t FLASHMEM ws_sine_fold[] = { -32766, -32682, -32595, -32504, -32410, -32315, -32218, -32121, -32025, -31931, -31840, -31754, -31673, -31599, -31531, -31470, -31416, -31367, -31322, -31279, -31235, -31188, -31132, -31064, -30980, -30874, -30744, -30584, -30392, -30166, -29903, -29605, -29273, -28911, -28524, -28119, -27704, -27290, -26888, -26510, -26167, -25871, -25633, -25461, -25361, -25337, -25389, -25511, -25696, -25931, -26197, -26475, -26739, -26962, -27116, -27171, -27099, -26876, -26478, -25891, -25105, -24119, -22940, -21584, -20079, -18458, -16766, -15052, -13374, -11789, -10357, -9135, -8176, -7526, -7217, -7272, -7698, -8484, -9603, -11013, -12652, -14446, -16308, -18142, -19847, -21320, -22465, -23190, -23420, -23094, -22176, -20652, -18533, -15860, -12697, -9137, -5292, -1294, 2713, 6576, 10143, 13266, 15812, 17665, 18734, 18960, 18316, 16811, 14491, 11437, 7763, 3614, -844, -5428, -9944, -14200, -18011, -21206, -23640, -25199, -25802, -25410, -24026, -21695, -18501, -14568, -10051, -5129, 0, 5129, 10051, 14568, 18501, 21695, 24026, 25410, 25802, 25199, 23640, 21206, 18011, 14200, 9944, 5428, 844, -3614, -7763, -11437, -14491, -16811, -18316, -18960, -18734, -17665, -15812, -13266, -10143, -6576, -2713, 1294, 5292, 9137, 12697, 15860, 18533, 20652, 22176, 23094, 23420, 23190, 22465, 21320, 19847, 18142, 16308, 14446, 12652, 11013, 9603, 8484, 7698, 7272, 7217, 7526, 8176, 9135, 10357, 11789, 13374, 15052, 16766, 18458, 20079, 21584, 22940, 24119, 25105, 25891, 26478, 26876, 27099, 27171, 27116, 26962, 26739, 26475, 26197, 25931, 25696, 25511, 25389, 25337, 25361, 25461, 25633, 25871, 26167, 26510, 26888, 27290, 27704, 28119, 28524, 28911, 29273, 29605, 29903, 30166, 30392, 30584, 30744, 30874, 30980, 31064, 31132, 31188, 31235, 31279, 31322, 31367, 31416, 31470, 31531, 31599, 31673, 31754, 31840, 31931, 32025, 32121, 32218, 32315, 32410, 32504, 32595, 32682, 32682, }; const int16_t FLASHMEM ws_tri_fold[] = { -78, -20070, -31636, -30481, -17545, 1825, 20257, 31198, 31144, 20555, 3335, -14748, -28051, -32765, -27869, -15160, 1526, 17553, 28787, 32606, 28401, 17522, 2767, -12404, -24698, -31675, -32164, -26370, -15686, -2305, 11261, 22670, 30122, 32609, 29985, 22895, 12593, 688, -11123, -21293, -28618, -32346, -32225, -28466, -21675, -12730, -2661, 7481, 16727, 24281, 29569, 32266, 32296, 29804, 25121, 18711, 11123, 2936, -5286, -13027, -19851, -25419, -29496, -31955, -32766, -31988, -29754, -26252, -21712, -16387, -10537, -4418, 1726, 7680, 13252, 18287, 22661, 26287, 29107, 31097, 32257, 32610, 32199, 31083, 29331, 27022, 24237, 21062, 17579, 13872, 10018, 6089, 2152, -1734, -5515, -9146, -12587, -15807, -18779, -21484, -23907, -26038, -27872, -29408, -30647, -31595, -32257, -32644, -32766, -32635, -32264, -31666, -30855, -29846, -28653, -27289, -25770, -24109, -22319, -20413, -18405, -16307, -14130, -11888, -9591, -7250, -4877, -2483, -78, 2327, 4722, 7095, 9435, 11732, 13975, 16151, 18249, 20257, 22163, 23953, 25615, 27134, 28497, 29691, 30700, 31510, 32108, 32479, 32610, 32488, 32101, 31439, 30492, 29253, 27717, 25883, 23752, 21329, 18624, 15651, 12431, 8990, 5359, 1578, -2307, -6245, -10174, -14028, -17735, -21217, -24393, -27177, -29487, -31238, -32354, -32765, -32412, -31253, -29263, -26442, -22817, -18442, -13407, -7835, -1882, 4263, 10381, 16231, 21557, 26096, 29598, 31832, 32610, 31800, 29341, 25263, 19695, 12871, 5130, -3091, -11279, -18867, -25276, -29960, -32452, -32422, -29725, -24437, -16883, -7636, 2505, 12574, 21519, 28311, 32069, 32191, 28462, 21137, 10967, -844, -12749, -23051, -30140, -32765, -30278, -22825, -11417, 2150, 15530, 26214, 32008, 31519, 24543, 12248, -2923, -17678, -28556, -32762, -28943, -17709, -1682, 15005, 27714, 32609, 27895, 14592, -3491, -20710, -31300, -31354, -20413, -1981, 17389, 30325, 31480, 19915, 19915, }; const int16_t* waveshaper_table[] = { ws_moderate_overdrive, ws_violent_overdrive, ws_sine_fold, ws_tri_fold, }; const uint8_t FLASHMEM wt_waves[] = { 104, 105, 107, 108, 110, 112, 115, 116, 118, 122, 124, 124, 126, 129, 131, 132, 135, 137, 138, 140, 143, 145, 145, 147, 148, 149, 148, 148, 148, 147, 146, 144, 142, 139, 137, 133, 127, 121, 116, 110, 101, 93, 88, 83, 78, 74, 73, 73, 75, 80, 86, 93, 104, 116, 130, 143, 158, 173, 188, 203, 218, 228, 236, 245, 255, 252, 248, 244, 240, 232, 222, 211, 200, 188, 177, 166, 153, 141, 132, 123, 114, 105, 98, 91, 85, 82, 78, 74, 72, 72, 73, 72, 72, 75, 78, 80, 83, 88, 92, 95, 100, 104, 108, 113, 117, 120, 122, 125, 126, 125, 125, 124, 122, 120, 118, 116, 113, 111, 110, 108, 107, 105, 105, 104, 103, 103, 104, 103, 104, 123, 122, 124, 120, 118, 117, 117, 118, 117, 113, 114, 115, 113, 110, 109, 109, 110, 110, 108, 110, 114, 116, 118, 122, 125, 131, 135, 136, 135, 139, 142, 141, 139, 138, 138, 138, 135, 131, 129, 127, 125, 119, 114, 111, 107, 100, 95, 90, 84, 82, 79, 80, 82, 87, 97, 111, 124, 140, 160, 182, 203, 218, 229, 241, 255, 246, 238, 231, 223, 208, 193, 180, 173, 166, 157, 150, 149, 149, 148, 145, 143, 143, 141, 138, 134, 131, 128, 125, 121, 116, 110, 105, 102, 97, 90, 86, 86, 85, 84, 82, 85, 90, 93, 95, 98, 105, 110, 111, 112, 114, 116, 115, 113, 111, 111, 112, 112, 112, 113, 117, 120, 122, 124, 124, 126, 127, 128, 125, 123, 149, 149, 148, 147, 148, 146, 143, 143, 142, 139, 138, 137, 136, 135, 134, 134, 133, 132, 132, 132, 130, 129, 127, 125, 121, 118, 114, 109, 105, 103, 99, 96, 95, 93, 92, 92, 91, 90, 88, 88, 86, 84, 82, 79, 77, 75, 73, 71, 70, 72, 74, 75, 78, 86, 93, 100, 113, 129, 141, 155, 175, 193, 203, 217, 236, 242, 245, 251, 255, 251, 245, 244, 238, 228, 219, 213, 203, 191, 184, 176, 165, 156, 148, 140, 129, 122, 115, 107, 98, 92, 85, 77, 70, 65, 58, 56, 55, 54, 55, 58, 63, 69, 76, 85, 92, 99, 108, 115, 119, 122, 127, 128, 128, 129, 130, 129, 128, 130, 130, 130, 131, 135, 137, 137, 141, 144, 145, 146, 149, 134, 129, 121, 119, 120, 118, 117, 123, 127, 125, 127, 128, 122, 116, 113, 109, 105, 108, 115, 123, 131, 144, 153, 156, 156, 153, 141, 127, 115, 105, 95, 93, 98, 104, 110, 125, 137, 140, 142, 147, 146, 135, 135, 139, 139, 142, 160, 173, 174, 185, 192, 174, 148, 133, 105, 60, 36, 38, 27, 28, 69, 116, 142, 183, 239, 255, 250, 254, 248, 204, 164, 149, 119, 80, 72, 78, 71, 70, 90, 102, 99, 110, 125, 129, 129, 147, 161, 162, 170, 182, 179, 167, 158, 147, 120, 97, 83, 69, 52, 51, 64, 74, 90, 118, 142, 156, 172, 185, 183, 170, 162, 146, 123, 105, 98, 87, 78, 83, 92, 96, 104, 120, 128, 131, 137, 143, 138, 134, 134, 148, 154, 158, 162, 163, 166, 166, 166, 164, 160, 156, 151, 142, 136, 128, 118, 110, 103, 96, 91, 87, 84, 83, 84, 86, 89, 92, 98, 103, 110, 116, 123, 129, 133, 137, 142, 144, 143, 142, 142, 139, 134, 130, 125, 120, 114, 107, 102, 95, 91, 85, 79, 75, 74, 72, 70, 73, 82, 90, 101, 121, 140, 155, 177, 203, 220, 230, 243, 254, 255, 248, 243, 235, 220, 202, 185, 168, 152, 136, 120, 106, 98, 90, 84, 77, 76, 77, 75, 75, 76, 79, 81, 84, 88, 92, 97, 105, 114, 121, 128, 138, 148, 155, 160, 164, 168, 168, 164, 158, 151, 143, 134, 123, 111, 104, 99, 92, 89, 90, 92, 94, 100, 106, 113, 121, 128, 135, 142, 148, 148, 163, 170, 171, 169, 162, 153, 144, 130, 115, 108, 105, 95, 81, 75, 75, 71, 69, 77, 96, 112, 126, 142, 154, 156, 155, 148, 132, 119, 113, 105, 90, 80, 76, 69, 60, 52, 54, 64, 75, 92, 116, 136, 150, 162, 163, 154, 143, 135, 132, 127, 121, 120, 121, 108, 80, 64, 62, 50, 43, 76, 112, 133, 172, 221, 239, 238, 247, 255, 240, 220, 214, 210, 194, 170, 151, 141, 127, 111, 105, 107, 113, 122, 137, 151, 164, 181, 195, 201, 202, 199, 197, 190, 172, 148, 121, 98, 74, 39, 14, 25, 45, 54, 71, 105, 139, 157, 166, 177, 184, 187, 185, 176, 168, 159, 145, 128, 108, 86, 74, 73, 67, 61, 70, 90, 103, 114, 130, 148, 178, 176, 172, 161, 160, 159, 143, 138, 137, 125, 121, 114, 106, 100, 95, 90, 84, 81, 80, 81, 70, 81, 78, 70, 75, 82, 80, 75, 79, 86, 87, 82, 89, 97, 89, 90, 96, 95, 90, 89, 95, 88, 85, 88, 87, 80, 82, 85, 79, 81, 84, 88, 83, 95, 102, 98, 104, 119, 126, 123, 141, 159, 154, 168, 190, 194, 201, 211, 224, 230, 232, 241, 248, 249, 253, 255, 255, 251, 250, 244, 236, 229, 224, 209, 193, 189, 179, 158, 148, 143, 119, 106, 100, 88, 75, 66, 58, 53, 47, 38, 39, 43, 40, 43, 46, 56, 59, 66, 79, 83, 94, 105, 110, 119, 134, 139, 143, 157, 164, 166, 169, 182, 181, 175, 183, 188, 183, 177, 178, 151, 153, 156, 144, 137, 143, 138, 126, 122, 129, 127, 115, 112, 116, 118, 113, 113, 118, 117, 118, 122, 130, 130, 128, 136, 142, 137, 143, 144, 134, 143, 153, 140, 128, 138, 145, 125, 113, 125, 119, 97, 90, 104, 99, 73, 67, 83, 77, 60, 65, 77, 64, 56, 82, 91, 72, 80, 107, 109, 102, 127, 146, 135, 143, 176, 187, 179, 186, 211, 220, 209, 218, 244, 238, 217, 233, 255, 230, 214, 232, 225, 197, 197, 201, 178, 156, 153, 149, 131, 112, 103, 100, 81, 63, 70, 64, 38, 38, 49, 34, 25, 46, 47, 33, 46, 63, 65, 65, 78, 94, 100, 101, 111, 126, 130, 131, 142, 153, 150, 150, 162, 166, 160, 159, 164, 163, 164, 160, 151, 183, 167, 151, 130, 125, 113, 83, 80, 89, 82, 80, 101, 122, 127, 133, 141, 157, 160, 148, 144, 143, 144, 131, 109, 99, 97, 84, 59, 53, 75, 105, 113, 117, 144, 166, 171, 144, 117, 119, 107, 65, 27, 46, 68, 39, 24, 55, 70, 68, 79, 103, 118, 122, 134, 136, 117, 120, 121, 103, 92, 116, 130, 106, 112, 150, 152, 132, 137, 168, 174, 153, 157, 188, 203, 195, 204, 222, 215, 209, 207, 186, 160, 158, 152, 120, 112, 145, 163, 162, 169, 187, 210, 207, 196, 194, 181, 160, 122, 101, 92, 85, 97, 77, 64, 97, 132, 152, 171, 210, 235, 228, 197, 149, 128, 112, 56, 1, 20, 62, 49, 30, 61, 102, 118, 134, 174, 208, 205, 183, 168, 158, 144, 129, 120, 116, 113, 114, 117, 124, 135, 140, 135, 135, 147, 152, 143, 141, 151, 160, 155, 152, 153, 142, 128, 117, 103, 84, 74, 83, 94, 101, 110, 130, 147, 150, 143, 134, 127, 112, 92, 71, 63, 61, 58, 54, 59, 71, 84, 95, 101, 102, 107, 114, 108, 91, 83, 84, 82, 74, 77, 84, 103, 146, 189, 201, 205, 232, 255, 229, 183, 163, 156, 132, 105, 103, 115, 125, 142, 162, 167, 165, 178, 187, 173, 155, 160, 174, 174, 167, 165, 170, 169, 156, 135, 113, 100, 89, 78, 71, 76, 92, 109, 128, 148, 163, 181, 192, 190, 177, 163, 139, 109, 85, 72, 51, 34, 44, 65, 75, 84, 114, 141, 153, 164, 182, 188, 178, 168, 120, 127, 135, 128, 123, 126, 125, 121, 124, 140, 158, 167, 160, 154, 168, 184, 184, 170, 159, 155, 146, 140, 140, 132, 116, 111, 113, 106, 95, 100, 119, 129, 115, 103, 111, 129, 132, 126, 114, 95, 79, 79, 94, 97, 75, 54, 51, 47, 34, 35, 52, 61, 53, 37, 20, 22, 53, 90, 102, 87, 73, 69, 94, 164, 244, 255, 202, 176, 217, 253, 243, 232, 241, 227, 179, 155, 160, 153, 139, 150, 161, 136, 99, 86, 108, 141, 167, 167, 149, 138, 141, 157, 176, 188, 181, 160, 151, 150, 134, 117, 131, 159, 149, 108, 84, 88, 101, 109, 120, 124, 108, 87, 86, 103, 113, 105, 100, 119, 134, 122, 112, 130, 144, 135, 128, 141, 148, 133, 120, 137, 136, 132, 142, 163, 167, 157, 157, 166, 170, 169, 170, 163, 154, 153, 155, 151, 141, 133, 129, 128, 127, 122, 111, 108, 113, 113, 105, 101, 102, 103, 104, 102, 101, 100, 95, 94, 101, 97, 79, 72, 83, 89, 72, 51, 50, 66, 69, 49, 33, 43, 61, 64, 51, 50, 65, 76, 80, 92, 117, 134, 123, 113, 149, 211, 216, 167, 157, 217, 255, 225, 191, 205, 227, 216, 194, 195, 203, 186, 156, 148, 166, 170, 137, 108, 115, 136, 135, 115, 102, 109, 124, 129, 122, 120, 129, 138, 138, 137, 141, 150, 152, 146, 146, 155, 159, 147, 136, 142, 149, 142, 124, 118, 123, 123, 112, 102, 105, 111, 104, 97, 104, 113, 110, 106, 113, 123, 131, 137, 173, 176, 164, 163, 190, 203, 190, 187, 197, 197, 198, 208, 206, 191, 186, 188, 191, 183, 174, 162, 149, 143, 149, 141, 115, 102, 101, 97, 87, 81, 67, 58, 50, 51, 50, 47, 33, 29, 27, 31, 35, 31, 20, 22, 24, 24, 35, 45, 26, 18, 35, 59, 58, 53, 50, 59, 75, 93, 106, 111, 123, 123, 120, 149, 210, 204, 156, 160, 231, 255, 226, 208, 237, 251, 237, 232, 251, 254, 234, 210, 212, 235, 242, 203, 168, 182, 203, 187, 161, 158, 154, 140, 129, 139, 138, 116, 98, 102, 103, 103, 97, 85, 76, 79, 82, 82, 85, 78, 68, 70, 88, 93, 83, 78, 92, 96, 93, 103, 118, 110, 104, 119, 134, 138, 137, 138, 143, 156, 173, 121, 124, 113, 110, 113, 122, 125, 116, 126, 130, 122, 143, 144, 128, 136, 142, 145, 141, 137, 135, 135, 140, 128, 134, 141, 101, 123, 147, 109, 104, 129, 136, 124, 126, 144, 146, 139, 160, 171, 134, 133, 163, 129, 117, 139, 94, 79, 100, 72, 55, 55, 37, 27, 34, 24, 19, 22, 38, 66, 51, 56, 112, 109, 101, 165, 183, 160, 189, 227, 231, 229, 231, 252, 255, 224, 230, 232, 203, 205, 189, 148, 153, 160, 113, 97, 112, 87, 74, 90, 80, 66, 76, 86, 87, 95, 97, 97, 95, 116, 129, 94, 105, 148, 123, 118, 143, 136, 144, 147, 147, 157, 148, 144, 156, 163, 148, 140, 155, 157, 142, 137, 137, 137, 133, 122, 126, 123, 111, 121, 172, 178, 185, 193, 193, 197, 210, 210, 205, 213, 216, 211, 209, 209, 207, 197, 194, 191, 185, 176, 169, 161, 149, 143, 139, 121, 114, 111, 96, 88, 85, 85, 67, 61, 62, 57, 48, 57, 48, 28, 39, 42, 33, 26, 42, 24, 24, 41, 38, 30, 38, 40, 44, 53, 54, 61, 71, 87, 97, 94, 116, 144, 135, 137, 187, 196, 172, 192, 236, 225, 219, 240, 253, 245, 246, 255, 252, 249, 247, 234, 228, 234, 222, 197, 196, 197, 177, 159, 165, 153, 126, 123, 129, 106, 93, 98, 89, 68, 75, 73, 54, 52, 63, 52, 46, 51, 48, 51, 58, 55, 55, 62, 69, 70, 77, 86, 88, 90, 102, 114, 115, 121, 134, 140, 139, 153, 166, 166, 172, 120, 102, 97, 114, 144, 171, 170, 151, 160, 185, 189, 196, 202, 172, 143, 137, 143, 150, 143, 119, 107, 115, 126, 135, 136, 123, 116, 121, 115, 107, 115, 122, 98, 68, 66, 81, 94, 102, 89, 62, 61, 87, 111, 112, 100, 86, 98, 110, 95, 93, 100, 85, 60, 43, 38, 63, 85, 82, 72, 73, 91, 107, 118, 163, 225, 233, 172, 131, 185, 255, 239, 168, 146, 167, 175, 166, 172, 185, 169, 143, 145, 177, 199, 193, 168, 140, 126, 147, 178, 162, 112, 90, 108, 128, 136, 136, 127, 111, 110, 113, 118, 137, 150, 128, 91, 79, 103, 134, 124, 85, 66, 80, 103, 118, 127, 122, 108, 111, 134, 154, 165, 162, 138, 112, 115, 143, 158, 144, 120, 104, 114, 124, 137, 148, 160, 170, 176, 181, 183, 184, 181, 179, 172, 164, 155, 145, 137, 127, 119, 112, 106, 98, 93, 88, 82, 81, 80, 82, 84, 88, 93, 100, 110, 120, 133, 142, 154, 163, 172, 179, 182, 186, 181, 177, 165, 157, 143, 128, 113, 96, 81, 66, 56, 50, 45, 46, 43, 45, 47, 55, 71, 91, 116, 137, 159, 177, 195, 215, 233, 247, 254, 255, 250, 239, 224, 208, 190, 170, 148, 126, 104, 84, 69, 59, 52, 49, 48, 50, 53, 59, 68, 80, 90, 102, 110, 118, 125, 134, 142, 148, 156, 162, 166, 169, 172, 174, 173, 174, 171, 168, 162, 153, 145, 135, 127, 116, 107, 97, 88, 80, 74, 72, 71, 74, 79, 87, 95, 104, 104, 102, 100, 100, 103, 108, 114, 121, 126, 136, 145, 152, 161, 161, 167, 165, 163, 158, 154, 147, 140, 133, 121, 113, 103, 95, 93, 91, 90, 89, 93, 98, 105, 116, 126, 136, 141, 148, 152, 159, 162, 163, 162, 156, 151, 136, 132, 122, 110, 100, 90, 79, 67, 63, 59, 59, 60, 58, 57, 56, 63, 75, 96, 122, 146, 167, 188, 208, 229, 246, 255, 255, 242, 232, 214, 200, 188, 177, 166, 154, 144, 139, 137, 137, 140, 140, 135, 130, 119, 110, 100, 92, 82, 70, 61, 49, 47, 45, 54, 63, 77, 89, 103, 119, 133, 150, 160, 168, 174, 172, 172, 167, 164, 155, 150, 142, 135, 131, 124, 122, 116, 117, 113, 111, 110, 108, 107, 105, 104, 52, 55, 65, 78, 99, 127, 152, 180, 202, 224, 236, 241, 239, 221, 206, 182, 163, 139, 120, 105, 91, 88, 80, 81, 78, 77, 78, 72, 72, 62, 63, 61, 65, 76, 88, 110, 130, 157, 178, 199, 216, 222, 228, 217, 205, 180, 159, 136, 112, 98, 82, 74, 66, 68, 73, 78, 87, 82, 79, 67, 62, 63, 69, 87, 100, 117, 132, 157, 185, 212, 233, 239, 242, 233, 221, 208, 194, 182, 162, 146, 129, 120, 117, 118, 123, 120, 117, 111, 107, 100, 92, 89, 79, 73, 63, 57, 49, 45, 54, 67, 92, 118, 154, 187, 215, 236, 245, 252, 255, 253, 233, 204, 175, 143, 120, 98, 85, 76, 71, 70, 66, 70, 69, 70, 67, 62, 57, 49, 52, 90, 91, 95, 102, 116, 130, 154, 170, 183, 193, 192, 181, 164, 142, 123, 103, 91, 80, 76, 76, 83, 99, 110, 121, 124, 126, 127, 122, 118, 110, 106, 105, 105, 112, 121, 138, 150, 161, 165, 166, 159, 149, 136, 120, 100, 76, 60, 51, 51, 59, 71, 84, 98, 113, 125, 137, 144, 138, 128, 112, 103, 103, 115, 134, 162, 183, 199, 210, 207, 198, 192, 183, 181, 180, 181, 188, 197, 212, 221, 230, 222, 208, 181, 151, 121, 90, 71, 56, 54, 56, 63, 83, 100, 119, 124, 122, 108, 85, 66, 57, 66, 83, 113, 142, 178, 204, 226, 245, 254, 255, 225, 185, 142, 100, 69, 49, 41, 38, 43, 53, 68, 92, 108, 119, 120, 117, 103, 95, 90, 116, 127, 136, 147, 159, 170, 180, 186, 191, 196, 196, 194, 191, 184, 179, 169, 159, 149, 139, 127, 118, 109, 103, 96, 89, 86, 86, 84, 86, 84, 88, 94, 96, 104, 103, 107, 106, 106, 104, 103, 98, 91, 87, 78, 74, 65, 64, 59, 59, 58, 61, 64, 70, 78, 88, 101, 116, 126, 134, 150, 158, 176, 186, 192, 206, 208, 210, 214, 219, 221, 224, 229, 231, 235, 233, 240, 241, 250, 248, 251, 246, 245, 236, 228, 219, 203, 192, 171, 154, 130, 108, 89, 72, 53, 38, 24, 15, 5, 1, 2, 9, 17, 28, 41, 55, 68, 78, 93, 104, 118, 124, 128, 131, 127, 128, 125, 122, 115, 113, 105, 100, 97, 93, 92, 93, 97, 100, 108, 116, 10, 15, 35, 61, 98, 130, 164, 193, 207, 208, 193, 170, 149, 126, 114, 112, 112, 123, 136, 153, 175, 183, 183, 169, 137, 107, 74, 44, 21, 2, 3, 20, 46, 91, 135, 178, 210, 228, 242, 240, 227, 204, 175, 145, 113, 81, 66, 58, 59, 62, 66, 72, 75, 81, 87, 99, 112, 115, 121, 140, 158, 195, 212, 213, 208, 174, 131, 115, 109, 119, 136, 159, 173, 198, 223, 247, 255, 242, 211, 157, 107, 69, 39, 29, 27, 34, 58, 91, 136, 175, 202, 218, 208, 183, 150, 113, 81, 46, 25, 16, 28, 62, 105, 147, 185, 195, 196, 181, 162, 143, 106, 73, 46, 28, 42, 67, 108, 151, 186, 213, 223, 227, 216, 181, 146, 97, 52, 25, 10, 128, 129, 125, 124, 122, 121, 117, 110, 101, 92, 84, 79, 79, 79, 86, 88, 94, 99, 104, 108, 114, 120, 123, 130, 131, 134, 137, 142, 145, 149, 155, 161, 162, 165, 166, 167, 168, 165, 164, 158, 150, 139, 126, 118, 109, 102, 93, 87, 81, 76, 76, 77, 82, 82, 84, 82, 82, 79, 83, 96, 114, 138, 156, 170, 179, 177, 172, 169, 171, 170, 169, 164, 163, 170, 187, 209, 233, 249, 255, 240, 218, 194, 168, 151, 138, 132, 127, 125, 120, 120, 118, 121, 120, 111, 98, 75, 53, 29, 18, 16, 28, 45, 68, 85, 99, 106, 108, 112, 112, 114, 111, 113, 111, 114, 124, 140, 160, 174, 190, 193, 192, 183, 170, 155, 144, 138, 132, 130, 128, 168, 171, 166, 165, 162, 163, 158, 155, 147, 144, 137, 131, 126, 122, 119, 114, 111, 106, 107, 103, 107, 105, 107, 105, 104, 101, 102, 101, 100, 100, 101, 104, 104, 109, 109, 115, 117, 122, 125, 129, 130, 129, 125, 122, 120, 112, 111, 105, 103, 96, 96, 96, 97, 104, 108, 120, 126, 127, 125, 128, 132, 143, 150, 161, 166, 167, 172, 181, 196, 212, 226, 236, 242, 249, 250, 255, 255, 255, 249, 236, 221, 208, 193, 179, 167, 155, 148, 132, 121, 107, 99, 88, 82, 71, 65, 52, 42, 30, 23, 20, 14, 15, 14, 19, 21, 26, 31, 43, 52, 66, 76, 88, 98, 105, 115, 125, 139, 143, 153, 154, 161, 162, 166, 165, 169, 170, 171, 170, 168, 105, 117, 127, 138, 143, 147, 145, 139, 130, 122, 115, 108, 109, 111, 120, 126, 131, 142, 144, 145, 136, 122, 99, 79, 60, 58, 72, 100, 140, 181, 217, 233, 230, 203, 165, 124, 91, 76, 82, 113, 154, 198, 229, 242, 227, 186, 133, 76, 32, 1, 5, 27, 66, 108, 137, 158, 154, 132, 99, 73, 51, 49, 59, 86, 114, 143, 169, 186, 196, 194, 189, 178, 171, 167, 165, 174, 181, 191, 195, 194, 187, 180, 164, 146, 131, 114, 101, 87, 82, 81, 87, 94, 106, 114, 114, 111, 101, 87, 73, 63, 59, 65, 79, 95, 119, 141, 158, 166, 165, 158, 139, 125, 110, 106, 109, 121, 137, 154, 167, 171, 169, 156, 142, 121, 107, 96, 94, 95, 105, 194, 198, 207, 201, 202, 189, 181, 167, 168, 164, 165, 154, 154, 139, 135, 120, 109, 107, 100, 97, 86, 82, 73, 73, 66, 70, 63, 66, 58, 66, 71, 88, 89, 91, 80, 78, 71, 76, 80, 91, 102, 103, 103, 103, 103, 101, 106, 102, 110, 96, 100, 96, 111, 124, 141, 156, 167, 153, 147, 141, 151, 172, 194, 211, 200, 191, 178, 186, 195, 219, 225, 229, 213, 206, 189, 198, 204, 215, 210, 197, 175, 161, 146, 139, 143, 141, 135, 113, 102, 81, 84, 74, 86, 77, 74, 56, 52, 38, 41, 49, 47, 49, 35, 16, 7, 1, 35, 72, 93, 109, 93, 88, 80, 100, 125, 158, 171, 180, 168, 166, 168, 184, 205, 218, 222, 214, 205, 190, 194, 129, 151, 182, 191, 195, 181, 171, 155, 155, 155, 168, 175, 189, 185, 178, 154, 131, 115, 117, 133, 150, 156, 144, 118, 88, 81, 83, 107, 122, 133, 117, 99, 75, 71, 79, 101, 113, 114, 98, 81, 71, 73, 86, 101, 113, 107, 103, 91, 92, 90, 99, 103, 119, 127, 142, 145, 145, 128, 118, 120, 134, 153, 159, 154, 136, 132, 150, 185, 204, 204, 181, 159, 151, 180, 212, 245, 240, 213, 173, 153, 158, 186, 209, 211, 189, 157, 132, 122, 133, 143, 153, 139, 129, 107, 97, 82, 81, 73, 78, 86, 95, 92, 71, 36, 7, 1, 33, 82, 114, 117, 75, 34, 7, 35, 87, 144, 166, 154, 107, 75, 70, 105, 155, 191, 195, 172, 143, 123, 129, 72, 66, 89, 126, 157, 167, 154, 123, 92, 78, 89, 113, 148, 170, 175, 155, 123, 96, 85, 97, 126, 156, 173, 165, 136, 103, 81, 81, 104, 138, 164, 170, 148, 115, 86, 77, 92, 124, 154, 168, 158, 134, 106, 93, 101, 125, 154, 171, 170, 148, 119, 98, 99, 116, 147, 176, 184, 166, 130, 89, 59, 48, 58, 95, 136, 171, 185, 165, 120, 75, 61, 91, 156, 226, 255, 238, 174, 108, 73, 93, 153, 220, 250, 224, 160, 90, 51, 58, 105, 155, 183, 173, 132, 80, 44, 37, 59, 99, 135, 152, 144, 116, 78, 46, 41, 66, 117, 167, 194, 183, 138, 89, 62, 80, 129, 187, 220, 212, 165, 109, 74, 77, 116, 163, 194, 189, 156, 108, 72, 76, 47, 48, 80, 136, 189, 213, 190, 135, 78, 52, 75, 142, 218, 255, 245, 177, 101, 52, 59, 117, 186, 232, 215, 159, 83, 32, 26, 66, 125, 166, 172, 139, 88, 45, 29, 48, 92, 132, 159, 160, 139, 109, 87, 86, 107, 145, 180, 200, 194, 163, 128, 105, 108, 139, 180, 211, 205, 170, 111, 60, 31, 39, 84, 132, 177, 190, 161, 101, 44, 25, 60, 133, 210, 241, 224, 161, 93, 59, 79, 142, 212, 250, 232, 175, 108, 66, 69, 108, 162, 194, 192, 158, 108, 66, 46, 61, 93, 131, 155, 153, 123, 82, 42, 28, 48, 98, 152, 182, 173, 131, 80, 52, 66, 118, 174, 213, 211, 169, 114, 78, 82, 119, 168, 199, 197, 170, 121, 76, 59, 42, 38, 46, 74, 92, 110, 118, 135, 175, 174, 229, 247, 255, 241, 232, 208, 188, 151, 126, 114, 101, 108, 84, 68, 33, 15, 22, 59, 113, 139, 139, 124, 105, 114, 143, 168, 190, 169, 133, 121, 119, 130, 124, 104, 82, 65, 81, 109, 130, 134, 109, 104, 119, 166, 223, 240, 206, 154, 96, 73, 64, 84, 112, 113, 127, 139, 137, 121, 84, 68, 70, 109, 186, 221, 236, 186, 119, 68, 71, 121, 197, 227, 202, 143, 73, 37, 41, 101, 154, 177, 167, 135, 106, 89, 94, 120, 136, 154, 166, 163, 155, 128, 83, 50, 37, 76, 128, 175, 182, 129, 64, 19, 35, 113, 183, 238, 227, 164, 107, 79, 112, 170, 210, 219, 183, 140, 92, 59, 184, 157, 84, 7, 109, 254, 193, 59, 87, 155, 124, 180, 203, 108, 31, 149, 236, 173, 92, 101, 116, 126, 190, 184, 86, 48, 138, 189, 141, 110, 114, 102, 116, 170, 159, 72, 70, 167, 182, 114, 94, 103, 101, 131, 183, 158, 64, 62, 132, 152, 154, 131, 106, 66, 103, 184, 198, 111, 83, 89, 110, 118, 187, 177, 94, 79, 147, 172, 123, 108, 124, 106, 102, 150, 144, 101, 116, 166, 128, 66, 89, 144, 160, 151, 144, 91, 72, 116, 168, 179, 130, 87, 72, 131, 205, 170, 69, 58, 158, 177, 134, 125, 107, 80, 139, 223, 141, 52, 90, 151, 146, 173, 191, 74, 11, 122, 255, 188, 96, 72, 52, 122, 253, 227, 43, 1, 137, 207, 184, 153, 93, 110, 120, 152, 124, 90, 124, 181, 155, 58, 125, 183, 150, 80, 131, 157, 144, 115, 110, 128, 149, 173, 93, 113, 118, 146, 124, 145, 117, 140, 116, 117, 129, 136, 144, 114, 126, 128, 117, 142, 134, 127, 97, 163, 163, 90, 67, 161, 149, 149, 95, 124, 137, 119, 122, 168, 142, 96, 89, 170, 119, 117, 142, 148, 52, 93, 194, 178, 58, 75, 150, 194, 107, 82, 102, 193, 151, 108, 57, 135, 220, 142, 31, 109, 232, 171, 24, 58, 239, 198, 51, 24, 179, 255, 92, 37, 102, 227, 141, 56, 110, 186, 152, 74, 118, 143, 148, 119, 114, 132, 156, 120, 91, 143, 140, 145, 119, 133, 152, 75, 101, 174, 188, 96, 82, 115, 182, 153, 118, 58, 1, 22, 51, 63, 40, 51, 87, 124, 133, 165, 194, 200, 185, 176, 160, 146, 130, 126, 132, 143, 134, 113, 120, 137, 141, 130, 129, 131, 129, 111, 100, 99, 106, 117, 110, 115, 121, 121, 125, 128, 129, 133, 143, 142, 119, 118, 135, 144, 151, 142, 137, 146, 154, 167, 173, 155, 128, 114, 132, 135, 123, 97, 75, 65, 85, 117, 118, 106, 109, 121, 136, 138, 137, 135, 139, 137, 131, 121, 116, 136, 138, 125, 135, 145, 144, 138, 143, 151, 139, 126, 124, 146, 153, 130, 106, 93, 108, 114, 114, 109, 106, 106, 116, 137, 131, 133, 150, 160, 152, 137, 119, 104, 98, 97, 121, 122, 119, 137, 167, 208, 214, 184, 171, 199, 208, 148, 118, 95, 66, 1, 2, 32, 50, 41, 56, 97, 138, 149, 166, 181, 186, 173, 165, 156, 149, 134, 122, 125, 138, 136, 123, 126, 140, 146, 136, 125, 120, 122, 118, 109, 102, 101, 107, 108, 110, 115, 120, 127, 132, 131, 134, 144, 146, 137, 137, 144, 144, 142, 139, 142, 147, 146, 143, 148, 147, 138, 129, 128, 122, 117, 111, 104, 94, 101, 114, 116, 112, 115, 122, 130, 132, 127, 123, 123, 122, 122, 115, 115, 126, 129, 123, 132, 144, 145, 140, 143, 151, 153, 143, 135, 137, 141, 133, 119, 108, 109, 111, 114, 113, 112, 112, 125, 139, 137, 132, 138, 138, 125, 110, 102, 98, 93, 95, 121, 147, 159, 164, 187, 229, 255, 220, 180, 192, 167, 113, 95, 94, 72, 1, 37, 86, 124, 92, 61, 71, 94, 94, 129, 170, 194, 167, 141, 133, 146, 149, 148, 153, 163, 152, 125, 110, 119, 131, 127, 116, 113, 118, 113, 105, 100, 105, 122, 126, 126, 120, 124, 127, 125, 126, 132, 143, 148, 139, 144, 154, 153, 148, 141, 146, 151, 147, 139, 134, 128, 124, 123, 128, 130, 133, 127, 117, 99, 103, 113, 121, 118, 113, 109, 109, 110, 109, 110, 120, 123, 125, 118, 120, 130, 133, 126, 140, 157, 163, 146, 129, 126, 131, 133, 136, 142, 149, 139, 127, 114, 118, 128, 141, 135, 119, 101, 97, 95, 89, 94, 121, 134, 130, 122, 137, 158, 153, 130, 152, 196, 215, 174, 181, 180, 146, 131, 130, 177, 173, 109, 94, 155, 118, 1, 15, 70, 93, 43, 12, 48, 118, 160, 171, 188, 200, 181, 171, 145, 131, 105, 97, 102, 103, 97, 93, 111, 147, 168, 159, 136, 130, 144, 152, 143, 123, 98, 103, 111, 111, 107, 104, 114, 121, 131, 136, 144, 153, 150, 164, 169, 162, 152, 140, 138, 127, 124, 118, 124, 130, 124, 128, 133, 138, 141, 137, 129, 108, 108, 109, 110, 105, 97, 92, 104, 123, 129, 123, 118, 114, 125, 129, 132, 137, 143, 133, 133, 140, 143, 137, 131, 128, 128, 123, 126, 135, 147, 145, 138, 124, 121, 123, 127, 114, 88, 66, 81, 107, 130, 139, 167, 192, 190, 170, 159, 178, 183, 133, 99, 103, 60, 59, 137, 196, 175, 126, 121, 195, 245, 192, 155, 149, 113, 27, 24, 64, 82, 52, 29, 56, 109, 146, 164, 175, 201, 218, 196, 154, 129, 101, 93, 106, 110, 98, 78, 85, 105, 127, 140, 144, 146, 158, 163, 149, 127, 115, 124, 132, 129, 120, 110, 116, 124, 131, 137, 145, 154, 154, 154, 145, 132, 125, 124, 128, 124, 118, 108, 110, 117, 119, 124, 128, 138, 143, 139, 133, 120, 118, 124, 133, 134, 127, 118, 118, 125, 127, 124, 126, 130, 135, 126, 113, 103, 109, 118, 125, 128, 123, 118, 121, 127, 139, 145, 149, 151, 156, 148, 132, 115, 107, 105, 115, 115, 101, 97, 128, 156, 162, 149, 164, 197, 212, 173, 136, 103, 58, 59, 75, 91, 70, 64, 112, 171, 189, 179, 180, 226, 255, 212, 149, 154, 122, 34, 1, 46, 77, 58, 26, 34, 75, 119, 152, 177, 192, 193, 174, 158, 154, 148, 132, 121, 108, 85, 81, 105, 133, 143, 138, 127, 124, 143, 160, 157, 134, 115, 111, 117, 121, 116, 113, 119, 123, 129, 131, 138, 146, 149, 150, 148, 140, 139, 135, 137, 129, 117, 106, 109, 122, 127, 122, 117, 118, 126, 132, 135, 132, 125, 125, 128, 130, 130, 128, 132, 139, 140, 131, 120, 114, 118, 116, 112, 100, 101, 105, 119, 131, 132, 130, 135, 145, 160, 157, 143, 135, 128, 125, 113, 104, 100, 103, 129, 148, 146, 131, 139, 178, 209, 201, 163, 156, 123, 82, 87, 90, 57, 30, 34, 68, 87, 109, 165, 224, 238, 207, 184, 215, 250, 221, 154, 177, 137, 65, 3, 35, 72, 77, 40, 25, 47, 85, 114, 136, 155, 167, 159, 153, 145, 139, 134, 135, 140, 159, 160, 145, 147, 148, 130, 120, 115, 123, 128, 126, 114, 101, 104, 120, 138, 143, 136, 130, 119, 106, 107, 121, 134, 135, 138, 146, 151, 146, 144, 145, 138, 129, 121, 112, 108, 107, 106, 108, 119, 136, 143, 145, 139, 138, 140, 137, 142, 145, 136, 125, 123, 123, 118, 113, 108, 108, 108, 111, 114, 114, 114, 121, 137, 136, 126, 130, 124, 114, 114, 112, 115, 127, 153, 174, 180, 171, 152, 161, 190, 203, 172, 134, 127, 89, 79, 94, 113, 98, 54, 54, 79, 77, 70, 79, 110, 124, 137, 174, 218, 232, 206, 176, 207, 255, 244, 177, 208, 145, 94, 36, 46, 74, 66, 36, 26, 53, 90, 117, 138, 155, 163, 157, 149, 143, 134, 127, 134, 144, 147, 135, 123, 142, 166, 175, 155, 129, 122, 124, 135, 131, 114, 99, 100, 105, 106, 111, 120, 124, 123, 124, 131, 139, 141, 141, 147, 144, 133, 124, 117, 120, 123, 117, 110, 112, 122, 134, 139, 139, 145, 150, 148, 142, 139, 142, 135, 126, 116, 111, 116, 121, 128, 125, 123, 128, 123, 122, 124, 125, 120, 109, 100, 102, 102, 94, 95, 105, 119, 137, 152, 171, 188, 199, 189, 187, 192, 190, 169, 141, 111, 63, 61, 92, 95, 78, 72, 96, 116, 112, 118, 130, 123, 101, 89, 96, 104, 110, 135, 178, 209, 201, 177, 194, 238, 255, 208, 231, 155, 102, 42, 38, 70, 72, 50, 28, 42, 81, 116, 138, 158, 176, 180, 173, 160, 145, 131, 121, 119, 117, 111, 111, 130, 151, 159, 148, 136, 143, 168, 176, 149, 119, 99, 95, 104, 105, 100, 98, 102, 106, 110, 117, 128, 139, 146, 151, 149, 141, 130, 124, 127, 129, 124, 117, 118, 129, 134, 132, 135, 149, 157, 153, 143, 135, 131, 132, 131, 119, 108, 116, 126, 129, 126, 120, 120, 114, 115, 120, 116, 101, 89, 85, 93, 105, 116, 138, 161, 170, 170, 169, 184, 210, 223, 191, 155, 110, 82, 98, 106, 93, 53, 48, 82, 114, 125, 130, 143, 154, 143, 138, 131, 115, 92, 78, 80, 92, 99, 124, 167, 205, 206, 179, 174, 215, 255, 231, 252, 166, 112, 42, 12, 55, 63, 37, 11, 31, 78, 118, 140, 164, 184, 188, 180, 169, 152, 136, 120, 120, 121, 115, 107, 117, 136, 147, 141, 135, 140, 162, 163, 144, 127, 123, 139, 139, 120, 96, 82, 94, 101, 100, 94, 96, 106, 120, 133, 146, 150, 149, 145, 147, 146, 139, 130, 133, 151, 159, 145, 133, 133, 145, 152, 143, 119, 103, 112, 121, 120, 111, 112, 126, 135, 132, 122, 113, 98, 89, 87, 89, 86, 90, 107, 140, 168, 170, 167, 181, 215, 234, 201, 159, 144, 121, 116, 116, 89, 58, 56, 78, 98, 86, 90, 124, 154, 158, 151, 149, 153, 141, 129, 121, 105, 81, 65, 70, 89, 101, 118, 155, 207, 228, 204, 183, 210, 255, 252, 255, 166, 114, 48, 5, 56, 79, 67, 35, 40, 78, 118, 142, 163, 177, 180, 170, 163, 153, 143, 127, 126, 126, 129, 126, 126, 136, 142, 129, 112, 104, 121, 138, 141, 127, 109, 110, 119, 119, 120, 132, 136, 118, 104, 97, 102, 123, 137, 139, 139, 139, 138, 139, 149, 155, 153, 138, 123, 128, 138, 134, 121, 112, 122, 141, 149, 140, 131, 135, 136, 129, 123, 127, 126, 115, 99, 82, 77, 85, 104, 127, 146, 143, 128, 128, 161, 208, 210, 170, 147, 121, 111, 124, 125, 116, 96, 95, 108, 107, 104, 120, 139, 145, 120, 107, 122, 141, 138, 127, 125, 134, 130, 128, 132, 130, 104, 77, 70, 91, 111, 128, 150, 186, 205, 187, 165, 193, 246, 255, 255, 181, 131, 75, 25, 67, 89, 76, 38, 38, 70, 111, 136, 161, 178, 181, 170, 164, 156, 149, 129, 119, 116, 120, 117, 119, 131, 143, 140, 131, 125, 129, 131, 119, 102, 86, 87, 99, 106, 110, 115, 124, 134, 144, 156, 165, 158, 152, 139, 137, 147, 144, 129, 110, 103, 110, 119, 123, 125, 130, 135, 140, 141, 143, 148, 153, 143, 128, 122, 117, 107, 95, 92, 100, 109, 118, 129, 149, 162, 158, 148, 160, 181, 183, 141, 113, 102, 79, 84, 99, 100, 89, 90, 107, 135, 151, 163, 167, 158, 139, 134, 136, 130, 105, 93, 102, 122, 127, 125, 132, 149, 149, 140, 131, 127, 111, 91, 74, 76, 88, 112, 141, 178, 193, 181, 162, 188, 235, 255, 255, 192, 135, 89, 28, 55, 80, 77, 51, 46, 76, 116, 138, 155, 171, 184, 180, 164, 145, 134, 119, 112, 111, 111, 109, 113, 127, 140, 139, 129, 126, 135, 147, 145, 125, 101, 94, 99, 98, 94, 95, 103, 119, 129, 135, 143, 158, 174, 184, 188, 172, 150, 139, 114, 102, 103, 104, 101, 102, 109, 120, 132, 140, 148, 155, 152, 133, 112, 105, 107, 109, 112, 127, 150, 161, 157, 147, 161, 184, 181, 149, 134, 103, 79, 84, 92, 93, 78, 79, 102, 119, 125, 132, 138, 145, 151, 158, 156, 140, 122, 123, 134, 140, 125, 110, 118, 138, 144, 133, 124, 131, 139, 137, 123, 110, 94, 81, 73, 78, 90, 112, 139, 174, 197, 193, 173, 184, 226, 255, 255, 213, 143, 96, 27, 35, 73, 82, 59, 44, 70, 111, 138, 151, 160, 168, 164, 153, 139, 130, 124, 119, 120, 119, 119, 129, 142, 148, 140, 122, 115, 125, 135, 133, 119, 101, 98, 108, 113, 111, 108, 109, 117, 123, 121, 121, 134, 156, 172, 173, 156, 145, 151, 166, 162, 136, 114, 97, 107, 120, 118, 107, 95, 97, 109, 124, 128, 126, 136, 157, 172, 164, 148, 154, 178, 195, 166, 133, 117, 89, 86, 99, 94, 71, 62, 78, 99, 107, 117, 136, 149, 150, 147, 144, 145, 147, 150, 147, 133, 117, 116, 127, 139, 127, 110, 109, 125, 142, 141, 130, 127, 129, 131, 124, 113, 96, 82, 76, 79, 87, 104, 136, 179, 214, 214, 189, 187, 221, 255, 255, 234, 160, 106, 41, 16, 50, 75, 66, 38, 43, 83, 122, 144, 158, 171, 178, 171, 155, 141, 127, 110, 102, 106, 108, 111, 119, 129, 132, 126, 125, 135, 146, 150, 142, 125, 113, 114, 117, 122, 124, 119, 115, 114, 113, 108, 107, 116, 130, 144, 148, 151, 153, 159, 162, 156, 145, 143, 143, 120, 96, 85, 81, 100, 131, 159, 164, 145, 137, 160, 200, 214, 180, 149, 127, 102, 98, 102, 99, 70, 55, 73, 90, 95, 101, 116, 124, 120, 125, 139, 144, 142, 138, 135, 138, 145, 154, 161, 156, 139, 123, 121, 128, 126, 119, 114, 117, 126, 123, 115, 115, 118, 125, 126, 110, 89, 76, 73, 81, 100, 125, 152, 184, 219, 230, 211, 194, 215, 255, 249, 255, 199, 133, 78, 21, 33, 62, 63, 44, 42, 73, 110, 133, 155, 173, 177, 164, 143, 128, 113, 98, 90, 95, 101, 107, 118, 131, 143, 148, 151, 151, 151, 154, 152, 145, 133, 119, 109, 104, 106, 111, 110, 106, 101, 104, 117, 132, 142, 147, 151, 153, 140, 126, 119, 120, 119, 119, 115, 108, 124, 157, 195, 206, 184, 169, 174, 193, 186, 144, 119, 89, 61, 79, 100, 95, 78, 84, 106, 109, 107, 117, 125, 125, 117, 115, 111, 107, 113, 128, 136, 137, 137, 141, 150, 157, 161, 162, 158, 145, 129, 121, 121, 114, 103, 96, 99, 109, 113, 116, 125, 132, 136, 136, 127, 118, 107, 96, 85, 86, 101, 122, 159, 198, 223, 212, 191, 207, 249, 183, 177, 165, 151, 137, 117, 105, 93, 85, 76, 71, 62, 52, 45, 38, 38, 38, 38, 35, 27, 19, 8, 2, 1, 7, 15, 26, 32, 36, 40, 43, 48, 58, 67, 78, 88, 96, 105, 116, 130, 145, 160, 173, 182, 186, 191, 198, 209, 222, 236, 245, 252, 252, 247, 243, 238, 235, 235, 235, 234, 232, 228, 222, 215, 207, 199, 188, 178, 164, 149, 139, 132, 124, 118, 111, 97, 83, 68, 58, 47, 43, 40, 36, 32, 26, 23, 20, 20, 26, 32, 39, 45, 51, 55, 60, 65, 74, 81, 90, 98, 104, 113, 125, 139, 153, 166, 178, 185, 190, 195, 204, 211, 219, 226, 226, 225, 218, 213, 210, 211, 215, 221, 223, 222, 215, 207, 197, 190, 183, 201, 199, 193, 181, 163, 143, 128, 115, 110, 107, 107, 99, 90, 76, 65, 56, 47, 42, 35, 25, 18, 9, 3, 1, 5, 11, 17, 20, 23, 25, 30, 35, 44, 49, 54, 56, 57, 59, 64, 74, 88, 101, 109, 112, 113, 113, 116, 127, 139, 153, 167, 177, 185, 190, 195, 202, 211, 218, 226, 230, 235, 239, 244, 247, 247, 242, 232, 218, 202, 186, 181, 178, 176, 174, 166, 153, 140, 125, 118, 114, 115, 114, 111, 101, 87, 76, 71, 68, 74, 80, 86, 90, 93, 98, 102, 108, 116, 119, 118, 116, 111, 111, 116, 126, 136, 144, 145, 140, 135, 130, 133, 143, 156, 172, 177, 178, 172, 168, 170, 179, 193, 209, 219, 224, 219, 211, 203, 199, 201, 115, 116, 117, 118, 115, 108, 99, 91, 84, 81, 81, 81, 79, 73, 64, 53, 42, 34, 29, 27, 26, 27, 26, 24, 22, 20, 19, 17, 16, 16, 16, 15, 16, 15, 17, 21, 27, 33, 40, 46, 53, 59, 65, 69, 75, 80, 87, 95, 104, 113, 120, 127, 135, 139, 143, 147, 149, 150, 151, 150, 152, 153, 158, 161, 166, 169, 169, 168, 164, 159, 157, 157, 158, 160, 164, 165, 167, 166, 167, 170, 175, 181, 188, 197, 203, 210, 216, 219, 225, 228, 233, 237, 242, 247, 251, 253, 255, 253, 246, 239, 228, 219, 211, 206, 201, 195, 189, 180, 171, 161, 154, 150, 147, 148, 145, 140, 133, 126, 121, 120, 122, 127, 133, 135, 132, 127, 120, 116, 115, 190, 185, 179, 173, 166, 159, 154, 149, 142, 136, 127, 118, 107, 97, 87, 78, 69, 60, 50, 40, 29, 19, 12, 5, 3, 1, 1, 3, 5, 8, 11, 13, 16, 18, 20, 23, 28, 34, 42, 50, 59, 65, 71, 76, 82, 89, 99, 110, 122, 133, 141, 147, 151, 154, 157, 161, 165, 168, 172, 174, 178, 181, 185, 187, 190, 190, 188, 186, 183, 181, 181, 181, 182, 183, 183, 180, 177, 172, 169, 167, 165, 165, 163, 162, 158, 155, 151, 147, 142, 138, 136, 133, 132, 132, 133, 134, 135, 135, 132, 131, 129, 128, 130, 131, 133, 135, 134, 134, 135, 137, 141, 147, 152, 159, 164, 169, 173, 178, 184, 190, 197, 201, 204, 204, 202, 199, 195, 192, 190, 146, 143, 139, 133, 123, 113, 102, 94, 86, 80, 75, 70, 65, 60, 53, 47, 41, 35, 30, 26, 21, 17, 13, 9, 5, 3, 1, 1, 1, 3, 5, 6, 6, 5, 5, 4, 4, 5, 8, 11, 14, 17, 19, 20, 21, 22, 23, 27, 33, 40, 48, 54, 60, 65, 69, 74, 80, 87, 97, 107, 119, 131, 143, 155, 165, 174, 181, 186, 190, 194, 200, 206, 214, 222, 230, 235, 237, 237, 236, 235, 236, 239, 241, 245, 246, 247, 245, 241, 236, 231, 229, 227, 226, 227, 229, 231, 232, 231, 228, 224, 217, 211, 205, 200, 197, 195, 193, 193, 194, 193, 191, 188, 184, 180, 176, 172, 170, 169, 170, 170, 169, 168, 165, 161, 156, 152, 149, 147, 146, 171, 166, 162, 155, 148, 139, 128, 117, 103, 92, 83, 77, 74, 71, 70, 68, 63, 57, 47, 37, 27, 18, 10, 5, 2, 1, 2, 5, 6, 9, 11, 12, 11, 12, 12, 15, 19, 24, 28, 30, 30, 27, 24, 22, 21, 25, 31, 41, 53, 64, 75, 83, 90, 95, 100, 107, 113, 120, 130, 139, 150, 160, 169, 176, 182, 186, 186, 187, 187, 187, 190, 193, 198, 202, 205, 204, 201, 199, 196, 195, 196, 198, 199, 200, 201, 199, 198, 194, 191, 189, 190, 190, 191, 193, 195, 199, 203, 205, 207, 206, 203, 198, 192, 186, 181, 178, 176, 175, 178, 178, 179, 176, 173, 171, 168, 167, 167, 170, 174, 178, 181, 184, 185, 185, 183, 181, 177, 174, 171, 189, 188, 189, 188, 188, 187, 185, 179, 170, 160, 150, 142, 136, 131, 129, 124, 118, 112, 104, 95, 86, 76, 65, 52, 40, 29, 22, 19, 19, 19, 19, 17, 12, 8, 6, 6, 10, 14, 17, 18, 17, 14, 13, 12, 17, 24, 32, 39, 46, 51, 57, 64, 72, 81, 89, 95, 98, 99, 101, 105, 112, 120, 130, 138, 144, 146, 147, 151, 158, 168, 179, 190, 199, 204, 206, 205, 206, 209, 215, 223, 233, 241, 247, 251, 252, 252, 253, 252, 253, 253, 255, 255, 254, 249, 242, 232, 220, 206, 193, 181, 169, 157, 145, 132, 119, 106, 96, 89, 85, 85, 86, 89, 90, 93, 97, 101, 105, 110, 115, 119, 122, 128, 137, 146, 158, 170, 179, 185, 189, 154, 160, 167, 173, 179, 184, 187, 187, 183, 179, 174, 172, 172, 174, 178, 180, 178, 177, 171, 165, 161, 157, 153, 149, 143, 134, 125, 115, 106, 97, 91, 83, 76, 69, 60, 54, 49, 45, 42, 39, 33, 27, 21, 16, 15, 17, 21, 25, 30, 33, 35, 36, 39, 42, 48, 55, 62, 67, 73, 79, 89, 100, 115, 129, 141, 151, 158, 164, 170, 177, 186, 195, 204, 212, 219, 222, 226, 230, 235, 239, 246, 250, 253, 255, 255, 253, 250, 245, 237, 227, 217, 206, 197, 187, 178, 169, 159, 146, 133, 121, 107, 96, 88, 79, 72, 66, 60, 55, 54, 53, 54, 58, 60, 65, 67, 71, 76, 82, 87, 94, 100, 105, 112, 118, 125, 133, 140, 148, 154, 109, 106, 104, 104, 102, 99, 93, 87, 79, 73, 68, 66, 63, 60, 58, 54, 50, 50, 52, 56, 62, 67, 70, 70, 68, 65, 64, 64, 66, 68, 69, 67, 64, 59, 55, 53, 53, 56, 58, 60, 59, 56, 52, 48, 46, 45, 44, 44, 44, 43, 42, 40, 40, 40, 42, 45, 48, 52, 58, 64, 73, 83, 93, 103, 111, 118, 123, 129, 136, 143, 153, 162, 171, 179, 185, 189, 194, 199, 207, 214, 223, 231, 236, 239, 240, 242, 243, 246, 249, 252, 255, 255, 254, 252, 251, 249, 248, 246, 243, 237, 230, 222, 215, 209, 204, 201, 199, 195, 191, 187, 182, 179, 178, 179, 178, 177, 173, 166, 157, 147, 139, 133, 130, 128, 127, 124, 119, 114, 109, 133, 118, 105, 94, 83, 73, 63, 53, 42, 32, 24, 19, 15, 12, 11, 7, 3, 2, 4, 8, 17, 27, 37, 43, 46, 49, 52, 57, 64, 70, 76, 80, 81, 80, 79, 80, 83, 88, 92, 97, 98, 98, 98, 98, 100, 102, 103, 104, 102, 100, 96, 93, 92, 93, 95, 96, 96, 97, 100, 104, 113, 123, 133, 142, 150, 156, 159, 163, 167, 170, 173, 175, 175, 173, 170, 166, 162, 159, 154, 150, 147, 144, 142, 141, 142, 143, 143, 143, 143, 142, 143, 145, 148, 152, 157, 162, 166, 168, 171, 176, 181, 188, 195, 202, 210, 218, 224, 230, 237, 243, 246, 249, 251, 254, 254, 255, 254, 249, 242, 231, 218, 206, 194, 185, 177, 167, 158, 146, 133, 187, 182, 180, 178, 172, 161, 145, 127, 108, 94, 84, 79, 72, 64, 55, 42, 29, 23, 22, 27, 36, 46, 54, 55, 54, 51, 50, 48, 48, 47, 45, 39, 31, 23, 19, 18, 20, 26, 31, 36, 41, 45, 53, 63, 77, 91, 105, 114, 121, 126, 128, 131, 138, 145, 152, 159, 165, 169, 173, 178, 189, 200, 214, 227, 238, 245, 247, 246, 242, 237, 232, 226, 216, 205, 191, 173, 155, 137, 120, 107, 98, 92, 88, 85, 81, 79, 77, 76, 77, 78, 78, 78, 76, 72, 70, 70, 72, 75, 79, 85, 90, 97, 108, 121, 138, 159, 180, 198, 212, 220, 224, 229, 234, 242, 249, 254, 255, 250, 240, 229, 217, 210, 207, 206, 206, 203, 197, 192, 187, 133, 128, 125, 120, 111, 95, 78, 60, 47, 39, 36, 37, 37, 34, 27, 17, 7, 1, 1, 7, 16, 27, 34, 36, 36, 33, 31, 30, 34, 38, 43, 45, 45, 42, 38, 35, 33, 34, 36, 37, 37, 36, 34, 33, 35, 37, 41, 43, 45, 44, 42, 42, 44, 50, 59, 68, 76, 80, 83, 83, 86, 94, 106, 123, 141, 157, 169, 177, 182, 186, 192, 199, 206, 213, 217, 218, 216, 213, 211, 209, 209, 208, 208, 207, 206, 206, 207, 209, 212, 212, 210, 206, 200, 196, 194, 196, 200, 203, 205, 204, 202, 200, 202, 206, 214, 223, 231, 236, 237, 237, 234, 235, 237, 241, 242, 242, 237, 229, 220, 211, 204, 198, 192, 184, 173, 161, 148, 139, 133, 135, 131, 128, 125, 119, 110, 98, 85, 73, 63, 56, 52, 48, 43, 39, 33, 28, 26, 26, 29, 34, 38, 40, 39, 36, 33, 30, 27, 25, 24, 22, 17, 12, 8, 4, 1, 1, 3, 6, 9, 12, 15, 17, 19, 23, 26, 30, 33, 36, 37, 39, 42, 46, 52, 59, 67, 75, 83, 90, 96, 106, 116, 127, 139, 150, 161, 168, 175, 180, 186, 192, 198, 204, 209, 210, 209, 207, 205, 204, 204, 208, 211, 214, 216, 218, 219, 221, 223, 226, 230, 230, 230, 226, 223, 217, 213, 211, 209, 209, 210, 211, 212, 214, 217, 221, 226, 230, 234, 235, 236, 235, 235, 233, 232, 228, 223, 214, 204, 195, 186, 179, 174, 171, 167, 162, 155, 148, 141, 135, 154, 150, 146, 140, 130, 114, 97, 81, 70, 63, 59, 56, 52, 46, 37, 27, 19, 14, 13, 15, 17, 18, 16, 11, 6, 2, 1, 2, 6, 11, 16, 18, 19, 21, 25, 32, 42, 55, 68, 79, 87, 90, 91, 93, 96, 101, 111, 121, 129, 134, 135, 134, 132, 132, 135, 139, 145, 149, 150, 147, 145, 142, 142, 145, 150, 155, 158, 158, 155, 152, 149, 149, 150, 153, 155, 154, 152, 147, 143, 141, 142, 144, 147, 148, 148, 147, 146, 146, 147, 151, 154, 156, 156, 156, 155, 153, 154, 156, 161, 168, 175, 183, 192, 200, 207, 212, 217, 220, 223, 228, 233, 240, 245, 248, 246, 242, 234, 226, 220, 217, 216, 214, 211, 205, 194, 181, 169, 159, 154, 107, 103, 100, 98, 94, 89, 82, 76, 71, 68, 66, 66, 65, 63, 59, 54, 48, 44, 42, 41, 41, 40, 37, 31, 26, 19, 15, 13, 12, 13, 13, 13, 11, 10, 10, 12, 17, 22, 27, 31, 33, 36, 38, 42, 47, 52, 58, 62, 64, 65, 65, 67, 69, 74, 79, 83, 86, 88, 90, 92, 98, 105, 113, 119, 125, 129, 129, 131, 133, 139, 145, 154, 162, 168, 172, 175, 179, 182, 189, 195, 202, 208, 212, 215, 216, 220, 224, 230, 236, 241, 244, 244, 243, 242, 241, 242, 245, 248, 250, 252, 253, 254, 254, 254, 255, 254, 252, 249, 244, 239, 233, 228, 224, 219, 213, 206, 196, 185, 175, 166, 158, 152, 147, 142, 135, 128, 120, 112, 107, 80, 78, 75, 71, 64, 56, 48, 40, 35, 33, 34, 35, 37, 38, 39, 37, 36, 38, 41, 47, 54, 61, 68, 71, 74, 76, 78, 81, 88, 94, 103, 109, 113, 114, 114, 112, 114, 117, 123, 128, 134, 137, 138, 136, 134, 131, 128, 124, 119, 112, 104, 97, 89, 82, 77, 70, 65, 60, 56, 54, 56, 61, 67, 73, 77, 79, 78, 78, 79, 84, 92, 101, 111, 119, 124, 127, 130, 134, 140, 146, 155, 162, 169, 175, 180, 187, 195, 204, 215, 222, 229, 231, 232, 232, 233, 235, 237, 239, 241, 244, 245, 247, 250, 252, 255, 255, 255, 253, 250, 246, 241, 235, 227, 216, 204, 190, 177, 163, 153, 144, 136, 129, 120, 110, 101, 92, 86, 81, 80, 200, 194, 180, 193, 171, 165, 153, 139, 129, 118, 96, 87, 76, 59, 64, 36, 34, 28, 1, 17, 11, 1, 17, 11, 22, 39, 37, 52, 69, 72, 93, 92, 110, 127, 116, 134, 156, 168, 206, 205, 236, 242, 233, 239, 248, 244, 246, 240, 231, 218, 184, 175, 165, 143, 139, 105, 112, 97, 65, 64, 57, 57, 66, 38, 48, 52, 39, 43, 54, 69, 80, 106, 119, 144, 133, 148, 159, 141, 158, 154, 163, 155, 136, 149, 125, 116, 134, 122, 138, 135, 128, 126, 114, 105, 111, 104, 101, 103, 83, 92, 88, 86, 116, 107, 140, 146, 149, 173, 182, 179, 198, 202, 202, 198, 178, 178, 165, 148, 168, 159, 171, 171, 165, 181, 172, 175, 199, 175, 200, 239, 237, 227, 238, 215, 198, 194, 175, 162, 143, 136, 118, 103, 90, 84, 70, 54, 36, 27, 11, 7, 1, 10, 23, 26, 46, 50, 58, 83, 66, 79, 78, 83, 86, 90, 103, 120, 122, 151, 154, 167, 185, 192, 197, 218, 216, 222, 211, 212, 197, 189, 189, 188, 183, 178, 167, 173, 154, 150, 149, 142, 131, 119, 103, 87, 87, 77, 64, 72, 79, 88, 91, 90, 105, 103, 106, 113, 116, 128, 124, 130, 118, 109, 115, 103, 101, 121, 109, 128, 129, 133, 128, 123, 116, 109, 92, 91, 88, 74, 81, 76, 77, 91, 85, 98, 109, 116, 135, 148, 144, 163, 171, 160, 159, 154, 149, 144, 138, 155, 155, 172, 181, 188, 201, 209, 208, 228, 219, 239, 250, 252, 252, 255, 240, 228, 212, 201, 190, 168, 156, 148, 136, 124, 108, 100, 81, 56, 41, 24, 14, 4, 12, 26, 27, 38, 50, 54, 67, 67, 67, 74, 77, 80, 87, 92, 110, 115, 122, 140, 153, 171, 182, 190, 213, 209, 205, 206, 197, 194, 188, 189, 197, 193, 191, 190, 182, 180, 170, 161, 161, 143, 132, 115, 87, 90, 78, 71, 79, 80, 87, 95, 89, 90, 89, 92, 96, 104, 119, 126, 122, 115, 111, 105, 101, 109, 121, 120, 126, 131, 127, 130, 117, 112, 108, 86, 83, 76, 66, 79, 73, 75, 83, 85, 90, 90, 96, 118, 125, 134, 147, 157, 158, 143, 140, 138, 120, 126, 135, 143, 160, 160, 178, 188, 191, 210, 220, 229, 250, 238, 248, 250, 255, 242, 233, 216, 204, 191, 171, 168, 161, 149, 146, 135, 123, 105, 85, 67, 42, 30, 25, 23, 30, 37, 44, 45, 59, 69, 67, 73, 84, 84, 83, 91, 98, 101, 108, 120, 126, 136, 157, 171, 176, 191, 200, 191, 186, 192, 190, 175, 184, 194, 192, 192, 205, 207, 195, 190, 187, 175, 157, 146, 129, 104, 90, 82, 69, 74, 80, 79, 82, 84, 88, 76, 82, 91, 89, 104, 114, 112, 106, 101, 103, 97, 100, 119, 120, 122, 135, 131, 132, 122, 124, 117, 90, 86, 84, 69, 75, 77, 82, 80, 84, 91, 88, 91, 109, 119, 128, 143, 156, 157, 148, 138, 133, 114, 116, 123, 125, 143, 148, 156, 167, 173, 191, 204, 215, 238, 232, 252, 255, 255, 242, 229, 210, 197, 177, 173, 166, 161, 155, 153, 141, 129, 116, 98, 75, 60, 46, 38, 29, 32, 35, 37, 40, 52, 55, 61, 70, 83, 85, 95, 104, 109, 110, 118, 122, 127, 138, 157, 167, 175, 189, 200, 188, 184, 181, 176, 166, 175, 185, 198, 207, 225, 226, 213, 204, 194, 173, 158, 145, 128, 103, 89, 74, 66, 68, 77, 78, 89, 90, 88, 80, 82, 79, 82, 90, 104, 101, 98, 96, 97, 92, 102, 114, 128, 137, 147, 148, 146, 134, 130, 113, 97, 87, 88, 79, 84, 87, 90, 89, 93, 92, 93, 99, 113, 120, 133, 144, 160, 154, 147, 135, 126, 107, 108, 107, 115, 123, 129, 131, 141, 148, 167, 189, 214, 232, 221, 251, 255, 242, 224, 198, 173, 158, 146, 153, 157, 155, 152, 148, 142, 128, 121, 111, 98, 84, 69, 56, 47, 43, 49, 57, 67, 72, 75, 76, 78, 83, 94, 105, 113, 116, 121, 124, 118, 117, 129, 143, 161, 177, 203, 215, 201, 186, 171, 152, 135, 143, 166, 191, 217, 230, 236, 217, 196, 182, 168, 161, 147, 123, 101, 75, 63, 66, 74, 82, 90, 105, 101, 90, 82, 80, 72, 75, 84, 99, 99, 92, 84, 81, 81, 100, 119, 141, 156, 165, 158, 154, 140, 128, 116, 102, 94, 96, 91, 96, 100, 103, 105, 111, 104, 103, 107, 115, 123, 139, 150, 162, 160, 152, 135, 123, 104, 101, 102, 108, 119, 125, 118, 120, 122, 137, 164, 194, 221, 209, 247, 255, 228, 197, 158, 119, 99, 105, 126, 137, 141, 135, 131, 124, 109, 113, 115, 109, 96, 85, 76, 68, 73, 77, 91, 95, 88, 81, 78, 72, 79, 98, 109, 118, 131, 133, 136, 115, 110, 123, 137, 155, 178, 218, 235, 213, 187, 159, 134, 103, 112, 149, 190, 221, 225, 227, 202, 172, 159, 157, 167, 154, 130, 110, 81, 69, 76, 93, 121, 139, 140, 122, 100, 71, 63, 65, 83, 94, 101, 95, 73, 53, 36, 46, 86, 112, 140, 158, 163, 147, 133, 128, 123, 117, 103, 103, 110, 107, 115, 126, 142, 134, 131, 132, 122, 119, 122, 139, 158, 167, 180, 187, 178, 144, 124, 109, 103, 105, 113, 141, 146, 124, 110, 95, 103, 119, 160, 209, 222, 255, 249, 216, 184, 141, 100, 89, 107, 128, 138, 137, 137, 132, 118, 104, 117, 117, 109, 95, 90, 76, 68, 75, 84, 102, 101, 92, 82, 74, 68, 82, 100, 110, 128, 142, 142, 134, 111, 109, 125, 140, 163, 197, 237, 245, 215, 185, 153, 125, 99, 121, 163, 209, 231, 236, 233, 199, 172, 161, 169, 170, 147, 120, 96, 70, 60, 70, 94, 123, 133, 125, 104, 82, 49, 46, 60, 76, 83, 91, 82, 58, 34, 25, 51, 94, 119, 149, 166, 164, 146, 137, 133, 127, 116, 109, 109, 117, 120, 131, 148, 159, 147, 144, 140, 125, 125, 129, 152, 167, 175, 188, 191, 169, 131, 115, 103, 99, 101, 119, 147, 136, 109, 87, 78, 89, 114, 166, 222, 242, 255, 236, 199, 155, 110, 84, 87, 103, 121, 127, 131, 129, 120, 109, 107, 111, 106, 96, 88, 77, 71, 72, 83, 94, 104, 96, 86, 74, 71, 75, 94, 109, 131, 143, 151, 139, 129, 116, 122, 136, 160, 194, 232, 254, 245, 211, 175, 138, 113, 110, 144, 190, 229, 248, 246, 226, 195, 175, 171, 170, 158, 131, 101, 73, 58, 59, 83, 106, 128, 124, 111, 83, 55, 33, 43, 56, 70, 76, 76, 56, 30, 11, 27, 58, 102, 132, 158, 163, 155, 141, 134, 125, 118, 112, 107, 109, 120, 130, 151, 161, 166, 161, 152, 139, 129, 133, 150, 168, 185, 197, 204, 187, 156, 124, 109, 100, 102, 120, 140, 140, 118, 86, 70, 69, 95, 142, 201, 242, 245, 243, 214, 161, 119, 88, 76, 80, 93, 109, 116, 119, 110, 103, 105, 99, 97, 93, 84, 72, 69, 66, 72, 93, 96, 98, 86, 77, 72, 77, 87, 106, 133, 149, 154, 150, 134, 131, 123, 139, 163, 204, 239, 254, 255, 236, 189, 153, 123, 128, 142, 183, 222, 251, 252, 236, 215, 196, 185, 171, 153, 136, 99, 75, 59, 62, 79, 101, 114, 116, 105, 81, 52, 42, 33, 41, 48, 57, 50, 40, 21, 6, 15, 40, 74, 118, 139, 156, 156, 150, 135, 125, 113, 107, 105, 107, 117, 136, 154, 169, 172, 178, 162, 151, 142, 142, 159, 175, 201, 218, 219, 201, 172, 145, 117, 109, 111, 129, 142, 131, 118, 90, 67, 64, 87, 136, 188, 230, 245, 238, 231, 193, 141, 96, 76, 66, 74, 86, 107, 115, 126, 114, 109, 103, 91, 80, 77, 67, 63, 66, 74, 83, 101, 90, 83, 70, 68, 73, 92, 107, 133, 157, 161, 151, 136, 120, 125, 128, 157, 187, 230, 253, 250, 235, 209, 165, 136, 118, 134, 153, 195, 228, 255, 251, 237, 220, 206, 194, 164, 127, 106, 72, 61, 54, 74, 98, 119, 121, 109, 88, 59, 38, 47, 45, 54, 56, 59, 38, 23, 10, 5, 32, 62, 93, 134, 147, 157, 153, 149, 130, 120, 103, 100, 101, 113, 129, 152, 173, 184, 178, 179, 152, 145, 146, 153, 174, 197, 219, 230, 211, 182, 150, 133, 115, 121, 126, 146, 146, 118, 92, 70, 56, 74, 107, 169, 210, 241, 238, 243, 242, 199, 144, 94, 52, 50, 57, 87, 122, 147, 165, 156, 131, 97, 73, 54, 52, 61, 66, 90, 100, 112, 116, 83, 71, 53, 58, 82, 102, 134, 161, 172, 162, 145, 115, 99, 103, 110, 147, 171, 215, 242, 236, 229, 192, 157, 133, 107, 101, 115, 158, 207, 249, 255, 252, 238, 208, 188, 139, 103, 83, 66, 80, 80, 101, 119, 128, 123, 97, 77, 58, 65, 69, 77, 88, 84, 91, 75, 52, 38, 21, 38, 66, 107, 146, 169, 177, 171, 153, 120, 96, 70, 70, 89, 106, 152, 171, 193, 191, 160, 135, 108, 110, 132, 157, 184, 207, 219, 202, 183, 146, 131, 130, 128, 145, 142, 150, 152, 125, 102, 64, 51, 66, 105, 153, 200, 236, 243, 252, 250, 219, 157, 97, 59, 49, 57, 93, 126, 154, 173, 164, 139, 99, 65, 50, 46, 57, 65, 84, 101, 106, 112, 89, 64, 54, 51, 67, 94, 125, 155, 172, 166, 146, 114, 95, 90, 100, 129, 162, 210, 244, 251, 238, 206, 168, 136, 115, 98, 104, 143, 191, 237, 255, 255, 243, 219, 198, 150, 109, 82, 67, 78, 82, 103, 124, 131, 127, 101, 73, 50, 54, 70, 83, 98, 96, 95, 84, 57, 38, 24, 32, 63, 108, 149, 174, 186, 176, 152, 121, 93, 69, 69, 86, 109, 145, 169, 191, 187, 161, 133, 105, 103, 120, 150, 179, 202, 218, 207, 177, 141, 124, 121, 133, 148, 149, 154, 153, 133, 109, 68, 50, 58, 95, 146, 195, 238, 252, 239, 224, 241, 204, 175, 154, 176, 161, 168, 165, 146, 142, 143, 143, 142, 126, 128, 111, 120, 108, 87, 92, 121, 157, 139, 142, 137, 131, 152, 172, 179, 175, 162, 134, 144, 157, 149, 159, 170, 207, 212, 214, 206, 188, 181, 198, 175, 183, 163, 151, 152, 169, 203, 224, 183, 167, 162, 158, 190, 170, 119, 123, 110, 77, 78, 84, 98, 122, 131, 128, 93, 60, 72, 63, 51, 44, 1, 15, 37, 29, 40, 20, 37, 53, 68, 93, 82, 34, 45, 69, 67, 74, 57, 30, 45, 41, 55, 61, 91, 106, 104, 117, 101, 65, 94, 113, 131, 146, 176, 147, 133, 127, 134, 125, 140, 136, 113, 108, 133, 106, 137, 142, 138, 144, 178, 193, 222, 243, 239, 226, 200, 199, 208, 212, 171, 153, 134, 145, 138, 119, 114, 97, 110, 133, 111, 99, 88, 62, 74, 83, 86, 88, 93, 107, 137, 122, 93, 75, 98, 141, 139, 123, 83, 98, 88, 89, 88, 93, 132, 149, 150, 150, 138, 116, 135, 122, 134, 119, 111, 113, 118, 148, 155, 107, 96, 120, 141, 172, 142, 111, 120, 123, 116, 106, 114, 128, 157, 175, 175, 151, 135, 135, 139, 118, 102, 90, 86, 99, 110, 106, 75, 81, 122, 174, 189, 163, 124, 117, 162, 156, 132, 112, 117, 126, 128, 85, 63, 94, 118, 134, 113, 78, 56, 77, 108, 130, 115, 117, 120, 135, 151, 156, 145, 124, 142, 157, 159, 121, 113, 147, 185, 171, 152, 151, 192, 254, 255, 226, 224, 232, 238, 227, 203, 174, 138, 158, 177, 149, 116, 129, 104, 83, 74, 46, 82, 85, 67, 60, 53, 56, 66, 72, 69, 79, 75, 103, 91, 88, 99, 99, 107, 69, 103, 79, 47, 83, 102, 112, 106, 75, 69, 113, 97, 88, 70, 89, 88, 78, 95, 52, 79, 111, 68, 79, 90, 91, 121, 92, 66, 105, 114, 113, 76, 104, 147, 149, 163, 151, 144, 192, 176, 169, 195, 162, 168, 194, 179, 179, 188, 150, 143, 170, 207, 217, 193, 200, 200, 244, 212, 174, 171, 180, 151, 151, 109, 101, 144, 105, 92, 85, 56, 60, 62, 55, 80, 111, 113, 97, 109, 123, 126, 133, 117, 129, 159, 191, 167, 168, 185, 188, 180, 183, 181, 209, 255, 246, 224, 237, 236, 240, 210, 205, 172, 156, 131, 147, 161, 155, 146, 113, 73, 63, 48, 68, 78, 72, 62, 50, 42, 61, 54, 36, 49, 77, 110, 114, 96, 95, 111, 137, 100, 78, 50, 56, 116, 129, 92, 64, 41, 54, 61, 48, 72, 33, 37, 45, 50, 55, 19, 32, 52, 37, 76, 75, 84, 89, 63, 61, 73, 74, 94, 71, 98, 111, 129, 137, 171, 170, 199, 214, 204, 234, 247, 239, 248, 254, 237, 254, 217, 196, 201, 212, 241, 248, 244, 242, 222, 223, 226, 198, 217, 164, 153, 140, 145, 171, 126, 97, 86, 50, 35, 50, 30, 47, 65, 91, 69, 73, 86, 115, 122, 114, 115, 134, 177, 182, 199, 201, 175, 169, 195, 195, 198, 236, 255, 237, 190, 198, 186, 157, 164, 142, 122, 113, 134, 148, 142, 150, 124, 83, 73, 53, 91, 121, 87, 72, 71, 67, 89, 75, 71, 80, 97, 127, 147, 117, 118, 120, 139, 105, 82, 79, 82, 128, 119, 77, 62, 41, 57, 80, 49, 35, 44, 57, 75, 51, 38, 22, 42, 67, 70, 73, 73, 77, 96, 69, 38, 56, 74, 94, 78, 84, 107, 123, 131, 149, 155, 207, 220, 213, 225, 211, 228, 255, 244, 224, 217, 214, 205, 217, 229, 243, 230, 229, 214, 219, 207, 189, 200, 202, 162, 167, 152, 160, 186, 150, 119, 98, 71, 84, 87, 67, 57, 70, 84, 87, 107, 128, 124, 137, 116, 110, 152, 182, 178, 171, 154, 152, 152, 150, 154, 166, 197, 200, 190, 166, 171, 179, 162, 155, 144, 139, 134, 137, 140, 124, 133, 137, 126, 115, 93, 100, 95, 88, 76, 84, 80, 96, 80, 80, 84, 106, 119, 138, 125, 135, 139, 150, 120, 111, 109, 109, 128, 105, 80, 77, 66, 77, 60, 45, 40, 43, 35, 48, 40, 39, 25, 50, 49, 55, 50, 48, 67, 84, 64, 45, 46, 55, 75, 60, 58, 73, 100, 108, 113, 133, 174, 188, 199, 209, 225, 226, 244, 255, 247, 247, 238, 239, 252, 252, 253, 246, 254, 252, 239, 225, 216, 208, 217, 213, 195, 173, 181, 186, 181, 152, 135, 111, 107, 90, 80, 63, 66, 75, 76, 72, 84, 95, 110, 114, 112, 121, 128, 132, 133, 144, 144, 139, 138, 144, 144, 155, 163, 166, 156, 151, 160, 157, 158, 141, 128, 125, 147, 152, 146, 157, 161, 146, 127, 117, 119, 99, 106, 107, 107, 99, 119, 111, 107, 108, 126, 138, 169, 165, 172, 165, 169, 152, 151, 144, 120, 126, 133, 133, 114, 102, 100, 77, 74, 64, 65, 44, 64, 64, 64, 57, 52, 43, 60, 67, 54, 55, 61, 56, 35, 48, 37, 39, 37, 50, 62, 88, 107, 102, 137, 167, 173, 184, 198, 205, 223, 239, 241, 229, 231, 234, 234, 255, 247, 243, 230, 242, 228, 215, 203, 207, 206, 202, 206, 180, 158, 175, 181, 157, 138, 124, 88, 82, 78, 63, 49, 46, 40, 58, 72, 68, 80, 98, 88, 81, 99, 115, 116, 113, 135, 136, 129, 115, 120, 127, 136, 147, 156, 151, 151, 147, 155, 145, 139, 136, 133, 148, 167, 151, 164, 164, 157, 157, 155, 156, 145, 151, 168, 157, 143, 147, 124, 125, 132, 153, 162, 157, 155, 149, 137, 144, 136, 129, 123, 117, 119, 114, 106, 91, 68, 75, 47, 46, 56, 44, 19, 37, 22, 18, 21, 29, 27, 35, 50, 41, 59, 67, 56, 64, 78, 67, 88, 97, 105, 102, 122, 151, 166, 199, 208, 201, 204, 220, 226, 242, 242, 253, 255, 247, 248, 251, 247, 245, 237, 219, 225, 211, 187, 162, 163, 157, 155, 153, 134, 114, 140, 146, 125, 109, 96, 66, 63, 69, 63, 54, 59, 51, 50, 60, 71, 78, 83, 86, 86, 94, 108, 111, 110, 125, 127, 123, 125, 129, 136, 156, 159, 151, 180, 188, 196, 204, 202, 214, 202, 208, 211, 213, 215, 195, 174, 181, 186, 182, 167, 148, 134, 138, 135, 118, 130, 102, 106, 126, 130, 110, 112, 97, 88, 83, 78, 78, 67, 38, 31, 42, 27, 22, 25, 21, 20, 10, 17, 24, 30, 1, 28, 21, 26, 56, 95, 85, 85, 82, 98, 119, 132, 122, 118, 118, 122, 155, 144, 148, 147, 178, 207, 232, 245, 230, 232, 233, 252, 255, 236, 208, 226, 241, 242, 226, 212, 205, 216, 211, 193, 195, 176, 149, 134, 144, 142, 150, 136, 110, 103, 116, 116, 99, 79, 56, 51, 54, 43, 42, 38, 46, 53, 52, 53, 68, 81, 84, 111, 113, 87, 86, 94, 116, 127, 133, 125, 138, 149, 168, 183, 193, 180, 218, 223, 211, 198, 193, 208, 199, 195, 191, 177, 155, 151, 127, 142, 136, 117, 122, 109, 96, 87, 73, 49, 50, 34, 40, 37, 57, 24, 34, 20, 16, 1, 41, 49, 41, 38, 41, 39, 71, 56, 70, 75, 85, 89, 126, 124, 125, 101, 127, 111, 133, 147, 168, 160, 149, 147, 162, 156, 161, 166, 161, 156, 158, 149, 138, 156, 151, 144, 159, 140, 146, 160, 167, 154, 163, 173, 151, 148, 167, 165, 172, 177, 164, 164, 164, 168, 159, 181, 165, 146, 126, 123, 126, 147, 140, 128, 98, 114, 129, 134, 117, 103, 87, 93, 86, 107, 98, 98, 81, 84, 84, 109, 92, 99, 120, 134, 118, 148, 136, 147, 160, 184, 172, 181, 191, 217, 228, 233, 218, 204, 211, 206, 200, 178, 175, 169, 153, 147, 135, 120, 117, 110, 105, 96, 80, 86, 59, 51, 35, 17, 15, 32, 4, 2, 1, 10, 4, 29, 32, 26, 16, 54, 81, 88, 76, 89, 100, 115, 134, 163, 165, 151, 148, 183, 200, 193, 165, 182, 181, 183, 199, 207, 184, 162, 177, 194, 185, 186, 168, 145, 152, 149, 134, 117, 108, 99, 103, 111, 107, 99, 106, 110, 111, 120, 124, 116, 118, 124, 123, 118, 141, 143, 131, 135, 139, 115, 141, 148, 120, 100, 115, 124, 129, 138, 124, 99, 112, 131, 133, 129, 110, 98, 123, 116, 116, 97, 104, 91, 85, 108, 133, 118, 134, 148, 155, 162, 188, 200, 189, 192, 212, 203, 223, 231, 224, 228, 216, 204, 181, 178, 173, 167, 153, 137, 128, 116, 109, 97, 86, 73, 68, 62, 54, 38, 38, 24, 19, 14, 11, 1, 8, 4, 7, 9, 20, 30, 43, 47, 59, 65, 89, 98, 99, 104, 116, 125, 149, 163, 165, 166, 174, 178, 189, 188, 185, 178, 177, 174, 175, 177, 172, 167, 158, 153, 156, 151, 141, 128, 117, 114, 111, 103, 90, 89, 90, 91, 93, 91, 91, 101, 111, 112, 112, 117, 115, 120, 122, 130, 132, 140, 144, 147, 146, 149, 144, 146, 150, 147, 137, 142, 148, 151, 154, 148, 136, 141, 150, 152, 146, 140, 136, 142, 141, 141, 131, 131, 134, 143, 154, 165, 170, 170, 181, 190, 196, 202, 206, 202, 210, 212, 208, 202, 206, 203, 198, 187, 181, 165, 156, 144, 142, 132, 118, 102, 90, 78, 71, 63, 57, 45, 36, 33, 18, 20, 13, 10, 9, 8, 1, 6, 10, 15, 22, 39, 49, 59, 74, 89, 94, 110, 117, 126, 130, 145, 159, 170, 181, 184, 187, 196, 194, 196, 195, 197, 190, 183, 181, 175, 169, 167, 161, 151, 147, 144, 128, 126, 118, 103, 94, 88, 80, 79, 88, 87, 79, 77, 77, 87, 101, 109, 104, 111, 109, 111, 116, 123, 129, 129, 139, 140, 136, 136, 144, 142, 140, 143, 144, 136, 143, 154, 152, 150, 145, 137, 143, 152, 153, 153, 146, 139, 144, 148, 151, 141, 153, 157, 162, 170, 183, 187, 192, 198, 207, 207, 213, 220, 220, 215, 216, 209, 199, 200, 194, 185, 173, 165, 166, 158, 146, 137, 126, 114, 102, 90, 79, 67, 56, 49, 40, 30, 24, 11, 9, 7, 4, 3, 3, 1, 3, 7, 9, 13, 19, 26, 39, 53, 63, 73, 84, 97, 106, 117, 133, 146, 156, 167, 171, 182, 186, 184, 190, 192, 195, 194, 190, 184, 181, 182, 177, 171, 162, 152, 144, 140, 129, 120, 109, 97, 90, 86, 81, 78, 78, 75, 73, 76, 83, 87, 95, 100, 103, 105, 109, 115, 123, 130, 134, 140, 142, 143, 145, 154, 156, 154, 156, 158, 154, 154, 159, 156, 157, 154, 150, 152, 159, 161, 163, 158, 153, 157, 163, 165, 163, 169, 168, 169, 178, 186, 188, 195, 203, 208, 214, 218, 219, 219, 222, 219, 215, 210, 202, 194, 191, 178, 166, 178, 171, 162, 153, 141, 128, 118, 106, 98, 87, 76, 70, 61, 51, 43, 33, 28, 23, 17, 11, 6, 1, 1, 3, 7, 10, 14, 21, 33, 44, 55, 65, 73, 83, 94, 103, 115, 126, 138, 148, 153, 163, 171, 174, 182, 185, 187, 188, 185, 184, 183, 183, 181, 177, 175, 169, 162, 157, 151, 141, 133, 121, 110, 105, 100, 95, 90, 86, 83, 84, 88, 89, 92, 97, 100, 101, 104, 105, 110, 119, 123, 127, 130, 134, 138, 144, 150, 149, 147, 149, 149, 152, 158, 157, 156, 155, 155, 157, 161, 163, 163, 160, 159, 159, 161, 161, 158, 159, 160, 163, 170, 176, 180, 184, 187, 190, 194, 200, 203, 203, 205, 204, 201, 200, 200, 195, 193, 185, 178, 193, 190, 184, 170, 155, 145, 141, 127, 119, 105, 92, 83, 80, 69, 58, 43, 36, 32, 31, 23, 10, 2, 1, 1, 7, 5, 4, 7, 20, 27, 36, 44, 46, 53, 67, 77, 89, 98, 108, 121, 127, 142, 152, 154, 161, 169, 175, 180, 180, 179, 180, 188, 189, 181, 181, 178, 172, 170, 161, 148, 137, 131, 117, 108, 102, 91, 83, 82, 78, 78, 85, 82, 81, 86, 93, 94, 99, 106, 110, 121, 133, 139, 145, 158, 161, 168, 178, 182, 181, 185, 182, 179, 187, 186, 182, 178, 175, 170, 174, 171, 162, 156, 153, 151, 150, 149, 144, 142, 143, 143, 150, 158, 158, 160, 166, 168, 173, 179, 186, 185, 187, 189, 194, 199, 203, 199, 199, 194, 193, 201, 194, 182, 167, 152, 137, 128, 120, 115, 113, 110, 107, 102, 97, 93, 88, 85, 84, 81, 75, 64, 49, 33, 18, 7, 1, 2, 9, 21, 33, 45, 56, 64, 71, 78, 84, 91, 99, 106, 111, 114, 118, 122, 125, 129, 136, 146, 156, 165, 175, 181, 186, 190, 193, 196, 201, 202, 201, 197, 190, 182, 176, 169, 163, 158, 152, 150, 145, 143, 140, 136, 129, 121, 112, 107, 102, 100, 99, 99, 97, 95, 92, 90, 91, 93, 96, 101, 105, 108, 109, 111, 113, 116, 116, 117, 115, 116, 117, 121, 125, 129, 133, 136, 138, 139, 141, 144, 150, 155, 163, 170, 175, 177, 177, 175, 172, 169, 166, 167, 172, 179, 190, 199, 207, 212, 211, 211, 206, 201, 200, 195, 188, 180, 170, 162, 156, 150, 145, 139, 130, 118, 104, 90, 78, 70, 66, 64, 62, 57, 47, 34, 23, 10, 3, 1, 3, 12, 21, 27, 34, 38, 39, 41, 43, 45, 46, 48, 51, 54, 57, 62, 68, 73, 77, 84, 94, 103, 112, 124, 135, 147, 157, 166, 175, 182, 185, 186, 187, 189, 192, 195, 198, 200, 200, 197, 195, 192, 189, 186, 181, 171, 160, 150, 143, 138, 137, 136, 136, 134, 131, 127, 123, 122, 122, 125, 128, 130, 129, 126, 121, 114, 109, 103, 98, 96, 96, 100, 104, 110, 115, 120, 125, 128, 131, 136, 142, 149, 156, 165, 174, 178, 181, 184, 190, 196, 201, 204, 207, 207, 205, 204, 205, 208, 210, 209, 208, 204, 200, 217, 230, 230, 212, 183, 148, 115, 97, 98, 114, 133, 142, 143, 129, 104, 87, 79, 82, 91, 102, 112, 113, 109, 102, 95, 86, 83, 88, 97, 89, 71, 47, 18, 1, 2, 16, 36, 56, 69, 73, 74, 74, 80, 82, 87, 97, 109, 123, 133, 151, 170, 186, 195, 203, 209, 207, 197, 186, 181, 185, 194, 207, 215, 216, 214, 205, 203, 200, 198, 191, 176, 147, 118, 90, 71, 55, 49, 55, 65, 68, 71, 79, 85, 96, 115, 141, 164, 176, 172, 162, 141, 121, 100, 84, 72, 65, 75, 93, 109, 118, 128, 131, 136, 139, 140, 136, 126, 109, 95, 94, 104, 115, 125, 143, 162, 174, 175, 170, 166, 157, 149, 156, 170, 184, 193, 192, 200, 206, 217, 163, 160, 155, 147, 138, 127, 115, 105, 99, 94, 91, 89, 85, 81, 76, 71, 66, 61, 57, 52, 47, 43, 41, 40, 40, 39, 36, 32, 26, 19, 13, 8, 4, 2, 1, 1, 2, 4, 8, 13, 18, 22, 25, 26, 27, 28, 33, 41, 49, 58, 66, 73, 80, 89, 99, 109, 117, 122, 128, 132, 136, 145, 152, 159, 165, 170, 175, 179, 183, 186, 188, 186, 185, 183, 183, 185, 188, 193, 196, 197, 196, 194, 192, 192, 195, 198, 201, 204, 207, 209, 211, 212, 212, 210, 206, 201, 196, 191, 187, 185, 183, 182, 183, 182, 181, 179, 176, 173, 170, 167, 164, 162, 163, 169, 178, 189, 197, 201, 201, 198, 194, 192, 190, 186, 182, 176, 171, 167, 163, 219, 210, 199, 186, 169, 150, 129, 112, 98, 89, 85, 84, 83, 80, 74, 66, 59, 53, 48, 46, 47, 52, 56, 59, 59, 56, 49, 42, 33, 23, 15, 8, 3, 1, 1, 4, 9, 15, 23, 30, 35, 38, 41, 42, 41, 42, 46, 50, 56, 62, 66, 69, 71, 76, 88, 106, 127, 147, 166, 179, 186, 190, 193, 194, 197, 199, 205, 209, 215, 219, 220, 215, 208, 200, 196, 191, 185, 181, 176, 169, 162, 158, 155, 155, 159, 164, 170, 177, 183, 187, 189, 188, 186, 183, 178, 172, 164, 151, 136, 120, 108, 98, 94, 92, 94, 95, 95, 94, 93, 96, 102, 113, 127, 148, 175, 200, 220, 235, 246, 251, 249, 251, 250, 248, 245, 240, 235, 228, 219, 159, 156, 152, 147, 139, 129, 117, 106, 96, 90, 86, 85, 84, 82, 79, 74, 67, 61, 55, 49, 45, 43, 41, 39, 37, 33, 29, 24, 19, 13, 9, 5, 3, 1, 1, 4, 8, 14, 21, 28, 34, 38, 42, 43, 42, 41, 41, 42, 44, 46, 48, 50, 52, 56, 66, 82, 101, 121, 139, 151, 157, 158, 157, 157, 159, 164, 172, 179, 186, 190, 192, 191, 191, 191, 193, 195, 196, 196, 193, 190, 185, 182, 180, 181, 184, 189, 195, 203, 210, 215, 219, 219, 218, 215, 212, 211, 211, 210, 208, 204, 197, 188, 178, 170, 164, 160, 157, 157, 157, 161, 166, 173, 180, 188, 195, 200, 202, 202, 201, 197, 192, 189, 185, 182, 178, 172, 167, 163, 159, 153, 149, 143, 137, 130, 122, 112, 101, 91, 82, 75, 70, 65, 61, 56, 50, 44, 39, 35, 31, 26, 23, 18, 15, 12, 9, 6, 4, 3, 2, 1, 1, 2, 2, 5, 6, 8, 9, 10, 10, 10, 11, 14, 18, 21, 24, 27, 29, 31, 33, 37, 43, 50, 58, 68, 82, 97, 110, 122, 133, 141, 147, 151, 155, 160, 165, 170, 175, 181, 186, 190, 194, 197, 200, 203, 205, 206, 206, 205, 203, 202, 202, 202, 203, 206, 209, 213, 218, 222, 226, 228, 228, 226, 224, 221, 218, 216, 215, 213, 211, 210, 207, 204, 202, 201, 201, 202, 203, 204, 205, 206, 207, 208, 211, 212, 212, 209, 206, 202, 197, 191, 186, 181, 176, 172, 167, 163, 158, 153, 173, 168, 163, 159, 154, 146, 134, 120, 106, 93, 84, 78, 74, 69, 63, 55, 48, 41, 37, 32, 29, 26, 22, 19, 16, 14, 11, 8, 5, 3, 1, 1, 1, 2, 5, 8, 12, 15, 19, 22, 25, 29, 35, 42, 48, 54, 59, 64, 70, 77, 85, 94, 101, 108, 115, 124, 135, 145, 156, 165, 170, 171, 170, 167, 167, 167, 170, 174, 179, 184, 187, 188, 189, 189, 190, 189, 188, 185, 180, 175, 169, 164, 161, 160, 162, 165, 169, 173, 177, 178, 178, 176, 173, 170, 166, 164, 162, 160, 159, 160, 162, 164, 171, 180, 191, 201, 210, 215, 215, 213, 210, 207, 206, 209, 211, 213, 212, 209, 204, 199, 194, 191, 188, 186, 185, 184, 181, 178, 173, 168, 159, 151, 146, 143, 137, 130, 119, 106, 92, 80, 69, 58, 49, 40, 32, 26, 21, 19, 15, 13, 13, 12, 12, 11, 10, 8, 5, 3, 1, 1, 2, 4, 9, 14, 19, 25, 31, 35, 38, 43, 50, 60, 71, 79, 87, 92, 97, 102, 107, 115, 124, 131, 137, 143, 149, 154, 158, 162, 166, 168, 168, 167, 164, 161, 160, 160, 161, 164, 166, 168, 168, 167, 166, 165, 164, 164, 163, 161, 157, 153, 150, 146, 143, 142, 142, 145, 149, 153, 154, 154, 152, 151, 149, 149, 154, 162, 168, 173, 178, 181, 182, 184, 190, 198, 207, 213, 218, 218, 218, 217, 217, 217, 220, 223, 224, 224, 222, 218, 214, 210, 208, 204, 201, 197, 193, 186, 178, 168, 152, 140, 130, 120, 113, 106, 97, 86, 75, 64, 53, 42, 32, 24, 16, 12, 12, 17, 22, 26, 28, 29, 26, 23, 20, 16, 13, 10, 8, 6, 4, 2, 1, 2, 6, 10, 12, 13, 13, 11, 10, 12, 19, 28, 38, 50, 60, 69, 76, 81, 83, 86, 88, 90, 93, 98, 105, 112, 118, 125, 129, 132, 134, 139, 147, 158, 171, 183, 192, 197, 199, 200, 201, 204, 207, 210, 212, 214, 212, 206, 198, 191, 182, 176, 172, 170, 170, 169, 169, 168, 167, 166, 163, 160, 158, 158, 163, 169, 179, 189, 198, 206, 214, 222, 229, 237, 245, 250, 253, 253, 251, 250, 248, 248, 247, 245, 242, 237, 230, 224, 217, 210, 204, 198, 191, 184, 175, 165, 152, 144, 135, 128, 120, 114, 105, 95, 85, 72, 63, 55, 48, 42, 37, 31, 26, 21, 19, 18, 17, 17, 18, 16, 13, 8, 4, 2, 1, 3, 4, 6, 7, 8, 10, 14, 18, 24, 32, 39, 45, 51, 57, 64, 71, 80, 87, 93, 97, 99, 100, 99, 100, 101, 102, 103, 106, 112, 121, 129, 136, 139, 140, 139, 137, 141, 147, 154, 161, 167, 171, 175, 178, 182, 184, 184, 183, 179, 174, 169, 163, 158, 155, 152, 150, 149, 148, 149, 149, 150, 152, 158, 165, 172, 179, 183, 187, 191, 194, 200, 209, 217, 224, 231, 237, 242, 245, 250, 253, 253, 251, 249, 245, 241, 238, 236, 233, 230, 228, 223, 217, 210, 201, 193, 185, 177, 169, 161, 154, 144, 127, 120, 115, 110, 106, 102, 96, 89, 81, 73, 66, 60, 54, 49, 41, 33, 26, 20, 17, 17, 17, 18, 18, 18, 15, 10, 7, 3, 2, 2, 3, 4, 7, 12, 19, 26, 36, 49, 60, 70, 79, 87, 93, 97, 101, 104, 106, 108, 110, 111, 111, 112, 111, 109, 107, 106, 107, 111, 115, 117, 116, 114, 113, 113, 117, 126, 134, 140, 144, 148, 154, 162, 170, 177, 182, 186, 184, 179, 174, 169, 163, 159, 155, 151, 148, 146, 146, 146, 148, 150, 154, 161, 172, 183, 193, 202, 209, 213, 216, 221, 226, 232, 238, 244, 248, 250, 254, 255, 255, 253, 251, 248, 244, 238, 232, 224, 217, 212, 206, 202, 196, 188, 178, 169, 159, 150, 141, 134, 127, 141, 132, 123, 116, 111, 105, 98, 92, 84, 77, 70, 64, 57, 48, 38, 27, 18, 12, 10, 13, 16, 19, 19, 18, 14, 10, 7, 5, 5, 5, 3, 2, 1, 3, 7, 14, 23, 32, 38, 44, 51, 56, 62, 70, 79, 89, 97, 106, 113, 118, 119, 121, 123, 126, 129, 133, 139, 144, 148, 150, 149, 148, 148, 148, 151, 153, 155, 154, 153, 152, 153, 155, 160, 162, 162, 162, 159, 155, 151, 147, 145, 145, 147, 148, 150, 150, 151, 149, 149, 148, 151, 156, 162, 169, 177, 183, 188, 192, 198, 208, 217, 226, 233, 239, 240, 240, 241, 242, 244, 245, 247, 248, 246, 243, 240, 235, 230, 224, 217, 212, 206, 198, 191, 185, 177, 169, 160, 151, 141, 148, 134, 119, 105, 97, 91, 89, 85, 81, 75, 67, 60, 53, 46, 38, 32, 26, 25, 26, 30, 33, 35, 33, 31, 28, 24, 21, 19, 17, 18, 20, 21, 24, 28, 33, 37, 44, 55, 68, 81, 95, 108, 119, 128, 135, 142, 150, 160, 169, 177, 181, 185, 186, 185, 183, 183, 186, 189, 193, 195, 196, 194, 190, 181, 169, 157, 146, 135, 126, 122, 121, 121, 120, 115, 108, 99, 90, 82, 77, 73, 74, 79, 84, 92, 97, 101, 102, 99, 95, 92, 92, 97, 107, 120, 133, 145, 154, 162, 169, 178, 189, 201, 213, 223, 231, 238, 244, 249, 253, 254, 255, 255, 253, 251, 248, 241, 233, 225, 216, 209, 203, 197, 192, 187, 182, 175, 167, 158, 148, 156, 150, 144, 135, 123, 111, 97, 83, 73, 66, 62, 63, 64, 63, 60, 56, 49, 43, 39, 37, 36, 36, 34, 33, 33, 33, 36, 38, 39, 39, 37, 33, 29, 26, 25, 26, 31, 41, 53, 66, 79, 90, 98, 105, 110, 118, 129, 143, 159, 172, 182, 191, 195, 197, 202, 208, 217, 224, 229, 231, 230, 225, 220, 213, 205, 199, 193, 186, 177, 171, 164, 156, 148, 138, 129, 118, 103, 88, 73, 60, 49, 44, 42, 45, 47, 48, 46, 40, 35, 30, 29, 33, 44, 61, 82, 102, 120, 136, 148, 161, 175, 191, 208, 223, 235, 243, 248, 248, 248, 249, 250, 253, 255, 254, 252, 246, 238, 229, 220, 213, 209, 203, 198, 192, 184, 176, 169, 162, 156, 135, 128, 123, 117, 110, 102, 93, 84, 78, 73, 70, 68, 65, 61, 55, 51, 48, 47, 49, 53, 56, 58, 60, 60, 59, 58, 56, 52, 47, 40, 32, 25, 20, 18, 16, 15, 14, 13, 13, 11, 11, 11, 13, 15, 19, 25, 34, 43, 52, 61, 68, 73, 78, 85, 97, 112, 128, 142, 154, 162, 168, 176, 187, 198, 209, 217, 221, 219, 214, 210, 206, 203, 201, 200, 200, 198, 194, 186, 176, 166, 157, 151, 148, 149, 148, 144, 138, 129, 120, 114, 111, 114, 121, 130, 140, 149, 155, 159, 163, 172, 182, 195, 209, 220, 228, 231, 231, 231, 234, 239, 245, 251, 255, 254, 248, 238, 228, 217, 208, 200, 194, 188, 183, 176, 168, 159, 150, 142, 135, 107, 95, 84, 72, 61, 52, 43, 34, 27, 21, 15, 12, 9, 7, 6, 7, 10, 14, 18, 23, 29, 34, 40, 43, 47, 51, 53, 55, 55, 55, 54, 51, 49, 45, 41, 36, 31, 26, 21, 18, 15, 11, 10, 10, 10, 11, 13, 16, 19, 23, 27, 33, 38, 43, 49, 57, 68, 77, 88, 99, 110, 123, 134, 147, 157, 167, 178, 186, 195, 203, 211, 218, 223, 228, 232, 234, 235, 235, 233, 232, 229, 225, 222, 219, 214, 209, 204, 199, 194, 191, 189, 188, 191, 193, 197, 202, 207, 213, 217, 224, 229, 234, 239, 243, 247, 250, 253, 254, 255, 255, 254, 254, 251, 249, 245, 239, 232, 224, 216, 207, 198, 188, 177, 166, 155, 144, 131, 120, 107, 118, 104, 89, 73, 59, 48, 40, 32, 24, 15, 7, 3, 1, 1, 4, 7, 11, 15, 19, 24, 31, 36, 43, 46, 50, 55, 59, 63, 62, 62, 61, 62, 61, 61, 58, 54, 45, 37, 31, 29, 29, 30, 31, 33, 29, 25, 22, 24, 29, 35, 41, 46, 47, 47, 47, 50, 57, 64, 72, 79, 90, 104, 118, 133, 143, 155, 165, 174, 185, 194, 207, 215, 221, 228, 233, 238, 242, 244, 242, 241, 234, 227, 224, 223, 223, 219, 212, 205, 195, 189, 187, 189, 194, 198, 203, 206, 209, 211, 213, 216, 217, 218, 221, 225, 232, 235, 238, 239, 240, 240, 240, 242, 243, 242, 238, 231, 224, 216, 210, 205, 199, 189, 179, 165, 154, 147, 139, 131, 118, 132, 113, 91, 69, 52, 43, 39, 35, 30, 18, 7, 1, 2, 7, 16, 23, 29, 29, 29, 31, 37, 45, 54, 56, 58, 62, 65, 66, 63, 60, 58, 59, 60, 62, 62, 55, 42, 28, 18, 17, 20, 28, 36, 40, 35, 25, 17, 16, 23, 35, 47, 55, 57, 52, 46, 45, 49, 54, 57, 62, 74, 91, 110, 128, 140, 151, 159, 164, 175, 188, 204, 216, 222, 230, 235, 241, 246, 249, 249, 246, 234, 223, 216, 216, 220, 219, 213, 201, 186, 177, 178, 186, 197, 206, 212, 215, 218, 219, 219, 219, 216, 212, 212, 215, 222, 226, 231, 236, 240, 244, 246, 247, 248, 246, 239, 230, 221, 212, 208, 205, 199, 189, 175, 159, 150, 148, 148, 145, 132, 146, 122, 94, 67, 46, 40, 44, 47, 47, 34, 20, 15, 19, 33, 50, 62, 67, 64, 57, 53, 58, 66, 76, 79, 77, 78, 77, 75, 69, 61, 57, 58, 59, 64, 63, 56, 40, 22, 6, 6, 12, 26, 40, 48, 42, 27, 12, 10, 19, 36, 57, 72, 75, 68, 58, 52, 50, 51, 51, 52, 63, 83, 106, 125, 137, 146, 150, 151, 160, 175, 196, 210, 218, 225, 228, 231, 237, 242, 242, 239, 221, 203, 192, 189, 198, 201, 196, 183, 166, 155, 161, 175, 192, 207, 215, 216, 219, 218, 219, 217, 209, 199, 196, 200, 209, 213, 220, 231, 244, 251, 255, 255, 254, 247, 236, 226, 215, 206, 200, 197, 193, 181, 163, 146, 139, 148, 157, 160, 146, 154, 127, 96, 69, 49, 46, 54, 64, 68, 58, 45, 41, 49, 69, 92, 108, 113, 105, 93, 86, 88, 97, 107, 109, 105, 102, 99, 93, 85, 74, 68, 68, 69, 73, 73, 65, 49, 28, 11, 10, 17, 34, 52, 60, 53, 33, 15, 11, 21, 41, 67, 87, 92, 86, 75, 66, 61, 57, 54, 52, 61, 81, 104, 124, 135, 141, 141, 138, 145, 161, 182, 197, 204, 209, 210, 211, 216, 221, 222, 217, 197, 175, 159, 155, 165, 172, 169, 157, 140, 129, 139, 158, 178, 196, 204, 204, 206, 206, 207, 203, 194, 183, 178, 181, 189, 195, 206, 222, 239, 251, 255, 253, 249, 239, 225, 214, 202, 192, 187, 185, 179, 165, 147, 130, 127, 140, 158, 165, 154, 157, 129, 97, 71, 52, 51, 64, 79, 87, 79, 68, 65, 76, 101, 128, 147, 151, 141, 126, 115, 115, 124, 134, 135, 128, 122, 116, 108, 98, 84, 76, 75, 75, 79, 77, 70, 52, 30, 11, 10, 17, 36, 55, 64, 56, 35, 14, 9, 20, 42, 71, 95, 103, 99, 89, 77, 71, 65, 59, 56, 64, 84, 108, 126, 136, 141, 138, 132, 137, 152, 174, 189, 195, 198, 197, 196, 199, 203, 204, 199, 175, 152, 134, 127, 138, 146, 145, 134, 119, 109, 121, 144, 166, 185, 194, 193, 195, 195, 196, 193, 184, 170, 165, 169, 178, 184, 197, 217, 238, 251, 255, 250, 245, 232, 215, 204, 192, 182, 176, 173, 166, 152, 132, 117, 116, 133, 155, 166, 157, 144, 117, 86, 61, 43, 45, 63, 84, 97, 92, 83, 84, 100, 126, 155, 175, 178, 167, 148, 133, 129, 136, 145, 145, 135, 126, 117, 106, 95, 79, 70, 67, 66, 68, 65, 57, 39, 18, 1, 1, 10, 31, 52, 64, 57, 37, 19, 18, 31, 55, 86, 112, 120, 117, 107, 92, 82, 72, 61, 53, 60, 81, 103, 121, 129, 132, 128, 123, 130, 147, 169, 187, 198, 204, 203, 201, 206, 212, 212, 204, 175, 148, 126, 115, 127, 136, 137, 128, 114, 104, 117, 142, 163, 180, 187, 185, 187, 186, 189, 189, 184, 171, 163, 162, 171, 177, 191, 212, 233, 249, 252, 245, 238, 226, 213, 205, 194, 183, 176, 172, 164, 147, 124, 106, 103, 118, 141, 152, 144, 117, 89, 64, 47, 31, 34, 55, 84, 102, 100, 96, 104, 126, 153, 178, 196, 196, 184, 163, 144, 136, 140, 145, 142, 128, 115, 107, 97, 88, 73, 65, 62, 58, 61, 58, 51, 35, 16, 1, 2, 11, 30, 53, 67, 64, 49, 35, 39, 54, 82, 113, 139, 147, 144, 132, 114, 100, 87, 72, 59, 61, 79, 97, 111, 115, 117, 114, 112, 124, 142, 162, 186, 206, 220, 222, 218, 228, 235, 231, 219, 185, 157, 131, 116, 125, 132, 134, 130, 118, 110, 122, 143, 161, 171, 177, 174, 174, 171, 176, 183, 181, 168, 156, 152, 158, 161, 171, 192, 212, 228, 232, 225, 221, 212, 205, 203, 195, 185, 177, 174, 167, 146, 118, 97, 89, 98, 114, 125, 117, 84, 61, 48, 40, 29, 31, 48, 78, 100, 105, 109, 124, 147, 171, 187, 195, 193, 181, 163, 142, 128, 128, 131, 125, 107, 94, 86, 79, 73, 63, 61, 63, 61, 63, 58, 52, 44, 33, 24, 24, 29, 45, 63, 76, 75, 69, 64, 71, 88, 113, 140, 161, 168, 167, 158, 139, 123, 106, 92, 77, 75, 88, 94, 103, 104, 102, 101, 101, 117, 134, 150, 176, 206, 229, 233, 231, 247, 255, 249, 236, 202, 179, 153, 133, 139, 141, 142, 142, 134, 128, 135, 151, 161, 160, 161, 156, 156, 155, 159, 173, 178, 165, 153, 144, 147, 144, 146, 160, 174, 188, 192, 187, 190, 186, 186, 191, 190, 183, 177, 176, 169, 147, 121, 100, 84, 83, 90, 94, 84, 69, 52, 46, 45, 37, 35, 45, 71, 93, 105, 116, 134, 154, 169, 175, 175, 168, 159, 145, 127, 113, 110, 110, 103, 86, 74, 69, 66, 64, 61, 63, 68, 71, 73, 68, 65, 66, 64, 62, 64, 67, 75, 83, 91, 91, 91, 94, 103, 119, 137, 156, 170, 176, 179, 173, 159, 145, 128, 114, 100, 96, 102, 100, 103, 102, 99, 98, 102, 120, 134, 141, 163, 193, 220, 225, 224, 244, 255, 251, 239, 212, 197, 176, 157, 158, 155, 155, 157, 150, 145, 146, 156, 160, 152, 150, 146, 145, 144, 148, 164, 170, 159, 146, 133, 133, 127, 124, 132, 139, 150, 154, 151, 156, 156, 161, 169, 170, 166, 162, 164, 162, 146, 127, 112, 95, 85, 81, 80, 69, 58, 44, 42, 42, 36, 33, 40, 61, 83, 99, 114, 133, 152, 161, 163, 160, 152, 145, 134, 119, 106, 100, 99, 92, 76, 66, 62, 62, 65, 67, 72, 80, 86, 88, 84, 81, 84, 87, 89, 91, 93, 96, 99, 103, 105, 110, 117, 126, 139, 153, 166, 174, 179, 183, 182, 173, 161, 146, 135, 124, 121, 124, 116, 115, 111, 105, 103, 109, 128, 138, 139, 157, 187, 215, 221, 220, 242, 255, 251, 237, 214, 202, 185, 166, 166, 160, 161, 164, 159, 154, 151, 156, 156, 142, 139, 135, 133, 131, 134, 152, 161, 155, 141, 127, 123, 117, 113, 117, 120, 127, 129, 126, 130, 132, 140, 149, 151, 149, 148, 152, 152, 139, 125, 113, 97, 82, 73, 68, 58, 59, 47, 44, 42, 37, 38, 43, 60, 80, 95, 108, 126, 147, 158, 158, 156, 152, 147, 135, 121, 108, 102, 101, 96, 82, 72, 65, 66, 70, 71, 76, 86, 94, 96, 91, 88, 89, 91, 95, 96, 94, 96, 98, 102, 103, 108, 117, 129, 142, 157, 170, 178, 183, 187, 188, 181, 172, 161, 152, 144, 144, 148, 140, 135, 127, 119, 118, 126, 147, 155, 150, 165, 195, 221, 224, 219, 242, 255, 249, 231, 205, 195, 177, 155, 156, 152, 151, 157, 153, 149, 146, 152, 153, 137, 131, 129, 129, 129, 135, 156, 170, 165, 149, 130, 118, 106, 102, 104, 103, 104, 106, 102, 101, 102, 113, 125, 131, 131, 134, 140, 140, 132, 123, 114, 99, 86, 76, 69, 59, 76, 67, 63, 60, 58, 61, 63, 71, 83, 95, 102, 119, 144, 163, 164, 161, 161, 155, 136, 121, 109, 104, 103, 100, 87, 73, 60, 59, 61, 61, 61, 72, 84, 85, 78, 70, 66, 65, 71, 75, 73, 75, 83, 92, 92, 96, 110, 131, 147, 168, 187, 196, 200, 202, 203, 197, 189, 182, 178, 171, 176, 183, 171, 161, 145, 135, 136, 148, 173, 178, 167, 177, 206, 233, 229, 220, 243, 255, 243, 218, 187, 176, 154, 128, 131, 130, 131, 143, 146, 146, 147, 158, 166, 146, 138, 142, 147, 152, 161, 188, 205, 195, 175, 146, 117, 92, 87, 88, 81, 72, 71, 63, 56, 51, 62, 79, 89, 92, 102, 114, 121, 122, 123, 122, 112, 105, 96, 87, 76, 107, 106, 107, 109, 113, 121, 120, 114, 110, 109, 109, 124, 155, 181, 187, 185, 187, 179, 150, 132, 124, 119, 116, 114, 100, 81, 59, 47, 47, 38, 26, 32, 44, 42, 27, 14, 2, 1, 14, 29, 34, 41, 63, 85, 88, 94, 116, 152, 176, 202, 228, 240, 239, 231, 225, 214, 207, 207, 207, 201, 205, 210, 194, 169, 141, 127, 132, 149, 175, 180, 163, 166, 192, 218, 207, 196, 222, 234, 220, 191, 157, 147, 125, 96, 106, 108, 106, 125, 136, 142, 147, 162, 177, 155, 141, 153, 161, 168, 183, 213, 232, 217, 198, 175, 131, 92, 88, 90, 77, 59, 59, 49, 29, 16, 20, 32, 41, 43, 56, 74, 89, 104, 120, 132, 135, 139, 134, 117, 107, 147, 152, 155, 158, 167, 174, 169, 154, 140, 129, 120, 124, 146, 170, 176, 175, 178, 170, 145, 133, 130, 129, 129, 128, 120, 104, 85, 75, 72, 60, 43, 43, 48, 41, 26, 14, 3, 1, 12, 29, 40, 48, 71, 92, 97, 102, 122, 154, 178, 202, 226, 234, 228, 214, 205, 195, 191, 196, 201, 198, 199, 200, 183, 158, 131, 119, 123, 134, 149, 151, 136, 134, 147, 160, 151, 142, 156, 165, 157, 140, 119, 118, 106, 88, 96, 101, 102, 116, 127, 135, 140, 154, 171, 157, 146, 156, 163, 168, 177, 197, 208, 196, 189, 179, 143, 112, 108, 111, 101, 85, 86, 79, 59, 45, 42, 43, 41, 38, 48, 63, 79, 99, 122, 143, 153, 162, 162, 151, 147, 173, 181, 185, 189, 199, 207, 198, 176, 154, 136, 122, 120, 136, 158, 164, 163, 165, 157, 131, 119, 119, 119, 120, 122, 118, 105, 90, 82, 79, 67, 52, 50, 54, 47, 31, 18, 6, 1, 12, 28, 37, 46, 65, 84, 87, 92, 112, 145, 172, 197, 222, 233, 225, 210, 200, 192, 191, 199, 207, 208, 209, 208, 191, 164, 135, 121, 123, 131, 140, 142, 129, 124, 128, 134, 125, 117, 125, 131, 126, 112, 97, 98, 93, 79, 87, 93, 94, 107, 118, 128, 138, 154, 177, 169, 160, 172, 180, 184, 191, 204, 212, 199, 195, 191, 156, 123, 118, 120, 108, 88, 89, 85, 65, 51, 43, 40, 32, 26, 35, 51, 68, 93, 125, 150, 167, 180, 182, 173, 173, 152, 160, 167, 161, 161, 184, 204, 199, 152, 92, 78, 104, 128, 147, 142, 151, 165, 178, 157, 145, 154, 154, 159, 147, 103, 68, 79, 113, 118, 100, 68, 84, 118, 132, 98, 79, 76, 85, 117, 99, 43, 9, 12, 46, 74, 83, 85, 113, 142, 188, 199, 165, 126, 84, 97, 107, 121, 119, 133, 156, 200, 255, 244, 196, 163, 120, 127, 160, 157, 145, 122, 140, 198, 232, 213, 215, 223, 201, 191, 166, 113, 103, 79, 68, 93, 117, 135, 169, 161, 139, 148, 166, 188, 143, 87, 79, 80, 63, 63, 98, 116, 124, 143, 156, 121, 70, 70, 92, 97, 70, 83, 82, 81, 83, 83, 99, 108, 94, 99, 120, 113, 103, 122, 162, 178, 174, 154, 141, 152, 159, 145, 116, 132, 154, 160, 154, 134, 88, 68, 67, 64, 70, 106, 156, 194, 198, 165, 118, 122, 166, 184, 186, 145, 109, 84, 118, 179, 202, 147, 73, 56, 108, 147, 90, 61, 47, 72, 108, 121, 82, 45, 6, 14, 61, 102, 97, 71, 87, 138, 170, 166, 127, 71, 80, 111, 141, 143, 140, 142, 181, 226, 233, 182, 126, 98, 123, 192, 204, 157, 106, 135, 218, 255, 207, 127, 88, 102, 154, 190, 179, 159, 110, 74, 102, 122, 122, 111, 91, 99, 139, 158, 171, 152, 155, 162, 145, 114, 92, 115, 148, 168, 192, 180, 101, 40, 61, 97, 105, 91, 97, 112, 140, 147, 131, 122, 108, 63, 55, 93, 128, 153, 158, 155, 163, 176, 179, 169, 159, 160, 162, 152, 149, 152, 148, 142, 125, 110, 103, 101, 103, 110, 121, 137, 159, 176, 188, 166, 153, 161, 179, 186, 168, 142, 108, 118, 134, 130, 115, 89, 79, 98, 113, 93, 73, 49, 50, 61, 68, 54, 42, 44, 54, 59, 65, 72, 80, 91, 104, 106, 90, 83, 92, 109, 132, 143, 144, 149, 159, 168, 183, 184, 164, 150, 148, 158, 163, 176, 187, 184, 194, 225, 255, 252, 233, 214, 188, 176, 180, 180, 175, 156, 135, 148, 167, 175, 165, 149, 141, 155, 168, 168, 143, 121, 114, 120, 120, 125, 123, 102, 86, 104, 115, 91, 63, 54, 53, 62, 64, 70, 71, 73, 79, 95, 105, 102, 95, 99, 117, 118, 120, 126, 133, 138, 136, 140, 144, 160, 147, 159, 148, 140, 131, 128, 128, 130, 114, 99, 99, 115, 129, 136, 143, 157, 184, 214, 222, 211, 202, 219, 233, 236, 212, 175, 168, 170, 162, 144, 115, 97, 99, 112, 108, 85, 60, 51, 48, 58, 51, 48, 44, 38, 33, 29, 34, 40, 54, 70, 74, 71, 71, 79, 93, 104, 109, 119, 131, 146, 163, 174, 173, 165, 164, 179, 193, 191, 190, 195, 207, 226, 241, 249, 255, 243, 235, 221, 201, 183, 172, 177, 179, 170, 168, 159, 152, 146, 135, 132, 145, 146, 133, 111, 111, 117, 126, 123, 114, 109, 87, 56, 44, 46, 39, 32, 43, 53, 57, 45, 48, 62, 78, 78, 80, 84, 93, 97, 104, 123, 127, 128, 131, 138, 142, 125, 116, 129, 147, 135, 158, 148, 144, 129, 108, 119, 122, 110, 88, 75, 97, 110, 128, 139, 133, 166, 202, 225, 220, 199, 210, 231, 230, 216, 179, 175, 167, 158, 140, 107, 90, 88, 103, 109, 96, 78, 71, 68, 78, 77, 83, 81, 61, 40, 35, 38, 37, 45, 65, 75, 75, 81, 98, 115, 112, 110, 118, 134, 143, 155, 162, 156, 151, 162, 174, 183, 183, 178, 182, 193, 213, 227, 238, 255, 255, 246, 233, 213, 195, 177, 174, 168, 154, 149, 143, 138, 140, 139, 142, 142, 137, 129, 116, 122, 134, 132, 116, 107, 113, 97, 56, 33, 30, 28, 26, 35, 55, 71, 68, 65, 73, 93, 95, 92, 90, 103, 117, 123, 126, 115, 118, 131, 141, 143, 126, 113, 124, 135, 119, 140, 135, 131, 113, 91, 100, 114, 112, 81, 69, 87, 109, 121, 124, 115, 149, 193, 225, 214, 191, 196, 233, 234, 216, 177, 164, 159, 156, 135, 112, 96, 90, 110, 122, 113, 89, 75, 68, 80, 88, 100, 101, 80, 53, 50, 56, 55, 56, 69, 83, 87, 90, 112, 131, 124, 115, 124, 141, 151, 159, 159, 149, 145, 161, 188, 204, 208, 202, 195, 206, 222, 228, 234, 248, 255, 247, 234, 226, 208, 192, 181, 175, 165, 157, 148, 138, 136, 143, 145, 146, 138, 127, 111, 113, 122, 124, 108, 106, 105, 96, 60, 32, 19, 23, 22, 26, 44, 61, 56, 53, 62, 88, 94, 89, 84, 97, 117, 129, 127, 106, 106, 116, 131, 126, 117, 105, 116, 119, 133, 148, 139, 130, 110, 83, 96, 117, 112, 84, 79, 98, 116, 131, 130, 122, 158, 204, 232, 228, 205, 213, 239, 244, 232, 196, 173, 165, 159, 144, 127, 107, 92, 108, 131, 122, 97, 72, 58, 71, 91, 108, 111, 87, 57, 51, 60, 58, 58, 66, 77, 78, 82, 106, 129, 121, 104, 115, 135, 150, 161, 154, 137, 134, 153, 185, 209, 215, 208, 199, 209, 226, 229, 227, 243, 255, 245, 235, 225, 205, 185, 180, 178, 170, 150, 136, 128, 130, 139, 140, 138, 133, 121, 102, 104, 115, 112, 101, 96, 93, 84, 54, 19, 7, 10, 11, 15, 35, 53, 48, 40, 54, 82, 95, 93, 85, 97, 121, 140, 136, 109, 106, 120, 136, 134, 115, 112, 119, 133, 129, 153, 151, 140, 114, 77, 84, 120, 118, 88, 71, 94, 122, 133, 131, 116, 142, 195, 240, 241, 212, 198, 234, 250, 241, 202, 172, 160, 159, 143, 121, 108, 94, 116, 130, 124, 100, 81, 68, 78, 93, 108, 115, 101, 72, 58, 65, 60, 60, 66, 84, 87, 89, 108, 130, 124, 109, 118, 135, 147, 153, 148, 130, 130, 144, 175, 205, 209, 198, 187, 197, 217, 214, 209, 229, 248, 240, 230, 218, 194, 175, 168, 169, 165, 145, 128, 116, 119, 133, 136, 134, 129, 118, 94, 96, 114, 113, 106, 92, 87, 84, 58, 21, 1, 4, 10, 13, 40, 55, 49, 45, 57, 95, 111, 106, 98, 113, 133, 152, 145, 121, 117, 123, 134, 137, 121, 123, 124, 129, 76, 122, 115, 84, 60, 22, 58, 125, 133, 107, 104, 82, 49, 34, 62, 75, 117, 145, 183, 176, 146, 114, 173, 181, 179, 127, 107, 111, 116, 107, 100, 134, 151, 190, 186, 152, 102, 91, 89, 121, 146, 141, 135, 126, 121, 130, 158, 155, 145, 136, 133, 125, 145, 189, 212, 183, 160, 175, 183, 170, 191, 190, 144, 113, 19, 46, 120, 183, 184, 218, 171, 146, 134, 156, 220, 255, 229, 190, 172, 130, 101, 130, 195, 234, 206, 157, 108, 86, 98, 124, 162, 177, 159, 90, 76, 102, 139, 170, 190, 176, 145, 82, 15, 6, 50, 82, 86, 96, 99, 65, 60, 66, 124, 139, 144, 119, 120, 104, 99, 105, 116, 142, 155, 137, 83, 55, 69, 56, 76, 3, 1, 4, 19, 34, 47, 80, 115, 127, 108, 67, 35, 22, 17, 23, 31, 53, 83, 117, 147, 161, 159, 147, 111, 80, 53, 42, 45, 61, 84, 106, 126, 142, 160, 165, 147, 112, 77, 55, 60, 82, 115, 150, 175, 191, 210, 232, 230, 196, 151, 122, 121, 139, 155, 160, 170, 192, 220, 244, 249, 239, 205, 157, 125, 125, 130, 145, 156, 171, 204, 230, 241, 246, 241, 231, 208, 181, 169, 163, 157, 162, 179, 206, 227, 231, 228, 215, 192, 160, 133, 120, 114, 105, 96, 108, 138, 170, 188, 189, 174, 146, 102, 69, 55, 59, 65, 68, 86, 116, 145, 161, 154, 141, 117, 87, 56, 46, 51, 58, 63, 75, 102, 129, 136, 122, 91, 64, 31, 3, 9, 17, 29, 44, 64, 89, 117, 134, 129, 104, 67, 36, 22, 22, 27, 33, 51, 88, 131, 155, 152, 131, 101, 70, 44, 30, 26, 34, 50, 75, 104, 131, 146, 151, 144, 125, 91, 55, 39, 51, 83, 114, 142, 170, 194, 211, 212, 193, 159, 125, 104, 102, 113, 126, 138, 157, 190, 228, 244, 231, 201, 163, 131, 111, 113, 115, 124, 144, 176, 217, 246, 255, 250, 237, 215, 189, 166, 155, 149, 149, 162, 187, 215, 237, 245, 242, 220, 183, 144, 119, 112, 112, 111, 118, 139, 170, 194, 203, 198, 177, 148, 114, 89, 80, 79, 87, 107, 140, 170, 186, 185, 168, 143, 114, 86, 65, 58, 60, 68, 83, 103, 127, 141, 138, 124, 94, 56, 22, 9, 18, 28, 39, 55, 80, 110, 134, 138, 116, 80, 47, 28, 24, 30, 37, 48, 68, 95, 121, 132, 118, 89, 58, 35, 24, 17, 16, 26, 47, 73, 99, 121, 129, 120, 101, 77, 56, 44, 48, 66, 91, 116, 141, 165, 183, 190, 178, 148, 116, 98, 96, 104, 118, 133, 148, 170, 193, 210, 211, 191, 164, 138, 121, 113, 116, 126, 142, 165, 196, 230, 251, 251, 241, 225, 204, 181, 165, 162, 168, 177, 192, 215, 240, 255, 252, 232, 203, 176, 151, 137, 136, 137, 136, 146, 173, 205, 219, 210, 188, 162, 140, 118, 103, 101, 108, 124, 149, 177, 198, 199, 185, 160, 135, 109, 85, 72, 72, 83, 97, 110, 126, 142, 144, 128, 99, 67, 42, 22, 18, 47, 56, 67, 83, 101, 113, 115, 102, 79, 52, 30, 25, 31, 46, 58, 66, 81, 97, 109, 105, 84, 54, 28, 14, 16, 28, 39, 48, 60, 73, 89, 102, 97, 78, 55, 38, 32, 38, 57, 77, 98, 115, 134, 152, 158, 152, 130, 104, 86, 84, 96, 112, 127, 140, 154, 173, 187, 190, 178, 155, 133, 118, 118, 127, 127, 141, 160, 187, 214, 237, 246, 238, 221, 198, 178, 169, 170, 179, 190, 198, 211, 229, 248, 255, 241, 215, 185, 167, 159, 159, 163, 166, 174, 188, 208, 223, 220, 204, 181, 162, 147, 138, 136, 139, 146, 159, 178, 194, 200, 193, 174, 144, 119, 102, 96, 99, 106, 111, 118, 128, 140, 145, 136, 109, 80, 56, 47, 45, 47, 75, 86, 93, 100, 106, 107, 98, 80, 56, 37, 28, 34, 48, 64, 77, 81, 85, 87, 85, 72, 52, 28, 7, 1, 11, 28, 44, 54, 63, 70, 76, 76, 65, 44, 24, 16, 22, 39, 62, 80, 94, 106, 119, 128, 130, 120, 99, 79, 72, 79, 98, 120, 137, 147, 155, 163, 164, 159, 147, 128, 111, 106, 114, 131, 146, 167, 184, 201, 216, 229, 230, 217, 196, 177, 170, 176, 190, 205, 217, 227, 238, 247, 249, 238, 217, 194, 174, 166, 171, 183, 194, 202, 209, 217, 225, 227, 215, 194, 170, 153, 149, 156, 169, 179, 185, 192, 199, 204, 201, 185, 161, 136, 121, 115, 119, 127, 133, 136, 143, 148, 149, 138, 117, 88, 65, 53, 54, 64, 75, 97, 108, 114, 112, 109, 99, 81, 62, 44, 35, 37, 51, 69, 87, 96, 97, 92, 83, 72, 53, 30, 11, 1, 7, 26, 48, 63, 68, 68, 62, 56, 50, 36, 20, 10, 12, 27, 50, 74, 94, 104, 109, 113, 108, 100, 87, 72, 65, 70, 85, 107, 131, 145, 151, 150, 147, 138, 127, 114, 100, 94, 100, 119, 146, 156, 179, 192, 200, 208, 211, 203, 186, 169, 160, 167, 185, 204, 224, 236, 242, 244, 243, 235, 218, 197, 179, 168, 170, 181, 199, 212, 221, 224, 222, 218, 212, 196, 178, 163, 156, 161, 176, 195, 207, 213, 215, 212, 208, 197, 176, 152, 131, 124, 129, 142, 156, 162, 161, 158, 151, 141, 122, 98, 74, 60, 59, 69, 84, 97, 114, 118, 113, 101, 88, 73, 57, 47, 42, 45, 56, 72, 87, 96, 95, 86, 71, 55, 40, 24, 9, 3, 5, 19, 39, 56, 61, 57, 48, 39, 28, 20, 11, 4, 6, 18, 39, 64, 84, 95, 98, 95, 88, 77, 67, 61, 60, 65, 81, 101, 120, 135, 143, 141, 133, 123, 109, 98, 92, 90, 97, 114, 141, 166, 178, 194, 201, 200, 197, 191, 182, 171, 164, 171, 190, 215, 235, 249, 255, 252, 245, 235, 222, 206, 188, 180, 182, 193, 209, 223, 231, 233, 228, 217, 204, 192, 179, 171, 169, 176, 190, 205, 220, 229, 229, 223, 212, 200, 185, 168, 153, 144, 149, 159, 172, 179, 177, 167, 154, 139, 123, 102, 85, 71, 68, 76, 91, 107, 114, 113, 111, 102, 88, 74, 60, 49, 47, 51, 61, 72, 82, 89, 89, 79, 61, 40, 25, 19, 16, 13, 15, 22, 36, 49, 56, 54, 42, 28, 16, 7, 6, 7, 12, 24, 42, 59, 73, 81, 80, 78, 72, 67, 58, 53, 55, 63, 77, 96, 111, 121, 128, 128, 120, 108, 97, 90, 91, 99, 109, 122, 140, 159, 172, 182, 188, 185, 179, 176, 175, 173, 172, 176, 189, 212, 233, 248, 255, 254, 244, 231, 219, 206, 195, 191, 197, 208, 219, 228, 234, 236, 233, 222, 208, 194, 184, 178, 179, 190, 202, 215, 225, 231, 232, 223, 211, 199, 190, 181, 170, 163, 161, 169, 178, 184, 183, 175, 160, 143, 125, 110, 95, 89, 87, 95, 105, 113, 115, 113, 106, 96, 85, 72, 63, 57, 57, 63, 69, 75, 80, 82, 79, 73, 59, 42, 28, 18, 16, 16, 18, 22, 29, 38, 41, 38, 27, 14, 6, 2, 1, 5, 11, 19, 33, 48, 60, 67, 68, 64, 60, 56, 54, 53, 56, 65, 77, 90, 102, 109, 112, 112, 107, 98, 89, 86, 88, 97, 109, 121, 134, 148, 162, 169, 176, 174, 169, 164, 165, 170, 177, 184, 195, 213, 234, 247, 249, 244, 236, 228, 220, 213, 208, 206, 209, 219, 229, 236, 239, 239, 234, 225, 213, 201, 194, 194, 199, 205, 214, 222, 230, 235, 235, 228, 215, 203, 194, 188, 185, 182, 181, 184, 190, 192, 188, 177, 162, 146, 131, 118, 109, 102, 99, 102, 109, 115, 118, 114, 106, 97, 87, 78, 70, 67, 67, 70, 74, 76, 79, 79, 74, 67, 56, 43, 32, 25, 21, 21, 22, 24, 27, 29, 30, 27, 21, 13, 4, 1, 1, 5, 13, 22, 31, 40, 48, 51, 55, 55, 53, 52, 51, 53, 58, 65, 74, 82, 90, 96, 97, 96, 94, 89, 86, 86, 90, 96, 104, 116, 126, 136, 146, 154, 155, 163, 161, 159, 161, 167, 176, 187, 200, 214, 227, 238, 242, 240, 235, 228, 223, 219, 217, 218, 221, 225, 232, 237, 238, 237, 232, 225, 215, 206, 202, 202, 207, 213, 219, 225, 230, 233, 231, 226, 219, 209, 203, 198, 196, 195, 195, 197, 197, 196, 190, 181, 168, 155, 141, 129, 121, 117, 114, 115, 116, 116, 116, 113, 107, 97, 94, 89, 84, 81, 81, 80, 79, 77, 73, 70, 65, 60, 53, 45, 38, 32, 29, 27, 25, 24, 21, 18, 15, 12, 9, 5, 3, 1, 2, 6, 10, 16, 21, 26, 30, 32, 35, 37, 39, 42, 44, 49, 54, 60, 65, 70, 74, 76, 78, 79, 79, 80, 81, 83, 88, 94, 102, 109, 115, 122, 128, 134, 140, 144, 152, 157, 163, 170, 180, 191, 201, 211, 218, 225, 229, 231, 231, 231, 230, 231, 231, 233, 236, 238, 239, 239, 239, 237, 234, 229, 225, 222, 221, 221, 223, 225, 228, 230, 229, 230, 229, 226, 222, 218, 214, 211, 209, 208, 207, 205, 201, 195, 189, 182, 174, 164, 156, 148, 142, 137, 133, 130, 127, 122, 118, 113, 108, 102, 94, 107, 103, 100, 96, 93, 90, 86, 80, 75, 71, 66, 62, 57, 51, 45, 40, 36, 30, 26, 20, 15, 11, 8, 5, 4, 2, 2, 1, 2, 3, 4, 7, 9, 12, 15, 17, 21, 26, 30, 33, 36, 40, 44, 48, 51, 53, 55, 57, 61, 64, 67, 71, 74, 77, 81, 85, 92, 95, 101, 107, 114, 121, 129, 136, 146, 152, 161, 169, 177, 185, 192, 199, 205, 210, 216, 221, 225, 228, 231, 233, 235, 236, 237, 237, 237, 236, 236, 237, 237, 237, 238, 238, 238, 239, 239, 239, 239, 239, 237, 238, 238, 237, 235, 232, 230, 227, 224, 221, 216, 210, 205, 199, 193, 187, 181, 175, 169, 163, 157, 151, 145, 139, 134, 128, 123, 118, 115, 112, 107, 118, 145, 115, 103, 137, 172, 138, 118, 93, 169, 152, 137, 134, 149, 145, 98, 107, 119, 93, 95, 70, 56, 47, 52, 80, 36, 55, 49, 64, 37, 22, 63, 39, 39, 34, 30, 45, 47, 43, 34, 37, 57, 97, 109, 98, 94, 90, 81, 104, 103, 82, 110, 98, 79, 70, 74, 127, 92, 86, 80, 113, 126, 118, 79, 199, 181, 201, 163, 192, 200, 176, 191, 189, 208, 220, 229, 213, 209, 232, 255, 213, 225, 218, 196, 214, 181, 216, 227, 235, 186, 215, 163, 195, 169, 173, 156, 200, 181, 129, 135, 129, 172, 149, 128, 137, 138, 118, 132, 143, 127, 75, 127, 118, 103, 105, 100, 130, 131, 109, 140, 156, 124, 128, 135, 160, 140, 138, 120, 118, 108, 77, 93, 91, 95, 100, 81, 85, 75, 111, 84, 68, 74, 65, 65, 50, 50, 79, 54, 37, 26, 45, 1, 33, 65, 33, 32, 16, 20, 29, 30, 52, 46, 41, 32, 43, 67, 94, 94, 68, 72, 69, 100, 158, 162, 150, 124, 103, 130, 138, 163, 176, 174, 146, 114, 146, 163, 150, 139, 133, 150, 171, 170, 139, 141, 155, 155, 153, 178, 173, 145, 141, 159, 163, 158, 163, 160, 162, 215, 248, 231, 221, 194, 175, 212, 210, 215, 239, 237, 210, 213, 189, 225, 206, 205, 203, 231, 207, 184, 164, 160, 196, 180, 159, 158, 159, 168, 179, 172, 159, 124, 148, 136, 141, 146, 128, 135, 121, 103, 105, 115, 105, 107, 117, 112, 91, 89, 86, 108, 90, 55, 83, 79, 62, 60, 57, 73, 77, 83, 52, 60, 49, 39, 42, 37, 39, 52, 41, 30, 25, 44, 1, 29, 44, 41, 48, 33, 26, 37, 46, 64, 50, 58, 52, 66, 91, 117, 124, 98, 82, 81, 113, 194, 197, 178, 150, 124, 146, 169, 198, 206, 199, 187, 154, 181, 205, 192, 154, 149, 174, 210, 215, 194, 122, 117, 131, 150, 190, 194, 158, 122, 129, 150, 163, 149, 153, 145, 206, 249, 239, 229, 198, 173, 198, 218, 232, 247, 234, 212, 205, 200, 222, 211, 214, 211, 229, 203, 199, 180, 171, 189, 177, 151, 145, 149, 162, 158, 147, 147, 122, 123, 111, 119, 139, 127, 114, 90, 94, 69, 69, 85, 98, 100, 76, 46, 48, 69, 90, 57, 29, 58, 68, 51, 40, 39, 53, 59, 53, 39, 69, 59, 34, 31, 28, 33, 46, 43, 38, 47, 43, 1, 23, 45, 53, 53, 44, 41, 44, 57, 73, 58, 80, 63, 72, 107, 142, 145, 114, 95, 98, 127, 223, 227, 210, 181, 148, 167, 196, 223, 229, 224, 217, 180, 194, 240, 222, 169, 149, 189, 238, 241, 217, 136, 100, 128, 144, 197, 214, 170, 123, 128, 161, 168, 142, 155, 137, 181, 235, 239, 225, 189, 157, 170, 209, 255, 251, 241, 216, 189, 195, 223, 219, 211, 201, 216, 188, 189, 178, 167, 174, 163, 143, 146, 150, 149, 115, 122, 128, 110, 106, 98, 98, 114, 105, 80, 70, 96, 67, 50, 64, 80, 80, 59, 33, 37, 65, 57, 37, 25, 47, 60, 52, 43, 42, 46, 52, 55, 61, 79, 70, 51, 45, 42, 40, 53, 62, 57, 57, 42, 23, 41, 53, 62, 66, 62, 60, 63, 77, 81, 77, 96, 87, 84, 114, 154, 159, 127, 110, 116, 147, 230, 236, 227, 211, 173, 175, 208, 236, 237, 232, 231, 210, 197, 239, 233, 188, 158, 191, 239, 248, 228, 140, 88, 117, 131, 181, 201, 162, 115, 120, 159, 145, 121, 154, 133, 153, 216, 231, 214, 173, 140, 150, 208, 255, 239, 228, 206, 180, 181, 210, 213, 199, 194, 199, 172, 170, 174, 157, 154, 145, 136, 137, 136, 126, 98, 97, 107, 98, 99, 97, 86, 89, 88, 77, 77, 88, 73, 55, 58, 69, 72, 60, 41, 41, 49, 37, 20, 17, 33, 46, 47, 43, 39, 37, 44, 57, 71, 86, 79, 63, 53, 45, 41, 55, 68, 64, 56, 40, 33, 46, 55, 63, 73, 72, 68, 71, 84, 89, 87, 101, 101, 96, 116, 159, 171, 145, 126, 131, 167, 235, 251, 250, 239, 202, 191, 220, 255, 254, 253, 251, 237, 215, 241, 251, 214, 172, 191, 236, 253, 229, 149, 85, 106, 121, 155, 183, 157, 107, 111, 146, 131, 108, 135, 131, 135, 194, 228, 210, 168, 133, 144, 204, 255, 242, 228, 210, 183, 177, 205, 211, 196, 193, 191, 167, 160, 167, 156, 142, 138, 132, 131, 127, 111, 82, 75, 82, 84, 90, 89, 75, 67, 70, 75, 80, 85, 74, 58, 49, 54, 59, 58, 45, 35, 31, 20, 27, 26, 38, 52, 61, 62, 57, 51, 55, 68, 82, 96, 95, 82, 67, 59, 58, 67, 76, 76, 69, 59, 56, 62, 72, 79, 86, 88, 84, 86, 94, 100, 103, 109, 111, 109, 121, 150, 168, 163, 146, 146, 171, 216, 245, 253, 240, 214, 199, 211, 240, 255, 254, 245, 234, 222, 230, 238, 217, 183, 180, 203, 220, 206, 158, 106, 99, 113, 130, 150, 144, 115, 104, 121, 122, 108, 113, 119, 126, 162, 198, 195, 168, 143, 145, 184, 225, 226, 212, 196, 179, 173, 186, 192, 185, 178, 172, 160, 156, 157, 148, 133, 125, 126, 125, 121, 104, 80, 70, 74, 82, 89, 88, 80, 71, 69, 76, 88, 91, 83, 70, 57, 52, 55, 60, 58, 51, 40, 27, 26, 23, 31, 46, 62, 69, 67, 60, 59, 67, 82, 97, 99, 88, 74, 62, 60, 67, 74, 76, 74, 67, 62, 68, 76, 83, 91, 96, 95, 96, 100, 107, 111, 115, 116, 118, 130, 153, 173, 176, 166, 163, 179, 213, 241, 254, 245, 226, 211, 213, 231, 249, 255, 246, 240, 234, 237, 240, 227, 199, 184, 191, 203, 198, 171, 125, 106, 110, 123, 138, 139, 123, 107, 110, 116, 112, 109, 110, 118, 146, 180, 191, 176, 158, 156, 179, 211, 223, 214, 199, 181, 171, 174, 183, 181, 174, 165, 157, 151, 151, 142, 127, 115, 114, 115, 111, 97, 78, 64, 64, 75, 86, 88, 82, 72, 66, 69, 80, 87, 82, 70, 53, 41, 41, 48, 52, 50, 39, 26, 1, 1, 5, 13, 22, 34, 45, 56, 64, 72, 77, 79, 77, 72, 66, 58, 52, 45, 40, 38, 37, 37, 40, 46, 55, 64, 72, 78, 85, 92, 98, 103, 107, 111, 116, 123, 131, 141, 152, 162, 171, 182, 192, 202, 207, 212, 214, 215, 215, 215, 214, 212, 210, 204, 199, 191, 183, 173, 162, 148, 135, 129, 125, 123, 122, 118, 121, 125, 129, 132, 131, 129, 127, 125, 124, 126, 130, 137, 146, 161, 180, 197, 210, 221, 231, 240, 246, 247, 245, 242, 237, 231, 225, 221, 217, 211, 204, 197, 189, 183, 173, 163, 151, 139, 127, 118, 110, 104, 99, 97, 98, 102, 106, 109, 112, 114, 116, 114, 109, 101, 91, 78, 64, 50, 36, 25, 13, 5, 1, 7, 1, 6, 20, 38, 59, 78, 94, 110, 125, 136, 143, 142, 134, 122, 107, 91, 75, 59, 46, 38, 34, 38, 46, 56, 67, 76, 84, 94, 106, 115, 120, 115, 106, 97, 91, 91, 98, 106, 113, 119, 126, 135, 149, 163, 177, 189, 194, 190, 181, 165, 146, 123, 99, 81, 67, 57, 46, 36, 24, 22, 34, 65, 105, 147, 173, 191, 197, 202, 210, 219, 227, 231, 225, 208, 186, 166, 158, 162, 176, 195, 209, 215, 215, 216, 219, 225, 230, 235, 237, 233, 222, 209, 197, 185, 179, 173, 169, 165, 159, 150, 139, 128, 119, 116, 116, 116, 114, 112, 114, 118, 124, 129, 137, 144, 152, 158, 160, 157, 148, 135, 116, 98, 79, 63, 49, 34, 19, 7, 78, 68, 70, 83, 101, 119, 134, 148, 161, 171, 178, 184, 184, 178, 168, 155, 139, 119, 100, 82, 73, 70, 75, 84, 94, 101, 106, 110, 118, 129, 140, 149, 149, 140, 124, 106, 93, 91, 100, 116, 130, 141, 147, 153, 161, 175, 191, 208, 219, 218, 200, 167, 123, 81, 51, 39, 39, 42, 37, 20, 2, 1, 30, 85, 150, 201, 228, 231, 220, 208, 204, 210, 220, 220, 199, 162, 117, 81, 62, 65, 83, 103, 116, 118, 117, 114, 116, 122, 134, 149, 159, 157, 146, 129, 115, 108, 108, 116, 125, 133, 136, 134, 128, 125, 127, 133, 138, 141, 141, 139, 136, 131, 128, 129, 134, 142, 149, 154, 156, 152, 145, 136, 127, 120, 113, 108, 101, 91, 78, 117, 113, 110, 107, 103, 100, 97, 94, 92, 89, 88, 87, 86, 85, 85, 85, 85, 86, 87, 88, 89, 90, 92, 93, 94, 95, 96, 95, 95, 95, 94, 92, 90, 87, 85, 81, 77, 74, 69, 65, 61, 56, 52, 49, 46, 43, 41, 39, 38, 39, 39, 42, 45, 48, 53, 59, 66, 74, 83, 92, 102, 112, 124, 136, 148, 159, 171, 182, 193, 203, 213, 221, 230, 237, 242, 247, 251, 253, 255, 255, 254, 253, 249, 245, 241, 235, 229, 222, 215, 207, 200, 192, 185, 178, 170, 164, 157, 152, 147, 143, 139, 136, 133, 131, 130, 129, 129, 129, 130, 131, 132, 133, 134, 136, 136, 137, 138, 138, 138, 138, 137, 135, 134, 132, 129, 127, 124, 121, 117, 124, 119, 113, 108, 104, 99, 95, 91, 88, 86, 84, 83, 83, 83, 84, 86, 88, 91, 94, 98, 101, 105, 109, 112, 115, 117, 119, 121, 122, 122, 121, 120, 117, 114, 110, 105, 99, 93, 87, 80, 72, 65, 58, 51, 45, 39, 34, 30, 26, 24, 23, 24, 25, 28, 33, 38, 45, 53, 63, 73, 85, 97, 110, 123, 137, 150, 164, 176, 189, 201, 212, 222, 231, 239, 245, 249, 253, 255, 255, 254, 252, 249, 244, 238, 231, 224, 216, 207, 197, 188, 179, 170, 162, 154, 147, 140, 134, 130, 126, 123, 121, 119, 119, 120, 121, 123, 125, 128, 131, 135, 138, 142, 145, 148, 151, 153, 155, 156, 156, 155, 154, 152, 149, 147, 143, 139, 134, 129, 124, 129, 129, 129, 128, 128, 127, 126, 124, 121, 119, 115, 112, 109, 105, 102, 99, 96, 94, 93, 92, 92, 92, 93, 95, 98, 101, 104, 108, 112, 116, 119, 122, 125, 125, 126, 125, 123, 120, 115, 109, 101, 94, 85, 76, 66, 56, 46, 37, 29, 22, 16, 13, 10, 10, 12, 16, 23, 32, 42, 54, 69, 85, 101, 118, 136, 153, 169, 185, 201, 215, 226, 236, 244, 250, 254, 255, 255, 252, 248, 242, 235, 227, 218, 208, 198, 188, 179, 170, 162, 155, 149, 143, 140, 137, 135, 134, 134, 135, 136, 138, 140, 142, 144, 145, 147, 147, 148, 148, 147, 147, 145, 144, 142, 140, 137, 135, 133, 131, 129, 128, 127, 126, 126, 126, 126, 127, 127, 128, 129, 155, 151, 139, 122, 110, 106, 110, 120, 129, 135, 133, 126, 117, 110, 105, 103, 101, 99, 97, 95, 97, 100, 105, 109, 109, 107, 103, 102, 107, 117, 128, 138, 141, 135, 124, 111, 103, 103, 109, 118, 122, 119, 106, 87, 65, 48, 35, 29, 27, 27, 28, 28, 30, 32, 34, 34, 32, 29, 29, 35, 52, 78, 109, 138, 160, 171, 173, 172, 174, 183, 199, 219, 238, 251, 255, 252, 246, 239, 233, 228, 222, 214, 205, 195, 187, 182, 177, 171, 162, 150, 138, 130, 127, 131, 139, 145, 146, 141, 131, 121, 117, 122, 135, 150, 164, 168, 165, 154, 142, 132, 128, 129, 133, 137, 141, 143, 145, 145, 143, 138, 129, 117, 107, 102, 106, 118, 134, 149, 155, 146, 163, 167, 157, 139, 123, 115, 118, 128, 139, 146, 146, 141, 133, 127, 122, 118, 113, 105, 96, 89, 88, 93, 103, 111, 114, 108, 98, 88, 86, 93, 108, 123, 131, 129, 116, 99, 86, 80, 85, 95, 102, 102, 92, 74, 55, 38, 27, 21, 19, 16, 15, 16, 21, 30, 41, 50, 52, 49, 42, 42, 53, 78, 114, 151, 180, 196, 198, 193, 188, 190, 201, 219, 238, 251, 255, 252, 246, 240, 234, 229, 220, 208, 194, 182, 176, 175, 178, 180, 176, 165, 149, 135, 130, 134, 147, 161, 169, 168, 156, 142, 132, 132, 141, 156, 169, 175, 170, 158, 143, 132, 124, 122, 121, 119, 117, 117, 120, 125, 131, 132, 126, 114, 98, 87, 87, 99, 122, 146, 143, 185, 207, 203, 181, 153, 134, 131, 144, 164, 181, 189, 187, 178, 167, 158, 148, 136, 118, 97, 79, 70, 75, 89, 104, 109, 99, 75, 50, 34, 35, 54, 82, 105, 112, 98, 74, 48, 35, 41, 58, 80, 93, 93, 78, 57, 37, 23, 16, 14, 11, 9, 11, 20, 37, 58, 76, 81, 70, 49, 31, 29, 50, 94, 149, 196, 223, 225, 208, 186, 171, 174, 192, 218, 240, 253, 255, 250, 244, 239, 234, 225, 210, 192, 177, 172, 179, 195, 212, 219, 210, 189, 163, 148, 150, 170, 197, 220, 225, 211, 185, 159, 145, 147, 163, 182, 192, 189, 171, 146, 123, 105, 95, 88, 81, 74, 71, 75, 87, 103, 115, 115, 99, 73, 49, 41, 57, 94, 143, 132, 163, 178, 172, 152, 135, 133, 149, 177, 200, 205, 189, 160, 132, 119, 126, 144, 159, 158, 137, 104, 74, 61, 69, 90, 109, 113, 98, 72, 49, 42, 56, 83, 108, 116, 103, 78, 55, 48, 60, 83, 104, 107, 90, 60, 32, 20, 29, 50, 70, 73, 58, 31, 9, 4, 21, 51, 81, 96, 91, 76, 65, 70, 96, 136, 171, 190, 189, 175, 162, 164, 185, 217, 245, 255, 243, 217, 193, 184, 194, 216, 235, 237, 218, 187, 160, 149, 159, 183, 203, 209, 195, 169, 147, 141, 156, 183, 207, 214, 201, 174, 150, 142, 152, 174, 192, 193, 173, 140, 110, 95, 100, 118, 134, 134, 114, 84, 57, 48, 60, 87, 112, 121, 113, 93, 76, 77, 98, 132, 128, 146, 162, 178, 193, 205, 216, 224, 230, 234, 234, 232, 229, 223, 215, 205, 195, 184, 172, 160, 149, 139, 130, 122, 115, 110, 106, 103, 102, 103, 104, 105, 107, 109, 111, 112, 113, 112, 110, 107, 102, 96, 89, 80, 71, 60, 50, 40, 30, 21, 13, 7, 3, 2, 2, 5, 10, 18, 29, 42, 57, 74, 91, 110, 130, 149, 167, 185, 202, 217, 229, 239, 247, 252, 255, 255, 253, 248, 242, 234, 225, 216, 205, 195, 185, 175, 167, 160, 154, 149, 147, 145, 144, 144, 145, 147, 149, 151, 153, 154, 154, 152, 150, 146, 140, 133, 125, 116, 105, 94, 82, 70, 59, 49, 40, 32, 26, 22, 21, 22, 26, 32, 41, 51, 64, 79, 95, 111, 128, 129, 150, 170, 190, 208, 223, 235, 245, 252, 255, 255, 252, 246, 237, 226, 213, 200, 185, 171, 156, 143, 131, 121, 113, 107, 103, 102, 102, 105, 109, 115, 121, 128, 136, 142, 148, 152, 154, 154, 153, 149, 143, 134, 124, 112, 99, 84, 69, 55, 41, 29, 18, 10, 4, 1, 1, 5, 12, 22, 34, 50, 68, 87, 108, 129, 150, 170, 190, 208, 223, 235, 245, 252, 255, 255, 252, 246, 237, 226, 213, 200, 185, 171, 156, 143, 131, 121, 113, 107, 103, 102, 102, 105, 109, 115, 121, 128, 136, 142, 148, 152, 154, 155, 153, 149, 143, 134, 124, 112, 99, 84, 70, 55, 41, 29, 18, 10, 4, 1, 1, 5, 12, 22, 34, 50, 68, 87, 108, 129, 123, 149, 167, 173, 171, 169, 173, 188, 209, 228, 236, 230, 213, 193, 180, 177, 180, 184, 179, 164, 141, 120, 109, 110, 121, 133, 138, 130, 116, 101, 95, 100, 114, 127, 133, 128, 114, 101, 95, 101, 114, 124, 126, 114, 92, 69, 54, 49, 54, 59, 57, 46, 28, 14, 10, 20, 40, 62, 78, 82, 80, 78, 85, 104, 131, 158, 177, 185, 184, 182, 188, 204, 226, 246, 255, 250, 233, 215, 202, 200, 204, 208, 205, 189, 167, 146, 136, 137, 148, 160, 165, 158, 143, 128, 122, 127, 140, 153, 159, 153, 139, 125, 118, 123, 135, 145, 145, 133, 110, 86, 69, 64, 67, 71, 68, 55, 37, 21, 15, 24, 43, 64, 78, 82, 78, 75, 80, 97, 123, 116, 146, 168, 179, 179, 168, 152, 136, 124, 119, 124, 136, 152, 167, 177, 179, 172, 158, 138, 117, 99, 85, 79, 79, 84, 94, 105, 114, 120, 121, 118, 109, 99, 86, 76, 69, 67, 71, 80, 92, 103, 111, 111, 103, 88, 65, 41, 19, 5, 1, 8, 24, 45, 65, 80, 86, 82, 72, 59, 48, 46, 56, 78, 110, 147, 181, 210, 227, 232, 226, 213, 201, 192, 190, 197, 210, 227, 242, 252, 253, 246, 230, 209, 187, 166, 151, 143, 142, 147, 155, 166, 175, 181, 182, 179, 172, 162, 152, 142, 137, 137, 143, 153, 166, 179, 187, 189, 181, 165, 142, 116, 93, 76, 70, 73, 84, 100, 114, 123, 122, 113, 95, 74, 57, 47, 49, 63, 88, 116, 117, 142, 159, 163, 154, 135, 110, 87, 72, 69, 78, 98, 121, 143, 158, 165, 160, 149, 134, 121, 112, 109, 113, 121, 131, 141, 147, 149, 148, 143, 136, 127, 116, 105, 93, 82, 73, 67, 66, 69, 75, 82, 86, 84, 76, 60, 41, 20, 6, 1, 8, 26, 50, 78, 99, 111, 112, 101, 84, 67, 58, 61, 78, 108, 144, 177, 204, 218, 218, 206, 186, 169, 158, 159, 170, 189, 213, 234, 247, 249, 241, 225, 205, 185, 171, 163, 162, 165, 170, 175, 178, 178, 174, 167, 160, 151, 142, 133, 125, 118, 113, 112, 116, 125, 137, 149, 158, 161, 156, 145, 129, 111, 97, 92, 98, 113, 134, 156, 171, 177, 169, 150, 123, 97, 77, 69, 75, 93, 117, 121, 162, 185, 184, 161, 125, 90, 68, 61, 69, 85, 103, 119, 132, 145, 154, 159, 155, 141, 121, 100, 90, 94, 113, 138, 159, 169, 163, 146, 129, 117, 116, 121, 124, 118, 102, 79, 58, 50, 56, 73, 92, 102, 97, 79, 52, 27, 8, 1, 3, 10, 22, 37, 57, 79, 100, 114, 112, 96, 68, 43, 33, 47, 87, 140, 191, 227, 237, 224, 197, 171, 155, 154, 167, 186, 205, 222, 235, 245, 251, 251, 242, 222, 195, 168, 151, 148, 159, 178, 194, 198, 188, 168, 148, 136, 134, 139, 144, 142, 129, 111, 96, 93, 105, 129, 155, 172, 175, 162, 141, 120, 105, 100, 103, 111, 122, 134, 149, 167, 182, 187, 176, 150, 112, 75, 53, 55, 81, 121, 126, 177, 206, 202, 170, 123, 83, 61, 62, 79, 100, 119, 129, 135, 142, 151, 161, 162, 152, 132, 109, 95, 97, 116, 142, 160, 159, 139, 107, 79, 70, 82, 109, 134, 143, 128, 97, 62, 39, 37, 52, 74, 88, 84, 65, 38, 15, 2, 2, 9, 17, 24, 31, 45, 67, 94, 117, 123, 108, 76, 41, 22, 32, 75, 138, 198, 238, 245, 222, 185, 152, 138, 145, 167, 193, 213, 226, 233, 240, 248, 255, 254, 240, 216, 189, 170, 167, 182, 202, 216, 212, 188, 153, 124, 113, 124, 151, 177, 188, 176, 147, 116, 97, 99, 119, 145, 164, 166, 150, 127, 106, 96, 97, 105, 112, 118, 123, 132, 150, 170, 186, 185, 162, 120, 74, 44, 44, 75, 126, 134, 184, 215, 219, 199, 163, 128, 104, 96, 99, 106, 112, 114, 116, 120, 128, 136, 138, 129, 113, 93, 80, 81, 96, 118, 137, 144, 136, 119, 104, 100, 112, 133, 153, 161, 153, 132, 109, 95, 94, 106, 120, 126, 117, 97, 70, 47, 34, 32, 36, 42, 47, 50, 56, 67, 81, 92, 91, 77, 52, 29, 20, 37, 81, 141, 200, 241, 255, 242, 215, 187, 170, 166, 174, 184, 192, 195, 196, 200, 205, 209, 207, 194, 172, 146, 128, 122, 132, 148, 162, 164, 151, 131, 113, 108, 118, 139, 160, 171, 165, 147, 129, 119, 124, 141, 161, 173, 171, 156, 134, 115, 106, 107, 114, 122, 126, 129, 133, 141, 150, 156, 149, 127, 94, 61, 44, 51, 85, 134, 24, 25, 27, 28, 29, 31, 32, 33, 34, 36, 37, 38, 40, 41, 42, 44, 45, 47, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 64, 66, 67, 69, 70, 72, 73, 75, 76, 78, 80, 81, 83, 84, 86, 88, 89, 91, 93, 94, 96, 98, 99, 101, 103, 104, 106, 108, 110, 111, 113, 115, 117, 119, 120, 122, 124, 126, 128, 130, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 192, 194, 196, 198, 200, 202, 205, 207, 209, 211, 213, 216, 218, 220, 222, 225, 227, 229, 232, 234, 236, 238, 241, 243, 245, 248, 250, 253, 255, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 2, 0, 6, 13, 19, 25, 31, 38, 44, 50, 55, 61, 67, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 120, 122, 124, 126, 127, 128, 129, 129, 130, 129, 129, 128, 127, 126, 124, 122, 120, 117, 114, 111, 108, 104, 100, 96, 92, 87, 82, 77, 72, 67, 61, 55, 50, 44, 38, 31, 25, 19, 13, 6, 0, 253, 246, 240, 234, 228, 221, 215, 209, 204, 198, 192, 187, 182, 177, 172, 167, 163, 159, 155, 151, 148, 145, 142, 139, 137, 135, 133, 132, 131, 130, 130, 130, 130, 130, 131, 132, 133, 135, 137, 139, 142, 145, 148, 151, 155, 159, 163, 167, 172, 177, 182, 187, 192, 198, 204, 209, 215, 221, 228, 234, 240, 246, 253, 0, 128, 128, 128, 128, 128, 128, 128, 128, 176, 176, 176, 176, 176, 176, 176, 176, 218, 218, 218, 218, 218, 218, 218, 218, 245, 245, 245, 245, 245, 245, 245, 245, 255, 255, 255, 255, 255, 255, 255, 255, 245, 245, 245, 245, 245, 245, 245, 245, 218, 218, 218, 218, 218, 218, 218, 218, 176, 176, 176, 176, 176, 176, 176, 176, 128, 128, 128, 128, 128, 128, 128, 128, 79, 79, 79, 79, 79, 79, 79, 79, 37, 37, 37, 37, 37, 37, 37, 37, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 37, 37, 37, 37, 37, 37, 37, 37, 79, 79, 79, 79, 79, 79, 79, 79, 128, 127, 134, 140, 146, 152, 158, 165, 170, 176, 182, 188, 193, 198, 203, 208, 213, 218, 222, 226, 230, 234, 237, 240, 243, 245, 248, 250, 251, 253, 254, 254, 255, 255, 255, 254, 254, 253, 251, 250, 248, 245, 243, 240, 237, 234, 230, 226, 222, 218, 213, 208, 203, 198, 193, 188, 182, 176, 170, 165, 158, 152, 146, 140, 134, 128, 121, 115, 109, 103, 97, 90, 85, 79, 73, 67, 62, 57, 52, 47, 42, 37, 33, 29, 25, 21, 18, 15, 12, 10, 7, 5, 4, 2, 1, 1, 0, 0, 0, 1, 1, 2, 4, 5, 7, 10, 12, 15, 18, 21, 25, 29, 33, 37, 42, 47, 52, 57, 62, 67, 73, 79, 85, 90, 97, 103, 109, 115, 121, 127, 128, 128, 128, 128, 128, 129, 131, 132, 135, 137, 141, 145, 149, 154, 160, 166, 173, 179, 186, 194, 201, 208, 215, 222, 228, 234, 239, 244, 248, 251, 253, 255, 255, 255, 253, 251, 248, 244, 239, 234, 228, 222, 215, 208, 201, 194, 186, 179, 173, 166, 160, 154, 149, 145, 141, 137, 135, 132, 131, 129, 128, 128, 128, 128, 128, 127, 127, 127, 127, 126, 124, 123, 120, 118, 114, 110, 106, 101, 95, 89, 82, 76, 69, 61, 54, 47, 40, 33, 27, 21, 16, 11, 7, 4, 2, 0, 0, 0, 2, 4, 7, 11, 16, 21, 27, 33, 40, 47, 54, 61, 69, 76, 82, 89, 95, 101, 106, 110, 114, 118, 120, 123, 124, 126, 127, 127, 127, 127, 128, 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 130, 132, 134, 137, 141, 145, 150, 156, 163, 170, 178, 187, 196, 204, 213, 222, 230, 237, 243, 248, 252, 254, 255, 254, 252, 248, 243, 237, 230, 222, 213, 204, 196, 187, 178, 170, 163, 156, 150, 145, 141, 137, 134, 132, 130, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 127, 127, 127, 127, 127, 127, 127, 126, 126, 125, 123, 121, 118, 114, 110, 105, 99, 92, 85, 77, 68, 59, 51, 42, 33, 25, 18, 12, 7, 3, 1, 0, 1, 3, 7, 12, 18, 25, 33, 42, 51, 59, 68, 77, 85, 92, 99, 105, 110, 114, 118, 121, 123, 125, 126, 126, 127, 127, 127, 127, 127, 127, 127, 128, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255, 255, 251, 247, 243, 239, 235, 231, 227, 223, 219, 215, 210, 206, 202, 198, 194, 190, 186, 182, 178, 174, 170, 166, 162, 158, 154, 150, 146, 142, 138, 134, 130, 125, 121, 117, 113, 109, 105, 101, 97, 93, 89, 85, 81, 77, 73, 69, 65, 61, 57, 53, 49, 45, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 0, 24, 26, 29, 32, 34, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 85, 88, 91, 95, 98, 102, 105, 109, 112, 116, 119, 123, 127, 131, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 187, 191, 195, 200, 204, 209, 213, 218, 222, 227, 231, 236, 241, 245, 250, 255, 24, 26, 29, 32, 34, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 85, 88, 91, 95, 98, 102, 105, 109, 112, 116, 119, 123, 127, 131, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 187, 191, 195, 200, 204, 209, 213, 218, 222, 227, 231, 236, 241, 245, 250, 255, 24, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 129, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 129, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 4, 0, 13, 26, 38, 50, 62, 73, 83, 93, 102, 109, 116, 122, 126, 129, 131, 132, 131, 129, 126, 122, 116, 109, 102, 93, 83, 73, 62, 50, 38, 26, 13, 0, 250, 238, 225, 213, 201, 190, 180, 170, 161, 154, 147, 142, 137, 134, 132, 132, 132, 134, 137, 142, 147, 154, 161, 170, 180, 190, 201, 213, 225, 238, 250, 0, 13, 26, 38, 50, 62, 73, 83, 93, 102, 109, 116, 122, 126, 129, 131, 132, 131, 129, 126, 122, 116, 109, 102, 93, 83, 73, 62, 50, 38, 26, 13, 0, 250, 238, 225, 213, 201, 190, 180, 170, 161, 154, 147, 142, 137, 134, 132, 132, 132, 134, 137, 142, 147, 154, 161, 170, 180, 190, 201, 213, 225, 238, 250, 0, 128, 128, 128, 128, 176, 176, 176, 176, 218, 218, 218, 218, 245, 245, 245, 245, 255, 255, 255, 255, 245, 245, 245, 245, 218, 218, 218, 218, 176, 176, 176, 176, 128, 128, 128, 128, 79, 79, 79, 79, 37, 37, 37, 37, 10, 10, 10, 10, 0, 0, 0, 0, 10, 10, 10, 10, 37, 37, 37, 37, 79, 79, 79, 79, 128, 128, 128, 128, 176, 176, 176, 176, 218, 218, 218, 218, 245, 245, 245, 245, 255, 255, 255, 255, 245, 245, 245, 245, 218, 218, 218, 218, 176, 176, 176, 176, 128, 128, 128, 128, 79, 79, 79, 79, 37, 37, 37, 37, 10, 10, 10, 10, 0, 0, 0, 0, 10, 10, 10, 10, 37, 37, 37, 37, 79, 79, 79, 79, 128, 128, 140, 152, 165, 176, 188, 198, 208, 218, 226, 234, 240, 245, 250, 253, 254, 255, 254, 253, 250, 245, 240, 234, 226, 218, 208, 198, 188, 176, 165, 152, 140, 128, 115, 103, 90, 79, 67, 57, 47, 37, 29, 21, 15, 10, 5, 2, 1, 0, 1, 2, 5, 10, 15, 21, 29, 37, 47, 57, 67, 79, 90, 103, 115, 128, 140, 152, 165, 176, 188, 198, 208, 218, 226, 234, 240, 245, 250, 253, 254, 255, 254, 253, 250, 245, 240, 234, 226, 218, 208, 198, 188, 176, 165, 152, 140, 128, 115, 103, 90, 79, 67, 57, 47, 37, 29, 21, 15, 10, 5, 2, 1, 0, 1, 2, 5, 10, 15, 21, 29, 37, 47, 57, 67, 79, 90, 103, 115, 128, 128, 128, 128, 131, 135, 141, 149, 160, 173, 186, 201, 215, 228, 239, 248, 253, 255, 253, 248, 239, 228, 215, 201, 186, 173, 160, 149, 141, 135, 131, 128, 128, 128, 127, 127, 124, 120, 114, 106, 95, 82, 69, 54, 40, 27, 16, 7, 2, 0, 2, 7, 16, 27, 40, 54, 69, 82, 95, 106, 114, 120, 124, 127, 127, 128, 128, 128, 131, 135, 141, 149, 160, 173, 186, 201, 215, 228, 239, 248, 253, 255, 253, 248, 239, 228, 215, 201, 186, 173, 160, 149, 141, 135, 131, 128, 128, 128, 127, 127, 124, 120, 114, 106, 95, 82, 69, 54, 40, 27, 16, 7, 2, 0, 2, 7, 16, 27, 40, 54, 69, 82, 95, 106, 114, 120, 124, 127, 127, 128, 128, 128, 128, 128, 129, 130, 134, 141, 150, 163, 178, 196, 213, 230, 243, 252, 255, 252, 243, 230, 213, 196, 178, 163, 150, 141, 134, 130, 129, 128, 128, 128, 128, 127, 127, 127, 126, 125, 121, 114, 105, 92, 77, 59, 42, 25, 12, 3, 0, 3, 12, 25, 42, 59, 77, 92, 105, 114, 121, 125, 126, 127, 127, 127, 128, 128, 128, 128, 129, 130, 134, 141, 150, 163, 178, 196, 213, 230, 243, 252, 255, 252, 243, 230, 213, 196, 178, 163, 150, 141, 134, 130, 129, 128, 128, 128, 128, 127, 127, 127, 126, 125, 121, 114, 105, 92, 77, 59, 42, 25, 12, 3, 0, 3, 12, 25, 42, 59, 77, 92, 105, 114, 121, 125, 126, 127, 127, 127, 128, 0, 8, 16, 24, 32, 40, 49, 57, 65, 73, 81, 89, 97, 105, 113, 121, 130, 138, 146, 154, 162, 170, 178, 186, 194, 202, 210, 219, 227, 235, 243, 251, 255, 247, 239, 231, 223, 215, 206, 198, 190, 182, 174, 166, 158, 150, 142, 134, 125, 117, 109, 101, 93, 85, 77, 69, 61, 53, 45, 36, 28, 20, 12, 4, 0, 8, 16, 24, 32, 40, 49, 57, 65, 73, 81, 89, 97, 105, 113, 121, 130, 138, 146, 154, 162, 170, 178, 186, 194, 202, 210, 219, 227, 235, 243, 251, 255, 247, 239, 231, 223, 215, 206, 198, 190, 182, 174, 166, 158, 150, 142, 134, 125, 117, 109, 101, 93, 85, 77, 69, 61, 53, 45, 36, 28, 20, 12, 4, 0, 122, 110, 98, 84, 71, 59, 49, 39, 28, 18, 12, 10, 8, 6, 2, 3, 7, 14, 19, 24, 28, 35, 42, 49, 56, 64, 72, 77, 81, 85, 88, 91, 93, 94, 93, 90, 86, 82, 77, 72, 67, 61, 55, 47, 41, 34, 28, 25, 21, 17, 15, 14, 15, 20, 24, 30, 37, 45, 55, 64, 77, 91, 105, 119, 135, 147, 162, 175, 188, 201, 211, 220, 229, 237, 244, 249, 252, 255, 255, 253, 249, 245, 242, 238, 232, 224, 214, 207, 201, 195, 189, 181, 175, 170, 166, 162, 160, 161, 164, 165, 167, 170, 174, 180, 188, 196, 202, 208, 212, 217, 225, 231, 234, 236, 237, 236, 236, 233, 230, 225, 219, 211, 199, 187, 176, 166, 153, 138, 122, 133, 117, 100, 84, 70, 55, 42, 30, 19, 10, 4, 2, 1, 3, 5, 10, 19, 31, 43, 55, 68, 83, 98, 112, 127, 142, 156, 167, 178, 188, 197, 202, 205, 207, 206, 204, 198, 191, 183, 174, 162, 149, 137, 122, 108, 93, 79, 66, 54, 44, 34, 27, 22, 20, 19, 21, 26, 32, 40, 50, 63, 78, 93, 109, 125, 141, 158, 174, 188, 203, 215, 227, 236, 243, 249, 253, 255, 253, 249, 244, 236, 227, 216, 203, 190, 175, 159, 144, 130, 116, 102, 88, 77, 67, 59, 52, 48, 47, 48, 51, 55, 63, 72, 83, 95, 109, 123, 136, 149, 163, 178, 191, 202, 211, 219, 226, 231, 234, 235, 233, 230, 223, 214, 204, 193, 180, 165, 150, 133, 123, 110, 95, 79, 66, 53, 42, 30, 19, 12, 5, 1, 1, 4, 5, 8, 16, 31, 42, 53, 63, 77, 92, 105, 118, 133, 149, 160, 170, 180, 190, 196, 199, 202, 202, 204, 199, 195, 189, 181, 171, 160, 151, 140, 126, 112, 98, 86, 75, 66, 59, 52, 46, 43, 42, 44, 47, 51, 59, 68, 80, 93, 107, 122, 137, 149, 164, 180, 193, 205, 215, 225, 234, 241, 248, 252, 255, 253, 248, 245, 238, 229, 217, 207, 196, 182, 167, 153, 139, 125, 110, 96, 85, 74, 64, 57, 52, 52, 52, 52, 54, 59, 67, 77, 88, 99, 110, 121, 131, 144, 159, 171, 181, 188, 193, 200, 206, 210, 210, 210, 208, 203, 195, 187, 178, 167, 152, 137, 123, 58, 62, 54, 37, 30, 29, 28, 18, 10, 9, 5, 1, 7, 23, 25, 18, 29, 59, 80, 83, 85, 104, 123, 127, 126, 145, 179, 190, 196, 204, 219, 227, 224, 221, 228, 242, 241, 241, 239, 232, 222, 217, 221, 216, 204, 186, 176, 173, 164, 159, 159, 157, 143, 135, 135, 141, 143, 140, 145, 150, 159, 165, 181, 198, 208, 203, 208, 226, 235, 238, 230, 229, 236, 239, 245, 251, 252, 239, 227, 222, 219, 205, 189, 181, 177, 168, 150, 136, 126, 109, 81, 65, 56, 47, 36, 26, 20, 26, 24, 13, 9, 8, 17, 31, 44, 46, 46, 48, 50, 63, 78, 92, 96, 89, 85, 88, 103, 105, 103, 107, 115, 116, 108, 106, 105, 99, 78, 61, 58, 89, 104, 103, 92, 95, 106, 118, 114, 111, 116, 116, 114, 117, 131, 135, 123, 133, 165, 186, 182, 167, 164, 170, 161, 153, 173, 219, 232, 230, 224, 223, 220, 213, 208, 216, 233, 229, 226, 220, 215, 207, 204, 203, 198, 185, 174, 178, 185, 179, 171, 167, 160, 145, 140, 147, 159, 160, 151, 144, 139, 139, 138, 153, 167, 168, 155, 155, 177, 192, 186, 161, 145, 139, 139, 151, 167, 175, 162, 139, 127, 122, 110, 100, 103, 114, 115, 104, 96, 92, 78, 54, 43, 39, 38, 40, 41, 43, 55, 47, 24, 8, 1, 16, 42, 63, 61, 53, 44, 34, 39, 46, 60, 69, 64, 59, 64, 79, 85, 81, 85, 92, 99, 94, 98, 111, 114, 98, 86, 89, 76, 76, 69, 64, 76, 92, 111, 110, 104, 103, 95, 92, 86, 86, 94, 99, 128, 163, 181, 169, 131, 90, 59, 38, 42, 82, 142, 174, 176, 151, 121, 97, 97, 105, 120, 138, 132, 133, 129, 140, 148, 144, 127, 106, 88, 93, 119, 146, 151, 133, 104, 77, 67, 82, 114, 150, 165, 156, 141, 123, 125, 130, 147, 166, 175, 182, 198, 231, 255, 254, 217, 179, 148, 143, 173, 210, 243, 252, 231, 208, 184, 165, 161, 170, 188, 196, 200, 202, 201, 186, 163, 143, 129, 125, 145, 170, 185, 190, 157, 103, 61, 47, 79, 131, 171, 172, 148, 104, 66, 50, 44, 58, 68, 66, 66, 67, 82, 94, 91, 91, 76, 66, 57, 58, 75, 87, 90, 86, 76, 124, 128, 127, 120, 116, 111, 104, 91, 75, 59, 48, 45, 45, 53, 67, 81, 104, 118, 120, 108, 81, 47, 20, 1, 1, 16, 37, 52, 55, 46, 36, 28, 34, 41, 46, 53, 46, 47, 43, 48, 45, 39, 23, 9, 4, 15, 39, 61, 76, 77, 71, 64, 68, 80, 95, 110, 112, 101, 90, 80, 85, 98, 117, 137, 156, 174, 195, 218, 232, 234, 213, 192, 166, 157, 167, 187, 211, 230, 234, 235, 229, 225, 227, 233, 244, 251, 253, 250, 244, 230, 217, 204, 197, 199, 216, 237, 251, 255, 240, 212, 190, 177, 186, 203, 214, 207, 189, 163, 143, 138, 141, 150, 157, 162, 167, 170, 174, 173, 166, 152, 130, 112, 95, 86, 89, 97, 107, 120, 124, 176, 193, 200, 196, 181, 158, 131, 101, 76, 57, 50, 56, 69, 90, 113, 133, 150, 158, 155, 141, 121, 98, 78, 60, 49, 43, 43, 44, 46, 47, 49, 56, 65, 75, 81, 87, 83, 79, 69, 57, 43, 28, 13, 4, 1, 7, 21, 36, 53, 68, 80, 92, 104, 110, 111, 106, 94, 82, 71, 67, 72, 85, 105, 127, 147, 167, 183, 197, 202, 199, 184, 167, 146, 133, 128, 132, 144, 159, 173, 187, 199, 207, 217, 224, 229, 228, 222, 209, 194, 175, 162, 153, 152, 160, 175, 193, 208, 221, 223, 217, 207, 194, 182, 172, 159, 145, 135, 128, 129, 137, 147, 160, 171, 178, 184, 185, 182, 178, 168, 155, 139, 122, 108, 101, 104, 114, 132, 154, 176, 205, 232, 241, 231, 208, 176, 142, 105, 72, 51, 48, 60, 82, 111, 141, 163, 179, 186, 182, 171, 153, 134, 120, 101, 82, 66, 60, 54, 51, 50, 50, 58, 67, 79, 92, 102, 101, 95, 79, 62, 41, 26, 17, 11, 1, 1, 16, 35, 54, 69, 87, 109, 127, 131, 132, 127, 112, 94, 79, 74, 77, 88, 107, 130, 151, 170, 184, 198, 202, 192, 172, 150, 124, 107, 101, 103, 112, 127, 140, 159, 177, 188, 200, 211, 218, 215, 203, 183, 162, 139, 122, 111, 113, 125, 144, 167, 186, 203, 207, 201, 188, 170, 154, 140, 124, 108, 101, 104, 116, 134, 151, 164, 179, 188, 195, 198, 193, 186, 173, 156, 137, 119, 104, 98, 106, 120, 145, 175, 205, 186, 220, 228, 208, 186, 165, 151, 133, 100, 81, 90, 106, 128, 162, 188, 194, 204, 215, 210, 201, 191, 179, 186, 170, 128, 107, 109, 104, 95, 86, 70, 58, 53, 61, 80, 86, 78, 79, 59, 35, 12, 27, 86, 92, 29, 1, 33, 75, 97, 85, 93, 144, 173, 162, 173, 185, 174, 156, 136, 140, 145, 140, 152, 168, 171, 170, 170, 190, 204, 183, 150, 123, 90, 70, 78, 93, 102, 107, 107, 117, 131, 129, 129, 150, 172, 166, 151, 139, 116, 98, 88, 71, 74, 84, 92, 117, 135, 150, 151, 136, 119, 103, 99, 120, 122, 98, 86, 90, 105, 140, 157, 153, 172, 176, 175, 186, 178, 166, 158, 140, 130, 122, 111, 105, 110, 123, 138, 155, 186, 151, 172, 170, 174, 166, 164, 178, 179, 164, 150, 168, 178, 186, 226, 242, 218, 217, 243, 225, 213, 233, 217, 230, 225, 168, 155, 162, 160, 145, 131, 108, 63, 47, 49, 59, 66, 52, 61, 54, 22, 1, 48, 168, 192, 86, 36, 79, 124, 152, 132, 116, 174, 208, 166, 170, 202, 192, 176, 177, 187, 181, 163, 168, 164, 150, 139, 117, 128, 144, 117, 91, 76, 55, 53, 69, 91, 96, 82, 73, 69, 75, 70, 59, 87, 111, 102, 91, 103, 91, 68, 78, 66, 56, 64, 64, 76, 76, 106, 95, 59, 83, 62, 57, 121, 138, 118, 108, 118, 123, 150, 175, 146, 147, 147, 138, 150, 143, 140, 142, 124, 132, 143, 135, 130, 129, 131, 129, 126, 151, 197, 211, 174, 218, 219, 189, 217, 217, 208, 192, 213, 210, 192, 226, 229, 193, 181, 226, 192, 153, 221, 179, 154, 188, 144, 119, 117, 123, 91, 80, 78, 39, 39, 31, 18, 36, 29, 24, 32, 31, 20, 38, 96, 109, 59, 60, 89, 73, 103, 122, 84, 116, 155, 114, 125, 165, 151, 136, 178, 180, 139, 168, 191, 156, 162, 194, 164, 159, 189, 172, 151, 156, 160, 150, 141, 158, 158, 131, 148, 134, 126, 147, 120, 128, 140, 130, 108, 115, 125, 73, 92, 110, 62, 58, 97, 76, 23, 119, 83, 1, 119, 67, 21, 106, 95, 79, 70, 111, 98, 72, 140, 113, 94, 121, 122, 121, 112, 126, 137, 116, 118, 156, 146, 132, 169, 167, 169, 169, 197, 213, 230, 195, 239, 245, 206, 239, 245, 228, 220, 239, 230, 213, 229, 232, 211, 187, 232, 205, 147, 228, 186, 138, 190, 158, 129, 120, 126, 98, 74, 80, 56, 41, 35, 19, 28, 24, 13, 23, 30, 25, 25, 48, 56, 30, 40, 59, 38, 56, 74, 45, 66, 92, 59, 76, 107, 91, 82, 132, 130, 89, 142, 162, 121, 138, 184, 156, 142, 186, 183, 157, 167, 195, 165, 149, 195, 172, 139, 191, 159, 140, 182, 147, 148, 162, 157, 130, 130, 161, 101, 100, 147, 95, 65, 134, 109, 20, 139, 106, 1, 136, 86, 31, 103, 87, 78, 57, 107, 100, 44, 121, 113, 74, 112, 116, 106, 108, 116, 136, 125, 122, 168, 156, 143, 189, 184, 185, 195, 213, 167, 178, 151, 205, 190, 126, 206, 209, 175, 183, 206, 168, 169, 202, 198, 155, 130, 197, 186, 86, 216, 161, 111, 192, 140, 153, 111, 113, 128, 83, 62, 100, 51, 37, 2, 60, 71, 3, 90, 50, 38, 93, 71, 133, 98, 49, 101, 103, 92, 95, 92, 108, 109, 41, 119, 125, 54, 101, 161, 95, 84, 175, 121, 113, 139, 159, 148, 105, 194, 191, 108, 143, 217, 108, 110, 209, 126, 124, 192, 130, 104, 201, 155, 131, 198, 189, 123, 114, 215, 146, 90, 206, 150, 49, 195, 201, 1, 163, 193, 2, 177, 117, 76, 131, 90, 163, 70, 98, 162, 71, 109, 172, 113, 87, 114, 120, 106, 78, 125, 106, 118, 134, 107, 136, 147, 146, 116, 171, 167, 125, 125, 163, 156, 129, 76, 157, 199, 134, 150, 194, 125, 102, 161, 174, 90, 77, 144, 167, 35, 163, 129, 65, 150, 105, 177, 87, 93, 170, 69, 49, 146, 63, 66, 1, 96, 126, 5, 153, 63, 64, 149, 80, 186, 147, 93, 141, 150, 133, 139, 135, 153, 154, 26, 165, 163, 42, 142, 183, 80, 117, 208, 94, 136, 152, 115, 174, 75, 185, 214, 71, 128, 227, 71, 76, 204, 99, 122, 180, 98, 75, 199, 159, 98, 213, 192, 90, 80, 229, 172, 75, 220, 177, 48, 208, 226, 17, 131, 213, 54, 164, 111, 124, 137, 74, 199, 92, 87, 194, 123, 94, 208, 176, 60, 116, 153, 124, 60, 113, 128, 160, 108, 98, 160, 115, 138, 71, 189, 125, 115, 116, 114, 109, 102, 96, 90, 83, 74, 67, 62, 60, 60, 60, 57, 50, 43, 36, 30, 24, 21, 19, 19, 21, 22, 23, 21, 17, 10, 4, 1, 1, 2, 5, 9, 14, 19, 21, 20, 17, 15, 16, 20, 28, 34, 40, 47, 53, 56, 57, 58, 58, 60, 63, 73, 84, 94, 101, 106, 108, 111, 112, 114, 122, 131, 141, 151, 159, 169, 175, 177, 176, 177, 178, 183, 190, 198, 207, 214, 220, 224, 225, 224, 224, 225, 228, 232, 237, 243, 248, 250, 250, 247, 244, 242, 240, 239, 242, 247, 249, 250, 246, 240, 233, 227, 223, 220, 218, 219, 221, 223, 221, 214, 204, 194, 186, 179, 173, 171, 172, 172, 168, 162, 155, 146, 135, 124, 118, 115, 155, 157, 157, 159, 162, 169, 176, 183, 185, 186, 186, 187, 188, 192, 197, 199, 198, 194, 190, 186, 182, 180, 180, 181, 179, 173, 164, 153, 141, 134, 128, 125, 119, 110, 99, 89, 78, 67, 59, 53, 49, 47, 42, 35, 25, 16, 14, 16, 21, 24, 26, 26, 23, 22, 28, 38, 51, 66, 80, 89, 97, 103, 111, 126, 147, 167, 183, 194, 203, 209, 214, 218, 226, 234, 244, 252, 255, 254, 246, 238, 233, 233, 233, 232, 227, 216, 202, 187, 175, 165, 158, 152, 145, 134, 122, 106, 92, 82, 77, 74, 72, 69, 62, 54, 46, 41, 40, 41, 47, 55, 61, 64, 62, 59, 60, 66, 75, 86, 99, 107, 111, 112, 114, 118, 125, 134, 143, 151, 155, 134, 126, 120, 116, 114, 113, 112, 110, 104, 98, 93, 90, 90, 92, 92, 90, 87, 82, 79, 77, 76, 76, 78, 79, 78, 74, 67, 62, 58, 57, 56, 55, 53, 47, 40, 34, 29, 25, 23, 22, 20, 18, 13, 9, 4, 2, 2, 5, 9, 13, 15, 17, 17, 19, 26, 35, 47, 59, 70, 78, 85, 93, 103, 119, 136, 154, 168, 177, 186, 193, 200, 207, 218, 228, 238, 245, 247, 249, 248, 247, 249, 252, 255, 255, 253, 248, 241, 233, 229, 225, 224, 222, 218, 214, 208, 199, 191, 187, 186, 186, 186, 184, 179, 173, 169, 167, 167, 169, 171, 173, 174, 172, 168, 163, 161, 162, 165, 167, 167, 165, 158, 153, 149, 147, 147, 146, 145, 141, 134, 133, 125, 119, 117, 116, 115, 115, 117, 121, 125, 126, 126, 123, 118, 109, 96, 80, 66, 58, 54, 55, 58, 60, 61, 64, 67, 69, 69, 68, 69, 71, 73, 73, 70, 66, 60, 55, 49, 43, 37, 36, 39, 45, 50, 52, 52, 51, 50, 48, 45, 41, 37, 31, 26, 21, 14, 7, 2, 2, 7, 18, 36, 66, 106, 151, 191, 221, 241, 252, 255, 251, 241, 230, 220, 215, 213, 214, 214, 215, 217, 220, 222, 222, 221, 219, 218, 217, 216, 213, 208, 200, 191, 185, 181, 178, 175, 175, 179, 185, 188, 190, 191, 192, 193, 193, 192, 192, 191, 191, 191, 187, 178, 166, 154, 144, 138, 134, 131, 132, 135, 139, 142, 143, 144, 144, 143, 142, 140, 133, 133, 130, 126, 128, 133, 138, 137, 137, 142, 150, 156, 158, 159, 159, 153, 140, 124, 110, 104, 104, 108, 113, 115, 115, 117, 121, 124, 125, 127, 132, 138, 142, 143, 145, 146, 142, 132, 118, 105, 95, 91, 95, 102, 106, 105, 102, 96, 88, 79, 72, 69, 65, 56, 47, 41, 35, 26, 16, 8, 7, 11, 23, 51, 96, 147, 191, 223, 244, 255, 254, 243, 228, 216, 207, 201, 195, 189, 187, 187, 187, 184, 178, 170, 165, 161, 158, 158, 159, 159, 154, 142, 126, 111, 104, 102, 104, 107, 112, 119, 125, 129, 132, 135, 138, 140, 140, 138, 138, 141, 145, 145, 139, 126, 112, 102, 97, 98, 100, 105, 112, 116, 119, 121, 125, 129, 131, 132, 133, 133, 125, 148, 134, 127, 159, 184, 152, 96, 85, 117, 135, 127, 138, 180, 202, 163, 89, 35, 32, 74, 130, 159, 135, 93, 92, 128, 142, 104, 67, 78, 107, 106, 94, 121, 182, 213, 189, 143, 104, 72, 54, 77, 135, 176, 173, 149, 128, 95, 51, 34, 65, 96, 74, 30, 37, 98, 142, 130, 99, 81, 55, 12, 1, 70, 176, 231, 217, 196, 207, 210, 163, 104, 105, 169, 225, 219, 180, 167, 190, 209, 200, 172, 140, 107, 82, 86, 124, 172, 198, 190, 153, 101, 55, 49, 89, 136, 154, 149, 157, 179, 180, 151, 124, 132, 156, 156, 127, 105, 123, 175, 221, 219, 162, 92, 63, 79, 102, 115, 137, 173, 179, 133, 82, 86, 122, 127, 96, 90, 125, 107, 156, 149, 126, 148, 184, 164, 101, 71, 95, 119, 116, 125, 163, 184, 146, 70, 16, 15, 61, 119, 143, 112, 66, 69, 111, 121, 75, 38, 59, 94, 84, 62, 97, 175, 212, 174, 115, 79, 54, 34, 51, 113, 166, 167, 139, 111, 75, 26, 5, 40, 84, 64, 8, 6, 81, 148, 142, 95, 65, 50, 24, 15, 71, 168, 226, 218, 200, 213, 218, 167, 100, 104, 186, 255, 244, 192, 179, 216, 244, 228, 190, 154, 119, 89, 95, 145, 201, 221, 207, 178, 132, 74, 50, 91, 161, 189, 172, 167, 197, 212, 181, 141, 147, 181, 185, 148, 117, 135, 190, 238, 238, 182, 110, 76, 93, 119, 130, 147, 182, 190, 138, 75, 77, 126, 134, 85, 62, 107, 103, 148, 144, 119, 127, 155, 146, 97, 65, 77, 94, 94, 96, 120, 133, 105, 50, 10, 11, 43, 83, 96, 70, 37, 40, 71, 75, 39, 12, 31, 59, 48, 28, 55, 119, 148, 116, 69, 45, 31, 17, 27, 73, 118, 121, 100, 79, 54, 18, 1, 30, 68, 58, 15, 11, 71, 130, 132, 93, 68, 63, 56, 53, 88, 153, 197, 198, 188, 200, 205, 170, 122, 128, 194, 251, 243, 202, 195, 229, 254, 241, 210, 184, 159, 137, 144, 185, 229, 241, 229, 213, 184, 138, 112, 142, 201, 227, 208, 199, 224, 241, 217, 183, 185, 212, 216, 185, 159, 170, 209, 242, 241, 202, 150, 123, 132, 150, 156, 163, 185, 190, 149, 97, 97, 135, 140, 95, 68, 103, 110, 136, 132, 112, 112, 127, 122, 91, 68, 70, 78, 76, 75, 85, 89, 71, 38, 15, 15, 32, 52, 57, 40, 20, 21, 37, 38, 16, 1, 12, 28, 22, 8, 25, 63, 79, 60, 33, 21, 16, 9, 15, 42, 70, 74, 64, 53, 40, 21, 13, 33, 58, 55, 33, 31, 69, 109, 113, 92, 79, 81, 82, 84, 104, 142, 171, 175, 173, 183, 188, 171, 146, 152, 194, 231, 228, 206, 204, 228, 245, 239, 222, 208, 196, 185, 191, 217, 243, 250, 244, 237, 223, 196, 179, 196, 231, 247, 235, 228, 242, 254, 240, 218, 217, 232, 233, 214, 197, 201, 221, 237, 236, 214, 182, 163, 166, 175, 174, 174, 183, 184, 158, 125, 122, 143, 143, 112, 92, 110, 120, 125, 119, 108, 103, 104, 99, 87, 75, 72, 70, 64, 60, 60, 58, 49, 35, 26, 24, 28, 30, 29, 22, 14, 13, 16, 14, 6, 1, 4, 9, 6, 2, 7, 19, 24, 19, 12, 10, 10, 10, 13, 23, 34, 38, 37, 36, 34, 31, 32, 42, 53, 57, 53, 57, 73, 89, 95, 92, 92, 96, 101, 107, 117, 134, 148, 155, 159, 166, 171, 170, 166, 172, 189, 205, 208, 204, 207, 218, 228, 229, 226, 224, 223, 221, 225, 235, 245, 249, 248, 248, 245, 238, 233, 238, 249, 254, 250, 247, 251, 254, 249, 241, 239, 241, 239, 232, 224, 223, 226, 228, 226, 216, 204, 194, 191, 190, 186, 182, 180, 176, 164, 150, 146, 149, 145, 130, 118, 120, 120, 117, 113, 109, 105, 103, 100, 97, 93, 91, 89, 86, 83, 80, 79, 77, 74, 71, 69, 68, 66, 63, 61, 58, 56, 54, 52, 49, 47, 45, 43, 40, 37, 34, 31, 28, 24, 20, 16, 12, 8, 6, 5, 5, 3, 2, 2, 1, 2, 4, 9, 14, 19, 25, 31, 40, 49, 58, 66, 75, 85, 95, 106, 119, 132, 144, 156, 166, 176, 186, 194, 202, 211, 219, 227, 233, 238, 242, 246, 250, 253, 253, 253, 253, 251, 251, 251, 250, 249, 246, 243, 240, 236, 233, 230, 227, 223, 220, 215, 212, 209, 206, 203, 200, 198, 196, 193, 190, 189, 188, 188, 186, 183, 181, 179, 177, 175, 171, 167, 164, 160, 154, 149, 145, 141, 136, 130, 124, 120, 117, 118, 120, 121, 121, 120, 119, 117, 114, 112, 110, 109, 108, 107, 106, 105, 105, 105, 106, 107, 106, 105, 103, 100, 98, 96, 93, 91, 88, 85, 82, 79, 75, 71, 67, 61, 54, 46, 37, 30, 24, 20, 17, 14, 11, 9, 6, 3, 3, 3, 5, 8, 11, 16, 22, 28, 34, 41, 47, 55, 64, 76, 93, 114, 135, 154, 171, 184, 194, 202, 208, 215, 221, 227, 232, 237, 241, 245, 249, 253, 255, 255, 253, 249, 244, 240, 237, 233, 229, 224, 217, 210, 202, 196, 192, 190, 188, 186, 182, 178, 173, 168, 164, 160, 157, 154, 150, 147, 145, 145, 146, 148, 151, 153, 154, 155, 155, 154, 152, 149, 146, 141, 136, 131, 127, 122, 119, 117, 117, 117, 128, 137, 142, 143, 142, 138, 133, 128, 125, 125, 129, 133, 138, 142, 145, 147, 151, 154, 158, 159, 158, 154, 149, 143, 138, 135, 131, 127, 124, 121, 121, 120, 118, 112, 102, 89, 75, 62, 51, 42, 35, 30, 25, 19, 14, 9, 7, 5, 5, 6, 9, 13, 19, 27, 35, 40, 41, 38, 34, 32, 39, 61, 97, 139, 176, 203, 217, 219, 217, 213, 213, 216, 222, 228, 232, 235, 239, 245, 251, 255, 255, 252, 246, 238, 229, 221, 216, 211, 204, 193, 179, 164, 152, 144, 142, 143, 145, 144, 140, 134, 126, 120, 116, 112, 109, 103, 98, 95, 96, 98, 102, 108, 113, 119, 124, 129, 132, 133, 132, 130, 126, 120, 115, 110, 107, 105, 108, 117, 115, 130, 142, 146, 144, 141, 138, 135, 133, 134, 137, 142, 145, 147, 151, 154, 158, 162, 166, 170, 172, 168, 162, 153, 145, 140, 137, 136, 135, 136, 137, 136, 134, 128, 118, 105, 91, 79, 70, 65, 62, 59, 54, 46, 37, 29, 25, 22, 21, 20, 19, 17, 15, 17, 25, 34, 40, 39, 29, 14, 1, 3, 29, 78, 140, 197, 236, 254, 251, 237, 223, 215, 215, 222, 229, 232, 231, 230, 231, 234, 237, 237, 235, 229, 219, 208, 199, 195, 194, 192, 187, 178, 166, 152, 140, 132, 129, 128, 127, 126, 123, 119, 114, 110, 106, 100, 93, 86, 83, 83, 87, 92, 99, 106, 111, 115, 118, 121, 124, 128, 129, 128, 123, 115, 107, 101, 98, 103, 115, 116, 131, 142, 143, 137, 132, 131, 133, 137, 143, 148, 149, 144, 140, 139, 139, 142, 146, 150, 154, 154, 150, 143, 137, 132, 129, 129, 132, 137, 142, 143, 140, 132, 120, 107, 95, 87, 85, 86, 89, 93, 98, 100, 96, 89, 84, 82, 82, 80, 75, 69, 62, 53, 47, 49, 56, 60, 55, 40, 20, 3, 1, 23, 74, 138, 199, 239, 255, 250, 233, 214, 199, 195, 200, 205, 205, 198, 189, 182, 178, 176, 175, 175, 172, 166, 158, 154, 157, 163, 169, 172, 173, 172, 165, 153, 140, 129, 122, 118, 117, 119, 122, 123, 120, 117, 113, 108, 102, 98, 98, 102, 109, 116, 122, 123, 122, 117, 115, 116, 122, 129, 132, 130, 123, 115, 107, 102, 104, 116, 109, 131, 148, 151, 153, 163, 175, 177, 172, 169, 163, 148, 130, 122, 127, 129, 122, 116, 121, 127, 126, 123, 130, 146, 159, 164, 167, 171, 172, 167, 158, 150, 141, 127, 109, 94, 86, 82, 78, 72, 74, 88, 104, 111, 112, 120, 138, 153, 148, 127, 108, 96, 83, 67, 61, 65, 66, 52, 32, 20, 10, 1, 10, 61, 142, 213, 242, 242, 238, 236, 225, 204, 190, 193, 200, 195, 177, 159, 142, 122, 106, 104, 121, 139, 143, 139, 144, 163, 180, 182, 172, 170, 175, 171, 154, 134, 122, 114, 101, 87, 84, 89, 92, 89, 91, 105, 122, 128, 123, 119, 124, 132, 138, 139, 140, 138, 129, 113, 99, 94, 93, 88, 83, 88, 102, 111, 107, 100, 109, 109, 131, 148, 154, 163, 182, 197, 196, 187, 180, 171, 149, 122, 113, 119, 121, 111, 104, 110, 115, 112, 110, 126, 153, 172, 178, 182, 190, 191, 180, 164, 155, 145, 129, 107, 91, 84, 79, 71, 62, 64, 83, 107, 119, 121, 132, 161, 186, 183, 153, 124, 110, 96, 76, 64, 67, 66, 47, 24, 16, 15, 3, 1, 49, 144, 226, 252, 240, 233, 240, 234, 210, 190, 192, 196, 186, 165, 147, 126, 97, 71, 71, 98, 126, 134, 132, 142, 169, 190, 191, 178, 173, 176, 174, 154, 131, 117, 109, 94, 74, 65, 71, 78, 77, 79, 99, 127, 142, 138, 131, 135, 145, 148, 146, 146, 146, 135, 112, 90, 80, 76, 67, 60, 69, 94, 111, 109, 101, 109, 82, 80, 81, 82, 86, 89, 93, 95, 97, 99, 100, 101, 101, 100, 99, 96, 94, 94, 95, 98, 104, 113, 120, 125, 126, 124, 120, 117, 117, 117, 116, 119, 123, 128, 133, 139, 143, 146, 146, 143, 137, 128, 117, 105, 93, 83, 77, 70, 66, 60, 55, 50, 46, 41, 37, 33, 29, 26, 26, 31, 41, 56, 79, 111, 146, 178, 206, 227, 239, 247, 250, 250, 247, 242, 235, 227, 220, 212, 206, 196, 186, 172, 159, 143, 125, 107, 90, 77, 67, 61, 57, 58, 59, 62, 67, 76, 85, 99, 112, 126, 140, 154, 168, 181, 196, 213, 229, 243, 251, 255, 253, 246, 235, 224, 211, 197, 182, 169, 154, 142, 131, 122, 114, 107, 102, 96, 91, 86, 82, 76, 82, 91, 94, 93, 89, 82, 75, 75, 78, 83, 89, 95, 97, 102, 108, 115, 131, 143, 152, 159, 162, 162, 159, 154, 146, 140, 131, 122, 113, 100, 91, 90, 90, 89, 89, 84, 81, 78, 77, 81, 88, 95, 100, 102, 101, 100, 99, 99, 98, 95, 86, 79, 70, 62, 58, 59, 61, 67, 73, 75, 79, 90, 105, 133, 157, 176, 192, 199, 199, 201, 203, 206, 208, 208, 200, 191, 177, 166, 159, 156, 153, 157, 155, 147, 139, 131, 123, 119, 117, 110, 104, 90, 72, 63, 60, 62, 79, 95, 109, 125, 138, 149, 165, 185, 206, 229, 245, 252, 255, 252, 246, 243, 242, 238, 228, 212, 190, 167, 147, 128, 118, 106, 96, 91, 82, 74, 74, 76, 91, 93, 102, 101, 89, 76, 58, 39, 36, 36, 37, 46, 48, 45, 48, 55, 67, 100, 128, 151, 176, 189, 195, 203, 207, 209, 217, 211, 200, 189, 168, 148, 143, 137, 133, 132, 119, 105, 95, 85, 84, 95, 103, 110, 113, 104, 92, 83, 77, 77, 80, 70, 60, 48, 31, 25, 32, 40, 57, 76, 82, 91, 105, 120, 150, 181, 204, 222, 228, 218, 213, 210, 207, 212, 216, 206, 194, 177, 154, 144, 143, 140, 149, 155, 146, 138, 129, 116, 114, 113, 104, 97, 81, 53, 34, 23, 15, 29, 44, 52, 64, 75, 79, 100, 130, 158, 198, 227, 240, 248, 249, 245, 249, 255, 253, 250, 238, 212, 189, 169, 150, 147, 140, 128, 124, 109, 92, 90, 91, 120, 116, 123, 120, 104, 91, 69, 45, 39, 35, 29, 32, 27, 16, 14, 17, 26, 58, 89, 115, 146, 164, 175, 191, 204, 214, 230, 234, 230, 228, 213, 197, 197, 192, 189, 189, 176, 160, 147, 133, 125, 131, 134, 134, 131, 116, 96, 82, 69, 65, 66, 55, 44, 30, 9, 1, 7, 16, 35, 59, 72, 87, 106, 122, 153, 185, 208, 229, 237, 227, 220, 218, 213, 217, 224, 217, 207, 192, 167, 155, 152, 144, 149, 154, 141, 131, 120, 104, 100, 101, 93, 89, 79, 52, 33, 21, 8, 13, 24, 26, 34, 40, 41, 61, 89, 117, 157, 187, 200, 211, 214, 209, 216, 226, 228, 231, 227, 208, 194, 181, 169, 171, 169, 161, 159, 145, 126, 123, 120, 150, 143, 144, 142, 130, 120, 104, 87, 84, 85, 84, 88, 83, 67, 59, 57, 64, 93, 123, 149, 176, 192, 198, 207, 210, 209, 214, 207, 196, 185, 168, 151, 150, 149, 149, 152, 143, 134, 127, 118, 109, 112, 112, 111, 108, 97, 82, 72, 68, 72, 81, 76, 65, 49, 23, 6, 1, 1, 13, 31, 42, 57, 78, 98, 133, 171, 201, 225, 237, 229, 225, 226, 228, 237, 248, 247, 241, 231, 211, 200, 194, 183, 183, 183, 167, 150, 134, 115, 110, 112, 110, 113, 110, 92, 78, 64, 47, 43, 43, 34, 30, 24, 17, 28, 50, 75, 108, 130, 137, 141, 139, 133, 137, 145, 148, 155, 158, 151, 149, 151, 154, 171, 181, 184, 188, 177, 160, 156, 150, 166, 153, 148, 144, 138, 137, 134, 131, 139, 151, 161, 169, 164, 148, 135, 129, 134, 157, 181, 202, 221, 230, 231, 229, 222, 211, 199, 180, 157, 134, 110, 91, 87, 86, 88, 91, 91, 92, 95, 95, 88, 86, 80, 73, 67, 58, 49, 47, 55, 74, 93, 99, 95, 79, 54, 32, 17, 8, 12, 22, 31, 46, 67, 91, 127, 166, 201, 226, 237, 233, 230, 232, 237, 247, 255, 254, 252, 248, 237, 230, 224, 214, 209, 203, 184, 161, 139, 119, 111, 114, 120, 132, 141, 141, 136, 125, 110, 97, 85, 65, 48, 29, 13, 13, 27, 44, 64, 76, 74, 67, 62, 57, 58, 61, 63, 68, 73, 77, 86, 101, 121, 151, 176, 191, 199, 195, 185, 177, 166, 169, 152, 139, 134, 135, 141, 149, 160, 178, 198, 217, 228, 226, 214, 200, 192, 196, 210, 227, 242, 252, 255, 253, 244, 230, 213, 189, 162, 132, 99, 70, 49, 40, 37, 39, 42, 49, 60, 71, 79, 75, 67, 55, 44, 32, 25, 21, 26, 45, 73, 100, 115, 117, 105, 84, 61, 40, 28, 25, 28, 36, 50, 68, 94, 128, 165, 201, 226, 236, 235, 233, 235, 241, 246, 248, 247, 245, 243, 242, 240, 235, 229, 222, 211, 191, 163, 137, 118, 109, 112, 124, 142, 161, 174, 178, 172, 159, 142, 122, 97, 71, 45, 24, 16, 21, 31, 39, 41, 33, 21, 14, 11, 11, 9, 9, 11, 15, 23, 36, 58, 90, 129, 163, 188, 200, 200, 195, 184, 169, 174, 154, 140, 133, 133, 138, 146, 159, 179, 206, 231, 246, 246, 232, 215, 202, 201, 211, 226, 240, 249, 252, 249, 240, 225, 206, 182, 154, 125, 95, 71, 54, 45, 39, 37, 37, 43, 55, 69, 78, 75, 65, 47, 30, 14, 4, 1, 6, 28, 61, 92, 113, 120, 112, 91, 68, 45, 30, 23, 22, 27, 40, 61, 93, 134, 176, 215, 238, 247, 243, 241, 243, 248, 254, 254, 252, 249, 245, 244, 243, 240, 237, 233, 227, 210, 185, 159, 137, 125, 125, 133, 150, 169, 181, 184, 175, 160, 139, 116, 87, 60, 33, 13, 7, 15, 28, 38, 38, 30, 17, 10, 7, 8, 6, 4, 2, 1, 7, 19, 42, 76, 117, 153, 181, 198, 204, 201, 191, 174, 185, 163, 143, 133, 128, 131, 141, 158, 182, 211, 239, 255, 254, 237, 214, 197, 192, 199, 211, 224, 232, 233, 227, 214, 196, 176, 154, 134, 119, 109, 104, 101, 96, 87, 75, 66, 62, 67, 77, 85, 82, 74, 57, 40, 25, 14, 9, 13, 32, 61, 91, 115, 128, 126, 113, 93, 72, 52, 39, 30, 28, 38, 60, 96, 140, 180, 210, 222, 220, 210, 204, 206, 215, 225, 229, 227, 221, 212, 205, 197, 193, 195, 202, 210, 211, 200, 180, 157, 136, 125, 127, 139, 155, 168, 171, 162, 145, 122, 95, 67, 43, 26, 20, 27, 46, 63, 74, 71, 57, 39, 25, 22, 23, 26, 28, 29, 29, 32, 37, 50, 70, 98, 126, 155, 181, 199, 207, 201, 185, 197, 175, 152, 136, 126, 125, 133, 152, 180, 211, 240, 255, 252, 233, 207, 186, 176, 179, 188, 198, 205, 205, 198, 184, 164, 142, 123, 113, 116, 129, 147, 162, 164, 154, 135, 114, 97, 91, 90, 92, 90, 85, 76, 67, 59, 54, 49, 47, 55, 71, 93, 117, 134, 142, 137, 125, 108, 86, 65, 45, 32, 36, 58, 97, 143, 179, 198, 193, 176, 153, 141, 142, 153, 169, 181, 185, 181, 167, 151, 133, 125, 129, 146, 171, 194, 203, 195, 172, 142, 120, 109, 113, 125, 137, 141, 136, 121, 99, 74, 51, 34, 29, 39, 60, 90, 114, 126, 120, 100, 74, 54, 45, 46, 54, 64, 72, 78, 81, 81, 81, 81, 86, 98, 122, 154, 184, 205, 209, 197, 195, 172, 147, 130, 119, 114, 115, 130, 156, 185, 209, 225, 230, 220, 204, 195, 196, 202, 208, 217, 228, 229, 223, 211, 195, 173, 148, 129, 123, 125, 130, 136, 136, 127, 110, 95, 84, 79, 76, 79, 87, 93, 93, 98, 105, 107, 101, 95, 95, 99, 103, 111, 120, 120, 112, 101, 85, 61, 36, 14, 1, 4, 25, 68, 119, 160, 186, 190, 183, 167, 157, 159, 172, 186, 196, 203, 200, 181, 154, 129, 116, 112, 120, 139, 158, 166, 156, 140, 122, 107, 99, 106, 122, 140, 150, 155, 152, 137, 113, 92, 76, 67, 66, 77, 96, 106, 106, 97, 80, 53, 29, 22, 26, 36, 48, 63, 81, 93, 97, 102, 109, 118, 127, 145, 172, 195, 208, 207, 195, 159, 138, 116, 105, 100, 96, 92, 101, 123, 144, 159, 175, 191, 194, 194, 200, 216, 226, 224, 225, 231, 230, 219, 206, 194, 175, 147, 123, 110, 104, 97, 93, 93, 91, 84, 83, 88, 91, 91, 98, 116, 130, 137, 148, 162, 166, 154, 141, 133, 122, 105, 96, 94, 83, 69, 59, 48, 30, 12, 2, 1, 6, 23, 61, 108, 144, 169, 183, 191, 185, 181, 186, 200, 207, 207, 207, 202, 179, 146, 116, 104, 97, 97, 105, 121, 126, 121, 118, 120, 121, 121, 132, 152, 170, 181, 191, 194, 181, 156, 135, 122, 108, 93, 89, 91, 84, 71, 61, 52, 34, 16, 16, 32, 49, 62, 83, 107, 123, 126, 133, 146, 157, 161, 167, 179, 186, 182, 173, 159, 119, 101, 83, 79, 83, 83, 76, 81, 97, 111, 119, 134, 159, 175, 187, 205, 231, 243, 234, 224, 223, 217, 200, 188, 181, 167, 140, 113, 98, 87, 73, 63, 63, 66, 70, 82, 103, 117, 122, 131, 151, 168, 173, 184, 196, 197, 179, 162, 149, 129, 101, 82, 71, 54, 35, 25, 19, 9, 1, 4, 14, 23, 36, 69, 110, 139, 159, 178, 195, 198, 199, 206, 219, 217, 203, 196, 189, 167, 135, 109, 100, 92, 85, 87, 97, 100, 100, 108, 125, 139, 148, 165, 187, 202, 209, 217, 221, 207, 181, 161, 150, 133, 108, 93, 84, 66, 44, 34, 32, 25, 15, 25, 53, 77, 90, 109, 133, 150, 151, 157, 172, 183, 182, 177, 177, 168, 152, 134, 119, 104, 118, 119, 108, 93, 67, 42, 54, 91, 125, 153, 162, 157, 148, 141, 153, 199, 232, 234, 222, 198, 163, 138, 134, 149, 171, 167, 140, 113, 79, 53, 58, 79, 108, 133, 137, 130, 121, 105, 114, 159, 197, 214, 224, 204, 170, 141, 123, 132, 147, 132, 109, 84, 35, 1, 5, 16, 34, 51, 44, 30, 14, 4, 38, 97, 144, 180, 196, 187, 168, 155, 161, 197, 222, 222, 214, 185, 135, 95, 79, 93, 119, 133, 131, 122, 98, 80, 94, 130, 165, 191, 202, 194, 182, 172, 177, 201, 213, 201, 181, 149, 104, 66, 57, 65, 77, 78, 66, 50, 25, 3, 21, 70, 117, 149, 162, 158, 147, 131, 133, 169, 204, 214, 207, 181, 141, 112, 99, 104, 114, 162, 172, 154, 125, 71, 39, 62, 101, 148, 185, 171, 136, 105, 78, 90, 147, 188, 202, 192, 142, 93, 74, 78, 120, 174, 186, 170, 138, 84, 60, 81, 111, 160, 196, 176, 144, 114, 78, 94, 154, 196, 224, 227, 176, 125, 99, 88, 124, 173, 170, 151, 115, 45, 13, 31, 55, 102, 133, 109, 75, 32, 1, 35, 91, 140, 188, 188, 153, 125, 102, 110, 168, 210, 220, 217, 168, 105, 79, 75, 107, 163, 184, 171, 146, 100, 70, 93, 134, 177, 213, 202, 162, 131, 104, 108, 155, 188, 193, 184, 134, 74, 46, 42, 69, 115, 127, 111, 87, 44, 18, 49, 103, 157, 199, 195, 161, 132, 101, 107, 159, 200, 216, 211, 163, 107, 87, 85, 114, 130, 202, 213, 191, 154, 80, 46, 78, 114, 165, 209, 174, 117, 75, 31, 46, 113, 152, 174, 166, 97, 42, 30, 40, 102, 178, 196, 188, 155, 87, 69, 104, 135, 196, 236, 195, 145, 103, 53, 76, 146, 188, 223, 221, 149, 94, 75, 69, 126, 195, 199, 184, 141, 58, 33, 61, 93, 158, 192, 152, 107, 45, 1, 39, 88, 137, 191, 174, 121, 93, 65, 77, 154, 203, 219, 221, 159, 90, 78, 82, 124, 199, 218, 196, 165, 100, 64, 97, 133, 176, 216, 186, 125, 86, 49, 56, 122, 165, 179, 178, 116, 52, 38, 41, 80, 149, 164, 145, 115, 57, 31, 74, 126, 183, 232, 211, 157, 119, 77, 85, 148, 188, 208, 206, 143, 84, 77, 83, 130, 90, 82, 58, 65, 78, 72, 93, 140, 157, 158, 177, 178, 153, 154, 175, 174, 164, 170, 161, 128, 119, 139, 148, 151, 170, 167, 134, 116, 114, 101, 106, 133, 135, 120, 120, 99, 56, 56, 85, 91, 112, 169, 183, 147, 143, 159, 131, 123, 185, 211, 168, 160, 155, 68, 7, 42, 47, 22, 73, 105, 42, 13, 41, 28, 37, 123, 176, 188, 230, 236, 183, 174, 188, 162, 167, 210, 192, 140, 124, 89, 25, 20, 59, 70, 87, 130, 137, 113, 116, 128, 130, 166, 221, 242, 251, 255, 220, 173, 157, 140, 118, 127, 129, 93, 66, 54, 22, 6, 37, 67, 83, 120, 156, 158, 159, 178, 189, 196, 212, 217, 201, 185, 160, 120, 98, 93, 80, 76, 90, 108, 89, 71, 90, 90, 70, 87, 111, 106, 120, 150, 148, 142, 165, 173, 164, 173, 178, 158, 150, 163, 166, 168, 179, 169, 138, 114, 97, 78, 79, 97, 102, 95, 91, 76, 52, 45, 60, 83, 112, 149, 174, 179, 167, 151, 146, 151, 158, 177, 193, 171, 128, 91, 43, 1, 9, 35, 44, 63, 78, 49, 19, 33, 56, 86, 147, 200, 214, 221, 214, 181, 159, 167, 169, 170, 183, 173, 130, 92, 65, 39, 36, 73, 109, 126, 145, 155, 142, 131, 143, 163, 189, 224, 247, 247, 232, 200, 162, 142, 132, 125, 131, 126, 103, 90, 83, 58, 51, 67, 63, 59, 93, 121, 126, 152, 177, 170, 176, 197, 190, 182, 202, 194, 161, 156, 148, 110, 97, 108, 140, 128, 105, 96, 82, 53, 34, 41, 62, 88, 109, 124, 131, 128, 127, 141, 159, 169, 184, 199, 203, 201, 198, 186, 163, 138, 113, 95, 80, 65, 58, 49, 27, 15, 15, 11, 21, 56, 88, 112, 146, 173, 180, 175, 158, 143, 147, 156, 170, 203, 210, 163, 115, 80, 37, 21, 49, 78, 95, 108, 80, 20, 1, 23, 47, 90, 152, 194, 213, 217, 188, 152, 151, 168, 182, 209, 223, 182, 118, 80, 53, 36, 57, 98, 124, 145, 154, 130, 98, 99, 118, 143, 183, 224, 248, 251, 221, 176, 155, 158, 156, 163, 183, 180, 147, 116, 93, 69, 51, 43, 47, 75, 114, 132, 131, 132, 142, 157, 173, 190, 213, 238, 237, 210, 187, 165, 142, 135, 140, 176, 161, 143, 131, 112, 98, 101, 110, 113, 111, 105, 92, 80, 77, 88, 106, 124, 138, 147, 148, 147, 151, 163, 172, 175, 171, 159, 135, 109, 93, 79, 64, 57, 57, 45, 28, 23, 24, 28, 47, 85, 120, 140, 149, 149, 138, 131, 142, 170, 197, 211, 205, 176, 129, 82, 57, 56, 67, 79, 86, 75, 41, 13, 11, 23, 52, 106, 162, 192, 200, 198, 182, 167, 172, 193, 213, 225, 217, 184, 136, 92, 61, 53, 68, 94, 115, 126, 122, 104, 91, 97, 120, 158, 208, 245, 255, 248, 229, 199, 175, 174, 180, 179, 175, 164, 135, 103, 88, 88, 95, 107, 121, 127, 122, 115, 115, 121, 133, 144, 153, 163, 163, 151, 146, 154, 156, 157, 170, 176, 172, 147, 130, 115, 90, 82, 87, 87, 94, 109, 106, 97, 105, 110, 103, 109, 120, 109, 92, 94, 101, 105, 124, 147, 150, 144, 142, 138, 135, 143, 150, 147, 139, 122, 84, 51, 36, 25, 21, 42, 68, 71, 68, 74, 65, 56, 82, 122, 150, 183, 214, 204, 170, 147, 127, 110, 115, 128, 124, 107, 79, 35, 1, 1, 13, 36, 87, 131, 144, 151, 162, 152, 152, 189, 222, 231, 246, 247, 200, 152, 134, 110, 89, 104, 122, 113, 105, 101, 83, 75, 98, 130, 162, 202, 230, 235, 235, 231, 215, 205, 209, 208, 195, 184, 167, 131, 103, 96, 90, 90, 111, 120, 106, 107, 115, 105, 112, 150, 164, 161, 183, 193, 166, 156, 171, 164, 157, 172, 172, 155, 149, 143, 145, 139, 126, 123, 128, 132, 131, 130, 127, 111, 96, 98, 97, 88, 92, 95, 79, 79, 100, 106, 115, 145, 156, 153, 175, 187, 167, 163, 171, 152, 135, 127, 101, 74, 76, 65, 36, 39, 59, 52, 51, 76, 92, 98, 128, 162, 170, 186, 207, 195, 182, 192, 179, 147, 145, 136, 100, 88, 74, 37, 45, 66, 35, 35, 88, 83, 60, 117, 155, 139, 178, 224, 202, 210, 255, 229, 184, 191, 173, 125, 118, 110, 68, 63, 83, 58, 35, 72, 108, 105, 124, 163, 175, 187, 219, 213, 190, 212, 227, 191, 178, 192, 158, 120, 125, 115, 88, 106, 128, 117, 116, 125, 112, 114, 134, 128, 118, 139, 147, 125, 118, 127, 121, 118, 139, 155, 129, 127, 122, 126, 124, 109, 99, 100, 92, 84, 87, 83, 68, 68, 74, 66, 70, 91, 93, 85, 100, 108, 94, 102, 119, 101, 87, 108, 104, 68, 58, 55, 29, 25, 37, 16, 1, 25, 34, 26, 42, 52, 41, 63, 98, 90, 84, 113, 123, 110, 119, 126, 115, 122, 128, 99, 82, 93, 81, 62, 75, 80, 69, 89, 110, 96, 102, 135, 135, 133, 168, 182, 172, 194, 207, 179, 182, 211, 192, 165, 177, 171, 143, 146, 149, 126, 134, 163, 153, 142, 175, 198, 191, 199, 218, 220, 231, 248, 235, 219, 226, 215, 186, 186, 193, 174, 169, 180, 167, 153, 170, 177, 170, 184, 195, 186, 189, 200, 184, 164, 169, 171, 154, 142, 141, 135, 126, 124, 129, 150, 169, 148, 129, 127, 116, 104, 101, 91, 89, 94, 85, 83, 107, 112, 89, 97, 109, 76, 54, 70, 63, 35, 42, 55, 34, 20, 30, 26, 12, 13, 18, 9, 3, 2, 2, 6, 14, 19, 30, 44, 34, 20, 31, 40, 23, 28, 58, 58, 45, 70, 87, 73, 85, 108, 93, 84, 106, 103, 87, 101, 112, 106, 120, 136, 132, 140, 144, 126, 127, 149, 144, 141, 174, 188, 173, 188, 211, 196, 184, 202, 209, 203, 213, 224, 217, 204, 204, 202, 192, 196, 214, 224, 216, 214, 223, 227, 223, 226, 240, 244, 234, 230, 239, 240, 232, 241, 255, 251, 247, 255, 251, 229, 213, 210, 197, 175, 165, 161, 139, 112, 103, 97, 74, 71, 103, 120, 123, 150, 131, 115, 109, 122, 114, 100, 108, 114, 105, 106, 99, 71, 56, 60, 48, 40, 63, 74, 55, 60, 75, 60, 56, 89, 102, 97, 115, 127, 102, 85, 79, 59, 40, 41, 38, 25, 22, 20, 8, 4, 11, 19, 33, 58, 78, 87, 99, 109, 109, 113, 131, 138, 137, 146, 142, 112, 95, 90, 68, 57, 74, 78, 73, 92, 102, 93, 104, 124, 131, 150, 185, 199, 200, 212, 212, 193, 190, 199, 189, 176, 179, 167, 137, 130, 135, 122, 123, 152, 163, 160, 184, 205, 200, 207, 229, 235, 238, 254, 255, 240, 227, 211, 189, 179, 178, 169, 170, 177, 167, 156, 166, 170, 163, 177, 202, 199, 192, 206, 201, 173, 177, 186, 160, 143, 158, 144, 113, 118, 131, 142, 142, 135, 122, 110, 97, 88, 85, 84, 81, 73, 63, 53, 47, 44, 42, 40, 34, 21, 11, 5, 2, 7, 19, 28, 33, 34, 30, 24, 22, 21, 23, 29, 31, 28, 22, 15, 5, 1, 2, 7, 15, 22, 28, 32, 34, 36, 43, 55, 67, 81, 94, 101, 103, 103, 99, 96, 100, 104, 109, 113, 113, 111, 108, 106, 108, 116, 126, 138, 152, 162, 167, 172, 178, 183, 191, 202, 212, 217, 216, 212, 207, 200, 195, 197, 200, 202, 205, 206, 202, 201, 204, 211, 220, 230, 242, 250, 253, 252, 252, 249, 246, 248, 253, 250, 244, 239, 228, 214, 206, 205, 203, 203, 205, 205, 197, 189, 185, 183, 184, 189, 194, 194, 185, 174, 163, 151, 143, 142, 142, 149, 151, 146, 136, 119, 103, 91, 86, 87, 84, 73, 64, 63, 59, 57, 63, 63, 47, 29, 17, 5, 1, 11, 27, 37, 41, 39, 34, 27, 21, 27, 42, 53, 59, 63, 58, 41, 30, 28, 29, 34, 45, 54, 55, 48, 41, 40, 43, 52, 72, 95, 107, 112, 115, 108, 99, 104, 117, 127, 138, 145, 143, 131, 117, 109, 111, 119, 132, 148, 158, 155, 151, 151, 151, 156, 176, 199, 212, 216, 216, 207, 193, 186, 190, 198, 203, 210, 211, 199, 184, 178, 178, 180, 192, 210, 223, 225, 222, 219, 214, 212, 219, 235, 245, 245, 242, 233, 212, 194, 193, 194, 194, 198, 201, 190, 171, 160, 154, 150, 156, 172, 182, 180, 173, 164, 150, 139, 142, 146, 144, 142, 141, 141, 138, 133, 128, 122, 110, 92, 76, 61, 53, 52, 53, 51, 45, 33, 21, 11, 4, 1, 3, 6, 6, 8, 9, 7, 7, 5, 4, 11, 20, 30, 43, 52, 52, 51, 49, 45, 44, 50, 54, 59, 60, 55, 50, 48, 44, 48, 60, 72, 83, 96, 99, 99, 106, 112, 118, 132, 147, 153, 157, 156, 148, 142, 140, 142, 149, 155, 155, 157, 158, 152, 149, 157, 168, 180, 194, 204, 209, 211, 208, 207, 209, 213, 221, 228, 226, 220, 213, 203, 195, 192, 195, 201, 207, 210, 211, 208, 203, 205, 214, 222, 230, 242, 245, 239, 232, 225, 216, 213, 213, 211, 205, 197, 185, 171, 157, 150, 150, 151, 153, 156, 157, 152, 147, 146, 121, 121, 118, 117, 121, 122, 121, 122, 121, 117, 109, 98, 89, 82, 72, 63, 57, 46, 36, 33, 31, 27, 24, 23, 21, 19, 20, 22, 21, 17, 11, 6, 2, 1, 6, 16, 26, 37, 45, 51, 53, 56, 60, 67, 75, 80, 83, 84, 79, 71, 69, 69, 67, 74, 84, 85, 86, 93, 96, 99, 110, 125, 136, 149, 160, 164, 166, 165, 164, 168, 171, 173, 175, 176, 169, 161, 158, 157, 157, 162, 172, 180, 183, 186, 193, 195, 199, 210, 219, 223, 227, 230, 227, 220, 215, 211, 209, 207, 205, 204, 199, 192, 188, 189, 191, 193, 203, 211, 213, 216, 220, 218, 215, 218, 219, 214, 210, 205, 195, 184, 173, 163, 154, 146, 140, 137, 131, 124, 121, 156, 155, 145, 135, 129, 123, 117, 117, 119, 114, 101, 87, 73, 58, 49, 46, 44, 40, 40, 39, 33, 24, 16, 9, 5, 8, 17, 24, 25, 23, 16, 7, 1, 1, 7, 15, 27, 38, 47, 54, 56, 52, 48, 48, 51, 55, 66, 76, 78, 76, 77, 73, 69, 78, 92, 101, 112, 128, 132, 128, 130, 135, 138, 144, 156, 164, 165, 164, 160, 155, 151, 151, 156, 165, 169, 167, 170, 171, 165, 166, 179, 186, 189, 200, 209, 204, 200, 203, 203, 200, 205, 211, 211, 209, 204, 197, 193, 190, 190, 197, 202, 202, 206, 210, 204, 200, 207, 211, 210, 217, 225, 220, 212, 211, 205, 193, 191, 194, 190, 183, 181, 176, 165, 156, 154, 153, 152, 152, 156, 163, 152, 138, 131, 133, 132, 127, 121, 113, 96, 76, 64, 59, 55, 55, 57, 51, 37, 26, 19, 14, 14, 17, 17, 14, 11, 8, 5, 3, 3, 7, 8, 4, 1, 4, 9, 18, 31, 45, 53, 48, 38, 35, 38, 42, 54, 75, 87, 85, 84, 85, 80, 79, 93, 110, 121, 130, 137, 131, 120, 120, 125, 132, 144, 156, 161, 157, 149, 143, 144, 145, 151, 167, 180, 180, 176, 176, 170, 163, 171, 189, 198, 202, 207, 205, 192, 186, 190, 194, 198, 207, 213, 210, 203, 196, 191, 190, 195, 205, 217, 220, 213, 209, 207, 199, 200, 213, 220, 217, 221, 220, 205, 194, 195, 195, 193, 200, 206, 200, 189, 181, 175, 170, 171, 179, 184, 179, 170, 163, 155, 155, 147, 135, 126, 120, 110, 102, 104, 103, 93, 85, 78, 67, 56, 52, 49, 45, 41, 39, 37, 30, 17, 8, 5, 1, 2, 13, 18, 14, 10, 8, 4, 2, 9, 19, 24, 29, 36, 43, 44, 46, 53, 59, 58, 60, 71, 79, 82, 88, 96, 95, 93, 98, 103, 104, 109, 119, 125, 126, 128, 131, 135, 135, 139, 148, 154, 155, 160, 165, 162, 158, 164, 169, 169, 172, 179, 180, 175, 174, 179, 180, 180, 187, 194, 193, 193, 195, 195, 192, 196, 202, 206, 207, 207, 208, 207, 199, 198, 205, 207, 204, 209, 212, 205, 200, 202, 199, 195, 200, 206, 205, 203, 201, 199, 195, 190, 192, 195, 192, 190, 191, 188, 177, 170, 168, 162, 156, 155, 170, 194, 214, 229, 240, 245, 243, 231, 213, 189, 162, 132, 107, 89, 79, 76, 77, 80, 83, 84, 84, 81, 73, 62, 53, 50, 49, 51, 54, 58, 63, 65, 65, 65, 65, 65, 65, 68, 72, 80, 87, 97, 106, 114, 120, 125, 132, 138, 142, 145, 149, 151, 149, 143, 133, 120, 105, 92, 82, 78, 82, 96, 119, 149, 180, 209, 233, 248, 255, 252, 243, 229, 213, 195, 177, 162, 150, 139, 128, 117, 108, 102, 98, 98, 100, 104, 110, 115, 116, 114, 110, 105, 99, 93, 90, 90, 95, 100, 108, 117, 124, 126, 126, 127, 126, 125, 124, 128, 137, 148, 160, 172, 184, 189, 188, 183, 173, 159, 142, 126, 113, 105, 101, 104, 111, 121, 132, 148, 170, 145, 168, 191, 211, 228, 242, 248, 244, 227, 201, 169, 136, 107, 88, 82, 86, 97, 111, 122, 130, 133, 131, 123, 114, 108, 106, 106, 108, 109, 111, 113, 112, 109, 105, 102, 97, 92, 89, 87, 88, 92, 99, 108, 119, 130, 138, 144, 147, 147, 143, 140, 136, 132, 127, 119, 105, 88, 70, 53, 40, 38, 48, 74, 111, 153, 194, 227, 248, 255, 249, 233, 214, 194, 175, 162, 152, 144, 136, 127, 116, 106, 100, 97, 100, 108, 120, 131, 140, 143, 142, 137, 129, 119, 111, 105, 102, 103, 104, 107, 111, 114, 114, 113, 111, 110, 107, 105, 105, 109, 118, 131, 146, 162, 173, 177, 172, 158, 135, 109, 83, 62, 51, 49, 57, 71, 88, 105, 123, 145, 135, 157, 179, 200, 221, 239, 250, 249, 233, 206, 171, 137, 106, 85, 77, 83, 98, 114, 130, 140, 146, 145, 139, 131, 126, 125, 126, 128, 130, 132, 133, 131, 126, 121, 114, 106, 97, 90, 87, 87, 92, 101, 113, 128, 141, 150, 154, 154, 149, 142, 135, 129, 125, 120, 113, 100, 82, 61, 40, 25, 19, 28, 55, 96, 142, 189, 225, 248, 255, 247, 229, 207, 186, 168, 156, 148, 143, 136, 127, 115, 105, 97, 93, 96, 106, 120, 135, 148, 156, 157, 154, 145, 134, 124, 115, 110, 107, 106, 106, 109, 111, 111, 110, 110, 109, 106, 102, 101, 103, 113, 126, 143, 161, 174, 179, 173, 154, 127, 95, 64, 41, 28, 28, 40, 58, 78, 97, 115, 135, 125, 141, 161, 182, 207, 230, 247, 255, 247, 225, 190, 147, 104, 68, 44, 35, 40, 55, 76, 97, 115, 125, 129, 128, 126, 126, 131, 140, 151, 163, 171, 170, 159, 138, 112, 86, 66, 56, 60, 77, 106, 140, 173, 199, 214, 217, 208, 191, 171, 152, 137, 128, 122, 117, 108, 92, 71, 46, 23, 6, 1, 12, 41, 84, 134, 182, 220, 244, 253, 246, 228, 205, 182, 163, 150, 142, 138, 131, 119, 103, 82, 62, 44, 35, 40, 59, 88, 122, 155, 181, 196, 197, 184, 163, 137, 114, 95, 87, 90, 99, 109, 119, 124, 126, 125, 122, 122, 128, 142, 162, 184, 205, 219, 221, 210, 184, 147, 104, 64, 31, 12, 7, 15, 32, 54, 75, 94, 109, 125, }; const uint8_t FLASHMEM wt_map[] = { 176, 255, 202, 193, 121, 122, 124, 123, 95, 197, 3, 8, 9, 35, 34, 32, 177, 30, 201, 185, 186, 83, 80, 54, 195, 196, 42, 41, 36, 37, 38, 33, 178, 31, 199, 184, 165, 82, 79, 86, 78, 45, 46, 47, 43, 44, 40, 39, 192, 198, 200, 183, 164, 81, 25, 26, 126, 125, 0, 1, 2, 6, 23, 22, 191, 179, 227, 228, 166, 84, 85, 14, 127, 128, 129, 130, 131, 132, 7, 209, 190, 134, 226, 229, 253, 204, 55, 12, 15, 10, 11, 163, 162, 167, 171, 208, 189, 133, 225, 230, 254, 216, 215, 214, 157, 158, 159, 160, 161, 168, 169, 170, 174, 234, 233, 231, 218, 217, 206, 205, 213, 56, 244, 242, 116, 115, 114, 243, 188, 235, 238, 232, 219, 207, 210, 211, 194, 145, 203, 245, 111, 112, 113, 108, 63, 27, 156, 237, 5, 149, 148, 246, 143, 144, 212, 52, 110, 109, 104, 172, 187, 28, 17, 236, 120, 150, 147, 50, 142, 141, 62, 60, 59, 102, 103, 57, 182, 29, 13, 239, 119, 151, 135, 138, 139, 140, 248, 99, 98, 100, 101, 61, 21, 19, 4, 240, 118, 152, 136, 137, 250, 251, 249, 247, 96, 53, 105, 106, 175, 24, 16, 241, 117, 153, 154, 155, 146, 51, 94, 93, 49, 97, 58, 107, 181, 252, 18, 220, 221, 64, 89, 90, 92, 91, 88, 87, 65, 66, 67, 68, 173, 20, 224, 223, 222, 48, 180, 77, 76, 75, 74, 73, 72, 71, 70, 69, }; const uint8_t FLASHMEM wt_code[] = { 5, 0, 132, 0, 20, 16, 20, 81, 16, 65, 8, 17, 4, 65, 17, 5, 0, 69, 1, 88, 17, 25, 0, 132, 144, 0, 64, 80, 0, 21, 148, 0, 65, 17, 5, 129, 4, 1, 68, 1, 65, 5, 65, 17, 21, 4, 20, 16, 4, 128, 80, 0, 4, 64, 20, 21, 0, 4, 1, 20, 16, 9, 17, 68, 17, 5, 17, 4, 1, 132, 0, 65, 16, 20, 81, 145, 1, 81, 17, 21, 16, 21, 81, 1, 20, 16, 21, 68, 16, 16, 144, 5, 0, 132, 17, 4, 65, 68, 129, 65, 20, 81, 129, 0, 4, 20, 65, 129, 17, 5, 80, 5, 64, 64, 1, 132, 64, 65, 17, 68, 65, 64, 17, 5, 80, 0, 4, 1, 20, 16, 25, 64, 4, 17, 4, 20, 16, 84, 20, 128, 5, 0, 132, 0, 65, 80, 1, 65, 24, 81, 0, 129, 80, 129, 17, 5, 64, 1, 65, 64, 16, 64, 16, 64, 17, 5, 64, 1, 65, 17, 5, 17, 132, 5, 80, 1, 64, 20, 1, 16, 25, 81, 0, 80, 4, 129, 16, 5, 0, 4, 20, 16, 4, 0, 8, 16, 4, 1, 20, 81, 16, 69, 1, 8, 21, 72, 0, 80, 4, 65, 1, 0, 80, 1, 65, 0, 64, 80, 65, 17, 4, 20, 20, 129, 1, 4, 21, 20, 16, 132, 17, 5, 16, 8, 1, 4, 4, 64, 0, 4, 5, 17, 21, 81, 0, 5, 128, 0, 65, 64, 17, 4, 80, 16, 68, 0, 4, 1, 1, 89, 17, 21, 64, 80, 1, 145, 0, 68, 20, 69, 1, 88, 17, 25, 0, 132, 16, 65, 80, 1, 81, 1, 4, 21, 16, 21, 1, 16, 9, 21, 20, 128, 4, 0, 69, 16, 20, 16, 21, 81, 65, 8, 20, 4, 64, 64, 1, 132, 21, 145, 1, 64, 24, 64, 16, 4, 80, 65, 1, 9, 5, 1, 4, 65, 4, 21, 64, 1, 81, 16, 16, 144, 17, 4, 1, 4, 5, 65, 20, 128, 80, 9, 5, 1, 4, 1, 88, 0, 64, 8, 81, 80, 1, 81, 17, 0, 145, 17, 69, 1, 4, 4, 17, 4, 9, 21, 20, 128, 81, 84, 17, 64, 17, 68, 16, 8, 16, 20, 81, 0, 21, 20, 128, 144, 5, 21, 0, 4, 1, 132, 64, 129, 1, 64, 80, 1, 65, 1, 5, 1, 1, 9, 9, 81, 64, 17, 64, 20, 68, 1, 24, 0, 4, 5, 65, 69, 65, 1, 68, 16, 8, 81, 4, 5, 65, 64, 65, 17, 8, 64, 0, 64, 80, 1, 68, 0, 24, 5, 85, 4, 65, 64, 80, 16, 64, 64, 17, 64, 20, 128, 80, 65, 1, 24, 69, 21, 1, 20, 65, 4, 129, 17, 5, 65, 1, 68, 16, 68, 1, 24, 0, 20, 81, 0, 5, 65, 1, 64, 17, 21, 4, 1, 1, 25, 81, 20, 64, 64, 16, 65, 80, 17, 0, 145, 1, 65, 0, 64, 20, 16, 20, 80, 64, 65, 17, 88, 0, 64, 24, 0, 4, 5, 65, 17, 0, 145, 17, 4, 65, 4, 145, 65, 4, 65, 0, 80, 17, 5, 80, 0, 4, 1, 1, 89, 0, 64, 4, 65, 8, 81, 80, 0, 88, 0, 64, 64, 0, 8, 17, 133, 65, 8, 64, 80, 64, 0, 24, 1, 5, 80, 17, 5, 8, 21, 0, 20, 81, 0, 149, 5, 0, 132, 0, 20, 16, 20, 81, 16, 65, 24, 16, 4, 65, 17, 5, 81, 1, 20, 17, 0, 88, 0, 64, 20, 16, 9, 5, 1, 4, 1, 8, 81, 17, 5, 65, 24, 65, 16, 64, 80, 0, 4, 64, 4, 128, 80, 65, 1, 8, 64, 5, 5, 65, 20, 128, 80, 25, 16, 21, 81, 0, 21, 1, 16, 9, 64, 64, 16, 64, 20, 84, 16, 16, 144, 20, 0, 21, 16, 68, 16, 65, 9, 16, 20, 81, 16, 8, 25, 16, 20, 81, 0, 5, 17, 4, 1, 68, 1, 0, 80, 5, 0, 4, 65, 132, 65, 4, 5, 65, 4, 129, 5, 0, 132, 1, 20, 81, 17, 5, 65, 17, 0, 145, 16, 5, 0, 20, 145, 16, 69, 16, 132, 20, 20, 65, 80, 17, 68, 1, 8, 20, 8, 25, 20, 81, 0, 68, 1, 0, 80, 16, 65, 64, 1, 65, 1, 5, 20, 20, 129, 1, 65, 17, 21, 84, 4, 64, 21, 1, 16, 9, 64, 68, 64, 65, 17, 8, 0, 20, 81, 16, 9, 16, 4, 5, 129, 5, 0, 68, 1, 145, 1, 65, 17, 5, 80, 16, 64, 1, 8, 16, 4, 1, 4, 20, 16, 20, 144, 64, 9, 21, 16, 4, 65, 17, 5, 64, 0, 88, 0, 64, 8, 65, 17, 21, 81, 81, 16, 16, 144, 144, 0, 4, 80, 1, 20, 64, 20, 24, 16, 4, 0, 20, 81, 16, 4, 80, 0, 24, 81, 0, 129, 16, 5, 0, 20, 81, 17, 5, 17, 4, 128, 80, 65, 1, 24, 16, 5, 20, 0, 20, 0, 4, 1, 68, 0, 24, 0, 4, 80, 16, 4, 64, 9, 16, 4, 65, 17, 21, 9, 25, 80, 64, 65, 1, 24, 81, 0, 129, 16, 81, 0, 21, 80, 24, 0, 20, 81, 1, 144, 80, 89, 0, 64, 8, 16, 4, 5, 129, 20, 20, 128, 17, 5, 16, 88, 0, 64, 8, 65, 17, 21, 81, 81, 16, 16, 144, 4, 0, 69, 16, 20, 16, 21, 0, 20, 81, 1, 20, 16, 25, 1, 5, 80, 64, 89, 80, 16, 64, 1, 5, 20, 20, 65, 16, 16, 144, 5, 0, 132, 1, 64, 80, 16, 84, 20, 20, 64, 4, 129, 5, 4, 17, 84, 17, 69, 1, 24, 0, 4, 21, 16, 20, 80, 17, 0, 145, 16, 5, 84, 0, 128, 5, 0, 132, 1, 4, 65, 64, 65, 1, 5, 64, 16, 16, 144, 16, 5, 0, 4, 85, 16, 17, 65, 0, 8, 0, 4, 5, 17, 4, 17, 68, 65, 64, 65, 17, 4, 16, 1, 24, 81, 20, 64, 64, 16, 65, 144, 16, 5, 0, 4, 4, 64, 16, 65, 4, 65, 20, 64, 16, 16, 144, 5, 0, 4, 85, 16, 17, 65, 0, 24, 0, 20, 16, 9, 64, 21, 81, 1, 65, 1, 5, 0, 4, 5, 80, 0, 68, 65, 16, 16, 80, 255, }; const uint8_t* wt_table[] = { wt_waves, wt_map, wt_code, }; const uint16_t FLASHMEM chr_characters[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 272, 1280, 29012, 46420, 9352, 39716, 256, 39936, 61440, 952, 340, 8, 68, 16, 136, 64648, 24704, 55364, 61504, 25668, 46148, 48196, 32912, 64580, 62532, 272, 264, 160, 4164, 520, 33936, 64592, 60484, 61776, 39936, 61712, 40004, 35908, 48192, 27716, 37136, 30720, 3236, 7168, 28288, 28192, 64512, 52292, 64544, 52324, 46148, 33040, 31744, 3208, 27688, 680, 656, 37000, 39936, 544, 61440, 40, 4096, 512, 63556, 7204, 6212, 28744, 39940, 35844, 62016, 11332, 4180, 12352, 432, 272, 10324, 8272, 14404, 35972, 50276, 80, 45632, 7172, 14336, 2056, 10280, 680, 29248, 4108, 37388, 272, 37088, 68, 0, 24736, 3592, 33408, 4136, 224, 524, 896, 56, 24712, 18568, 24, 40, 60416, 10308, 4368, 3616, 64520, 64516, 65024, 64768, 64640, 64576, 64544, 64528, 49152, 57344, 28672, 14336, 6144, 7168, 35840, 50176, 65532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65532, }; const uint16_t* char_table[] = { chr_characters, }; } // namespace braids ================================================ FILE: lib/braids/resources.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resources definitions. // // Automatically generated with: // make resources #ifndef BRAIDS_RESOURCES_H_ #define BRAIDS_RESOURCES_H_ #include "stmlib/stmlib.h" namespace braids { typedef uint8_t ResourceId; extern const char* string_table[]; extern const uint16_t* lookup_table_table[]; extern const int16_t* lookup_table_signed_table[]; extern const uint32_t* lookup_table_hr_table[]; extern const int16_t* waveform_table[]; extern const int16_t* waveshaper_table[]; extern const uint8_t* wt_table[]; extern const uint16_t* char_table[]; extern const uint16_t lut_resonator_coefficient[]; extern const uint16_t lut_resonator_scale[]; extern const uint16_t lut_svf_cutoff[]; extern const uint16_t lut_svf_damp[]; extern const uint16_t lut_svf_scale[]; extern const uint16_t lut_granular_envelope[]; extern const uint16_t lut_granular_envelope_rate[]; extern const uint16_t lut_bowing_envelope[]; extern const uint16_t lut_bowing_friction[]; extern const uint16_t lut_blowing_envelope[]; extern const uint16_t lut_flute_body_filter[]; extern const uint16_t lut_fm_frequency_quantizer[]; extern const uint16_t lut_vco_detune[]; extern const uint16_t lut_bell[]; extern const uint16_t lut_env_expo[]; extern const int16_t lut_blowing_jet[]; extern const uint32_t lut_oscillator_increments[]; extern const uint32_t lut_oscillator_delays[]; extern const uint32_t lut_env_portamento_increments[]; extern const int16_t wav_formant_sine[]; extern const int16_t wav_formant_square[]; extern const int16_t wav_sine[]; extern const int16_t wav_bandlimited_comb_0[]; extern const int16_t wav_bandlimited_comb_1[]; extern const int16_t wav_bandlimited_comb_2[]; extern const int16_t wav_bandlimited_comb_3[]; extern const int16_t wav_bandlimited_comb_4[]; extern const int16_t wav_bandlimited_comb_5[]; extern const int16_t wav_bandlimited_comb_6[]; extern const int16_t wav_bandlimited_comb_7[]; extern const int16_t wav_bandlimited_comb_8[]; extern const int16_t wav_bandlimited_comb_9[]; extern const int16_t wav_bandlimited_comb_10[]; extern const int16_t wav_bandlimited_comb_11[]; extern const int16_t wav_bandlimited_comb_12[]; extern const int16_t wav_bandlimited_comb_13[]; extern const int16_t wav_bandlimited_comb_14[]; extern const int16_t ws_moderate_overdrive[]; extern const int16_t ws_violent_overdrive[]; extern const int16_t ws_sine_fold[]; extern const int16_t ws_tri_fold[]; extern const uint8_t wt_waves[]; extern const uint8_t wt_map[]; extern const uint8_t wt_code[]; extern const uint16_t chr_characters[]; #define STR_DUMMY 0 // dummy #define LUT_RESONATOR_COEFFICIENT 0 #define LUT_RESONATOR_COEFFICIENT_SIZE 129 #define LUT_RESONATOR_SCALE 1 #define LUT_RESONATOR_SCALE_SIZE 129 const int LUT_SVF_CUTOFF = 2; #define LUT_SVF_CUTOFF_SIZE 257 const int LUT_SVF_DAMP = 3; #define LUT_SVF_DAMP_SIZE 257 const int LUT_SVF_SCALE = 4; #define LUT_SVF_SCALE_SIZE 257 #define LUT_GRANULAR_ENVELOPE 5 #define LUT_GRANULAR_ENVELOPE_SIZE 513 #define LUT_GRANULAR_ENVELOPE_RATE 6 #define LUT_GRANULAR_ENVELOPE_RATE_SIZE 257 #define LUT_BOWING_ENVELOPE 7 #define LUT_BOWING_ENVELOPE_SIZE 752 #define LUT_BOWING_FRICTION 8 #define LUT_BOWING_FRICTION_SIZE 257 #define LUT_BLOWING_ENVELOPE 9 #define LUT_BLOWING_ENVELOPE_SIZE 392 #define LUT_FLUTE_BODY_FILTER 10 #define LUT_FLUTE_BODY_FILTER_SIZE 128 const int LUT_FM_FREQUENCY_QUANTIZER = 11; const int LUT_FM_FREQUENCY_QUANTIZER_SIZE = 129; #define LUT_VCO_DETUNE 12 #define LUT_VCO_DETUNE_SIZE 257 #define LUT_BELL 13 #define LUT_BELL_SIZE 257 const int LUT_ENV_EXPO = 14; #define LUT_ENV_EXPO_SIZE 257 #define LUT_BLOWING_JET 0 #define LUT_BLOWING_JET_SIZE 257 const int LUT_OSCILLATOR_INCREMENTS = 0; #define LUT_OSCILLATOR_INCREMENTS_SIZE 97 #define LUT_OSCILLATOR_DELAYS 1 #define LUT_OSCILLATOR_DELAYS_SIZE 97 #define LUT_ENV_PORTAMENTO_INCREMENTS 2 #define LUT_ENV_PORTAMENTO_INCREMENTS_SIZE 128 #define WAV_FORMANT_SINE 0 #define WAV_FORMANT_SINE_SIZE 256 #define WAV_FORMANT_SQUARE 1 #define WAV_FORMANT_SQUARE_SIZE 256 const int WAV_SINE = 2; const int WAV_SINE_SIZE = 257; #define WAV_BANDLIMITED_COMB_0 3 #define WAV_BANDLIMITED_COMB_0_SIZE 257 #define WAV_BANDLIMITED_COMB_1 4 #define WAV_BANDLIMITED_COMB_1_SIZE 257 #define WAV_BANDLIMITED_COMB_2 5 #define WAV_BANDLIMITED_COMB_2_SIZE 257 #define WAV_BANDLIMITED_COMB_3 6 #define WAV_BANDLIMITED_COMB_3_SIZE 257 #define WAV_BANDLIMITED_COMB_4 7 #define WAV_BANDLIMITED_COMB_4_SIZE 257 #define WAV_BANDLIMITED_COMB_5 8 #define WAV_BANDLIMITED_COMB_5_SIZE 257 #define WAV_BANDLIMITED_COMB_6 9 #define WAV_BANDLIMITED_COMB_6_SIZE 257 #define WAV_BANDLIMITED_COMB_7 10 #define WAV_BANDLIMITED_COMB_7_SIZE 257 #define WAV_BANDLIMITED_COMB_8 11 #define WAV_BANDLIMITED_COMB_8_SIZE 257 #define WAV_BANDLIMITED_COMB_9 12 #define WAV_BANDLIMITED_COMB_9_SIZE 257 #define WAV_BANDLIMITED_COMB_10 13 #define WAV_BANDLIMITED_COMB_10_SIZE 257 #define WAV_BANDLIMITED_COMB_11 14 #define WAV_BANDLIMITED_COMB_11_SIZE 257 #define WAV_BANDLIMITED_COMB_12 15 #define WAV_BANDLIMITED_COMB_12_SIZE 257 #define WAV_BANDLIMITED_COMB_13 16 #define WAV_BANDLIMITED_COMB_13_SIZE 257 #define WAV_BANDLIMITED_COMB_14 17 #define WAV_BANDLIMITED_COMB_14_SIZE 257 #define WS_MODERATE_OVERDRIVE 0 #define WS_MODERATE_OVERDRIVE_SIZE 257 #define WS_VIOLENT_OVERDRIVE 1 #define WS_VIOLENT_OVERDRIVE_SIZE 257 #define WS_SINE_FOLD 2 #define WS_SINE_FOLD_SIZE 257 #define WS_TRI_FOLD 3 #define WS_TRI_FOLD_SIZE 257 #define WT_WAVES 0 #define WT_WAVES_SIZE 33024 #define WT_MAP 1 #define WT_MAP_SIZE 256 #define WT_CODE 2 #define WT_CODE_SIZE 1064 #define CHR_CHARACTERS 0 #define CHR_CHARACTERS_SIZE 256 } // namespace braids #endif // BRAIDS_RESOURCES_H_ ================================================ FILE: lib/braids/settings.cc ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Settings #include "settings.h" #include //#include "stmlib/system/storage.h" //#include "stmlib/utils/murmurhash3.h" namespace braids { using namespace stmlib; const SettingsData kInitSettings = { MACRO_OSC_SHAPE_CSAW, RESOLUTION_16_BIT, SAMPLE_RATE_48K, 0, // AD->timbre false, // Trig source 1, // Trig delay false, // Meta modulation PITCH_RANGE_EXTERNAL, 2, 0, // Quantizer is off false, false, false, 2, // Brightness 0, // AD attack 5, // AD decay 0, // AD->FM 0, // AD->COLOR 0, // AD->VCA 0, // Quantizer root 50, 15401, 2048, { 0, 0 }, { 32768, 32768 }, "GREETINGS FROM MUTABLE INSTRUMENTS *EDIT ME*", }; //Storage<0x8020000, 4> storage; void Settings::Init() { // if (!storage.ParsimoniousLoad(&data_, &version_token_)) { Reset(); // } bool settings_within_range = true; for (int32_t i = 0; i <= SETTING_LAST_EDITABLE_SETTING; ++i) { const Setting setting = static_cast(i); const SettingMetadata& setting_metadata = metadata(setting); uint8_t value = GetValue(setting); settings_within_range = settings_within_range && \ value >= setting_metadata.min_value && \ value <= setting_metadata.max_value; } settings_within_range = settings_within_range && data_.magic_byte == 'M'; for (int i = 0; i < 2; ++i) { settings_within_range = settings_within_range && \ data_.parameter_cv_scale[i] > 16384; settings_within_range = settings_within_range && \ data_.parameter_cv_offset[i] < 8000; settings_within_range = settings_within_range && \ data_.parameter_cv_offset[i] > -8000; } if (!settings_within_range) { Reset(); } CheckPaques(); } void Settings::Reset() { memcpy(&data_, &kInitSettings, sizeof(SettingsData)); data_.magic_byte = 'M'; } void Settings::Save() { data_.magic_byte = 'M'; //storage.ParsimoniousSave(data_, &version_token_); CheckPaques(); } void Settings::CheckPaques() { paques_ = !strcmp(data_.marquee_text, "49"); } const char* const boolean_values[] = { "OFF ", "ON " }; const char* const intensity_values[] = { "OFF ", " 1", " 2", " 3", "FULL" }; const char* const zero_to_fifteen_values[] = { " 0", " 1", " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9", " 10", " 11", " 12", " 13", " 14", " 15"}; const char* const algo_values[] = { "CSAW", "/\\-_", //"^\x88\x8D_" "//-_", //"\x88\x8A\x8C\x8D" "FOLD", "UUUU", //"\x8E\x8E\x8E\x8E", "SUB-", //"SUB\x8C" "SUB/", //"SUB\x88", "SYN-", //"SYN\x8C" "SYN/", //"SYN\x88", "//x3", //"\x88\x88x3", "-_x3", //"\x8C_x3", "/\\x3", "SIx3", "RING", "////", //"\x88\x89\x88\x89", "//UU", //"\x88\x88\x8E\x8E", "TOY*", "ZLPF", "ZPKF", "ZBPF", "ZHPF", "VOSM", "VOWL", "VFOF", "HARM", "FM ", "FBFM", "WTFM", "PLUK", "BOWD", "BLOW", "FLUT", "BELL", "DRUM", "KICK", "CYMB", "SNAR", "WTBL", "WMAP", "WLIN", "WTx4", "NOIS", "TWNQ", "CLKN", "CLOU", "PRTC", "QPSK", "****", // "NAME" // For your algorithm // Braids Renaissance https://burns.ca/eurorack.html "//CH", // "\x88\x88" "CH", "-_CH", // "\x8C_CH", "/\\CH", "SICH", "WTCH", "//x6", //"\x88\x88x6", "-_x6", //"\x8C_x6", "/\\x6", "SIx6", "WTx6", }; const char* const bits_values[] = { "2BIT", "3BIT", "4BIT", "6BIT", "8BIT", "12B", "16B " }; const char* const rates_values[] = { "4KHZ", "8KHZ", "16K ", "24K ", "32K ", "48K ", "96K " }; const char* const quantization_values[] = { "OFF ", "SEMI", "IONI", "DORI", "PHRY", "LYDI", "MIXO", "AEOL", "LOCR", "BLU+", "BLU-", "PEN+", "PEN-", "FOLK", "JAPA", "GAME", "GYPS", "ARAB", "FLAM", "WHOL", "PYTH", "EB/4", "E /4", "EA/4", "BHAI", "GUNA", "MARW", "SHRI", "PURV", "BILA", "YAMA", "KAFI", "BHIM", "DARB", "RAGE", "KHAM", "MIMA", "PARA", "RANG", "GANG", "KAME", "PAKA", "NATB", "KAUN", "BAIR", "BTOD", "CHAN", "KTOD", "JOGE" }; const char* const trig_source_values[] = { "EXT.", "AUTO" }; const char* const pitch_range_values[] = { "EXT.", "FREE", "XTND", "440 ", "LFO " }; const char* const octave_values[] = { "-2", "-1", "0", "1", "2" }; const char* const trig_delay_values[] = { "NONE", "125u", "250u", "500u", "1ms ", "2ms ", "4ms " }; const char* const brightness_values[] = { "\xff ", "\xff\xff ", "\xff\xff\xff\xff", }; const char* const note_values[] = { "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B", }; /* static */ const SettingMetadata Settings::metadata_[] = { { 0, MACRO_OSC_SHAPE_LAST - 2, "WAVE", algo_values }, { 0, RESOLUTION_LAST - 1, "BITS", bits_values }, { 0, SAMPLE_RATE_LAST - 1, "RATE", rates_values }, { 0, 15, "\x8F""TIM", zero_to_fifteen_values }, { 0, 1, "TSRC", trig_source_values }, { 0, 6, "TDLY", trig_delay_values }, { 0, 1, "META", boolean_values }, { 0, 3, "RANG", pitch_range_values }, { 0, 4, "OCTV", octave_values }, { 0, 48, "QNTZ", quantization_values }, { 0, 1, "FLAT", boolean_values }, { 0, 4, "DRFT", intensity_values }, { 0, 4, "SIGN", intensity_values }, { 0, 2, "BRIG", brightness_values }, { 0, 15, "\x8F""ATT", zero_to_fifteen_values }, { 0, 15, "\x8F""DEC", zero_to_fifteen_values }, { 0, 15, "\x8F""FM ", zero_to_fifteen_values }, { 0, 15, "\x8F""COL", zero_to_fifteen_values }, { 0, 1, "\x8F""VCA", boolean_values }, { 0, 11, "ROOT", note_values }, { 0, 0, "CAL.", NULL }, { 0, 0, " ", NULL }, // Placeholder for CV tester { 0, 0, " ", NULL }, // Placeholder for marquee { 0, 0, "v1.9", NULL }, // Placeholder for version string }; /* static */ const Setting Settings::settings_order_[] = { SETTING_OSCILLATOR_SHAPE, SETTING_META_MODULATION, SETTING_RESOLUTION, SETTING_SAMPLE_RATE, SETTING_TRIG_SOURCE, SETTING_TRIG_DELAY, SETTING_AD_ATTACK, SETTING_AD_DECAY, SETTING_AD_FM, SETTING_AD_TIMBRE, SETTING_AD_COLOR, SETTING_AD_VCA, SETTING_PITCH_RANGE, SETTING_PITCH_OCTAVE, SETTING_QUANTIZER_SCALE, SETTING_QUANTIZER_ROOT, SETTING_VCO_FLATTEN, SETTING_VCO_DRIFT, SETTING_SIGNATURE, SETTING_BRIGHTNESS, SETTING_CALIBRATION, SETTING_CV_TESTER, SETTING_MARQUEE, SETTING_VERSION, }; /* extern */ Settings settings; } // namespace braids ================================================ FILE: lib/braids/settings.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Settings #ifndef BRAIDS_SETTINGS_H_ #define BRAIDS_SETTINGS_H_ #include "stmlib/stmlib.h" namespace braids { enum MacroOscillatorShape { MACRO_OSC_SHAPE_CSAW, MACRO_OSC_SHAPE_MORPH, MACRO_OSC_SHAPE_SAW_SQUARE, MACRO_OSC_SHAPE_SINE_TRIANGLE, MACRO_OSC_SHAPE_BUZZ, MACRO_OSC_SHAPE_SQUARE_SUB, MACRO_OSC_SHAPE_SAW_SUB, MACRO_OSC_SHAPE_SQUARE_SYNC, MACRO_OSC_SHAPE_SAW_SYNC, MACRO_OSC_SHAPE_TRIPLE_SAW, MACRO_OSC_SHAPE_TRIPLE_SQUARE, MACRO_OSC_SHAPE_TRIPLE_TRIANGLE, MACRO_OSC_SHAPE_TRIPLE_SINE, MACRO_OSC_SHAPE_TRIPLE_RING_MOD, MACRO_OSC_SHAPE_SAW_SWARM, MACRO_OSC_SHAPE_SAW_COMB, MACRO_OSC_SHAPE_TOY, MACRO_OSC_SHAPE_DIGITAL_FILTER_LP, MACRO_OSC_SHAPE_DIGITAL_FILTER_PK, MACRO_OSC_SHAPE_DIGITAL_FILTER_BP, MACRO_OSC_SHAPE_DIGITAL_FILTER_HP, MACRO_OSC_SHAPE_VOSIM, MACRO_OSC_SHAPE_VOWEL, MACRO_OSC_SHAPE_VOWEL_FOF, MACRO_OSC_SHAPE_HARMONICS, MACRO_OSC_SHAPE_FM, MACRO_OSC_SHAPE_FEEDBACK_FM, MACRO_OSC_SHAPE_CHAOTIC_FEEDBACK_FM, MACRO_OSC_SHAPE_PLUCKED, MACRO_OSC_SHAPE_BOWED, MACRO_OSC_SHAPE_BLOWN, MACRO_OSC_SHAPE_FLUTED, MACRO_OSC_SHAPE_STRUCK_BELL, MACRO_OSC_SHAPE_STRUCK_DRUM, MACRO_OSC_SHAPE_KICK, MACRO_OSC_SHAPE_CYMBAL, MACRO_OSC_SHAPE_SNARE, MACRO_OSC_SHAPE_WAVETABLES, MACRO_OSC_SHAPE_WAVE_MAP, MACRO_OSC_SHAPE_WAVE_LINE, MACRO_OSC_SHAPE_WAVE_PARAPHONIC, MACRO_OSC_SHAPE_FILTERED_NOISE, MACRO_OSC_SHAPE_TWIN_PEAKS_NOISE, MACRO_OSC_SHAPE_CLOCKED_NOISE, MACRO_OSC_SHAPE_GRANULAR_CLOUD, MACRO_OSC_SHAPE_PARTICLE_NOISE, MACRO_OSC_SHAPE_DIGITAL_MODULATION, MACRO_OSC_SHAPE_QUESTION_MARK, // MACRO_OSC_SHAPE_YOUR_ALGO // Braids Renaissance https://burns.ca/eurorack.html MACRO_OSC_SHAPE_CHORD_SAW, MACRO_OSC_SHAPE_CHORD_SQUARE, MACRO_OSC_SHAPE_CHORD_TRIANGLE, MACRO_OSC_SHAPE_CHORD_SINE, MACRO_OSC_SHAPE_CHORD_WAVETABLE, MACRO_OSC_SHAPE_STACK_SAW, MACRO_OSC_SHAPE_STACK_SQUARE, MACRO_OSC_SHAPE_STACK_TRIANGLE, MACRO_OSC_SHAPE_STACK_SINE, MACRO_OSC_SHAPE_STACK_WAVETABLE, MACRO_OSC_SHAPE_LAST, MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META = MACRO_OSC_SHAPE_DIGITAL_MODULATION }; enum Resolution { RESOLUTION_2_BIT, RESOLUTION_3_BIT, RESOLUTION_4_BIT, RESOLUTION_6_BIT, RESOLUTION_8_BIT, RESOLUTION_12_BIT, RESOLUTION_16_BIT, RESOLUTION_LAST }; enum SampleRate { SAMPLE_RATE_4K, SAMPLE_RATE_8K, SAMPLE_RATE_16K, SAMPLE_RATE_24k, SAMPLE_RATE_32k, SAMPLE_RATE_48K, SAMPLE_RATE_96K, SAMPLE_RATE_LAST }; enum PitchRange { PITCH_RANGE_EXTERNAL, PITCH_RANGE_FREE, PITCH_RANGE_EXTENDED, PITCH_RANGE_440, PITCH_RANGE_LFO // This setting is hidden by default! }; enum Setting { SETTING_OSCILLATOR_SHAPE, SETTING_RESOLUTION, SETTING_SAMPLE_RATE, SETTING_AD_TIMBRE, SETTING_TRIG_SOURCE, SETTING_TRIG_DELAY, SETTING_META_MODULATION, SETTING_PITCH_RANGE, SETTING_PITCH_OCTAVE, SETTING_QUANTIZER_SCALE, SETTING_VCO_FLATTEN, SETTING_VCO_DRIFT, SETTING_SIGNATURE, SETTING_BRIGHTNESS, SETTING_AD_ATTACK, SETTING_AD_DECAY, SETTING_AD_FM, SETTING_AD_COLOR, SETTING_AD_VCA, SETTING_QUANTIZER_ROOT, SETTING_LAST_EDITABLE_SETTING = SETTING_QUANTIZER_ROOT, // Not settings per-se, but used for menu display! SETTING_CALIBRATION, SETTING_CV_TESTER, SETTING_MARQUEE, SETTING_VERSION, SETTING_LAST }; struct SettingsData { uint8_t shape; uint8_t resolution; uint8_t sample_rate; uint8_t ad_timbre; uint8_t auto_trig; uint8_t trig_delay; uint8_t meta_modulation; uint8_t pitch_range; uint8_t pitch_octave; uint8_t quantizer_scale; uint8_t vco_flatten; uint8_t vco_drift; uint8_t signature; uint8_t brightness; uint8_t ad_attack; uint8_t ad_decay; uint8_t ad_fm; uint8_t ad_color; uint8_t ad_vca; uint8_t quantizer_root; int32_t pitch_cv_offset; int32_t pitch_cv_scale; int32_t fm_cv_offset; int16_t parameter_cv_offset[2]; uint16_t parameter_cv_scale[2]; char marquee_text[55]; char magic_byte; }; struct SettingMetadata { uint8_t min_value; uint8_t max_value; const char name[5]; const char* const* strings; int16_t Clip(int16_t value) const { if (value > max_value) { value = max_value; } else if (value < min_value) { value = min_value; } return value; } }; class Settings { public: Settings() { } ~Settings() { } void Init(); void Save(); void Reset(); void SetValue(Setting setting, uint8_t value) { uint8_t* data = static_cast(static_cast(&data_)); data[setting] = value; } uint8_t GetValue(Setting setting) const { const uint8_t* data = static_cast( static_cast(&data_)); return data[setting]; } inline MacroOscillatorShape shape() const { return static_cast(data_.shape); } inline Resolution resolution() const { return static_cast(data_.resolution); } inline SampleRate sample_rate() const { return static_cast(data_.sample_rate); } inline bool vco_flatten() const { return data_.vco_flatten; } inline uint8_t vco_drift() const { return data_.vco_drift; } inline uint8_t signature() const { return data_.signature; } inline bool meta_modulation() const { return data_.meta_modulation; } inline uint8_t trig_delay() const { return data_.trig_delay; } inline int32_t quantizer_root() const { return data_.quantizer_root; } inline const char* marquee_text() const { return data_.marquee_text; } inline char* mutable_marquee_text() { return data_.marquee_text; } inline const SettingsData& data() const { return data_; } inline SettingsData* mutable_data() { return &data_; } void Calibrate( int32_t adc_code_c2, int32_t adc_code_c4, int32_t adc_code_fm, int32_t adc_code_p0_min, int32_t adc_code_p0_max, int32_t adc_code_p1_min, int32_t adc_code_p1_max) { if (adc_code_c4 != adc_code_c2) { int32_t scale = (24 * 128 * 4096L) / (adc_code_c4 - adc_code_c2); data_.pitch_cv_scale = scale; data_.pitch_cv_offset = (60 << 7) - (scale * ((adc_code_c2 + adc_code_c4) >> 1) >> 12); data_.fm_cv_offset = adc_code_fm; } // int32_t min_code[2] = { adc_code_p0_min, adc_code_p1_min }; // int32_t max_code[2] = { adc_code_p0_max, adc_code_p1_max }; // // for (int i = 0; i < 2; ++i) { // int32_t d = max_code[i] - min_code[i]; // if (d > 3700) { // int32_t scale = (32768 * 4106) / d; // int32_t offset = -(min_code[i] * scale >> 12) - 40; // data_.parameter_cv_offset[i] = offset; // data_.parameter_cv_scale[i] = scale; // } // } Save(); } inline int32_t adc_to_pitch(int32_t pitch_adc_code) const { if (data_.pitch_range == PITCH_RANGE_EXTERNAL || data_.pitch_range == PITCH_RANGE_LFO) { pitch_adc_code = pitch_adc_code * data_.pitch_cv_scale >> 12; pitch_adc_code += data_.pitch_cv_offset; } else if (data_.pitch_range == PITCH_RANGE_FREE) { pitch_adc_code = (pitch_adc_code - 1638); pitch_adc_code = pitch_adc_code * data_.pitch_cv_scale >> 12; pitch_adc_code += 60 << 7; } else if (data_.pitch_range == PITCH_RANGE_440) { pitch_adc_code = 69 << 7; } else { pitch_adc_code = (pitch_adc_code - 1638) * 9 >> 1; pitch_adc_code += 60 << 7; } return pitch_adc_code; } inline int32_t pitch_transposition() const { int32_t t = data_.pitch_range == PITCH_RANGE_LFO ? (unsigned)-36 << 7 : 0; t += (static_cast(data_.pitch_octave) - 2) * 12 * 128; return t; } inline int32_t adc_to_fm(int32_t fm_adc_code) const { fm_adc_code -= data_.fm_cv_offset; fm_adc_code = fm_adc_code * 7680 >> 12; if (data_.pitch_range == PITCH_RANGE_440) { fm_adc_code = 0; } return fm_adc_code; } inline int32_t adc_to_parameter(int index, int32_t adc_code) const { int32_t scale = static_cast(data_.parameter_cv_scale[index]); int32_t offset = static_cast(data_.parameter_cv_offset[index]); return (scale * adc_code >> 12) + offset; } inline bool paques() const { return paques_; } static const SettingMetadata& metadata(Setting setting) { return metadata_[setting]; } static const Setting& setting_at_index(int16_t index) { return settings_order_[index]; } private: void CheckPaques(); SettingsData data_; uint16_t version_token_; bool paques_; static const SettingMetadata metadata_[SETTING_LAST]; static const Setting settings_order_[SETTING_LAST]; DISALLOW_COPY_AND_ASSIGN(Settings); }; extern Settings settings; } // namespace braids #endif // BRAIDS_SETTINGS_H_ ================================================ FILE: lib/braids/svf.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // SVF used for modeling the bridged T-networks. #ifndef BRAIDS_SVF_H_ #define BRAIDS_SVF_H_ #include "stmlib/stmlib.h" #include "braids/resources.h" #include "stmlib/utils/dsp.h" namespace braids { enum SvfMode { SVF_MODE_LP, SVF_MODE_BP, SVF_MODE_HP }; class Svf { public: Svf() { } ~Svf() { } void Init() { lp_ = 0; bp_ = 0; frequency_ = 33 << 7; resonance_ = 16384; dirty_ = true; punch_ = 0; mode_ = SVF_MODE_BP; } void set_frequency(int16_t frequency) { dirty_ = dirty_ || (frequency_ != frequency); frequency_ = frequency; } void set_resonance(int16_t resonance) { resonance_ = resonance; dirty_ = true; } void set_punch(uint16_t punch) { punch_ = (static_cast(punch) * punch) >> 24; } void set_mode(SvfMode mode) { mode_ = mode; } inline int32_t Process(int32_t in) { if (dirty_) { f_ = stmlib::Interpolate824(lut_svf_cutoff, frequency_ << 17); damp_ = stmlib::Interpolate824(lut_svf_damp, resonance_ << 17); dirty_ = false; } int32_t f = f_; int32_t damp = damp_; if (punch_) { int32_t punch_signal = lp_ > 4096 ? lp_ : 2048; f += ((punch_signal >> 4) * punch_) >> 9; damp += ((punch_signal - 2048) >> 3); } int32_t notch = in - (bp_ * damp >> 15); lp_ += f * bp_ >> 15; CLIP(lp_) int32_t hp = notch - lp_; bp_ += f * hp >> 15; CLIP(bp_) return mode_ == SVF_MODE_BP ? bp_ : (mode_ == SVF_MODE_HP ? hp : lp_); } private: bool dirty_; int16_t frequency_; int16_t resonance_; int32_t punch_; int32_t f_; int32_t damp_; int32_t lp_; int32_t bp_; SvfMode mode_; DISALLOW_COPY_AND_ASSIGN(Svf); }; } // namespace braids #endif // BRAIDS_SVF_H_ ================================================ FILE: lib/braids/vco_jitter_source.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // A noise source used to add jitter to the VCO. #ifndef BRAIDS_VCO_JITTER_SOURCE_H_ #define BRAIDS_VCO_JITTER_SOURCE_H_ #include "stmlib/stmlib.h" #include #include "braids/resources.h" #include "stmlib/utils/dsp.h" #include "stmlib/utils/random.h" namespace braids { using namespace stmlib; class VcoJitterSource { public: VcoJitterSource() { } ~VcoJitterSource() { } inline void Init() { external_temperature_ = 0; room_temperature_ = 0; phase_ = 0; phase_step_ = 0; } inline int16_t Render(int32_t intensity) { // External temperature change, with 1-order filtering. uint16_t external_temperature_toss = Random::GetWord(); if (external_temperature_toss == 0) { phase_step_ = phase_step_ * 1664525L + 1013904223L; phase_ += (phase_step_ >> 16) * (phase_step_ >> 16); external_temperature_ = wav_sine[phase_ >> 24] << 8; } room_temperature_ += (external_temperature_ - room_temperature_) >> 16; int32_t pitch_noise = room_temperature_ * intensity >> 19; return pitch_noise; } private: uint32_t phase_step_; uint32_t phase_; int32_t external_temperature_; int32_t room_temperature_; DISALLOW_COPY_AND_ASSIGN(VcoJitterSource); }; } // namespace braids #endif // BRAIDS_VCO_JITTER_SOURCE_H_ ================================================ FILE: lib/claps/cp808.h ================================================ const uint8_t FLASHMEM cp808_raw[] = { 0xb9, 0xff, 0xb5, 0xff, 0x05, 0x00, 0x05, 0x00, 0x88, 0x00, 0x15, 0x00, 0xc6, 0x01, 0x9e, 0xff, 0xe4, 0x17, 0xfa, 0x2e, 0xb8, 0x35, 0x8b, 0x36, 0x19, 0x1c, 0xa2, 0x01, 0x5d, 0xed, 0x17, 0xe3, 0xea, 0xe7, 0x43, 0xd3, 0x24, 0xcf, 0x2e, 0xdf, 0x26, 0xf7, 0x24, 0xfe, 0x25, 0x02, 0x01, 0x02, 0xdf, 0xe9, 0x59, 0xe2, 0x10, 0xc6, 0x10, 0xd9, 0x1a, 0x07, 0x21, 0x08, 0xa2, 0x19, 0xb2, 0x25, 0xee, 0x16, 0xa7, 0x09, 0x01, 0xfd, 0x67, 0xea, 0x35, 0xf1, 0xac, 0xff, 0x21, 0xf5, 0x13, 0xe7, 0x9e, 0xda, 0x77, 0xf3, 0x62, 0x15, 0xea, 0x1a, 0x31, 0x25, 0x9c, 0x25, 0xa4, 0x20, 0x03, 0x30, 0x3c, 0x38, 0x20, 0x49, 0x3f, 0x38, 0x76, 0x20, 0x74, 0x22, 0x05, 0x27, 0x9f, 0x1a, 0x24, 0xfe, 0xad, 0xe5, 0x77, 0xd3, 0x6a, 0xdb, 0xf8, 0xe3, 0xe6, 0xf4, 0x9c, 0xec, 0x5f, 0xe0, 0xe4, 0xe7, 0x3e, 0xe9, 0xc7, 0xe3, 0x66, 0xdd, 0x84, 0xf2, 0x99, 0x00, 0x8b, 0x07, 0xe7, 0x0b, 0xa4, 0xfc, 0x83, 0xee, 0x20, 0xe9, 0x44, 0xf0, 0xf9, 0xf8, 0x59, 0xf5, 0x09, 0xef, 0xc3, 0xf5, 0xb6, 0xfc, 0x5d, 0xf8, 0x0f, 0xf6, 0x13, 0x02, 0xda, 0x09, 0x27, 0x12, 0x37, 0x19, 0xbe, 0x20, 0x20, 0x2e, 0x3b, 0x38, 0x50, 0x37, 0x08, 0x36, 0x3d, 0x36, 0x20, 0x29, 0xe5, 0x18, 0x67, 0x0b, 0xb1, 0x06, 0x47, 0xfd, 0xa4, 0xf5, 0x8a, 0xeb, 0xe1, 0xdd, 0x6c, 0xd4, 0x0e, 0xce, 0x69, 0xc4, 0xd4, 0xbf, 0xd7, 0xd1, 0x90, 0xdb, 0x41, 0xe3, 0x92, 0xf4, 0xaf, 0x03, 0x7a, 0x05, 0x8f, 0x06, 0xf0, 0x07, 0x12, 0x05, 0x5b, 0x08, 0xcf, 0x10, 0x3c, 0x15, 0x98, 0x0b, 0xeb, 0x02, 0x76, 0xfd, 0xe7, 0xf9, 0x6a, 0xfd, 0xad, 0x05, 0xef, 0x06, 0xe4, 0x0a, 0xa3, 0x0e, 0xfb, 0x0e, 0x0a, 0x13, 0x0f, 0x0d, 0x2f, 0x08, 0x20, 0x05, 0x2c, 0x07, 0xf3, 0x0b, 0x18, 0x0c, 0xbf, 0x0e, 0x16, 0x0b, 0xa4, 0x07, 0x93, 0x07, 0x60, 0xff, 0x9b, 0x00, 0xde, 0xf3, 0xdb, 0xea, 0x61, 0xec, 0x59, 0xe9, 0x80, 0xea, 0xeb, 0xe7, 0x77, 0xe2, 0x46, 0xe0, 0xdb, 0xe4, 0xa4, 0xec, 0x6f, 0xea, 0xcb, 0xe6, 0x25, 0xeb, 0x8b, 0xef, 0x6a, 0xfc, 0x62, 0x04, 0x6f, 0x01, 0x7b, 0x00, 0x77, 0xff, 0x76, 0x0a, 0x92, 0x0d, 0x60, 0x10, 0xf1, 0x14, 0x30, 0x18, 0xed, 0x15, 0xed, 0x0c, 0xa8, 0x0c, 0x64, 0x0f, 0x3a, 0x0e, 0x05, 0x0c, 0x22, 0x10, 0x52, 0x15, 0xb3, 0x19, 0x19, 0x12, 0xc8, 0x05, 0xd8, 0xfc, 0x5a, 0xf5, 0xdf, 0xf6, 0x0e, 0xf7, 0xdf, 0xf2, 0x15, 0xf0, 0x30, 0xf6, 0xfc, 0xf9, 0x2b, 0x00, 0x47, 0x05, 0xe7, 0x07, 0x8d, 0x08, 0x42, 0x07, 0xec, 0x06, 0xf5, 0x01, 0xd5, 0xfd, 0xb7, 0xfa, 0x95, 0xf9, 0x8b, 0xf6, 0xa6, 0xf4, 0x66, 0xf2, 0xfb, 0xed, 0x86, 0xee, 0x54, 0xf1, 0x39, 0xf2, 0xd2, 0xf3, 0x4b, 0xfc, 0x88, 0x03, 0x1a, 0x06, 0x38, 0x05, 0xe7, 0x05, 0x4a, 0x06, 0x99, 0x06, 0x57, 0x07, 0x93, 0x03, 0xcf, 0x01, 0xc3, 0x04, 0xac, 0x03, 0xd6, 0x01, 0xe0, 0x02, 0x36, 0x02, 0xed, 0xfe, 0x2b, 0xfa, 0x48, 0xf8, 0x52, 0xfc, 0xdc, 0x00, 0xd6, 0xfd, 0x96, 0xfb, 0x98, 0xfc, 0x38, 0xff, 0x8d, 0x02, 0x3e, 0x07, 0xd2, 0x0a, 0xdd, 0x08, 0xb6, 0x08, 0xbe, 0x06, 0x99, 0x04, 0xb6, 0x01, 0x49, 0x00, 0xbd, 0x03, 0x26, 0x04, 0x81, 0x01, 0x91, 0xfe, 0xf6, 0xf6, 0x5f, 0xf2, 0x57, 0xf4, 0x26, 0xf6, 0x97, 0xf6, 0xa8, 0xf7, 0xb6, 0xf8, 0x59, 0xfe, 0xd8, 0x00, 0x54, 0x01, 0x1d, 0x03, 0xe8, 0x02, 0xd0, 0x02, 0xb9, 0x00, 0xb3, 0xfd, 0x2c, 0xf9, 0x64, 0xf8, 0xd3, 0xf8, 0x4d, 0xfc, 0xdf, 0x00, 0x54, 0x03, 0xc0, 0x03, 0x63, 0x04, 0x55, 0x09, 0xf4, 0x07, 0xc9, 0x04, 0x15, 0x02, 0x2c, 0xff, 0x29, 0xfc, 0x4c, 0xfb, 0x1a, 0xf9, 0xfa, 0xfb, 0x13, 0x01, 0x84, 0x03, 0x8d, 0x07, 0x3c, 0x08, 0xf1, 0x04, 0x59, 0x03, 0x84, 0x02, 0x16, 0x00, 0x55, 0xff, 0x6d, 0x01, 0x97, 0x04, 0x52, 0x06, 0x51, 0x07, 0x95, 0x05, 0x48, 0x02, 0xed, 0x01, 0x33, 0x02, 0x76, 0x00, 0xa9, 0xfc, 0x54, 0xfa, 0xb3, 0xf9, 0x08, 0xfa, 0x2f, 0xf9, 0xfa, 0xf6, 0x21, 0xf6, 0xd6, 0xf5, 0xc8, 0xf7, 0x22, 0xf9, 0x9c, 0xfb, 0xd2, 0xfc, 0xbb, 0xfa, 0xf2, 0xf9, 0x57, 0xfb, 0x9d, 0xfe, 0x38, 0x00, 0x2a, 0x00, 0xc3, 0x01, 0xf6, 0x03, 0xf6, 0x04, 0x23, 0x05, 0x1f, 0x05, 0xa3, 0x02, 0x26, 0x01, 0x09, 0x04, 0x75, 0x06, 0xff, 0x06, 0x5e, 0x07, 0xf5, 0x04, 0xfe, 0x02, 0x9c, 0x02, 0x21, 0x03, 0x0a, 0x03, 0x6b, 0x02, 0xcd, 0x01, 0x0e, 0xfe, 0xc9, 0xfb, 0xa3, 0xfb, 0x72, 0xfd, 0x69, 0x00, 0xcd, 0x00, 0x2c, 0x03, 0x3f, 0x05, 0x78, 0x02, 0x98, 0x01, 0x2e, 0x01, 0xec, 0x00, 0x75, 0x00, 0x8f, 0xff, 0x9c, 0xfd, 0x8a, 0xfb, 0xd4, 0xfb, 0x9c, 0xfb, 0x99, 0xfc, 0x63, 0xfc, 0xb0, 0xfb, 0x51, 0xfd, 0xd5, 0xfe, 0x66, 0xff, 0xe3, 0xff, 0x77, 0x00, 0x0d, 0x01, 0x28, 0x00, 0x19, 0xfe, 0xb4, 0xfc, 0xa1, 0xfa, 0x40, 0xfa, 0x33, 0xfa, 0x52, 0xfa, 0x4b, 0xfb, 0xad, 0xfd, 0xfd, 0xfe, 0x2f, 0xff, 0x43, 0x01, 0x6f, 0x02, 0x65, 0x03, 0x6c, 0x03, 0xca, 0x03, 0x08, 0x04, 0xa4, 0x03, 0xdf, 0x02, 0xa6, 0x01, 0x1f, 0x02, 0x47, 0x02, 0xd6, 0x00, 0xa8, 0xff, 0x99, 0xff, 0x45, 0x00, 0x6d, 0x01, 0xef, 0x01, 0x30, 0x00, 0x9e, 0xff, 0xfe, 0xff, 0xb6, 0xff, 0xc2, 0xff, 0x2f, 0x00, 0x5d, 0x00, 0xe0, 0xff, 0x66, 0xfe, 0x3a, 0xfd, 0xb3, 0xfd, 0x2d, 0xfe, 0xdb, 0xfe, 0x00, 0x00, 0x28, 0x01, 0x2a, 0x01, 0x2c, 0x01, 0xcc, 0x01, 0x32, 0x02, 0x7d, 0x01, 0x6a, 0x00, 0x93, 0xff, 0x1b, 0x00, 0xc2, 0xff, 0xf7, 0xfe, 0x4d, 0xff, 0x4e, 0xff, 0x20, 0xff, 0x25, 0xfe, 0x29, 0xfe, 0x56, 0xfe, 0xe6, 0xfd, 0x4d, 0xfe, 0x84, 0xfe, 0xe8, 0xfe, 0x63, 0xff, 0x77, 0xff, 0x1d, 0xff, 0x50, 0xff, 0x11, 0x00, 0xe5, 0x00, 0x29, 0x02, 0xbb, 0x01, 0x35, 0x00, 0xfc, 0xfe, 0xb2, 0xff, 0x44, 0x00, 0x14, 0x01, 0x39, 0x01, 0x65, 0x00, 0xf7, 0x00, 0x22, 0x01, 0x17, 0x01, 0x7e, 0x01, 0xa5, 0x01, 0xa5, 0x01, 0x38, 0x01, 0x3a, 0x00, 0x1f, 0x00, 0x1e, 0x00, 0xc7, 0xfe, 0x52, 0xfe, 0x3d, 0xfe, 0xce, 0xfd, 0xbe, 0xfd, 0x81, 0xfd, 0x1a, 0xfd, 0x66, 0xfd, 0x87, 0xfe, 0x65, 0xff, 0x79, 0x00, 0x22, 0x02, 0xc6, 0x02, 0x65, 0x03, 0x5b, 0x03, 0x69, 0x02, 0x78, 0x01, 0xc8, 0x00, 0x1c, 0x00, 0xa6, 0xff, 0x0e, 0xff, 0xb1, 0xfe, 0xfe, 0xfe, 0x6d, 0xff, 0xf2, 0xfe, 0x12, 0xfe, 0x4b, 0xfe, 0x01, 0xff, 0xb1, 0xff, 0x3e, 0x00, 0x76, 0x00, 0x23, 0x00, 0x64, 0xff, 0x01, 0xff, 0x83, 0xff, 0x0f, 0x00, 0x92, 0xff, 0x34, 0xff, 0xea, 0xff, 0x08, 0x00, 0x47, 0x00, 0xb2, 0x00, 0xcb, 0x00, 0xa0, 0x00, 0x16, 0x00, 0x09, 0xff, 0xc9, 0xff, 0xc5, 0xf9, 0xdb, 0xfe, 0x34, 0x03, 0x0b, 0xee, 0xe0, 0xf7, 0x9d, 0x10, 0xa9, 0x0b, 0x5a, 0x11, 0xd8, 0x35, 0xe5, 0x55, 0xd5, 0x3b, 0x50, 0x0c, 0xb6, 0x01, 0xd7, 0xf9, 0xb4, 0xe9, 0x72, 0xe6, 0x61, 0xe4, 0x99, 0xea, 0xd0, 0x02, 0x33, 0x14, 0x74, 0xf8, 0x0a, 0xdc, 0x13, 0xd3, 0xa8, 0xd4, 0xce, 0xe4, 0x25, 0xe7, 0x9b, 0xd5, 0x73, 0xd3, 0xce, 0xd8, 0x7d, 0xdb, 0xbf, 0xe5, 0xc5, 0xfc, 0xb4, 0x1b, 0x4e, 0x32, 0x86, 0x3d, 0xd4, 0x38, 0xfa, 0x19, 0x62, 0x0e, 0xfa, 0x10, 0x3c, 0x1a, 0xe1, 0x20, 0xfb, 0x1d, 0xa2, 0x18, 0x57, 0x10, 0xf8, 0x20, 0x7c, 0x3d, 0x5e, 0x3a, 0xa2, 0x2a, 0x5f, 0x29, 0x29, 0x26, 0xee, 0x11, 0xc7, 0x03, 0x1c, 0xfb, 0xda, 0xe5, 0x25, 0xde, 0x77, 0xcf, 0xea, 0xca, 0x0a, 0xbc, 0xb4, 0xbd, 0x51, 0xbb, 0x9c, 0x9d, 0x2d, 0x95, 0xea, 0xa1, 0xc4, 0xb5, 0x76, 0xc6, 0x45, 0xe4, 0x3d, 0xe7, 0x4e, 0xf0, 0xa9, 0x01, 0xde, 0x11, 0x1d, 0x27, 0xd5, 0x21, 0x72, 0x1f, 0x92, 0x29, 0xe5, 0x29, 0xf9, 0x27, 0x88, 0x24, 0x09, 0x17, 0xd8, 0x1b, 0x76, 0x1d, 0x00, 0x09, 0xab, 0x10, 0x48, 0x26, 0xdb, 0x2f, 0x33, 0x3b, 0x75, 0x37, 0xb0, 0x28, 0x1c, 0x1a, 0x22, 0x15, 0xbf, 0x1a, 0x8a, 0x18, 0x23, 0x11, 0x8b, 0x0f, 0x9f, 0x00, 0x72, 0xec, 0x32, 0xed, 0x1d, 0xee, 0xa3, 0xde, 0x26, 0xdd, 0x12, 0xe4, 0x43, 0xe7, 0x8f, 0xe1, 0x4f, 0xde, 0xfe, 0xdb, 0x4b, 0xe8, 0xb3, 0xf1, 0x48, 0xed, 0x4c, 0xe8, 0xd8, 0xef, 0x4f, 0xf1, 0x07, 0xf2, 0x07, 0xf1, 0x1d, 0xe8, 0xc0, 0xe4, 0x71, 0xe6, 0xc8, 0xe7, 0xc9, 0xe9, 0x0c, 0xfb, 0x02, 0x12, 0xea, 0x23, 0xe1, 0x24, 0xc5, 0x22, 0x8f, 0x1f, 0xe2, 0x21, 0x5b, 0x2e, 0x61, 0x35, 0xae, 0x27, 0x53, 0x15, 0xe2, 0x00, 0xd5, 0xf8, 0x84, 0xfd, 0x64, 0x07, 0x81, 0x04, 0x90, 0xf4, 0x37, 0xed, 0xe4, 0xef, 0xb8, 0xed, 0xfd, 0xef, 0xae, 0xf4, 0x07, 0xf0, 0x9e, 0xed, 0xea, 0xe8, 0x79, 0xea, 0xb2, 0xe0, 0xce, 0xd5, 0xd6, 0xe2, 0xf4, 0xed, 0x6d, 0xf6, 0x43, 0xfd, 0x27, 0x07, 0x78, 0x14, 0x51, 0x13, 0x7f, 0x08, 0x13, 0xfe, 0x7a, 0x04, 0xcd, 0x00, 0x04, 0xfc, 0x81, 0x0c, 0xcc, 0x17, 0x79, 0x19, 0x77, 0x16, 0x07, 0x1c, 0xb5, 0x1b, 0x48, 0x0f, 0xc1, 0x08, 0x82, 0x0a, 0x4c, 0x0f, 0x23, 0x17, 0x5a, 0x1b, 0x18, 0x22, 0x96, 0x1a, 0xb0, 0x0b, 0xcc, 0x01, 0xb9, 0x03, 0x6f, 0x09, 0x1f, 0x06, 0xa0, 0xfa, 0xb5, 0xf2, 0xde, 0xf1, 0x7e, 0xe5, 0x65, 0xde, 0xad, 0xda, 0xb5, 0xd9, 0xc5, 0xd8, 0xe7, 0xda, 0x08, 0xde, 0xab, 0xe6, 0x88, 0xea, 0xa9, 0xed, 0xd8, 0xf9, 0xb1, 0xff, 0xe4, 0xff, 0xbb, 0x02, 0xc7, 0x03, 0xca, 0x07, 0x42, 0x0b, 0xc0, 0x0b, 0xa8, 0x10, 0xd6, 0x11, 0x12, 0x14, 0xa2, 0x14, 0x68, 0x10, 0x14, 0x10, 0x1b, 0x11, 0xfe, 0x09, 0x7e, 0x05, 0x25, 0xfc, 0xf1, 0xf3, 0x91, 0xfa, 0x5d, 0xfc, 0xc4, 0xfc, 0x34, 0x02, 0xac, 0x04, 0xf3, 0x03, 0x7c, 0x03, 0x13, 0x00, 0x45, 0xfd, 0xa4, 0xfa, 0xe4, 0xfd, 0x3b, 0x00, 0xa5, 0xf5, 0x1f, 0xef, 0x92, 0xef, 0xe9, 0xf0, 0x3e, 0xf3, 0x0c, 0xff, 0x1e, 0x09, 0xa6, 0x08, 0xaf, 0x03, 0xec, 0xfc, 0xc6, 0xfc, 0xeb, 0xf9, 0x80, 0xf7, 0xbc, 0xf5, 0x84, 0xfb, 0xbf, 0x04, 0xfa, 0x0a, 0xfe, 0x0d, 0x96, 0x0d, 0xfb, 0x0c, 0x14, 0x0d, 0x2f, 0x10, 0xf1, 0x11, 0x27, 0x12, 0xf8, 0x0f, 0x1e, 0x0a, 0x6a, 0xff, 0xb1, 0xfa, 0xf2, 0xfa, 0xcd, 0xfb, 0xf3, 0xfb, 0x30, 0xfd, 0xa1, 0xfb, 0xed, 0xf6, 0xbc, 0xf6, 0x50, 0xf6, 0x92, 0xf4, 0xc3, 0xf2, 0xa5, 0xf6, 0x68, 0xf8, 0x3d, 0xfa, 0xae, 0xfa, 0x20, 0xfb, 0xf3, 0xfd, 0xf5, 0xf9, 0xda, 0xf8, 0x6d, 0xfa, 0x40, 0xfe, 0x8c, 0x04, 0xf2, 0x07, 0xc1, 0x0b, 0x71, 0x0b, 0x52, 0x0a, 0xdf, 0x07, 0x47, 0x06, 0x7b, 0x04, 0xe2, 0xfe, 0x84, 0xfc, 0x4c, 0xfc, 0x17, 0x00, 0x81, 0x00, 0xb5, 0x01, 0x70, 0x02, 0x27, 0x05, 0x94, 0x09, 0xd6, 0x0a, 0xc8, 0x09, 0xe2, 0x07, 0x01, 0x05, 0x86, 0xfe, 0x0f, 0xfa, 0x83, 0xf9, 0x6a, 0xfb, 0x82, 0xfa, 0x8e, 0xf8, 0xaa, 0xf7, 0x94, 0xf6, 0x44, 0xf7, 0x6a, 0xf6, 0x1a, 0xf4, 0x59, 0xf1, 0x44, 0xf4, 0x3f, 0xfb, 0xd0, 0xfe, 0xdd, 0x00, 0xd7, 0x02, 0xb4, 0x03, 0xe6, 0x06, 0xd5, 0x07, 0x76, 0x06, 0x4e, 0x06, 0x4a, 0x04, 0x50, 0x02, 0x07, 0xff, 0x41, 0xfe, 0xb9, 0xff, 0xea, 0xfe, 0x7f, 0xfe, 0x4e, 0xfe, 0x46, 0xfc, 0x66, 0xfb, 0x5c, 0xfc, 0x82, 0xfe, 0xc1, 0x01, 0xca, 0x02, 0xca, 0x01, 0x82, 0x01, 0xd0, 0x02, 0x89, 0x05, 0xce, 0x04, 0x1e, 0x01, 0xe8, 0xfd, 0xf8, 0xfe, 0x90, 0x00, 0xb3, 0x00, 0x7d, 0x02, 0x4a, 0x03, 0x41, 0x02, 0x77, 0x00, 0x7b, 0xfe, 0x32, 0xfd, 0x4d, 0xfe, 0xd1, 0x01, 0x2e, 0x03, 0x0c, 0x04, 0xff, 0x04, 0x78, 0x06, 0x2f, 0x06, 0xa2, 0x02, 0x7a, 0x00, 0xc5, 0xfe, 0x56, 0xfc, 0x04, 0xfc, 0x60, 0xfb, 0x39, 0xfc, 0x02, 0xfe, 0x49, 0xfe, 0xd3, 0xfd, 0xc6, 0xfe, 0x81, 0xfe, 0xd9, 0xfd, 0x25, 0xff, 0xfb, 0xfd, 0x5d, 0xfd, 0x16, 0xfc, 0x44, 0xfd, 0x54, 0xfd, 0xe2, 0xfd, 0x27, 0xff, 0x3d, 0xfe, 0x89, 0xfe, 0x24, 0xff, 0xb9, 0xff, 0xe4, 0xff, 0xb0, 0x00, 0xa3, 0x01, 0x16, 0x02, 0x0e, 0x03, 0x9b, 0x03, 0xc2, 0x03, 0x7b, 0x01, 0x1f, 0x01, 0x63, 0x01, 0x4a, 0xff, 0xab, 0xff, 0x64, 0x00, 0x39, 0x00, 0x5a, 0xfe, 0x3c, 0xfd, 0x14, 0xfd, 0x61, 0xfc, 0x4c, 0xfd, 0x16, 0xff, 0xc0, 0x00, 0x3c, 0x01, 0x70, 0x00, 0x7f, 0xff, 0x4b, 0x00, 0x7e, 0x01, 0xd8, 0x01, 0xd9, 0x01, 0xb0, 0x00, 0x82, 0x00, 0xcc, 0x00, 0x7d, 0xff, 0x6e, 0xfe, 0x17, 0xfe, 0xe3, 0xfd, 0x36, 0xfd, 0x57, 0xfd, 0x5b, 0xff, 0x41, 0x00, 0x89, 0xff, 0xe7, 0xff, 0xc3, 0x01, 0x0c, 0x04, 0xdf, 0x04, 0x42, 0x03, 0x0d, 0x03, 0x00, 0x04, 0xc7, 0x04, 0x9d, 0x03, 0x30, 0x02, 0xeb, 0x01, 0x8d, 0x01, 0x1f, 0x01, 0x60, 0x01, 0x31, 0x01, 0x0f, 0x01, 0xa5, 0x00, 0x19, 0xff, 0xab, 0xfd, 0x7f, 0xfd, 0x3a, 0xfd, 0xde, 0xfc, 0x25, 0xfd, 0x4d, 0xfd, 0x53, 0xfc, 0x90, 0xfc, 0x3f, 0xfc, 0x76, 0xfb, 0x63, 0xfb, 0x50, 0xfb, 0xf6, 0xfb, 0xc3, 0xfc, 0x6d, 0xfc, 0x0e, 0xfe, 0xeb, 0x00, 0x5f, 0x02, 0xac, 0x03, 0xc9, 0x03, 0xca, 0x03, 0x3f, 0x04, 0xd4, 0x04, 0x9e, 0x04, 0x53, 0x03, 0xf3, 0x01, 0x48, 0x01, 0x4a, 0x00, 0x9e, 0xff, 0x96, 0xff, 0x5e, 0xff, 0x1d, 0xff, 0x5b, 0xff, 0x64, 0x00, 0xb6, 0x00, 0x35, 0x00, 0xba, 0xff, 0xb9, 0xff, 0xec, 0xff, 0x0d, 0x00, 0xaf, 0xfe, 0x5b, 0xfd, 0x5e, 0xfd, 0xbe, 0xfd, 0xb8, 0xfe, 0xc2, 0xff, 0x3e, 0x00, 0x30, 0x00, 0x82, 0xff, 0xa7, 0xff, 0x9e, 0x00, 0x8d, 0x01, 0x4f, 0x01, 0x6b, 0x01, 0xe3, 0x00, 0xc7, 0xff, 0x00, 0x00, 0x4f, 0xff, 0x89, 0xfe, 0x5d, 0xfe, 0x9c, 0xfe, 0x63, 0xff, 0x46, 0x00, 0xee, 0x00, 0x4f, 0x01, 0x51, 0x01, 0x5e, 0x01, 0x26, 0x02, 0xf2, 0x01, 0xea, 0x00, 0xb7, 0x00, 0x4f, 0x00, 0x66, 0x00, 0x3f, 0x00, 0x66, 0xff, 0xa6, 0xfe, 0x54, 0xfd, 0x2d, 0xfd, 0x69, 0xfe, 0x28, 0xff, 0x57, 0xff, 0xbe, 0xff, 0xbc, 0xff, 0xea, 0xff, 0x36, 0xff, 0xc8, 0xfe, 0x6f, 0xfe, 0xf6, 0xfe, 0xf5, 0xff, 0x36, 0x00, 0xc4, 0xff, 0x87, 0xff, 0xb8, 0x00, 0xa3, 0x01, 0x1b, 0x02, 0x5e, 0x02, 0xd3, 0x01, 0xf4, 0x00, 0x7f, 0x00, 0xfc, 0xff, 0xdb, 0xff, 0x98, 0x00, 0xb2, 0x00, 0x2c, 0x00, 0x6f, 0xff, 0xbe, 0xff, 0xa4, 0xff, 0x60, 0x00, 0x27, 0xff, 0x68, 0xff, 0x4b, 0xfe, 0x54, 0xff, 0x09, 0xfe, 0x32, 0x01, 0x48, 0xf6, 0x57, 0xe7, 0x06, 0xf3, 0xf8, 0x02, 0x7a, 0x2f, 0x68, 0x29, 0xcf, 0x25, 0x70, 0x2d, 0x1e, 0x13, 0x87, 0x02, 0x84, 0xec, 0x5b, 0xf3, 0x70, 0xf8, 0xda, 0xd7, 0x7f, 0xd1, 0x9f, 0xce, 0x99, 0xce, 0xbc, 0xe2, 0xb4, 0x06, 0x46, 0x08, 0xe7, 0xfa, 0xde, 0xed, 0xfa, 0xe1, 0xf2, 0xe0, 0x7a, 0xdd, 0xbf, 0xcc, 0x48, 0xd6, 0xdd, 0x00, 0x75, 0x01, 0x75, 0x04, 0xe5, 0x0c, 0x1b, 0x14, 0xe9, 0x26, 0xe3, 0x40, 0x40, 0x4d, 0xe5, 0x35, 0x8e, 0x2b, 0x43, 0x34, 0x19, 0x3a, 0x77, 0x40, 0x60, 0x40, 0x3e, 0x3d, 0xb0, 0x2a, 0x5b, 0x11, 0xe3, 0xfa, 0x68, 0xee, 0x05, 0xeb, 0xac, 0xe7, 0xb1, 0xdc, 0x4b, 0xc7, 0xdf, 0xc8, 0x88, 0xdb, 0xb1, 0xe7, 0x3a, 0xee, 0x8c, 0xf3, 0x83, 0xf7, 0x06, 0x0c, 0xd0, 0x12, 0x6f, 0x05, 0x69, 0x01, 0xa1, 0xed, 0x28, 0xe7, 0x50, 0xf9, 0x8b, 0xef, 0x62, 0xe7, 0x38, 0xf4, 0x6e, 0x07, 0xf4, 0x15, 0x71, 0x1a, 0x79, 0x20, 0x92, 0x26, 0xad, 0x21, 0xc9, 0x1d, 0xe9, 0x0a, 0xc1, 0xe7, 0x34, 0xec, 0x0d, 0xf1, 0x74, 0xec, 0x05, 0xdf, 0x7c, 0xce, 0x38, 0xc3, 0xe1, 0xb1, 0xb7, 0xb8, 0xc6, 0xc6, 0x9e, 0xd7, 0xb1, 0xea, 0x12, 0x00, 0xbd, 0x0d, 0xac, 0x10, 0x48, 0x2c, 0x46, 0x4b, 0x45, 0x49, 0x26, 0x3a, 0x96, 0x2c, 0x5f, 0x2b, 0xcf, 0x30, 0x12, 0x35, 0x8d, 0x2d, 0x7d, 0x20, 0xdf, 0x1a, 0x6f, 0x0e, 0xc0, 0x02, 0x78, 0xf7, 0x1e, 0xec, 0x3f, 0xda, 0x71, 0xd3, 0x6b, 0xd2, 0x99, 0xcf, 0x05, 0xd0, 0x87, 0xcc, 0xeb, 0xcc, 0x04, 0xdb, 0xea, 0xe0, 0xa4, 0xef, 0xca, 0x06, 0x29, 0x18, 0x94, 0x21, 0x89, 0x17, 0x86, 0x0f, 0xab, 0x10, 0x6e, 0x12, 0x02, 0x05, 0xef, 0xf6, 0xea, 0xf5, 0x32, 0xfe, 0xa3, 0xff, 0x3a, 0xf6, 0xdb, 0xf8, 0x13, 0xfd, 0xf1, 0x04, 0xae, 0x11, 0x64, 0x10, 0xff, 0x15, 0x98, 0x0a, 0x9a, 0x00, 0xa1, 0xf7, 0xd6, 0xf3, 0xfe, 0xf9, 0x59, 0xf9, 0xfe, 0xfe, 0xce, 0x02, 0x48, 0x07, 0x29, 0x0a, 0x96, 0x03, 0x49, 0xff, 0xb5, 0xfb, 0x5d, 0xf7, 0xb1, 0xe3, 0x8e, 0xe1, 0xfd, 0xee, 0xf8, 0xf9, 0x59, 0xfc, 0xc9, 0x03, 0xa9, 0x0d, 0x2b, 0x1b, 0x3e, 0x21, 0x3a, 0x1b, 0x30, 0x1c, 0xca, 0x21, 0x4e, 0x23, 0xec, 0x17, 0xec, 0x0c, 0xab, 0x02, 0x0a, 0x0b, 0x57, 0x0a, 0x1c, 0xfc, 0xb3, 0xf4, 0xe4, 0xf0, 0x75, 0xef, 0x08, 0xea, 0x66, 0xe6, 0x4c, 0xeb, 0x07, 0xf7, 0xf2, 0x03, 0x73, 0x03, 0xfd, 0x00, 0x5e, 0x00, 0xfe, 0x01, 0x6d, 0x04, 0xc8, 0xff, 0x26, 0xfe, 0x8a, 0x01, 0x86, 0x02, 0xc0, 0x01, 0xe4, 0xff, 0x53, 0xf6, 0xfa, 0xf0, 0x5d, 0xf0, 0x84, 0xf2, 0x3e, 0xf6, 0x23, 0xf4, 0x05, 0xf1, 0x2f, 0xed, 0xc1, 0xeb, 0x10, 0xed, 0x1f, 0xee, 0x28, 0xf9, 0x43, 0x01, 0xd4, 0x06, 0x4d, 0x07, 0x64, 0x0a, 0xc4, 0x13, 0x6a, 0x1a, 0x42, 0x17, 0x10, 0x0f, 0xba, 0x0f, 0x00, 0x0b, 0x04, 0x04, 0xb9, 0x02, 0x11, 0x03, 0x2a, 0x0b, 0x20, 0x0d, 0x30, 0x03, 0x29, 0x02, 0x65, 0x05, 0xa6, 0x0a, 0x9a, 0x0a, 0xaa, 0x09, 0x7b, 0x05, 0x32, 0xfd, 0xc4, 0xf5, 0x6f, 0xf3, 0x3c, 0xef, 0xc8, 0xe8, 0xc9, 0xe7, 0x9d, 0xeb, 0xa5, 0xf0, 0xff, 0xf0, 0x94, 0xf7, 0xb2, 0xfc, 0x97, 0xff, 0x64, 0x00, 0x1f, 0xff, 0x3c, 0xfd, 0x7d, 0xfd, 0x56, 0x06, 0xfd, 0x09, 0x6d, 0x06, 0x27, 0x01, 0xd3, 0x01, 0xaf, 0x00, 0xeb, 0xff, 0x22, 0x00, 0xb4, 0xfe, 0xb5, 0xfb, 0xeb, 0xfc, 0x5e, 0x03, 0xdb, 0x05, 0x09, 0x04, 0x3e, 0x04, 0x5e, 0x07, 0x2d, 0x07, 0x21, 0x05, 0xd2, 0x03, 0x8a, 0x02, 0x7d, 0x02, 0xf9, 0x05, 0x6f, 0x0a, 0x3b, 0x0f, 0xfc, 0x13, 0x80, 0x11, 0x23, 0x0a, 0x19, 0x05, 0xa5, 0xfe, 0xfb, 0xfb, 0xca, 0xfb, 0x00, 0xf7, 0x71, 0xf3, 0xff, 0xef, 0x77, 0xee, 0x9b, 0xf2, 0x58, 0xf1, 0x54, 0xf0, 0x5b, 0xf3, 0x2b, 0xf5, 0xae, 0xf6, 0xa7, 0xfa, 0x3c, 0xfc, 0x38, 0xfd, 0xab, 0xfd, 0xb6, 0xf5, 0x9f, 0xf5, 0x96, 0xf9, 0xe0, 0xfa, 0xad, 0xff, 0xc3, 0x07, 0xf9, 0x0c, 0xff, 0x08, 0xaf, 0x07, 0x82, 0x07, 0xfb, 0x08, 0x49, 0x0a, 0x8b, 0x0a, 0xd3, 0x09, 0xc3, 0x08, 0x86, 0x0a, 0x89, 0x0d, 0xff, 0x0e, 0x08, 0x0c, 0x17, 0x06, 0x9f, 0x00, 0xb6, 0xff, 0x5f, 0xfe, 0xb5, 0xfe, 0x6c, 0xfe, 0x53, 0xfc, 0xfe, 0xf8, 0x08, 0xf8, 0xda, 0xf7, 0x5d, 0xf8, 0x64, 0xf9, 0xeb, 0xf9, 0x6b, 0xf8, 0x12, 0xf8, 0x7a, 0xfa, 0x80, 0xfa, 0xa7, 0xfa, 0x71, 0xfd, 0xc9, 0x00, 0xa8, 0x05, 0x69, 0x08, 0x3b, 0x04, 0x43, 0xfd, 0x28, 0xfc, 0xb3, 0x00, 0x3c, 0x02, 0x7e, 0x02, 0x8e, 0x00, 0x0b, 0x00, 0x4c, 0x02, 0x23, 0x01, 0x5a, 0x05, 0x88, 0x10, 0x53, 0x15, 0xd0, 0x17, 0xe1, 0x38, 0x53, 0x3e, 0x12, 0x2b, 0x61, 0x3c, 0x89, 0x3a, 0x2f, 0x30, 0x10, 0x06, 0xd7, 0xec, 0x55, 0xde, 0x7e, 0xc2, 0xd9, 0xb8, 0x3b, 0x9d, 0x73, 0x9f, 0x31, 0xba, 0x3b, 0xe9, 0xaa, 0x01, 0xb7, 0x04, 0xef, 0xfe, 0x37, 0x0b, 0x22, 0x12, 0xaf, 0x07, 0x7a, 0x03, 0x21, 0xe0, 0xc2, 0xe2, 0xfc, 0xf7, 0x36, 0xf1, 0x69, 0xe3, 0x74, 0xd3, 0x42, 0xc2, 0xb4, 0xd7, 0x36, 0x01, 0x8e, 0x33, 0x8d, 0x3d, 0x1b, 0x1e, 0x66, 0x1c, 0xd7, 0x25, 0xf1, 0x21, 0x9a, 0x21, 0xb2, 0x23, 0xa2, 0x0f, 0xa3, 0x04, 0xca, 0x09, 0xcc, 0x0c, 0xd0, 0x08, 0x74, 0xfa, 0xee, 0x01, 0xc3, 0x19, 0x3c, 0x37, 0xc2, 0x33, 0x92, 0x27, 0x7b, 0x23, 0x52, 0xfd, 0xb2, 0xdb, 0x6c, 0xcd, 0xb9, 0xd5, 0x90, 0xdf, 0xe5, 0xd4, 0x5b, 0xd4, 0x51, 0xe0, 0xc9, 0x0f, 0x68, 0x34, 0x13, 0x32, 0x81, 0x2d, 0x6f, 0x27, 0x33, 0x1c, 0xbd, 0x06, 0x7e, 0x05, 0x9e, 0x10, 0xfb, 0x07, 0xe3, 0xea, 0x87, 0xd7, 0xf9, 0xbd, 0xe6, 0xba, 0xb2, 0xcc, 0xc1, 0xe4, 0xf8, 0x04, 0xd2, 0x08, 0x24, 0xf8, 0x7e, 0xfd, 0xf3, 0xfc, 0x5a, 0x0c, 0x8e, 0x11, 0x2a, 0x04, 0x55, 0xf5, 0x93, 0x07, 0x6d, 0x16, 0x11, 0x12, 0x9f, 0x01, 0x57, 0xff, 0x0f, 0xf6, 0x61, 0xf0, 0x9b, 0xee, 0x14, 0xfe, 0x2e, 0x08, 0x6f, 0x12, 0xbb, 0x08, 0xa5, 0xe6, 0x29, 0xde, 0x8c, 0xdd, 0x5e, 0xd4, 0xa2, 0xdd, 0x6b, 0xf4, 0x82, 0x01, 0xf9, 0x10, 0x7e, 0x0c, 0x3b, 0x0a, 0x0f, 0x05, 0x0a, 0x12, 0x7e, 0x1c, 0x76, 0x16, 0x46, 0x1c, 0x80, 0x0b, 0x6d, 0x15, 0xdf, 0x1d, 0xe9, 0x05, 0xb6, 0xe9, 0xf6, 0xd6, 0x42, 0xe8, 0xff, 0x00, 0x28, 0x0c, 0xf6, 0xf6, 0xd1, 0xe2, 0x9f, 0xea, 0x16, 0x05, 0x6a, 0x15, 0x1a, 0x2d, 0x49, 0x23, 0x31, 0x0c, 0x17, 0x1e, 0xfc, 0x34, 0xaa, 0x2f, 0x4a, 0x0d, 0x23, 0xf1, 0xf9, 0xe1, 0x22, 0xec, 0xb8, 0xfb, 0xd0, 0xe1, 0xa5, 0xcb, 0xbd, 0xd3, 0x37, 0xdd, 0x34, 0xf1, 0x2e, 0x10, 0x1f, 0x1c, 0x5d, 0x14, 0xc9, 0x0a, 0xf0, 0x04, 0x77, 0xf7, 0xbe, 0xf6, 0x30, 0x06, 0xc8, 0x04, 0xbc, 0xf6, 0x62, 0xe9, 0x23, 0xed, 0xd7, 0xf9, 0x57, 0x09, 0xe1, 0x07, 0x62, 0x0b, 0xc9, 0x23, 0xec, 0x36, 0xc6, 0x38, 0xb8, 0x23, 0xaa, 0x20, 0xc6, 0x27, 0x42, 0x2c, 0x36, 0x36, 0xa2, 0x2c, 0x6d, 0x12, 0x4c, 0xf3, 0x70, 0xcf, 0xc6, 0xae, 0xc4, 0x9e, 0x55, 0xa4, 0xf0, 0xbe, 0x8e, 0xc6, 0xd9, 0xbf, 0x2e, 0xcd, 0x5a, 0xe6, 0x83, 0xe5, 0x83, 0xfc, 0xe8, 0x03, 0x56, 0x02, 0x4f, 0x12, 0xa3, 0x05, 0x7d, 0x06, 0x31, 0x21, 0x29, 0x26, 0xb4, 0x34, 0xb7, 0x41, 0x0f, 0x28, 0x44, 0x24, 0x40, 0x20, 0x21, 0x10, 0x64, 0x11, 0x3e, 0x18, 0x83, 0x1b, 0x07, 0x1e, 0xc4, 0x22, 0xa9, 0x17, 0xdb, 0x05, 0x42, 0xf4, 0x60, 0xdc, 0x66, 0xda, 0x9d, 0xe2, 0x38, 0xd9, 0x81, 0xdc, 0x3f, 0xda, 0xf0, 0xe2, 0xb3, 0xfa, 0xbb, 0x0a, 0xab, 0xff, 0x19, 0xd8, 0x15, 0xed, 0x84, 0x0b, 0x89, 0x0b, 0xdc, 0x09, 0x0d, 0x00, 0xd4, 0x00, 0x6e, 0x02, 0xf9, 0xfe, 0x27, 0xf0, 0xbe, 0xef, 0xac, 0x00, 0xf5, 0x1f, 0xaf, 0x32, 0xa3, 0x26, 0x3e, 0x10, 0x3a, 0x0b, 0xe4, 0x19, 0x9f, 0x18, 0xc7, 0x13, 0x82, 0xfe, 0x83, 0xdd, 0xa8, 0xce, 0x91, 0xc9, 0xf9, 0xb9, 0x99, 0xad, 0x51, 0xb6, 0xa0, 0xb1, 0xa4, 0xbe, 0x9e, 0xcd, 0xc6, 0xd0, 0x09, 0xf1, 0xd0, 0x1f, 0x71, 0x38, 0x71, 0x1a, 0x68, 0x01, 0x23, 0x08, 0x17, 0x18, 0x33, 0x27, 0x36, 0x44, 0x59, 0x62, 0x15, 0x72, 0x0c, 0x65, 0x89, 0x54, 0x5f, 0x46, 0x43, 0x37, 0x5f, 0x34, 0xfe, 0x3b, 0xfd, 0x38, 0x85, 0x30, 0x87, 0x19, 0x68, 0xfd, 0x27, 0xe2, 0xc8, 0xd0, 0xaf, 0xcb, 0x45, 0xb9, 0x7c, 0xb4, 0xc2, 0xbc, 0x94, 0xc8, 0x31, 0xd7, 0x98, 0xe2, 0x59, 0xf1, 0x8c, 0x0b, 0xdd, 0x0d, 0x30, 0x04, 0x2c, 0xea, 0x55, 0xd4, 0x69, 0xc8, 0x1b, 0xc6, 0x9b, 0xda, 0xe3, 0xe3, 0xc0, 0xe9, 0x86, 0xef, 0xc2, 0xe5, 0x35, 0xe8, 0xdd, 0xea, 0xdf, 0xf2, 0xbc, 0x05, 0xe6, 0x18, 0x35, 0x1d, 0xb0, 0x2e, 0xcd, 0x3c, 0x75, 0x41, 0x9f, 0x2e, 0xca, 0x13, 0xc3, 0x03, 0x4e, 0xf6, 0xd9, 0x01, 0x8e, 0x05, 0x9f, 0x08, 0xb7, 0x0e, 0x1c, 0x22, 0x5b, 0x26, 0x51, 0x22, 0x05, 0x1c, 0x49, 0x0c, 0x76, 0xf8, 0xfb, 0xf2, 0x1a, 0xfb, 0x3b, 0xfb, 0x97, 0xf8, 0xf5, 0xf4, 0x68, 0xe5, 0xb0, 0xe9, 0x18, 0xe6, 0x9e, 0xdc, 0x5d, 0xe2, 0x64, 0xe8, 0xe2, 0xe3, 0x76, 0xe4, 0x0b, 0xea, 0xfa, 0xf6, 0xe5, 0x00, 0x25, 0x05, 0x3c, 0x06, 0x22, 0x0b, 0xd6, 0x1c, 0x92, 0x22, 0x51, 0x22, 0x2f, 0x30, 0x0c, 0x34, 0x8b, 0x24, 0x38, 0x20, 0x80, 0x26, 0x54, 0x14, 0xa6, 0xfc, 0x5a, 0xed, 0xa0, 0xef, 0x8f, 0xea, 0xcf, 0xe4, 0x95, 0xe6, 0xed, 0xef, 0x3e, 0xeb, 0x1b, 0xd9, 0xeb, 0xe2, 0x90, 0xd7, 0x74, 0xd4, 0x2e, 0xcd, 0x38, 0xc4, 0x5a, 0xd5, 0x1f, 0xd9, 0x0f, 0xd1, 0x6d, 0xcc, 0x0e, 0xd6, 0x58, 0xed, 0x2a, 0x06, 0xad, 0x1a, 0xb4, 0x2f, 0x6d, 0x3f, 0xdc, 0x48, 0xd8, 0x54, 0xa3, 0x63, 0x21, 0x63, 0x27, 0x4d, 0x9f, 0x31, 0x7a, 0x21, 0xfd, 0x0a, 0xd8, 0xf8, 0x71, 0x05, 0x59, 0x27, 0x15, 0x36, 0xd2, 0x32, 0x5f, 0x2c, 0x40, 0x11, 0x58, 0xfe, 0x9a, 0xf6, 0xe1, 0x01, 0xd3, 0x16, 0x05, 0x0f, 0x27, 0x00, 0xac, 0xe9, 0xa3, 0xdf, 0x3b, 0xd0, 0x52, 0xbb, 0x50, 0xb6, 0x9c, 0xbd, 0x03, 0xb7, 0xd4, 0xb3, 0xf0, 0xc5, 0xaa, 0xc9, 0x30, 0xd0, 0xa2, 0xe2, 0xb5, 0xf6, 0x6f, 0xf3, 0xcc, 0xe6, 0xb4, 0xe6, 0x83, 0xed, 0xc7, 0xf9, 0x2d, 0x01, 0x1c, 0x05, 0x59, 0x08, 0x1e, 0x11, 0x82, 0x21, 0x27, 0x28, 0x1d, 0x13, 0xd7, 0xfa, 0xb9, 0x00, 0xa8, 0x03, 0x6d, 0xee, 0x58, 0xf1, 0x60, 0x05, 0xc6, 0x13, 0xb4, 0x21, 0x90, 0x31, 0x04, 0x48, 0x42, 0x44, 0x0a, 0x3b, 0xca, 0x43, 0xd5, 0x3d, 0x78, 0x3c, 0x89, 0x42, 0x0a, 0x3a, 0xe8, 0x22, 0x65, 0x19, 0xff, 0x13, 0x20, 0xf3, 0x72, 0xe8, 0xf7, 0xd9, 0xef, 0xcd, 0x30, 0xdb, 0x76, 0xd5, 0xa3, 0xc9, 0x80, 0xc9, 0x7f, 0xc8, 0xbc, 0xb5, 0xb6, 0xb2, 0x5d, 0xc0, 0xdc, 0xdb, 0x8b, 0xfb, 0xbf, 0x00, 0xee, 0xec, 0x5c, 0xe6, 0xed, 0xf6, 0xee, 0x0d, 0x02, 0x16, 0xf2, 0x1f, 0xfc, 0x1d, 0x75, 0x13, 0x58, 0x15, 0x00, 0x22, 0x49, 0x2f, 0x03, 0x40, 0x41, 0x3c, 0x26, 0x25, 0xc9, 0x24, 0x09, 0x24, 0x87, 0x12, 0xf8, 0x04, 0xb8, 0xf7, 0x92, 0xe9, 0x4e, 0xd6, 0x7c, 0xd4, 0x48, 0xe3, 0xc8, 0xec, 0x7d, 0xeb, 0xe4, 0xee, 0x76, 0xf4, 0xaa, 0xfa, 0x5f, 0x03, 0x6a, 0x03, 0x1f, 0x05, 0x8f, 0x01, 0x30, 0xfb, 0x56, 0xf6, 0x4a, 0xfa, 0x73, 0x03, 0x56, 0x01, 0x6b, 0xfb, 0x91, 0xf5, 0xd5, 0xec, 0x3c, 0xe9, 0xd0, 0xdd, 0xa3, 0xe5, 0x53, 0x02, 0x94, 0x11, 0x3f, 0x1a, 0xfe, 0x0c, 0xb9, 0x02, 0xd7, 0x0e, 0x1c, 0x0b, 0x46, 0x0a, 0x5c, 0x00, 0x6a, 0xec, 0x87, 0xe9, 0x68, 0xec, 0xa9, 0xed, 0xb1, 0xee, 0x73, 0xfe, 0xc4, 0x0f, 0x51, 0x15, 0xc3, 0x16, 0x09, 0x0b, 0x75, 0x0f, 0xa6, 0x1c, 0x13, 0x2f, 0x79, 0x3e, 0x28, 0x39, 0x87, 0x2a, 0x79, 0x16, 0x93, 0xfd, 0x5f, 0xdc, 0x37, 0xd6, 0x73, 0xdb, 0x07, 0xe7, 0x26, 0xed, 0x88, 0xe9, 0xeb, 0xdd, 0xbf, 0xdb, 0xc6, 0xe0, 0x36, 0xf0, 0xe0, 0x09, 0xa8, 0x12, 0xa1, 0x10, 0xad, 0x0c, 0x4f, 0x10, 0x39, 0x1a, 0xda, 0x26, 0xe0, 0x27, 0xf3, 0x1f, 0xdd, 0x16, 0x2b, 0x05, 0x48, 0xf8, 0x31, 0xef, 0xed, 0xeb, 0x47, 0xf8, 0x59, 0x02, 0xe0, 0x06, 0xbf, 0xfa, 0x3e, 0x01, 0xe9, 0x0d, 0xfc, 0x0c, 0x9b, 0x09, 0x8f, 0x0c, 0x3f, 0x09, 0xea, 0xfd, 0xf6, 0xf9, 0x72, 0xf8, 0x9c, 0xf5, 0xe8, 0xec, 0xf6, 0xf4, 0x09, 0x0a, 0xd8, 0xfe, 0xd8, 0xef, 0x28, 0xe2, 0x7b, 0xd5, 0x52, 0xd5, 0x09, 0xdf, 0x0b, 0xf8, 0x16, 0x0b, 0x53, 0x25, 0xa2, 0x33, 0x80, 0x27, 0xcb, 0x15, 0xfb, 0x0a, 0xda, 0x02, 0x67, 0xf4, 0x1d, 0xe8, 0x3e, 0xe9, 0x78, 0xf4, 0xc3, 0xf5, 0x4c, 0xf4, 0x41, 0xfa, 0xe4, 0xfa, 0x5d, 0xef, 0x10, 0xec, 0x7f, 0xf1, 0x7a, 0xf8, 0x79, 0xfd, 0x3d, 0x04, 0x7e, 0x04, 0x13, 0xf6, 0x81, 0xf4, 0xc8, 0xf5, 0x17, 0x0f, 0xb6, 0x17, 0x7b, 0x0f, 0x30, 0x19, 0x4a, 0x26, 0x1d, 0x30, 0x42, 0x2f, 0x0e, 0x1e, 0x6d, 0x08, 0x7b, 0xfb, 0x90, 0xfe, 0x03, 0x06, 0x7c, 0x16, 0x9b, 0x1d, 0xe9, 0x11, 0x88, 0x03, 0x53, 0xf7, 0xea, 0xf8, 0x1a, 0x05, 0x51, 0x0c, 0x78, 0x03, 0x3c, 0xf8, 0xa5, 0xec, 0x4e, 0xef, 0xb8, 0xf0, 0xc4, 0xeb, 0xe0, 0xdf, 0xaa, 0xd4, 0x9d, 0xd9, 0xbd, 0xd5, 0xff, 0xdd, 0x9a, 0xe9, 0x4d, 0xed, 0xfa, 0xf1, 0xda, 0xf2, 0xf7, 0xe5, 0x05, 0xec, 0x8b, 0x02, 0x9a, 0x11, 0x30, 0x0e, 0x66, 0x08, 0x1e, 0x0f, 0xc6, 0x16, 0x2c, 0x1d, 0x8f, 0x1f, 0x42, 0x19, 0x28, 0xfe, 0x02, 0xf0, 0x0a, 0xf4, 0x38, 0xfd, 0x24, 0x05, 0x2c, 0x0c, 0x74, 0x0e, 0xf2, 0x14, 0x3d, 0x13, 0xae, 0x12, 0xfd, 0x1d, 0x21, 0x1c, 0xec, 0x1b, 0x4b, 0x18, 0xb4, 0x1b, 0xf6, 0x12, 0xce, 0x04, 0xde, 0x0a, 0x3e, 0x0e, 0xe6, 0x0e, 0x7f, 0x07, 0x79, 0x04, 0x74, 0xf4, 0x1e, 0xec, 0x80, 0xec, 0xcd, 0xe1, 0x06, 0xe5, 0x4f, 0xf2, 0x50, 0xf7, 0xc1, 0x00, 0x85, 0xfc, 0x88, 0xec, 0xcf, 0xdd, 0xeb, 0xda, 0x5d, 0xe7, 0xbd, 0xf0, 0x14, 0xf0, 0xf5, 0xf9, 0x64, 0x0c, 0x0b, 0x12, 0xf1, 0x17, 0x2a, 0x1a, 0x21, 0x0e, 0x4f, 0x09, 0xdc, 0x06, 0xe3, 0xfe, 0xfd, 0x07, 0x7e, 0x0d, 0x64, 0x0e, 0xf1, 0x07, 0x0a, 0xff, 0x38, 0xfa, 0x58, 0xfe, 0x08, 0xfe, 0xb1, 0xf5, 0x89, 0xf7, 0x19, 0xf8, 0x83, 0xfd, 0x68, 0xf7, 0x4b, 0xf6, 0x2d, 0xfe, 0xc9, 0x04, 0x79, 0x0a, 0x52, 0x0e, 0xae, 0x08, 0xd4, 0x02, 0xbd, 0xf9, 0x0f, 0xfd, 0x46, 0x0f, 0x4f, 0x19, 0xdc, 0x14, 0x90, 0x12, 0xf9, 0x17, 0xf4, 0x16, 0x0b, 0x10, 0xf5, 0x06, 0x61, 0xf4, 0x98, 0xe7, 0xcf, 0xe9, 0xe7, 0xe3, 0x87, 0xe2, 0x30, 0xee, 0x16, 0xf1, 0x83, 0xed, 0x25, 0xe7, 0x13, 0xdf, 0x2e, 0xd9, 0x5b, 0xda, 0x33, 0xec, 0x92, 0xfa, 0x0e, 0x00, 0x35, 0x15, 0x0a, 0x1f, 0x71, 0x24, 0x90, 0x1d, 0xd8, 0x1b, 0x02, 0x20, 0xa0, 0x1e, 0xcc, 0x1d, 0x73, 0x19, 0x0e, 0x1b, 0x71, 0x12, 0x11, 0x0e, 0xa1, 0x0d, 0x7a, 0xff, 0xef, 0xe9, 0x95, 0xd7, 0x50, 0xd6, 0x9b, 0xe1, 0x84, 0xe6, 0x59, 0xee, 0x83, 0xf2, 0xe2, 0xed, 0x52, 0xef, 0x9f, 0xed, 0x3f, 0xf8, 0xa3, 0xff, 0x44, 0x03, 0xe9, 0x0a, 0xeb, 0x05, 0x07, 0xfc, 0x37, 0xf7, 0x89, 0xff, 0x33, 0x08, 0x49, 0x0b, 0x28, 0x0f, 0x39, 0x16, 0x98, 0x13, 0x4a, 0x17, 0xb0, 0x14, 0x45, 0x05, 0x3e, 0xfc, 0xb3, 0xfc, 0x70, 0x09, 0x00, 0x14, 0x1b, 0x12, 0xbf, 0x12, 0xf4, 0x15, 0x81, 0x20, 0x65, 0x21, 0x97, 0x0e, 0xdd, 0x07, 0xfe, 0x0b, 0x96, 0x06, 0xee, 0xef, 0x57, 0xe6, 0x92, 0xdf, 0xfd, 0xd7, 0x0f, 0xdc, 0xa5, 0xe8, 0x80, 0xf1, 0x94, 0xee, 0x76, 0xe5, 0xcd, 0xeb, 0xcf, 0xfa, 0xac, 0x04, 0x60, 0x02, 0x4b, 0xff, 0xe2, 0x07, 0x77, 0x00, 0xe8, 0xf8, 0x93, 0xf6, 0x57, 0xfb, 0x11, 0x06, 0x08, 0x08, 0x95, 0x07, 0xa6, 0x0a, 0xf3, 0x08, 0xd7, 0x01, 0x5e, 0xfe, 0xb3, 0xfe, 0x9a, 0xff, 0x9d, 0xf9, 0x4d, 0xf6, 0x88, 0x00, 0x48, 0x07, 0xe9, 0x02, 0x51, 0x08, 0x63, 0x1a, 0x4d, 0x1a, 0x80, 0x0c, 0x64, 0x04, 0x6d, 0xec, 0xb9, 0xe4, 0x8f, 0xf2, 0x7e, 0xfe, 0x99, 0xfc, 0x32, 0x00, 0xba, 0x05, 0x45, 0x0c, 0xc0, 0x00, 0x2e, 0xfb, 0xa6, 0xfa, 0x32, 0xfc, 0x3b, 0x03, 0x12, 0x05, 0xe0, 0x06, 0xef, 0x07, 0xc3, 0x01, 0x5f, 0xfb, 0xb2, 0xff, 0x4e, 0x00, 0x3f, 0xf7, 0x3c, 0xf1, 0xf1, 0xfa, 0x2f, 0x05, 0x2c, 0x0c, 0x5c, 0x12, 0xd7, 0x20, 0xfc, 0x26, 0x38, 0x1f, 0x2b, 0x12, 0x97, 0x03, 0x8b, 0xfd, 0x8a, 0x02, 0x68, 0xfc, 0x9d, 0xfb, 0x3b, 0xfd, 0x60, 0xf8, 0x15, 0xf2, 0x20, 0xe9, 0xae, 0xed, 0xe4, 0xef, 0xa0, 0xed, 0x20, 0xde, 0xb8, 0xe1, 0x6c, 0xf2, 0xac, 0xec, 0xa1, 0xed, 0x67, 0xfc, 0x56, 0x0a, 0xf7, 0x07, 0xef, 0xfe, 0x5f, 0xfc, 0x7a, 0x06, 0xce, 0x12, 0x37, 0x15, 0xc7, 0x14, 0x0f, 0x1d, 0x54, 0x18, 0x90, 0x0f, 0x2b, 0x0e, 0xc6, 0x0c, 0x18, 0x11, 0x3c, 0x15, 0xaa, 0x15, 0xdd, 0x14, 0xb7, 0x0e, 0xbe, 0x0c, 0x9d, 0x0b, 0x48, 0x06, 0x50, 0xf9, 0x33, 0xee, 0x85, 0xf8, 0x63, 0x07, 0x9e, 0x06, 0x7d, 0x07, 0x27, 0x0b, 0xa4, 0xfc, 0x03, 0xfa, 0x0b, 0xf2, 0x9d, 0xe0, 0x92, 0xde, 0xd0, 0xdf, 0x71, 0xe1, 0x02, 0xe2, 0x3c, 0xdb, 0xb9, 0xd1, 0xe7, 0xcb, 0xa5, 0xd4, 0xad, 0xe3, 0xd1, 0xeb, 0xa6, 0xf4, 0x34, 0xf9, 0x4d, 0xfb, 0xd5, 0x08, 0x39, 0x16, 0x37, 0x1a, 0xa7, 0x14, 0x24, 0x13, 0x07, 0x13, 0xa6, 0x14, 0xf2, 0x14, 0xdf, 0x12, 0x59, 0x19, 0x86, 0x1e, 0xe8, 0x1b, 0x4f, 0x12, 0x16, 0x18, 0xdd, 0x1f, 0xed, 0x1b, 0xab, 0x10, 0x63, 0x06, 0xa6, 0xfd, 0x86, 0xfc, 0x9e, 0xf6, 0xdc, 0xed, 0xff, 0xe6, 0xc0, 0xe6, 0xdf, 0xe7, 0xbb, 0xe8, 0x3b, 0xef, 0x75, 0xf2, 0xab, 0xff, 0x56, 0x0a, 0xc1, 0x08, 0xa7, 0x04, 0x7c, 0x0a, 0xc2, 0x10, 0x62, 0x0e, 0xd7, 0xfc, 0xad, 0xef, 0xee, 0xf1, 0x60, 0xe8, 0x2f, 0xe6, 0x16, 0xf3, 0xd3, 0xf7, 0x97, 0xf6, 0xaf, 0xf2, 0x1a, 0xf4, 0xe2, 0x02, 0x17, 0x03, 0x27, 0xf8, 0xbd, 0xf4, 0x13, 0xf2, 0xd7, 0xf6, 0x45, 0xfc, 0x7a, 0x00, 0xd9, 0x07, 0x25, 0x0c, 0x76, 0x0e, 0x2b, 0x11, 0xc4, 0x12, 0x6c, 0x19, 0xa5, 0x20, 0x36, 0x20, 0xed, 0x1a, 0xf7, 0x09, 0x57, 0x04, 0xd6, 0x04, 0x5d, 0x02, 0x65, 0x08, 0x06, 0x02, 0x32, 0x02, 0x96, 0x02, 0x04, 0xfc, 0x85, 0xf8, 0xf3, 0x03, 0x9b, 0x0e, 0xa9, 0x08, 0x36, 0x03, 0x48, 0x09, 0x73, 0x0e, 0x73, 0x03, 0x86, 0xf8, 0xf9, 0xed, 0x9c, 0xe1, 0x95, 0xe4, 0x7b, 0xf0, 0x15, 0xf8, 0x9c, 0xf6, 0x6a, 0xf6, 0x18, 0xf5, 0x6a, 0xf1, 0xf2, 0xf2, 0x5f, 0xef, 0x90, 0xef, 0x0a, 0xf1, 0x29, 0xf1, 0xaf, 0xeb, 0xee, 0xef, 0xd1, 0xfa, 0xad, 0x01, 0xeb, 0x06, 0x5d, 0x09, 0x80, 0x0c, 0x45, 0x0d, 0x2b, 0x0d, 0x13, 0x12, 0x98, 0x19, 0xc2, 0x1c, 0x03, 0x26, 0xf5, 0x22, 0x07, 0x1c, 0xcb, 0x18, 0xdc, 0x0d, 0xac, 0x06, 0x73, 0x09, 0x84, 0x04, 0xac, 0xf9, 0x7e, 0xf9, 0xe7, 0xfa, 0x0b, 0xf7, 0x46, 0xed, 0xe2, 0xec, 0x96, 0xf3, 0x95, 0xf2, 0x4d, 0xec, 0x70, 0xeb, 0xdb, 0xf0, 0x67, 0xf6, 0x1e, 0xf6, 0xfb, 0xec, 0x31, 0xf1, 0x81, 0xf5, 0x91, 0xf0, 0x66, 0xf1, 0x64, 0xf3, 0x24, 0xf6, 0xcd, 0xf7, 0x21, 0xfa, 0x0b, 0x03, 0xd9, 0x0e, 0x1c, 0x11, 0x92, 0x0e, 0x1b, 0x0d, 0x96, 0xff, 0xe3, 0xf2, 0xd4, 0xec, 0x6f, 0xee, 0x01, 0xfb, 0x92, 0x01, 0x86, 0x02, 0x19, 0x02, 0xb2, 0x05, 0xa9, 0x0a, 0x18, 0x0f, 0x41, 0x18, 0x8e, 0x1a, 0x8e, 0x1d, 0xff, 0x26, 0xf8, 0x26, 0xab, 0x1d, 0x16, 0x16, 0x40, 0x12, 0x2f, 0x09, 0x73, 0x07, 0xc5, 0x0c, 0xe6, 0x0b, 0x1f, 0x0b, 0x57, 0x09, 0x5a, 0xff, 0x60, 0xfe, 0xf3, 0xf7, 0x0e, 0xee, 0x8b, 0xe5, 0x65, 0xe8, 0xa1, 0xec, 0x12, 0xe6, 0x51, 0xe6, 0xe5, 0xe5, 0x62, 0xea, 0x05, 0xef, 0xad, 0xee, 0xe6, 0xe7, 0x41, 0xe0, 0xe9, 0xe3, 0x53, 0xe6, 0xa1, 0xe5, 0x62, 0xeb, 0xab, 0xf4, 0xcb, 0xf3, 0xdc, 0xee, 0x2b, 0xf6, 0x60, 0xfa, 0x2c, 0xff, 0x38, 0x06, 0x8e, 0x0e, 0xe6, 0x14, 0x3c, 0x14, 0x9f, 0x10, 0x63, 0x0d, 0x17, 0x15, 0xa9, 0x1b, 0x4c, 0x1c, 0x80, 0x1c, 0x8a, 0x16, 0xc9, 0x0f, 0xc9, 0x09, 0xc3, 0x03, 0xb2, 0x03, 0xa9, 0x10, 0x6d, 0x14, 0xa1, 0x15, 0x9b, 0x14, 0xc2, 0x09, 0x76, 0x03, 0x0c, 0x05, 0x91, 0x08, 0x02, 0x07, 0xdb, 0x01, 0x58, 0xf6, 0x52, 0xf3, 0x74, 0xf6, 0x7d, 0xf3, 0x32, 0xed, 0xfe, 0xe9, 0xd3, 0xea, 0x5c, 0xed, 0x89, 0xe9, 0x80, 0xe4, 0x8a, 0xe7, 0xf9, 0xe6, 0x84, 0xec, 0x9d, 0xf7, 0xa9, 0x00, 0x22, 0x0b, 0x31, 0x0f, 0xa0, 0x08, 0xa5, 0x06, 0x3a, 0x06, 0xde, 0x06, 0x2c, 0x07, 0x54, 0x0b, 0x1c, 0x0d, 0x1d, 0x07, 0x5d, 0x00, 0xea, 0xf8, 0xa7, 0xf2, 0x2d, 0xf3, 0x99, 0xfc, 0xc9, 0x03, 0xa3, 0x06, 0x72, 0xff, 0x3a, 0xff, 0x6b, 0x07, 0x50, 0x0a, 0xa0, 0x01, 0x2b, 0xfc, 0xae, 0xff, 0x28, 0x04, 0x58, 0x02, 0x78, 0xfe, 0xb0, 0x05, 0xca, 0x11, 0x97, 0x13, 0x50, 0x0d, 0x97, 0x0c, 0x8f, 0x0b, 0x81, 0x08, 0xae, 0x02, 0x20, 0xf7, 0x98, 0xe9, 0xd7, 0xe7, 0x62, 0xee, 0x2b, 0xf0, 0x9a, 0xea, 0x9e, 0xe9, 0x42, 0xf1, 0x71, 0xfb, 0x18, 0x05, 0x25, 0x04, 0x44, 0xff, 0xab, 0x00, 0xcc, 0x0b, 0xf1, 0x13, 0x95, 0x17, 0xf8, 0x15, 0x29, 0x0f, 0xed, 0x05, 0x38, 0xff, 0xe9, 0xff, 0x15, 0x09, 0xb4, 0x0b, 0xae, 0x09, 0x13, 0x07, 0x81, 0x04, 0x12, 0x02, 0x5f, 0xfc, 0x54, 0xfd, 0x13, 0xf7, 0x34, 0xed, 0x05, 0xec, 0xaf, 0xf3, 0xe5, 0xfd, 0x37, 0x00, 0x05, 0xfc, 0x8e, 0xfc, 0xc7, 0xfe, 0xf1, 0xff, 0x6d, 0xff, 0x0f, 0xfb, 0x49, 0xee, 0x82, 0xed, 0xe7, 0xf9, 0x7a, 0x02, 0x73, 0x05, 0x01, 0x05, 0xb2, 0x08, 0x2a, 0x05, 0x0f, 0x01, 0xd5, 0x03, 0x9a, 0x04, 0x13, 0x05, 0x23, 0x05, 0x7a, 0xfe, 0x32, 0xf5, 0xc9, 0xf6, 0x23, 0xfb, 0x21, 0xfd, 0x2a, 0xfd, 0xa4, 0xff, 0x22, 0x01, 0x72, 0x00, 0xb0, 0x01, 0xe5, 0x00, 0xc0, 0xff, 0x47, 0x00, 0x89, 0x01, 0x5e, 0xfe, 0x1c, 0xfb, 0x0d, 0x01, 0x67, 0x04, 0x9e, 0x06, 0x8d, 0x06, 0xb0, 0xff, 0x2b, 0xff, 0x9c, 0xf8, 0xac, 0xfb, 0xe2, 0x01, 0x00, 0xfe, 0x58, 0xff, 0x44, 0x05, 0xb1, 0x06, 0x0a, 0x08, 0x4c, 0x08, 0xd3, 0x08, 0xef, 0x08, 0x92, 0x02, 0xa4, 0xfd, 0x73, 0xf7, 0x58, 0xf3, 0xde, 0xf2, 0xd2, 0xf4, 0xdc, 0xf7, 0x0d, 0xfb, 0x19, 0xfa, 0x57, 0xfa, 0x37, 0xfa, 0x5b, 0xf9, 0xed, 0xf6, 0x64, 0xf8, 0x91, 0xfc, 0x3c, 0xf8, 0xfc, 0xf7, 0x20, 0xfe, 0x98, 0x09, 0x6f, 0x0d, 0xcf, 0x0e, 0x76, 0x10, 0xb4, 0x0c, 0xfd, 0x0d, 0x53, 0x13, 0x21, 0x19, 0x26, 0x17, 0x5c, 0x10, 0xea, 0x0a, 0xbe, 0x05, 0x9d, 0x03, 0xbc, 0xfd, 0x50, 0xfb, 0x67, 0xfb, 0xf2, 0xfc, 0x7c, 0xfc, 0xfb, 0xfc, 0x8f, 0xff, 0x5a, 0xfd, 0xa1, 0xf8, 0x53, 0xfb, 0xf8, 0xff, 0xbb, 0xfd, 0x46, 0xf7, 0x26, 0xf0, 0x19, 0xed, 0xa1, 0xec, 0x1b, 0xf0, 0xfe, 0xf4, 0xad, 0xf4, 0x5b, 0xf2, 0x8b, 0xf2, 0xb8, 0xf9, 0x2f, 0x00, 0xc3, 0xfd, 0x26, 0xf8, 0x81, 0xf6, 0xc1, 0xfa, 0xae, 0xfc, 0x50, 0xfd, 0x44, 0x00, 0x3b, 0x06, 0xf0, 0x0c, 0x69, 0x15, 0xbb, 0x13, 0x11, 0x0d, 0xa6, 0x11, 0xb6, 0x15, 0xf1, 0x11, 0x3f, 0x0a, 0x9c, 0xfd, 0x9c, 0xf9, 0xf2, 0xf9, 0x21, 0xfd, 0x8a, 0xfd, 0x39, 0xf7, 0x6c, 0xf5, 0xd0, 0xfb, 0x2a, 0xfd, 0x8e, 0xf8, 0x57, 0xfa, 0xa2, 0xfd, 0xc8, 0xfe, 0xcb, 0x00, 0x94, 0x03, 0x13, 0x02, 0x9e, 0xff, 0xef, 0xf8, 0x96, 0xf7, 0xae, 0xfa, 0x79, 0xfe, 0xb4, 0xff, 0x99, 0x00, 0xa5, 0x08, 0x26, 0x09, 0x01, 0x05, 0x14, 0x02, 0x3b, 0xfc, 0xb2, 0xfa, 0x7e, 0xfc, 0x5f, 0xff, 0xf2, 0x01, 0x1d, 0x04, 0x4d, 0x0b, 0x78, 0x10, 0x37, 0x0b, 0xa0, 0x05, 0xeb, 0xfd, 0x2e, 0xf9, 0x2c, 0xfa, 0xb6, 0xfa, 0xfd, 0xfa, 0x97, 0xf8, 0xf6, 0xf6, 0x09, 0xf7, 0xfe, 0xf6, 0xe5, 0xf3, 0xb0, 0xf5, 0xac, 0xf9, 0x4a, 0xfe, 0xdd, 0x01, 0x04, 0x00, 0xfe, 0xfa, 0x11, 0xfc, 0xc3, 0xfe, 0x5b, 0x01, 0xed, 0xfe, 0xb6, 0xfd, 0x0d, 0x05, 0x17, 0x05, 0x68, 0xff, 0x8e, 0xfe, 0x3c, 0x04, 0x1e, 0x04, 0xbc, 0x03, 0x9a, 0x01, 0xc8, 0xff, 0x04, 0x00, 0x13, 0x03, 0x5d, 0x03, 0xb1, 0xff, 0xb9, 0xfd, 0x48, 0xff, 0x14, 0x04, 0x23, 0x03, 0xe8, 0x04, 0x27, 0x06, 0x1c, 0x03, 0x06, 0xfe, 0xdd, 0xfe, 0xd3, 0x01, 0x06, 0x02, 0xa6, 0x02, 0x08, 0x01, 0xa9, 0x06, 0x10, 0x04, 0xdd, 0x00, 0x5d, 0x04, 0xa1, 0x09, 0xf3, 0x0b, 0x4b, 0x0b, 0xc5, 0x05, 0xc6, 0xfd, 0xc7, 0xf0, 0x91, 0xeb, 0x83, 0xf0, 0x48, 0xee, 0x6f, 0xea, 0xc4, 0xe8, 0x2c, 0xeb, 0x71, 0xf2, 0xc2, 0xf6, 0xbb, 0xf5, 0x2e, 0xfe, 0x11, 0x05, 0x5b, 0x0a, 0x07, 0x0f, 0xc9, 0x13, 0xb6, 0x17, 0xaf, 0x14, 0x79, 0x10, 0xa3, 0x0d, 0xf0, 0x06, 0x4f, 0x05, 0x27, 0x06, 0xac, 0x03, 0x52, 0x03, 0xd1, 0x01, 0x82, 0x00, 0x4f, 0xfe, 0x53, 0xf9, 0x9a, 0xf9, 0xec, 0xfe, 0x36, 0xff, 0x2f, 0x00, 0xa5, 0x05, 0xe0, 0x06, 0xea, 0x05, 0x77, 0x03, 0x81, 0x00, 0x05, 0xfb, 0x12, 0xf5, 0x9d, 0xf1, 0x9e, 0xf2, 0x07, 0xf3, 0xbc, 0xf1, 0x91, 0xf4, 0xcf, 0xf6, 0x8d, 0xf9, 0xfa, 0x00, 0xf4, 0x06, 0xcd, 0x06, 0xd5, 0x07, 0x3c, 0x08, 0x5e, 0x05, 0xb4, 0x02, 0xfe, 0x01, 0x8c, 0x07, 0xe4, 0x05, 0x89, 0xff, 0xa9, 0xfc, 0xee, 0xfb, 0xd8, 0xfa, 0x77, 0xfb, 0xdc, 0xfb, 0x05, 0xfc, 0x2d, 0xfb, 0xcc, 0xfc, 0x54, 0xf9, 0x15, 0xf3, 0x91, 0xf5, 0x43, 0xfa, 0xb3, 0xff, 0x74, 0x05, 0xef, 0x07, 0xfe, 0x05, 0xf2, 0x01, 0x3e, 0x00, 0xfa, 0x01, 0x51, 0x06, 0xc9, 0x08, 0xd3, 0x05, 0x4a, 0x07, 0x32, 0x0a, 0x95, 0x07, 0xc0, 0x02, 0x05, 0xfe, 0x28, 0x04, 0x5b, 0x0b, 0x39, 0x0b, 0x2f, 0x07, 0xce, 0x01, 0x6a, 0x02, 0xb4, 0x03, 0xda, 0x05, 0x95, 0x01, 0xf7, 0xfd, 0x8e, 0xfb, 0x27, 0xf7, 0xd4, 0xf3, 0x45, 0xf5, 0xd4, 0xf5, 0x4b, 0xf6, 0x5b, 0xf8, 0x40, 0xf5, 0xb1, 0xf5, 0x69, 0xf3, 0xbd, 0xf0, 0xf6, 0xf0, 0x38, 0xf2, 0xc5, 0xef, 0x6f, 0xef, 0x97, 0xf3, 0x6f, 0xf4, 0xfb, 0xf7, 0xff, 0xfb, 0x51, 0xfe, 0x7a, 0x00, 0x04, 0x05, 0x2a, 0x0d, 0xc7, 0x0e, 0x32, 0x0b, 0x2f, 0x09, 0xf5, 0x0a, 0xea, 0x0d, 0xcf, 0x0c, 0x3d, 0x0f, 0xb8, 0x0b, 0x2f, 0x08, 0xeb, 0x08, 0x5f, 0x0c, 0x57, 0x0a, 0xc4, 0x04, 0xeb, 0x08, 0x37, 0x08, 0x46, 0x06, 0xa8, 0x05, 0xc6, 0x04, 0x5f, 0x04, 0x60, 0xfe, 0x19, 0xf9, 0x15, 0xf7, 0x4b, 0xf8, 0x2b, 0xfa, 0x03, 0xfd, 0x89, 0xfd, 0x7f, 0xfa, 0x5b, 0xf9, 0xd6, 0xf5, 0xe8, 0xf1, 0x72, 0xf3, 0xa9, 0xf3, 0x89, 0xf4, 0x2d, 0xf9, 0x98, 0xfd, 0xbc, 0xff, 0xb3, 0x01, 0x2e, 0xff, 0xe5, 0xfc, 0xb4, 0xfd, 0x79, 0xfa, 0xbf, 0xfb, 0x8d, 0xfd, 0xc7, 0x01, 0xd5, 0x09, 0x8f, 0x0d, 0xea, 0x0b, 0x68, 0x0b, 0x60, 0x0b, 0xac, 0x09, 0xe1, 0x0c, 0x0d, 0x0f, 0x65, 0x0c, 0x75, 0x0a, 0x9d, 0x06, 0x92, 0x03, 0xd6, 0x01, 0x97, 0x00, 0xf5, 0xfe, 0x4b, 0xfa, 0x54, 0xf7, 0x66, 0xfb, 0xca, 0xfe, 0x40, 0xfd, 0xd9, 0xfb, 0x40, 0xfa, 0x8c, 0xf5, 0xc6, 0xf4, 0x42, 0xf3, 0x48, 0xf2, 0xed, 0xf7, 0x26, 0xfa, 0x0d, 0xf8, 0x66, 0xfb, 0x97, 0x00, 0x9c, 0x01, 0x2a, 0x02, 0x37, 0x02, 0xfd, 0xfe, 0xbc, 0xfc, 0xd6, 0x00, 0x89, 0x03, 0x71, 0xff, 0x57, 0xfb, 0x2c, 0xfa, 0x66, 0xfb, 0xf1, 0xfc, 0x7d, 0xfe, 0x1c, 0x00, 0x2a, 0xff, 0x56, 0x00, 0x36, 0x01, 0x68, 0x02, 0x3e, 0x03, 0xfc, 0x01, 0x56, 0xfe, 0x70, 0xf9, 0xb2, 0xfa, 0x2c, 0xfd, 0x75, 0xfc, 0x8e, 0xfa, 0xa5, 0xf7, 0xa1, 0xf9, 0x6e, 0x00, 0xf1, 0x04, 0xb5, 0x07, 0xcc, 0x05, 0x46, 0x05, 0xb5, 0x03, 0xa5, 0x01, 0x8e, 0x04, 0x04, 0x07, 0x4c, 0x07, 0x03, 0x05, 0x54, 0x00, 0x74, 0x00, 0x62, 0x05, 0x71, 0x04, 0xaf, 0x03, 0x08, 0x05, 0xc1, 0x08, 0xbe, 0x07, 0xeb, 0x00, 0x38, 0xfd, 0x6a, 0xfa, 0x95, 0xfa, 0xb3, 0xfc, 0x75, 0xfd, 0xb7, 0xf7, 0x1e, 0xf5, 0x86, 0xf6, 0xee, 0xf8, 0x4e, 0xfc, 0x2d, 0xfe, 0xd6, 0xfe, 0xde, 0xfd, 0xf8, 0xfc, 0x36, 0xfe, 0xa0, 0xff, 0x7f, 0x02, 0xc9, 0x05, 0x85, 0x05, 0xe9, 0x04, 0xd3, 0x01, 0x5a, 0xfe, 0x43, 0xff, 0x04, 0x06, 0x53, 0x0c, 0x6e, 0x0b, 0x19, 0x04, 0xb9, 0x01, 0x02, 0x03, 0x95, 0xff, 0x0f, 0xfd, 0x8d, 0xfd, 0x7e, 0xfe, 0x7b, 0xff, 0x91, 0x01, 0x10, 0x04, 0xa9, 0x04, 0x12, 0x02, 0xbf, 0xfd, 0xc6, 0xfb, 0x75, 0xf8, 0x46, 0xf9, 0x00, 0xfd, 0xc7, 0xfd, 0xc6, 0xfc, 0x9c, 0xfb, 0xcb, 0xfb, 0x80, 0xfc, 0xf0, 0xfb, 0xdf, 0xf9, 0xbb, 0xf8, 0xd2, 0xf7, 0x44, 0xf8, 0x75, 0xf7, 0xbb, 0xf9, 0x34, 0x00, 0x6d, 0x05, 0x30, 0x04, 0x4d, 0x02, 0x93, 0x01, 0xdb, 0xff, 0x4f, 0x01, 0x58, 0xff, 0x65, 0xfe, 0x57, 0x02, 0x54, 0x06, 0xb5, 0x09, 0x9a, 0x0a, 0x5a, 0x07, 0x5b, 0x02, 0x42, 0xff, 0x80, 0x00, 0x98, 0x04, 0x44, 0x09, 0xd8, 0x07, 0xf8, 0x01, 0xfc, 0xfc, 0x80, 0xfc, 0xe4, 0xfc, 0xf8, 0xf7, 0x36, 0xf4, 0x74, 0xf4, 0x77, 0xf9, 0x25, 0xfd, 0x18, 0xff, 0x80, 0x02, 0xa8, 0x02, 0x6f, 0x01, 0xd3, 0xfe, 0xbf, 0xfd, 0x75, 0xfd, 0x06, 0xfd, 0xbf, 0xfe, 0x4f, 0x01, 0x5c, 0xfe, 0xb1, 0xf7, 0x38, 0xf7, 0x40, 0xfd, 0x8b, 0xfc, 0xc9, 0xf9, 0x2b, 0xfc, 0xfe, 0x02, 0x14, 0x09, 0xde, 0x09, 0xd6, 0x0a, 0x15, 0x0a, 0x24, 0x07, 0x7e, 0x03, 0x40, 0x03, 0xb0, 0x05, 0xa4, 0x0c, 0x83, 0x0e, 0x50, 0x0e, 0x10, 0x0f, 0x18, 0x0b, 0x47, 0x08, 0x53, 0x06, 0x63, 0x03, 0x65, 0xfe, 0x12, 0xf9, 0xa8, 0xf6, 0x82, 0xf4, 0xad, 0xf2, 0x25, 0xef, 0x98, 0xed, 0x15, 0xed, 0xda, 0xec, 0x61, 0xf2, 0xa5, 0xf5, 0x1b, 0xfa, 0xf8, 0xfc, 0xf0, 0xfb, 0x13, 0xf8, 0x9a, 0xf5, 0x42, 0xf5, 0xb8, 0xf8, 0x20, 0xfb, 0x14, 0xfd, 0xf7, 0x00, 0x50, 0x03, 0x2d, 0x07, 0x4c, 0x0c, 0x42, 0x10, 0x41, 0x12, 0x77, 0x11, 0x3d, 0x10, 0x39, 0x11, 0x4b, 0x10, 0x64, 0x0d, 0x84, 0x08, 0xa0, 0x05, 0xa5, 0x05, 0x3c, 0x05, 0x4b, 0x05, 0x6f, 0x07, 0xb8, 0x05, 0x25, 0x01, 0x83, 0xff, 0x99, 0xfe, 0x0c, 0xfc, 0x1b, 0xfb, 0x5a, 0xfa, 0xf6, 0xf5, 0x1e, 0xf2, 0xfb, 0xf3, 0x32, 0xf9, 0x6d, 0xfe, 0xb1, 0xff, 0xde, 0xfb, 0x7a, 0xf7, 0xe5, 0xf4, 0xfc, 0xf3, 0xa0, 0xf3, 0x58, 0xf7, 0x6a, 0xfb, 0xf9, 0xfb, 0x7d, 0xfc, 0x4a, 0xfe, 0xcb, 0xfc, 0x83, 0xfb, 0x2b, 0xfe, 0xba, 0xff, 0x99, 0x04, 0xe4, 0x05, 0xc1, 0x04, 0x2d, 0x03, 0xf8, 0x02, 0xfe, 0x05, 0xa5, 0x04, 0xe7, 0x03, 0xf1, 0x03, 0x60, 0x04, 0x86, 0x03, 0xf6, 0x03, 0x0b, 0x06, 0xd3, 0x02, 0xc6, 0xfb, 0x35, 0xf7, 0xa1, 0xf6, 0x04, 0xf5, 0x8a, 0xf4, 0xbb, 0xf4, 0x27, 0xf5, 0x50, 0xf4, 0x51, 0xf5, 0xa3, 0xf5, 0x82, 0xf7, 0x2a, 0xfc, 0x8d, 0xfe, 0x14, 0x01, 0x62, 0x03, 0x99, 0x07, 0x94, 0x08, 0x29, 0x08, 0xb0, 0x08, 0x33, 0x07, 0x1b, 0x08, 0xcd, 0x08, 0x8d, 0x07, 0x05, 0x07, 0x73, 0x08, 0x02, 0x08, 0x1f, 0x08, 0x33, 0x08, 0xb8, 0x05, 0x79, 0x03, 0x4d, 0x01, 0xa4, 0xfb, 0xdb, 0xf6, 0x90, 0xf5, 0xd8, 0xf5, 0x92, 0xf9, 0xaf, 0xfc, 0x77, 0xfb, 0xb6, 0xfb, 0x34, 0xfc, 0x01, 0xfe, 0xa6, 0x00, 0xe3, 0x00, 0xd9, 0xff, 0xd0, 0xfd, 0xf5, 0xfb, 0xa2, 0xfb, 0xf4, 0xfc, 0x5a, 0x00, 0xbc, 0x01, 0x11, 0x00, 0x14, 0x02, 0x7a, 0x06, 0x1c, 0x09, 0x83, 0x0a, 0x39, 0x0c, 0x30, 0x0b, 0x7a, 0x08, 0x62, 0x08, 0x6b, 0x08, 0xb9, 0x05, 0xcb, 0x03, 0xfa, 0x01, 0x5d, 0xfd, 0xe2, 0xf8, 0x9d, 0xf4, 0x4b, 0xf2, 0xe6, 0xf4, 0xff, 0xf8, 0x24, 0xf7, 0x03, 0xf6, 0x02, 0xf5, 0x9e, 0xf4, 0x89, 0xf7, 0x62, 0xf8, 0x2c, 0xf7, 0x34, 0xf6, 0xd6, 0xf6, 0x0a, 0xfa, 0xa7, 0xfd, 0xcd, 0xff, 0xf7, 0x02, 0x10, 0x05, 0x9c, 0x06, 0x5f, 0x09, 0x17, 0x0c, 0x1a, 0x0c, 0x2f, 0x0c, 0x56, 0x0f, 0x8f, 0x10, 0xa2, 0x10, 0x7c, 0x10, 0xaf, 0x0d, 0x5b, 0x0a, 0xbb, 0x0a, 0xfc, 0x09, 0x42, 0x08, 0x0a, 0x05, 0x65, 0x02, 0x80, 0x02, 0xab, 0x01, 0xc5, 0xfe, 0x7e, 0xff, 0xfd, 0xff, 0x00, 0xff, 0xae, 0xfc, 0x7b, 0xfa, 0x94, 0xf9, 0xe8, 0xf7, 0xc7, 0xf4, 0x52, 0xf2, 0x39, 0xf2, 0x0d, 0xf1, 0xf3, 0xed, 0x27, 0xee, 0xeb, 0xf2, 0xc8, 0xf4, 0x18, 0xf3, 0x83, 0xf0, 0x42, 0xf1, 0x59, 0xf1, 0xfe, 0xf2, 0x2c, 0xf6, 0xca, 0xfa, 0xa1, 0x00, 0x85, 0x04, 0x14, 0x04, 0xa2, 0x06, 0x28, 0x08, 0xb1, 0x05, 0xb2, 0x03, 0x1a, 0x03, 0xa0, 0x06, 0xec, 0x06, 0xad, 0x08, 0x21, 0x0b, 0x68, 0x0b, 0x8e, 0x0c, 0x0e, 0x0c, 0xa7, 0x08, 0x28, 0x06, 0xaa, 0x05, 0x13, 0x03, 0xe2, 0xff, 0x46, 0xfe, 0x90, 0xff, 0x3e, 0x00, 0x1e, 0x01, 0x62, 0x01, 0xf9, 0xfd, 0x59, 0xfb, 0xcc, 0xfb, 0x4b, 0xfe, 0x6b, 0x01, 0xf5, 0xff, 0x55, 0xfd, 0x57, 0xff, 0x55, 0x02, 0x0b, 0x02, 0x50, 0x00, 0x9f, 0xff, 0x3a, 0xff, 0x43, 0xff, 0xb8, 0xfe, 0x49, 0xfd, 0x23, 0xfb, 0xa2, 0xf8, 0x9b, 0xf8, 0x6a, 0xf8, 0x0e, 0xf9, 0x19, 0xfd, 0x1b, 0xfe, 0xa4, 0x00, 0x4f, 0x03, 0x32, 0x05, 0x4c, 0x05, 0x1c, 0x04, 0x32, 0x05, 0xb1, 0x04, 0xc6, 0x02, 0x57, 0x02, 0x10, 0x03, 0xdb, 0x01, 0x39, 0x03, 0xf7, 0x02, 0xea, 0x02, 0x44, 0x04, 0x77, 0x02, 0x94, 0xfd, 0x54, 0xf8, 0xef, 0xf6, 0xb5, 0xf4, 0xce, 0xf4, 0x4f, 0xf7, 0xca, 0xf6, 0x2f, 0xf6, 0x22, 0xf9, 0xbc, 0xfc, 0x80, 0xfe, 0x66, 0x00, 0x56, 0x02, 0x87, 0x00, 0x26, 0xfe, 0xd5, 0xfb, 0x4a, 0xfc, 0x33, 0xfc, 0x2b, 0xfb, 0xa6, 0xfc, 0x5d, 0xfe, 0x60, 0xfc, 0xd5, 0xfc, 0xcf, 0x00, 0x28, 0x03, 0x46, 0x02, 0x77, 0x03, 0x75, 0x04, 0x82, 0x04, 0xab, 0x04, 0x64, 0x03, 0xf4, 0x03, 0xb6, 0x04, 0x42, 0x05, 0xe7, 0x06, 0xef, 0x06, 0xe9, 0x06, 0xab, 0x06, 0xdd, 0x06, 0x87, 0x06, 0x02, 0x04, 0xfc, 0x02, 0x51, 0x02, 0x32, 0x03, 0x0c, 0x04, 0x63, 0x01, 0x0e, 0x00, 0xf1, 0x02, 0x9b, 0x04, 0xec, 0x02, 0x5c, 0x02, 0xd1, 0x01, 0x09, 0x02, 0xc9, 0x01, 0x5b, 0xfe, 0xfe, 0xfc, 0x32, 0xfc, 0xca, 0xfa, 0x1e, 0xfa, 0xe8, 0xfb, 0xf7, 0xf8, 0xbd, 0xf6, 0x22, 0xf5, 0xe3, 0xf4, 0xac, 0xf4, 0x94, 0xf2, 0x76, 0xf3, 0xa6, 0xf3, 0x27, 0xf4, 0x04, 0xf7, 0x25, 0xfa, 0xcc, 0xfa, 0x91, 0xfb, 0x4a, 0xfe, 0x62, 0x02, 0xb9, 0x06, 0xea, 0x08, 0xa6, 0x0b, 0x98, 0x0d, 0xa1, 0x0d, 0x6f, 0x0e, 0x1c, 0x0e, 0x87, 0x0d, 0xa7, 0x0c, 0x35, 0x08, 0x0a, 0x03, 0x61, 0x00, 0xf4, 0xfe, 0x18, 0xfe, 0x08, 0xfb, 0x3c, 0xf8, 0xae, 0xf8, 0xac, 0xfb, 0x78, 0xfc, 0x57, 0xfc, 0xad, 0xfb, 0xe7, 0xfa, 0x0f, 0xfb, 0x3a, 0xfb, 0x15, 0xfb, 0xbd, 0xf8, 0x09, 0xf7, 0x73, 0xf4, 0x63, 0xf4, 0x20, 0xf7, 0xf5, 0xf8, 0x87, 0xfc, 0xaa, 0xff, 0x5c, 0x03, 0xcd, 0x06, 0xdd, 0x08, 0x0f, 0x09, 0xba, 0x09, 0xa1, 0x0a, 0x9e, 0x0b, 0x02, 0x0b, 0xfe, 0x09, 0x5a, 0x07, 0x7c, 0x04, 0x50, 0x05, 0x07, 0x04, 0x77, 0x00, 0x69, 0xff, 0x21, 0x00, 0xd7, 0x01, 0x5a, 0x01, 0x4c, 0xff, 0x45, 0xfa, 0x0e, 0xf8, 0x41, 0xfa, 0xf1, 0xfb, 0xb5, 0xfd, 0xc1, 0xfd, 0x8e, 0xfd, 0x0c, 0xfe, 0x20, 0xfe, 0x93, 0xfe, 0xd1, 0xfe, 0xb9, 0xff, 0x43, 0xfe, 0x80, 0xfc, 0x70, 0xff, 0x52, 0x02, 0x17, 0x03, 0xcc, 0x04, 0xbf, 0x07, 0x59, 0x07, 0x8d, 0x05, 0x5c, 0x02, 0x5b, 0x00, 0xee, 0x00, 0x46, 0x01, 0x07, 0xff, 0xe9, 0xfa, 0x34, 0xf9, 0x54, 0xf8, 0xba, 0xf6, 0x8d, 0xf5, 0x5a, 0xf7, 0x86, 0xf9, 0x62, 0xfc, 0xb1, 0xff, 0xbf, 0x00, 0xbe, 0x01, 0x7f, 0x01, 0x62, 0x01, 0x83, 0x02, 0x7a, 0x04, 0x7d, 0x03, 0x5b, 0x03, 0xac, 0x04, 0x6c, 0x04, 0xeb, 0x03, 0xcd, 0x00, 0x78, 0xfd, 0x7a, 0xfb, 0x22, 0xfb, 0xc9, 0xfa, 0xbf, 0xfa, 0x7e, 0xfd, 0xc0, 0xff, 0x62, 0x01, 0xda, 0x02, 0x48, 0x07, 0xcb, 0x08, 0x1f, 0x07, 0xac, 0x05, 0xdf, 0x01, 0xde, 0xff, 0xdf, 0xfc, 0x8b, 0xfa, 0x10, 0xf9, 0xc6, 0xf8, 0x21, 0xf7, 0x40, 0xf5, 0xcf, 0xf6, 0x89, 0xf7, 0x9a, 0xf8, 0xa7, 0xfb, 0x7a, 0xfe, 0x91, 0xfc, 0xf0, 0xfb, 0xde, 0xfd, 0xf1, 0xfe, 0xaa, 0xff, 0x00, 0x00, 0xe7, 0xff, 0xde, 0xfd, 0x63, 0xfd, 0xd7, 0xfe, 0x4b, 0x02, 0x2c, 0x04, 0x98, 0x03, 0x78, 0x03, 0x37, 0x04, 0xf6, 0x06, 0x65, 0x09, 0x5d, 0x09, 0xff, 0x08, 0x20, 0x07, 0x21, 0x06, 0xa6, 0x06, 0xd6, 0x07, 0x49, 0x0a, 0x37, 0x0c, 0x2d, 0x0b, 0x41, 0x07, 0x99, 0x03, 0x01, 0x01, 0x39, 0x00, 0xa8, 0xfe, 0xe0, 0xfd, 0xeb, 0xfc, 0xbe, 0xfa, 0x30, 0xf9, 0xec, 0xf8, 0xd8, 0xf9, 0x67, 0xfb, 0xf4, 0xfb, 0x8b, 0xfb, 0x8e, 0xfb, 0xd9, 0xf9, 0xa7, 0xf8, 0x1b, 0xf8, 0x9d, 0xf8, 0xcd, 0xf9, 0xe1, 0xfa, 0xe5, 0xfc, 0x26, 0xfd, 0x51, 0xfa, 0x2b, 0xfb, 0x5c, 0xfd, 0x48, 0xff, 0xb6, 0x02, 0x28, 0x03, 0x7a, 0x04, 0xa8, 0x04, 0xf3, 0x02, 0xf0, 0x00, 0x40, 0x00, 0x78, 0x00, 0x66, 0x01, 0x81, 0x02, 0xf9, 0x02, 0x27, 0x03, 0x2d, 0x02, 0x9a, 0x01, 0x43, 0x02, 0xb4, 0x03, 0x32, 0x05, 0xaf, 0x05, 0x60, 0x06, 0x14, 0x08, 0xc4, 0x06, 0x47, 0x04, 0xc4, 0x01, 0x59, 0x00, 0x2b, 0xfe, 0x99, 0xfb, 0x8f, 0xfb, 0x10, 0xfb, 0x4b, 0xfa, 0xff, 0xf9, 0x0d, 0xf9, 0xb2, 0xf6, 0x91, 0xf6, 0x7d, 0xf9, 0x00, 0xfa, 0x65, 0xf9, 0x6a, 0xfa, 0x21, 0xfc, 0x0a, 0xfd, 0xf4, 0xfc, 0xd6, 0xfe, 0xd8, 0xff, 0x41, 0x01, 0x25, 0x03, 0x3a, 0x04, 0x09, 0x05, 0x98, 0x05, 0xb0, 0x05, 0x84, 0x05, 0x5e, 0x04, 0x63, 0x01, 0xf5, 0xfe, 0xad, 0xfd, 0x76, 0xfe, 0x2d, 0xff, 0xec, 0xfe, 0xef, 0xfe, 0x33, 0xfe, 0xa9, 0xfb, 0xd9, 0xfa, 0xf4, 0xfb, 0x4e, 0xfd, 0xb6, 0xfd, 0xbc, 0xfe, 0x1d, 0x01, 0x8b, 0x02, 0x47, 0x03, 0xc2, 0x03, 0xab, 0x01, 0x01, 0xff, 0x7d, 0xfe, 0xa1, 0xff, 0x94, 0x00, 0xfb, 0x00, 0xb0, 0x02, 0x34, 0x04, 0x9a, 0x04, 0x51, 0x04, 0x95, 0x02, 0x1f, 0x01, 0x33, 0xff, 0xe3, 0xfc, 0x13, 0xfd, 0xc7, 0xfd, 0x03, 0xfe, 0x42, 0xff, 0x39, 0x01, 0xac, 0x02, 0x5a, 0x02, 0x38, 0x02, 0x04, 0x02, 0xbb, 0x00, 0xf5, 0xff, 0xaa, 0xfd, 0xb3, 0xfd, 0x00, 0xff, 0x9c, 0x00, 0xdb, 0x00, 0xdf, 0x00, 0x4e, 0x01, 0xfb, 0x00, 0x63, 0x01, 0x6c, 0x01, 0x30, 0x01, 0xe4, 0x00, 0x45, 0x01, 0xbe, 0xff, 0x30, 0xfe, 0x46, 0xfd, 0x1f, 0xfb, 0x27, 0xfc, 0xa3, 0xfd, 0x8c, 0xfe, 0x6b, 0xfe, 0xb0, 0xfe, 0x05, 0xff, 0x16, 0xfe, 0x5c, 0xff, 0x30, 0xfe, 0x29, 0xfd, 0xb5, 0xfb, 0xfd, 0xf8, 0x50, 0xf9, 0x0d, 0xfc, 0xef, 0xfe, 0xde, 0xff, 0x33, 0xff, 0xb8, 0xfe, 0x0a, 0x00, 0x86, 0x00, 0xaa, 0x02, 0xd8, 0x03, 0xa1, 0x05, 0x7d, 0x07, 0xca, 0x08, 0x9a, 0x0a, 0x93, 0x09, 0x83, 0x07, 0x35, 0x07, 0x4e, 0x06, 0xe4, 0x03, 0x9a, 0x02, 0xec, 0x02, 0xa2, 0x01, 0x1e, 0x00, 0x80, 0xfe, 0xc3, 0xfb, 0xc7, 0xf9, 0x8d, 0xf8, 0x75, 0xf8, 0x9c, 0xf8, 0xcb, 0xf8, 0x2d, 0xf8, 0x7f, 0xf9, 0xae, 0xfb, 0xa5, 0xfc, 0x7a, 0xfe, 0x64, 0x00, 0x43, 0x00, 0xe3, 0xff, 0xd0, 0xff, 0x5d, 0x00, 0x32, 0x01, 0x9b, 0x00, 0xd9, 0xfe, 0xde, 0xfd, 0x8e, 0xfc, 0x6f, 0xfb, 0xd9, 0xfc, 0x22, 0xfe, 0x02, 0xff, 0xdd, 0xff, 0x1b, 0x01, 0x5b, 0x01, 0xb8, 0x00, 0x23, 0x01, 0x73, 0xff, 0xb8, 0xfe, 0xc0, 0xfe, 0x04, 0xff, 0x76, 0x00, 0x67, 0x02, 0x00, 0x04, 0xa2, 0x03, 0x8e, 0x04, 0x5f, 0x05, 0xee, 0x04, 0xc1, 0x04, 0x7a, 0x05, 0xaf, 0x06, 0x0a, 0x07, 0xa5, 0x04, 0x9a, 0x02, 0x2a, 0x00, 0x22, 0xff, 0x22, 0xff, 0xcf, 0xfe, 0x6a, 0xfd, 0xc3, 0xfc, 0xcc, 0xfd, 0xa3, 0xfd, 0x60, 0xfd, 0xae, 0xfe, 0xc4, 0xfe, 0xba, 0xfc, 0x77, 0xfa, 0x06, 0xf9, 0x73, 0xf8, 0x0d, 0xf8, 0x20, 0xf8, 0xb0, 0xf8, 0x93, 0xf8, 0x52, 0xf9, 0x11, 0xfd, 0x62, 0x00, 0x39, 0x02, 0x1d, 0x04, 0xed, 0x04, 0xaa, 0x05, 0x7b, 0x06, 0x55, 0x06, 0x0d, 0x07, 0xc2, 0x06, 0xa0, 0x05, 0x0f, 0x05, 0xc2, 0x04, 0xef, 0x02, 0xa0, 0x01, 0x43, 0x01, 0x1e, 0x02, 0xdf, 0x01, 0xd0, 0x00, 0x39, 0x01, 0x39, 0x00, 0x45, 0xff, 0xd6, 0xfe, 0x4d, 0xfe, 0xcd, 0xfc, 0x3f, 0xfa, 0x32, 0xf8, 0x75, 0xf8, 0x76, 0xf8, 0x53, 0xf7, 0x55, 0xf6, 0x41, 0xf6, 0x93, 0xf7, 0xf7, 0xf6, 0x34, 0xf5, 0xb3, 0xf6, 0xdb, 0xf9, 0x0d, 0xfc, 0x37, 0xfe, 0x36, 0x00, 0x29, 0x01, 0x09, 0x02, 0x37, 0x04, 0x47, 0x06, 0xcb, 0x08, 0x57, 0x0b, 0x6e, 0x0d, 0x12, 0x0e, 0x26, 0x0d, 0x38, 0x0b, 0xaa, 0x09, 0xe2, 0x08, 0x2e, 0x08, 0x76, 0x07, 0x2e, 0x07, 0xa0, 0x05, 0xaa, 0x03, 0xee, 0x01, 0xb3, 0xff, 0xf8, 0xfd, 0x0b, 0xfc, 0x2c, 0xfa, 0x3f, 0xf9, 0x82, 0xf9, 0x7a, 0xfa, 0x4c, 0xfa, 0x6d, 0xfb, 0xf9, 0xfc, 0x30, 0xfd, 0x87, 0xfc, 0x19, 0xfc, 0xe9, 0xfc, 0x62, 0xfd, 0xdf, 0xfd, 0x1e, 0xff, 0xc6, 0xff, 0xbc, 0xff, 0x1f, 0xfe, 0xd8, 0xfc, 0x65, 0xfc, 0xb6, 0xfc, 0x37, 0xfd, 0x02, 0xfe, 0x43, 0xff, 0x81, 0xff, 0xb8, 0xff, 0x8f, 0xff, 0x16, 0xfe, 0x7e, 0xfe, 0xcd, 0x00, 0x31, 0x02, 0x6b, 0x02, 0x0e, 0x03, 0xa4, 0x04, 0x97, 0x06, 0xf2, 0x06, 0x18, 0x06, 0x48, 0x04, 0x46, 0x04, 0x5a, 0x05, 0x31, 0x06, 0xea, 0x06, 0x6b, 0x05, 0xd7, 0x02, 0x76, 0xfe, 0x29, 0xfb, 0xea, 0xf9, 0x8e, 0xf8, 0xa9, 0xf6, 0x4b, 0xf6, 0xcc, 0xf6, 0x17, 0xf8, 0xe5, 0xf8, 0x8e, 0xf8, 0xb3, 0xf8, 0x7c, 0xf9, 0xdd, 0xfa, 0xc2, 0xfc, 0xaf, 0xff, 0xc2, 0x01, 0x88, 0x02, 0xca, 0x03, 0x2d, 0x05, 0x7c, 0x06, 0x66, 0x07, 0x2d, 0x07, 0x99, 0x05, 0x32, 0x03, 0x85, 0x01, 0xd0, 0xff, 0xc6, 0xff, 0xcb, 0xff, 0xa2, 0xff, 0x87, 0xff, 0x24, 0xff, 0xf4, 0xfe, 0x00, 0x00, 0x7a, 0x00, 0xa2, 0xff, 0x27, 0xfe, 0xd0, 0xfc, 0x3e, 0xfd, 0x00, 0xfd, 0x6b, 0xfc, 0x09, 0xfd, 0x6a, 0xfe, 0xfa, 0xfd, 0x4e, 0xfd, 0x5f, 0xfd, 0xd5, 0xfd, 0xa5, 0xfe, 0x1f, 0xff, 0xe6, 0xfd, 0x4e, 0xfc, 0x45, 0xfc, 0x37, 0xfe, 0x3e, 0x01, 0x4b, 0x02, 0x22, 0x04, 0xbd, 0x05, 0x6d, 0x05, 0xae, 0x05, 0x25, 0x06, 0xe8, 0x04, 0x08, 0x04, 0x03, 0x03, 0xcc, 0x01, 0x2e, 0x01, 0x04, 0x00, 0xb8, 0xff, 0x87, 0xff, 0xdf, 0xfe, 0xab, 0xfc, 0x9a, 0xfa, 0xf5, 0xf9, 0x63, 0xfa, 0xc1, 0xfb, 0x20, 0xfd, 0xbe, 0xfd, 0xce, 0xfe, 0xdc, 0xfe, 0x56, 0xfe, 0x39, 0xfe, 0x32, 0xfe, 0xd4, 0xfe, 0xa7, 0x00, 0x12, 0x02, 0xa5, 0x02, 0x1b, 0x03, 0x79, 0x03, 0xbd, 0x04, 0x04, 0x05, 0x7e, 0x04, 0xec, 0x03, 0xd9, 0x03, 0x3a, 0x03, 0x9f, 0x01, 0xaa, 0x00, 0xb6, 0xff, 0xcb, 0xfe, 0x99, 0xfe, 0xb7, 0xfe, 0x3a, 0xfe, 0x04, 0xfe, 0x3d, 0xfe, 0xe7, 0xfd, 0x44, 0xfd, 0x6e, 0xfd, 0x2b, 0xfe, 0x0c, 0xff, 0xf2, 0xff, 0x4c, 0x00, 0x05, 0x00, 0xff, 0xff, 0xcb, 0xfe, 0x2e, 0xfe, 0x38, 0xff, 0x7e, 0x00, 0xf3, 0x00, 0xbf, 0x00, 0x55, 0x00, 0x2c, 0x00, 0xac, 0x00, 0x69, 0x01, 0x64, 0x02, 0x63, 0x01, 0xb4, 0xff, 0x7d, 0xff, 0xea, 0xff, 0x26, 0xff, 0xff, 0xfd, 0xee, 0xfd, 0xb8, 0xfe, 0x33, 0xff, 0x88, 0xff, 0x4b, 0xff, 0xa4, 0xfe, 0xd9, 0xfd, 0xe5, 0xfd, 0xed, 0xfc, 0xe2, 0xfb, 0x70, 0xfc, 0xdf, 0xfc, 0x97, 0xfd, 0x2d, 0xfd, 0x55, 0xfd, 0x8e, 0xfd, 0x04, 0xfd, 0xed, 0xfd, 0x2f, 0xff, 0x55, 0x00, 0x93, 0x02, 0x89, 0x03, 0x19, 0x03, 0x4c, 0x04, 0x40, 0x05, 0x93, 0x05, 0x92, 0x05, 0xba, 0x04, 0x23, 0x03, 0xc6, 0x00, 0x8c, 0xfe, 0x9d, 0xfe, 0x56, 0xfe, 0xa8, 0xfd, 0xab, 0xfe, 0xa0, 0xfe, 0x03, 0xfd, 0x78, 0xfc, 0x03, 0xfd, 0x2e, 0xfd, 0xca, 0xfd, 0x07, 0xff, 0x64, 0xff, 0xbf, 0xff, 0x5f, 0x01, 0x33, 0x03, 0x83, 0x04, 0x12, 0x06, 0x64, 0x07, 0x7d, 0x07, 0xd3, 0x05, 0xd4, 0x03, 0x3d, 0x02, 0xfd, 0x00, 0x2f, 0x00, 0x4f, 0x00, 0xbf, 0xff, 0xf1, 0xfe, 0x4b, 0xfe, 0x03, 0xfd, 0xff, 0xfb, 0xed, 0xfb, 0x2b, 0xfd, 0x48, 0xfe, 0xd2, 0xfd, 0xf0, 0xfc, 0x35, 0xfd, 0x22, 0xff, 0xf9, 0x00, 0x89, 0x01, 0xa3, 0x01, 0xef, 0x00, 0x67, 0x01, 0x71, 0x02, 0xd9, 0x02, 0xe4, 0x00, 0xf0, 0xfe, 0xf6, 0xfd, 0xfa, 0xfc, 0x7f, 0xfd, 0x6b, 0xfd, 0xc5, 0xfd, 0x6b, 0xfd, 0xf8, 0xfc, 0x1a, 0xfd, 0x99, 0xfb, 0xa0, 0xfa, 0x6e, 0xfa, 0xe5, 0xfa, 0xfa, 0xfa, 0xc6, 0xfa, 0xd8, 0xfb, 0x5c, 0xfd, 0x46, 0xfe, 0x00, 0x00, 0xdb, 0x00, 0x65, 0x00, 0x62, 0x00, 0xc6, 0x01, 0x96, 0x02, 0x27, 0x03, 0x47, 0x04, 0x69, 0x04, 0x57, 0x04, 0x6a, 0x04, 0x16, 0x05, 0xa9, 0x05, 0x64, 0x04, 0xd4, 0x01, 0xde, 0xff, 0x31, 0xff, 0x2d, 0xff, 0x88, 0xfe, 0xf8, 0xfe, 0xc6, 0xfe, 0x62, 0xfe, 0xd7, 0xfe, 0xc4, 0xff, 0x65, 0x00, 0x9b, 0x01, 0x35, 0x04, 0xa4, 0x06, 0xe8, 0x06, 0x32, 0x06, 0x75, 0x06, 0x63, 0x05, 0x14, 0x04, 0x58, 0x03, 0x3c, 0x02, 0xe4, 0x01, 0xaf, 0x01, 0x7a, 0x00, 0x0b, 0xff, 0x89, 0xfe, 0x8b, 0xfd, 0xe9, 0xfb, 0x25, 0xfb, 0xe3, 0xf9, 0x9f, 0xf9, 0x44, 0xfa, 0x6f, 0xfb, 0x7b, 0xfc, 0xaa, 0xfc, 0x2c, 0xfc, 0x28, 0xfc, 0x2c, 0xfb, 0xd5, 0xfa, 0xa9, 0xfb, 0x85, 0xfb, 0x75, 0xfb, 0x8d, 0xfb, 0x0b, 0xfc, 0xf3, 0xfb, 0x3e, 0xfb, 0xcc, 0xfb, 0x22, 0xfd, 0x86, 0xfd, 0x14, 0xfe, 0x82, 0xfe, 0xb9, 0xfe, 0x9d, 0x00, 0xe5, 0x02, 0xaa, 0x04, 0xf6, 0x05, 0x41, 0x06, 0xa6, 0x06, 0xa9, 0x07, 0x24, 0x06, 0x98, 0x04, 0xf1, 0x03, 0x12, 0x04, 0x6e, 0x04, 0x90, 0x03, 0xd2, 0x03, 0xd1, 0x03, 0xd1, 0x03, 0x70, 0x03, 0xf9, 0x02, 0xf3, 0x02, 0xd2, 0x01, 0xf5, 0x00, 0xc8, 0xff, 0x39, 0xfe, 0x3f, 0xfc, 0xd1, 0xfa, 0x59, 0xfa, 0x6f, 0xfa, 0x13, 0xfb, 0xda, 0xfb, 0x4c, 0xfd, 0x4a, 0xfe, 0x56, 0xfe, 0x77, 0xfe, 0x57, 0xff, 0xc3, 0xff, 0x0a, 0xff, 0x9a, 0xff, 0xde, 0x00, 0x5e, 0x01, 0x50, 0x00, 0x0d, 0xfe, 0x7e, 0xfc, 0x11, 0xfc, 0x58, 0xfc, 0x38, 0xfd, 0x1c, 0xfe, 0x81, 0xfe, 0xb1, 0xff, 0x98, 0x00, 0x76, 0x01, 0xbb, 0x01, 0xd9, 0x02, 0x98, 0x03, 0xe7, 0x02, 0x0c, 0x03, 0xee, 0x02, 0x30, 0x03, 0xb9, 0x03, 0xd2, 0x03, 0x05, 0x03, 0xd9, 0x01, 0x05, 0x01, 0x13, 0x00, 0xf8, 0xfe, 0x48, 0xfe, 0xeb, 0xfd, 0x13, 0xfe, 0x01, 0xfe, 0x38, 0xfd, 0xd0, 0xfc, 0x4a, 0xfc, 0xe2, 0xfb, 0xa5, 0xfc, 0xdb, 0xfc, 0x51, 0xfc, 0xe7, 0xfb, 0xe3, 0xfb, 0x92, 0xfc, 0x69, 0xfd, 0xa8, 0xfd, 0x2a, 0xfe, 0x05, 0xff, 0xee, 0xff, 0x87, 0x00, 0x08, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x6b, 0xff, 0xb1, 0xfe, 0x50, 0xff, 0x6b, 0x00, 0x5a, 0x01, 0x8d, 0x01, 0x9c, 0x01, 0xc6, 0x01, 0x91, 0x02, 0x86, 0x03, 0x11, 0x04, 0xd0, 0x04, 0x7f, 0x04, 0xaa, 0x04, 0xca, 0x04, 0x49, 0x04, 0x90, 0x04, 0x1f, 0x04, 0x0e, 0x03, 0x03, 0x02, 0x82, 0x00, 0x15, 0xff, 0xd0, 0xfe, 0xf1, 0xfd, 0x69, 0xfc, 0x0a, 0xfb, 0x6a, 0xfa, 0x22, 0xfa, 0x03, 0xfb, 0x7f, 0xfc, 0x90, 0xfd, 0x9b, 0xfe, 0x25, 0xff, 0x9b, 0xff, 0xeb, 0xff, 0xe6, 0xff, 0xb4, 0x00, 0x74, 0x02, 0x84, 0x03, 0x51, 0x03, 0x3f, 0x03, 0x1b, 0x03, 0xd4, 0x01, 0xb7, 0x00, 0x52, 0x00, 0x43, 0x00, 0x6f, 0x00, 0xae, 0xff, 0x7e, 0xff, 0xcc, 0xff, 0xa2, 0xff, 0x98, 0xfe, 0x01, 0xfe, 0xc2, 0xfc, 0x89, 0xfc, 0xa8, 0xfc, 0x20, 0xfd, 0x0b, 0xff, 0xfa, 0xff, 0xd1, 0x00, 0x28, 0x01, 0x1e, 0x00, 0x23, 0xff, 0x94, 0xfe, 0x0c, 0xfe, 0x64, 0xfd, 0x80, 0xfd, 0x42, 0xfe, 0x38, 0xff, 0xd0, 0xff, 0x1a, 0x00, 0x73, 0xff, 0x09, 0xff, 0x00, 0xff, 0x29, 0xff, 0x6c, 0xff, 0x47, 0xff, 0x3b, 0xff, 0x22, 0x00, 0x3f, 0x00, 0x2b, 0x00, 0xbb, 0xff, 0xdc, 0x00, 0xc3, 0x02, 0x3f, 0x03, 0x84, 0x03, 0x3f, 0x03, 0xb5, 0x02, 0x2b, 0x02, 0xda, 0x02, 0xdf, 0x02, 0x26, 0x02, 0xdc, 0x01, 0xf0, 0x01, 0x92, 0x02, 0xc7, 0x02, 0x49, 0x03, 0xb3, 0x03, 0xe5, 0x02, 0x62, 0x01, 0x5f, 0x00, 0x51, 0x00, 0x67, 0x00, 0x61, 0x00, 0x67, 0x00, 0xef, 0xff, 0xf2, 0xfd, 0x1a, 0xfc, 0xcc, 0xfb, 0x6a, 0xfb, 0xbd, 0xfa, 0x04, 0xf9, 0xb2, 0xf8, 0x31, 0xf9, 0x94, 0xf9, 0x8e, 0xfa, 0xc5, 0xfb, 0xfb, 0xfc, 0x72, 0xfd, 0xf0, 0xfd, 0x8b, 0xfe, 0x8d, 0xfe, 0x02, 0xfe, 0x13, 0xfe, 0x41, 0xff, 0x8c, 0x00, 0xa8, 0x01, 0xe2, 0x01, 0xb3, 0x02, 0x5b, 0x03, 0x58, 0x03, 0xce, 0x02, 0xde, 0x01, 0x35, 0x02, 0x98, 0x02, 0x22, 0x03, 0x9d, 0x03, 0x37, 0x04, 0xef, 0x04, 0x09, 0x05, 0x7a, 0x04, 0x24, 0x04, 0x64, 0x03, 0xb7, 0x01, 0x13, 0x01, 0x6e, 0x01, 0x37, 0x01, 0x76, 0x00, 0xdc, 0xff, 0xb0, 0xff, 0xc7, 0xff, 0x15, 0x00, 0x41, 0xff, 0xfc, 0xfd, 0xfe, 0xfd, 0xf0, 0xfd, 0xb8, 0xfd, 0x02, 0xfe, 0x21, 0xfe, 0xce, 0xfd, 0x85, 0xfd, 0xda, 0xfc, 0x4e, 0xfc, 0x92, 0xfc, 0x80, 0xfd, 0xf9, 0xfd, 0x4a, 0xfd, 0x26, 0xfc, 0xf8, 0xfb, 0x3d, 0xfc, 0x96, 0xfc, 0x07, 0xfd, 0x08, 0xfe, 0x9e, 0xff, 0x2b, 0x00, 0x2c, 0x00, 0xd0, 0xff, 0x67, 0xff, 0x86, 0xff, 0x3a, 0x00, 0xfd, 0x00, 0x91, 0x00, 0x00, 0x00, 0xb7, 0x00, 0xf3, 0x01, 0xbd, 0x02, 0xd9, 0x02, 0x03, 0x02, 0x09, 0x02, 0x9b, 0x02, 0x5e, 0x03, 0x03, 0x04, 0xd5, 0x03, 0x55, 0x04, 0x78, 0x04, 0x07, 0x04, 0xd8, 0x02, 0x60, 0x02, 0x1a, 0x02, 0x08, 0x01, 0x44, 0x00, 0xb3, 0xff, 0xfd, 0xff, 0x22, 0x00, 0xa4, 0xff, 0xf0, 0xfe, 0x4a, 0xfe, 0x3d, 0xfe, 0xd9, 0xfe, 0xd5, 0xfe, 0x4c, 0xfe, 0x73, 0xfd, 0xd7, 0xfc, 0x87, 0xfc, 0x48, 0xfd, 0x55, 0xfd, 0x79, 0xfd, 0x5b, 0xfd, 0xb7, 0xfd, 0x90, 0xfe, 0x7c, 0xfe, 0x34, 0xfe, 0xe2, 0xfd, 0x0d, 0xfe, 0x1a, 0xfe, 0xef, 0xfd, 0xfe, 0xfc, 0xd9, 0xfb, 0x15, 0xfc, 0xea, 0xfc, 0xbb, 0xfd, 0x75, 0xfe, 0x50, 0xff, 0xd6, 0x00, 0x7b, 0x02, 0x87, 0x03, 0xbb, 0x04, 0x71, 0x05, 0x09, 0x05, 0x6f, 0x05, 0xb2, 0x05, 0xdc, 0x04, 0x2a, 0x04, 0x4c, 0x03, 0x3f, 0x02, 0x98, 0x01, 0xe2, 0x01, 0x19, 0x02, 0xe2, 0x01, 0x02, 0x01, 0x77, 0x00, 0x5e, 0x00, 0x2f, 0x00, 0x79, 0xff, 0x1d, 0xff, 0xb6, 0xfe, 0x01, 0xfe, 0xa5, 0xfd, 0x62, 0xfd, 0xca, 0xfc, 0x1e, 0xfc, 0x1e, 0xfc, 0xb9, 0xfb, 0x58, 0xfb, 0x06, 0xfb, 0x26, 0xfb, 0x37, 0xfb, 0xb0, 0xfb, 0x9a, 0xfc, 0xcb, 0xfc, 0x3e, 0xfd, 0xfd, 0xfd, 0x2f, 0xff, 0xc2, 0xff, 0x64, 0x00, 0xa3, 0x00, 0x5f, 0x00, 0xb7, 0x00, 0x6e, 0x01, 0xc8, 0x01, 0xcf, 0x01, 0x1e, 0x02, 0x9e, 0x02, 0xd2, 0x02, 0xe9, 0x02, 0xdd, 0x02, 0xbd, 0x02, 0xdb, 0x02, 0xa4, 0x02, 0x0e, 0x03, 0x9f, 0x03, 0xf0, 0x03, 0xeb, 0x03, 0xe2, 0x03, 0x14, 0x04, 0xda, 0x03, 0x77, 0x03, 0xcb, 0x02, 0x2d, 0x02, 0x6c, 0x01, 0x96, 0x00, 0x08, 0x00, 0x57, 0xff, 0x3a, 0xff, 0x7b, 0xff, 0xcf, 0xff, 0x1b, 0x00, 0xf4, 0xff, 0xf4, 0xff, 0xa9, 0xff, 0x88, 0xfe, 0x40, 0xfd, 0xe3, 0xfc, 0x95, 0xfc, 0xb0, 0xfc, 0x0c, 0xfd, 0xfe, 0xfc, 0x33, 0xfc, 0x69, 0xfc, 0x59, 0xfc, 0x47, 0xfc, 0x79, 0xfc, 0x30, 0xfc, 0xa4, 0xfc, 0xa5, 0xfd, 0xe4, 0xfe, 0xe6, 0xff, 0xfd, 0xff, 0xf9, 0xff, 0x21, 0x00, 0x63, 0x00, 0xa1, 0x00, 0x99, 0x00, 0xce, 0x00, 0x16, 0x01, 0xa6, 0x01, 0xff, 0x01, 0x15, 0x02, 0x5d, 0x02, 0x52, 0x02, 0x26, 0x02, 0x03, 0x02, 0xe3, 0x01, 0x8a, 0x00, 0xfa, 0xfe, 0xe2, 0xfd, 0x3e, 0xfd, 0x4e, 0xfd, 0x30, 0xfd, 0x1f, 0xfd, 0x09, 0xfd, 0xdf, 0xfd, 0x97, 0xfe, 0x1a, 0xff, 0x9e, 0xff, 0xbd, 0xff, 0x5b, 0x00, 0x68, 0x00, 0x59, 0x00, 0x12, 0x00, 0x01, 0x00, 0x1e, 0x00, 0xf6, 0xff, 0xea, 0xff, 0x91, 0xff, 0x42, 0xff, 0x3b, 0xff, 0x29, 0x00, 0x2f, 0x01, 0x67, 0x02, 0xc8, 0x02, 0x2b, 0x02, 0x25, 0x01, 0x07, 0x00, 0xcf, 0xfe, 0xee, 0xfc, 0xec, 0xfb, 0x1e, 0xfc, 0x39, 0xfc, 0x67, 0xfc, 0x4c, 0xfc, 0x72, 0xfc, 0x1c, 0xfd, 0x5e, 0xfe, 0xf1, 0xff, 0x37, 0x01, 0x2f, 0x02, 0x2b, 0x03, 0x62, 0x04, 0x5c, 0x05, 0xed, 0x05, 0x53, 0x06, 0xf3, 0x05, 0xe2, 0x04, 0xdf, 0x03, 0x2c, 0x03, 0x8c, 0x02, 0x49, 0x02, 0x6e, 0x01, 0x2f, 0x00, 0xa3, 0xff, 0xab, 0xff, 0x96, 0xff, 0xd3, 0xfe, 0x35, 0xfe, 0x50, 0xfd, 0x59, 0xfc, 0x01, 0xfc, 0xbb, 0xfc, 0xee, 0xfc, 0x0e, 0xfc, 0x93, 0xfb, 0x0c, 0xfc, 0xd6, 0xfc, 0x03, 0xfe, 0xe8, 0xfe, 0x83, 0xff, 0xa9, 0x00, 0x98, 0x01, 0xfb, 0x01, 0x04, 0x03, 0x21, 0x04, 0x1b, 0x04, 0x7b, 0x03, 0x82, 0x03, 0x64, 0x03, 0x07, 0x03, 0xa5, 0x02, 0x80, 0x02, 0x1a, 0x02, 0x62, 0x01, 0x5c, 0x00, 0x9a, 0xff, 0x96, 0xff, 0x1b, 0xff, 0xa9, 0xfe, 0x4c, 0xfe, 0xf4, 0xfd, 0xdb, 0xfd, 0x8e, 0xfd, 0xdc, 0xfd, 0xc8, 0xfe, 0x4e, 0xff, 0x47, 0x00, 0xf7, 0x00, 0xd0, 0x00, 0xf4, 0x00, 0xc9, 0x00, 0x26, 0x00, 0x4f, 0x00, 0x3a, 0x00, 0xb4, 0xff, 0x28, 0xff, 0x73, 0xfe, 0x32, 0xfe, 0x76, 0xfd, 0x70, 0xfc, 0xf2, 0xfb, 0xdc, 0xfb, 0xf4, 0xfb, 0x35, 0xfc, 0x68, 0xfc, 0x1c, 0xfd, 0x65, 0xfe, 0x40, 0xff, 0x25, 0x00, 0x3e, 0x01, 0x7b, 0x02, 0x8a, 0x03, 0xf8, 0x03, 0x60, 0x03, 0x22, 0x03, 0x07, 0x02, 0xdf, 0x00, 0xb3, 0x00, 0xbd, 0x00, 0x33, 0x00, 0x12, 0xff, 0x9f, 0xfe, 0xec, 0xfd, 0xbb, 0xfc, 0xac, 0xfb, 0x9f, 0xfb, 0x18, 0xfc, 0xa8, 0xfc, 0x5a, 0xfd, 0xf7, 0xfd, 0xd9, 0xfe, 0x0a, 0xff, 0xd9, 0xfe, 0x05, 0xff, 0x79, 0xff, 0x70, 0x00, 0x66, 0x01, 0x28, 0x02, 0x5e, 0x03, 0x97, 0x04, 0xbc, 0x04, 0xa9, 0x04, 0xfe, 0x04, 0x9c, 0x05, 0x98, 0x05, 0x63, 0x05, 0x7f, 0x04, 0xe1, 0x02, 0xfc, 0x01, 0xe4, 0x00, 0xf6, 0xff, 0x9c, 0xff, 0xf1, 0xff, 0x73, 0x00, 0x6a, 0x00, 0x74, 0x00, 0xf2, 0xff, 0xcf, 0xfe, 0x37, 0xfe, 0x59, 0xfd, 0xe0, 0xfc, 0x0f, 0xfd, 0x0f, 0xfd, 0x45, 0xfd, 0x3f, 0xfd, 0xbb, 0xfd, 0x10, 0xfe, 0xce, 0xfd, 0x5a, 0xfd, 0x27, 0xfd, 0xc3, 0xfd, 0x12, 0xfe, 0xca, 0xfe, 0x8d, 0xff, 0xab, 0xff, 0x8d, 0xff, 0x98, 0xff, 0x65, 0x00, 0x44, 0x01, 0xc2, 0x01, 0xce, 0x01, 0x19, 0x01, 0x9b, 0x00, 0x5c, 0x00, 0xe7, 0xff, 0x52, 0xff, 0x8d, 0xfe, 0x2a, 0xfe, 0x8e, 0xfd, 0xea, 0xfc, 0xc0, 0xfc, 0x7d, 0xfc, 0xaf, 0xfc, 0x3f, 0xfd, 0xad, 0xfd, 0xa5, 0xfe, 0x8e, 0xff, 0x62, 0x00, 0x07, 0x01, 0xaf, 0x01, 0xd4, 0x02, 0xd5, 0x03, 0xae, 0x04, 0x01, 0x05, 0xbd, 0x04, 0xfd, 0x03, 0xa0, 0x02, 0x9d, 0x01, 0xf4, 0x00, 0xb1, 0x00, 0x9f, 0x00, 0xb3, 0x00, 0xee, 0x00, 0x2f, 0x01, 0xa1, 0x00, 0x0c, 0x00, 0x4e, 0xff, 0xbf, 0xfe, 0x77, 0xfe, 0xa7, 0xfd, 0xd1, 0xfc, 0x5c, 0xfc, 0xc9, 0xfb, 0x1c, 0xfb, 0xb5, 0xfa, 0xfb, 0xfa, 0x74, 0xfb, 0x2d, 0xfc, 0x62, 0xfd, 0x31, 0xfe, 0xba, 0xfe, 0xa1, 0xff, 0x85, 0x00, 0x1f, 0x01, 0x9d, 0x01, 0xd7, 0x01, 0x5b, 0x02, 0xb4, 0x02, 0x47, 0x03, 0xfc, 0x02, 0xc4, 0x02, 0x37, 0x03, 0x14, 0x04, 0xc2, 0x04, 0xec, 0x04, 0xa6, 0x04, 0x54, 0x04, 0x7b, 0x04, 0xbb, 0x04, 0x05, 0x04, 0x33, 0x03, 0xc3, 0x02, 0x5f, 0x01, 0x46, 0x00, 0x2b, 0xff, 0xc6, 0xfd, 0xe7, 0xfc, 0x8e, 0xfc, 0x68, 0xfc, 0xbf, 0xfb, 0x18, 0xfb, 0xb2, 0xfa, 0x10, 0xfb, 0x93, 0xfb, 0x88, 0xfb, 0xab, 0xfb, 0xed, 0xfb, 0xfd, 0xfc, 0xa8, 0xfd, 0xaf, 0xfe, 0x93, 0x00, 0x33, 0x02, 0xe5, 0x03, 0xcc, 0x04, 0x60, 0x05, 0x18, 0x06, 0x3a, 0x06, 0xcd, 0x05, 0x95, 0x05, 0x83, 0x05, 0xbb, 0x04, 0x22, 0x03, 0x24, 0x01, 0xb2, 0xff, 0x25, 0xff, 0xff, 0xfe, 0xe1, 0xfe, 0x92, 0xfe, 0x3b, 0xfe, 0xd9, 0xfd, 0x18, 0xfd, 0xa6, 0xfc, 0xcc, 0xfb, 0x22, 0xfb, 0x2d, 0xfb, 0xcb, 0xfa, 0xa1, 0xfa, 0xd5, 0xfa, 0x0d, 0xfb, 0xa7, 0xfb, 0x6c, 0xfc, 0x58, 0xfd, 0x40, 0xfe, 0x79, 0xfe, 0xb0, 0xfe, 0x97, 0xff, 0x12, 0x00, 0xaa, 0x00, 0x55, 0x01, 0x78, 0x01, 0x9a, 0x01, 0x8e, 0x01, 0xb6, 0x01, 0x1c, 0x02, 0x93, 0x02, 0xc2, 0x02, 0xfb, 0x02, 0xa3, 0x02, 0x72, 0x02, 0x4b, 0x02, 0xdc, 0x01, 0x17, 0x02, 0x3f, 0x02, 0x5e, 0x02, 0x32, 0x02, 0xf8, 0x01, 0xd6, 0x01, 0xda, 0x01, 0xe1, 0x01, 0xc2, 0x01, 0x51, 0x01, 0x92, 0x00, 0x6b, 0x00, 0x3f, 0x00, 0x01, 0x00, 0x7d, 0xff, 0x20, 0xff, 0xac, 0xfe, 0x69, 0xfd, 0x27, 0xfc, 0x7a, 0xfb, 0x02, 0xfb, 0x48, 0xfa, 0xa9, 0xf9, 0x89, 0xf9, 0xa7, 0xf9, 0xed, 0xf9, 0x25, 0xfa, 0xa6, 0xfa, 0xa8, 0xfb, 0xc7, 0xfc, 0x90, 0xfd, 0x81, 0xfe, 0x66, 0xff, 0x06, 0x00, 0xab, 0x00, 0x92, 0x01, 0x66, 0x02, 0x34, 0x03, 0xfb, 0x03, 0x6f, 0x04, 0xe9, 0x04, 0x41, 0x05, 0x06, 0x05, 0xb9, 0x04, 0x86, 0x04, 0x67, 0x04, 0x29, 0x05, 0xfb, 0x05, 0xce, 0x05, 0x98, 0x05, 0xf6, 0x04, 0x26, 0x04, 0x48, 0x03, 0xae, 0x02, 0xa5, 0x02, 0x25, 0x02, 0x26, 0x01, 0x6e, 0x00, 0xcc, 0xff, 0xef, 0xfe, 0x72, 0xfe, 0xae, 0xfd, 0xc2, 0xfc, 0xbe, 0xfb, 0x50, 0xfb, 0x1e, 0xfb, 0xab, 0xfa, 0xa7, 0xfa, 0x98, 0xfa, 0xd9, 0xfa, 0x07, 0xfb, 0x77, 0xfb, 0xc2, 0xfb, 0x22, 0xfc, 0xf4, 0xfc, 0x92, 0xfd, 0xf6, 0xfd, 0xb7, 0xfe, 0x3f, 0xff, 0x5a, 0xff, 0xf3, 0xff, 0x70, 0x00, 0xe2, 0x00, 0x94, 0x01, 0x67, 0x02, 0xd6, 0x02, 0x23, 0x03, 0x8c, 0x03, 0xba, 0x03, 0xed, 0x03, 0x3d, 0x04, 0x2f, 0x04, 0x18, 0x04, 0x31, 0x04, 0x8c, 0x04, 0x94, 0x04, 0xe5, 0x03, 0xf7, 0x02, 0xc5, 0x01, 0x18, 0x01, 0x38, 0x00, 0xf1, 0xfe, 0x21, 0xfe, 0x6e, 0xfd, 0x00, 0xfd, 0xc5, 0xfd, 0x8f, 0xfe, 0xbc, 0xfe, 0xcd, 0xfe, 0xf6, 0xfe, 0xe7, 0xfe, 0xc5, 0xfe, 0x70, 0xfe, 0xe5, 0xfd, 0x8b, 0xfd, 0x50, 0xfd, 0x55, 0xfd, 0x76, 0xfd, 0x71, 0xfd, 0x50, 0xfd, 0x42, 0xfd, 0x67, 0xfd, 0x99, 0xfd, 0x8e, 0xfd, 0x58, 0xfd, 0x45, 0xfd, 0xc0, 0xfd, 0x67, 0xfe, 0x54, 0xfe, 0xbf, 0xfe, 0x74, 0xff, 0x3b, 0x00, 0xf2, 0x00, 0x65, 0x01, 0xc5, 0x01, 0xeb, 0x01, 0x7b, 0x01, 0x26, 0x01, 0xf5, 0x00, 0xf1, 0x00, 0x3d, 0x01, 0x2b, 0x01, 0xcd, 0x00, 0xc3, 0xff, 0xbd, 0xfe, 0x53, 0xfe, 0x83, 0xfe, 0x7e, 0xfe, 0x6b, 0xfe, 0x85, 0xfe, 0x1f, 0xfe, 0xd0, 0xfd, 0xa0, 0xfd, 0x90, 0xfd, 0x2e, 0xfe, 0xd5, 0xfe, 0x97, 0xff, 0x8c, 0x00, 0x78, 0x01, 0x34, 0x02, 0xd5, 0x02, 0x72, 0x03, 0xe6, 0x03, 0x1b, 0x04, 0x50, 0x04, 0x37, 0x04, 0xf5, 0x03, 0xf3, 0x03, 0x62, 0x03, 0xaa, 0x02, 0xd1, 0x01, 0xf7, 0x00, 0x30, 0x00, 0xc4, 0xff, 0x66, 0xff, 0x29, 0xff, 0xf2, 0xfe, 0xf2, 0xfe, 0xe5, 0xfe, 0x47, 0xff, 0xab, 0xff, 0xa9, 0xff, 0xa5, 0xff, 0xd4, 0xff, 0x3b, 0x00, 0x0a, 0x00, 0x80, 0xff, 0x9a, 0xff, 0xfb, 0xff, 0x61, 0x00, 0xf9, 0x00, 0x9b, 0x01, 0x78, 0x01, 0x03, 0x01, 0x8c, 0x00, 0xf6, 0xff, 0x5a, 0xff, 0xd1, 0xfe, 0x5d, 0xfe, 0xea, 0xfd, 0xb0, 0xfd, 0x47, 0xfd, 0x0b, 0xfd, 0xc3, 0xfc, 0x7f, 0xfc, 0xb1, 0xfc, 0xc4, 0xfc, 0x97, 0xfc, 0x4f, 0xfc, 0x55, 0xfc, 0xaa, 0xfc, 0x8a, 0xfd, 0x0c, 0xfe, 0x34, 0xfe, 0x4a, 0xfe, 0x89, 0xfe, 0xe1, 0xfe, 0x2f, 0xff, 0xa5, 0xff, 0x92, 0x00, 0x91, 0x01, 0x2c, 0x02, 0xb0, 0x02, 0xf1, 0x02, 0xe7, 0x02, 0x9c, 0x02, 0x9b, 0x02, 0x1a, 0x03, 0xf1, 0x03, 0x73, 0x04, 0x6c, 0x04, 0x93, 0x04, 0x8e, 0x04, 0xf0, 0x03, 0x66, 0x03, 0xc0, 0x02, 0x19, 0x02, 0x44, 0x01, 0x6c, 0x00, 0xe4, 0xff, 0x5c, 0xff, 0x16, 0xff, 0xbe, 0xfe, 0x4b, 0xfe, 0xef, 0xfd, 0x9d, 0xfd, 0x0a, 0xfd, 0x98, 0xfc, 0x3e, 0xfc, 0x23, 0xfc, 0x0a, 0xfc, 0x0b, 0xfc, 0x9b, 0xfc, 0x36, 0xfd, 0xb9, 0xfd, 0x11, 0xfe, 0x20, 0xfe, 0x69, 0xfe, 0xc2, 0xfe, 0x43, 0xff, 0xa8, 0xff, 0x2e, 0x00, 0xc2, 0x00, 0xb9, 0x00, 0x02, 0x01, 0xb2, 0x01, 0x68, 0x02, 0x6f, 0x02, 0x11, 0x02, 0x34, 0x02, 0x52, 0x02, 0x10, 0x02, 0xd5, 0x01, 0x6f, 0x01, 0x27, 0x01, 0xdf, 0x00, 0x86, 0x00, 0x9e, 0x00, 0x90, 0x00, 0x60, 0x00, 0x84, 0x00, 0x18, 0x01, 0x95, 0x01, 0xeb, 0x01, 0x18, 0x02, 0x8a, 0x01, 0x2b, 0x01, 0xd7, 0x00, 0x99, 0x00, 0x8c, 0x00, 0xb7, 0x00, 0xce, 0x00, 0x95, 0x00, 0xfb, 0xff, 0x48, 0xff, 0xf6, 0xfe, 0x38, 0xff, 0x80, 0xff, 0xa1, 0xff, 0x6e, 0xff, 0xd8, 0xfe, 0x5d, 0xfe, 0x04, 0xfe, 0xcb, 0xfd, 0xad, 0xfd, 0x98, 0xfd, 0x54, 0xfd, 0x6e, 0xfd, 0x94, 0xfd, 0xa7, 0xfd, 0xd7, 0xfd, 0xf6, 0xfd, 0x3e, 0xfe, 0xdb, 0xfe, 0x9b, 0xff, 0xd1, 0xff, 0xbb, 0xff, 0xa7, 0xff, 0xc2, 0xff, 0x2b, 0x00, 0x9c, 0x00, 0xd7, 0x00, 0x0b, 0x01, 0xe9, 0x00, 0x90, 0x00, 0xf5, 0x00, 0x6f, 0x01, 0x62, 0x01, 0xba, 0x01, 0x3a, 0x02, 0x91, 0x02, 0x97, 0x02, 0x4d, 0x02, 0x00, 0x02, 0xa8, 0x01, 0x6e, 0x01, 0xe0, 0x00, 0x5e, 0x00, 0x8f, 0xff, 0x0a, 0xff, 0xd1, 0xfe, 0x72, 0xfe, 0xeb, 0xfd, 0x87, 0xfd, 0x50, 0xfd, 0x45, 0xfd, 0x7a, 0xfd, 0x60, 0xfd, 0x44, 0xfd, 0x34, 0xfd, 0x77, 0xfd, 0x95, 0xfd, 0xc8, 0xfd, 0x55, 0xfe, 0xe6, 0xfe, 0x5e, 0xff, 0xc5, 0xff, 0x14, 0x00, 0xa9, 0x00, 0x93, 0x01, 0x40, 0x02, 0x39, 0x02, 0x93, 0x01, 0xd0, 0x00, 0x6d, 0x00, 0x60, 0x00, 0x4a, 0x00, 0x7a, 0x00, 0x2d, 0x00, 0xd6, 0xff, 0x02, 0x00, 0x74, 0x00, 0x0b, 0x01, 0x9e, 0x01, 0x22, 0x02, 0x12, 0x02, 0xee, 0x01, 0xef, 0x01, 0xb0, 0x01, 0x6e, 0x01, 0x1f, 0x01, 0x42, 0x01, 0x66, 0x01, 0x8a, 0x01, 0xad, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x9e, 0xff, 0x16, 0xff, 0xea, 0xfe, 0xd6, 0xfe, 0xb6, 0xfe, 0x2c, 0xfe, 0xc7, 0xfd, 0x0b, 0xfe, 0x3e, 0xfe, 0x16, 0xfe, 0x00, 0xfe, 0x25, 0xfe, 0x30, 0xfe, 0x1a, 0xfe, 0x6f, 0xfe, 0x5c, 0xfe, 0x2a, 0xfe, 0xf4, 0xfd, 0xf6, 0xfd, 0x6a, 0xfe, 0xb5, 0xfe, 0x22, 0xff, 0x9e, 0xff, 0x06, 0x00, 0x3b, 0x00, 0x67, 0x00, 0xd5, 0x00, 0x5c, 0x01, 0xc9, 0x01, 0x8d, 0x02, 0x2a, 0x03, 0x5a, 0x03, 0x36, 0x03, 0xd5, 0x02, 0x70, 0x02, 0x07, 0x02, 0x8d, 0x01, 0x0c, 0x01, 0xba, 0x00, 0x67, 0x00, 0x36, 0x00, 0xf0, 0xff, 0xcc, 0xff, 0xc5, 0xff, 0xfb, 0xfe, 0x97, 0xfe, 0xab, 0xfe, 0x3f, 0xfe, 0xdc, 0xfd, 0xf1, 0xfd, 0xc2, 0xfe, 0xb3, 0xff, 0x75, 0x00, 0xee, 0x00, 0x81, 0x01, 0xd1, 0x01, 0xf1, 0x01, 0xca, 0x01, 0x4f, 0x01, 0xd5, 0x00, 0x8a, 0x00, 0x45, 0x00, 0xb1, 0xff, 0x44, 0xff, 0x45, 0xff, 0x7d, 0xff, 0x72, 0xff, 0x2a, 0xff, 0x1f, 0xff, 0x1c, 0xff, 0x11, 0xff, 0xe8, 0xfe, 0xbc, 0xfe, 0xcb, 0xfe, 0xe4, 0xfe, 0x1a, 0xff, 0x73, 0xff, 0x07, 0x00, 0x92, 0x00, 0xd9, 0x00, 0xd8, 0x00, 0x9f, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x53, 0x00, 0x07, 0x00, 0x40, 0x00, 0xbc, 0x00, 0xd5, 0x00, 0xc5, 0x00, 0xdf, 0x00, 0x20, 0x01, 0x00, 0x01, 0xd3, 0x00, 0xa4, 0x00, 0x77, 0x00, 0x62, 0x00, 0x1b, 0x00, 0xc5, 0xff, 0x19, 0xff, 0x87, 0xfe, 0xf4, 0xfd, 0x72, 0xfd, 0x34, 0xfd, 0xe3, 0xfc, 0x89, 0xfc, 0xc0, 0xfc, 0x42, 0xfd, 0x85, 0xfd, 0xee, 0xfd, 0x39, 0xfe, 0xcb, 0xfe, 0x8b, 0xff, 0x2f, 0x00, 0x99, 0x00, 0xa7, 0x00, 0x82, 0x00, 0xb5, 0xff, 0x23, 0xff, 0x03, 0xff, 0x02, 0xff, 0x1d, 0xff, 0x69, 0xff, 0xb4, 0xff, 0xbc, 0xff, 0x0e, 0x00, 0xbf, 0x00, 0x55, 0x01, 0xfd, 0x01, 0x9b, 0x02, 0x27, 0x03, 0x4a, 0x03, 0x04, 0x03, 0xb9, 0x02, 0x45, 0x02, 0x81, 0x01, 0xe5, 0x00, 0x38, 0x00, 0xea, 0xff, 0xf1, 0xff, 0xe5, 0xff, 0x02, 0x00, 0xf1, 0xff, 0x0b, 0x00, 0x20, 0x00, 0x25, 0x00, 0x1b, 0x00, 0xc8, 0xff, 0x6a, 0xff, 0x0a, 0xff, 0xf6, 0xfe, 0x32, 0xff, 0x4a, 0xff, 0xb2, 0xff, 0x34, 0x00, 0x5e, 0x00, 0x8c, 0x00, 0x97, 0x00, 0x80, 0x00, 0x67, 0x00, 0x42, 0x00, 0x2c, 0x00, 0x74, 0x00, 0x94, 0x00, 0x79, 0x00, 0x93, 0x00, 0x01, 0x01, 0x1b, 0x01, 0x0e, 0x01, 0xf5, 0x00, 0x83, 0x00, 0x1e, 0x00, 0xb9, 0xff, 0x32, 0xff, 0x9e, 0xfe, 0x21, 0xfe, 0x03, 0xfe, 0x14, 0xfe, 0x3d, 0xfe, 0x85, 0xfe, 0xe7, 0xfe, 0x00, 0xff, 0xd5, 0xfe, 0x70, 0xfe, 0x25, 0xfe, 0xa1, 0xfd, 0x0f, 0xfd, 0xe4, 0xfc, 0xa7, 0xfc, 0x74, 0xfc, 0x87, 0xfc, 0xca, 0xfc, 0x5c, 0xfd, 0x3e, 0xfe, 0x5e, 0xff, 0xa8, 0x00, 0xa6, 0x01, 0xb1, 0x02, 0xaa, 0x03, 0x62, 0x04, 0x92, 0x04, 0x84, 0x04, 0x7c, 0x04, 0x31, 0x04, 0xa8, 0x03, 0x2c, 0x03, 0xf5, 0x02, 0xea, 0x02, 0x8b, 0x02, 0x4b, 0x02, 0x22, 0x02, 0xda, 0x01, 0xcd, 0x01, 0xaa, 0x01, 0x37, 0x01, 0x96, 0x00, 0xe6, 0xff, 0x0e, 0xff, 0x7f, 0xfe, 0x20, 0xfe, 0xa8, 0xfd, 0xa2, 0xfd, 0xc0, 0xfd, 0xa4, 0xfd, 0x51, 0xfd, 0xc3, 0xfc, 0x92, 0xfc, 0x6c, 0xfc, 0x39, 0xfc, 0x93, 0xfc, 0x3e, 0xfd, 0x00, 0xfe, 0xe0, 0xfe, 0xe1, 0xff, 0x91, 0x00, 0x19, 0x01, 0xab, 0x01, 0x34, 0x02, 0x63, 0x02, 0x83, 0x02, 0xa0, 0x02, 0x73, 0x02, 0xde, 0x01, 0x2c, 0x01, 0x9e, 0x00, 0x0f, 0x00, 0xc0, 0xff, 0x6d, 0xff, 0x3b, 0xff, 0x2f, 0xff, 0x60, 0xff, 0x64, 0xff, 0x55, 0xff, 0x7b, 0xff, 0x9c, 0xff, 0x8b, 0xff, 0x32, 0xff, 0xbb, 0xfe, 0xce, 0xfe, 0xfb, 0xfe, 0x2c, 0xff, 0x68, 0xff, 0xc9, 0xff, 0x23, 0x00, 0x4b, 0x00, 0x55, 0x00, 0xa0, 0x00, 0xef, 0x00, 0x33, 0x01, 0x98, 0x01, 0x43, 0x02, 0xf9, 0x02, 0x45, 0x03, 0x22, 0x03, 0xf5, 0x02, 0xb9, 0x02, 0x78, 0x02, 0x24, 0x02, 0xb2, 0x01, 0x4a, 0x01, 0xf0, 0x00, 0x3f, 0x00, 0x77, 0xff, 0xd5, 0xfe, 0x24, 0xfe, 0x95, 0xfd, 0x44, 0xfd, 0xce, 0xfc, 0x22, 0xfc, 0xad, 0xfb, 0x8a, 0xfb, 0x7e, 0xfb, 0x90, 0xfb, 0x79, 0xfb, 0x66, 0xfb, 0xdc, 0xfb, 0x65, 0xfc, 0x0f, 0xfd, 0xac, 0xfd, 0x33, 0xfe, 0xa6, 0xfe, 0x4b, 0xff, 0xd9, 0xff, 0x28, 0x00, 0x98, 0x00, 0x18, 0x01, 0xc6, 0x01, 0xb3, 0x02, 0x61, 0x03, 0xa5, 0x03, 0xfb, 0x03, 0xcd, 0x04, 0xc3, 0x05, 0x74, 0x06, 0x39, 0x07, 0x9b, 0x07, 0x98, 0x07, 0x1f, 0x07, 0x7b, 0x06, 0xaf, 0x05, 0xf9, 0x04, 0xb5, 0x04, 0xe9, 0x03, 0xba, 0x02, 0x09, 0x01, 0x5c, 0xff, 0xcf, 0xfd, 0x8a, 0xfc, 0x82, 0xfb, 0xc3, 0xfa, 0x4a, 0xfa, 0xcf, 0xf9, 0xaa, 0xf9, 0xd0, 0xf9, 0x41, 0xfa, 0xbe, 0xfa, 0xc9, 0xfa, 0xb7, 0xfa, 0xad, 0xfa, 0xc4, 0xfa, 0x13, 0xfb, 0x88, 0xfb, 0x2c, 0xfc, 0x6e, 0xfc, 0xd0, 0xfc, 0x4d, 0xfd, 0xfe, 0xfd, 0xae, 0xfe, 0x48, 0xff, 0x03, 0x00, 0x9c, 0x00, 0x69, 0x01, 0xea, 0x01, 0x77, 0x02, 0x4b, 0x03, 0xfc, 0x03, 0x74, 0x04, 0xa9, 0x04, 0x27, 0x05, 0xab, 0x05, 0xe6, 0x05, 0x7f, 0x05, 0xdc, 0x04, 0x35, 0x04, 0x99, 0x03, 0x98, 0x02, 0x88, 0x01, 0xfa, 0x00, 0x96, 0x00, 0xf0, 0xff, 0x93, 0xff, 0x49, 0xff, 0x19, 0xff, 0x07, 0xff, 0xcd, 0xfe, 0x71, 0xfe, 0xdc, 0xfd, 0x8c, 0xfd, 0x28, 0xfd, 0xf3, 0xfc, 0x0e, 0xfd, 0x80, 0xfd, 0xed, 0xfd, 0x09, 0xfe, 0x2e, 0xfe, 0x5b, 0xfe, 0x61, 0xfe, 0x76, 0xfe, 0xa4, 0xfe, 0xec, 0xfe, 0x5f, 0xff, 0xa6, 0xff, 0xe0, 0xff, 0x09, 0x00, 0xf1, 0xff, 0xa4, 0xff, 0x46, 0xff, 0xf7, 0xfe, 0x86, 0xfe, 0x7a, 0xfe, 0x70, 0xfe, 0xba, 0xfe, 0x27, 0xff, 0xab, 0xff, 0x30, 0x00, 0xab, 0x00, 0x6a, 0x01, 0x28, 0x02, 0xbf, 0x02, 0x3d, 0x03, 0x66, 0x03, 0x8c, 0x03, 0xa2, 0x03, 0x6e, 0x03, 0x5f, 0x03, 0x68, 0x03, 0x17, 0x03, 0x7d, 0x02, 0xdb, 0x01, 0x0b, 0x01, 0x66, 0x00, 0xd5, 0xff, 0x38, 0xff, 0x8e, 0xfe, 0xf3, 0xfd, 0x92, 0xfd, 0x5b, 0xfd, 0x96, 0xfd, 0xb8, 0xfd, 0x84, 0xfd, 0x1c, 0xfd, 0xc5, 0xfc, 0xcb, 0xfc, 0xe4, 0xfc, 0x26, 0xfd, 0x7f, 0xfd, 0x94, 0xfd, 0x98, 0xfd, 0xef, 0xfd, 0x2c, 0xfe, 0x48, 0xfe, 0x95, 0xfe, 0xe1, 0xfe, 0x62, 0xff, 0xb9, 0xff, 0xd7, 0xff, 0x18, 0x00, 0x68, 0x00, 0xb6, 0x00, 0x05, 0x01, 0x2b, 0x01, 0x49, 0x01, 0x62, 0x01, 0x6e, 0x01, 0x2a, 0x01, 0xf8, 0x00, 0xdb, 0x00, 0xe7, 0x00, 0x2d, 0x01, 0x3c, 0x01, 0x1f, 0x01, 0x04, 0x01, 0x1b, 0x01, 0x0b, 0x01, 0xa6, 0x00, 0x7d, 0x00, 0x27, 0x00, 0xec, 0xff, 0xde, 0xff, 0xa2, 0xff, 0x4f, 0xff, 0x10, 0xff, 0xc9, 0xfe, 0xcd, 0xfe, 0xe6, 0xfe, 0x22, 0xff, 0x4f, 0xff, 0x95, 0xff, 0xdf, 0xff, 0x05, 0x00, 0x07, 0x00, 0xe0, 0xff, 0xbd, 0xff, 0xb6, 0xff, 0x7f, 0xff, 0x63, 0xff, 0x8a, 0xff, 0xff, 0xff, 0xa7, 0x00, 0x76, 0x01, 0x6b, 0x02, 0x55, 0x03, 0xf5, 0x03, 0x49, 0x04, 0xa5, 0x04, 0xe2, 0x04, 0xab, 0x04, 0xf7, 0x03, 0x5a, 0x03, 0xf8, 0x02, 0x42, 0x02, 0x4c, 0x01, 0x86, 0x00, 0xd7, 0xff, 0x23, 0xff, 0x8f, 0xfe, 0x12, 0xfe, 0xa7, 0xfd, 0x7b, 0xfd, 0x7a, 0xfd, 0xa5, 0xfd, 0xdc, 0xfd, 0x22, 0xfe, 0x93, 0xfe, 0xee, 0xfe, 0xc3, 0xfe, 0x63, 0xfe, 0xcf, 0xfd, 0x3a, 0xfd, 0xbe, 0xfc, 0x60, 0xfc, 0x5e, 0xfc, 0x7b, 0xfc, 0x01, 0xfd, 0xbb, 0xfd, 0x4a, 0xfe, 0x93, 0xfe, 0x20, 0xff, 0x87, 0xff, 0xb3, 0xff, 0xa8, 0xff, 0x8f, 0xff, 0x48, 0xff, 0x15, 0xff, 0xfe, 0xfe, 0x0f, 0xff, 0x6b, 0xff, 0xf6, 0xff, 0x93, 0x00, 0x54, 0x01, 0x43, 0x02, 0x5c, 0x03, 0x41, 0x04, 0xb0, 0x04, 0xed, 0x04, 0x95, 0x04, 0x05, 0x04, 0x70, 0x03, 0xec, 0x02, 0x5d, 0x02, 0xcb, 0x01, 0x51, 0x01, 0xff, 0x00, 0x59, 0x00, 0x98, 0xff, 0xed, 0xfe, 0xae, 0xfe, 0x6e, 0xfe, 0x16, 0xfe, 0xf4, 0xfd, 0xf3, 0xfd, 0xf6, 0xfd, 0x46, 0xfe, 0xb2, 0xfe, 0x09, 0xff, 0x58, 0xff, 0xa3, 0xff, 0xed, 0xff, 0xe6, 0xff, 0xb6, 0xff, 0x94, 0xff, 0x49, 0xff, 0xc3, 0xfe, 0x98, 0xfe, 0x90, 0xfe, 0x79, 0xfe, 0x6a, 0xfe, 0x5e, 0xfe, 0x91, 0xfe, 0xce, 0xfe, 0x60, 0xff, 0xcd, 0xff, 0xd9, 0xff, 0xee, 0xff, 0x1f, 0x00, 0x1c, 0x00, 0x46, 0x00, 0xa4, 0x00, 0xdb, 0x00, 0x16, 0x01, 0x2a, 0x01, 0x05, 0x01, 0xac, 0x00, 0x4a, 0x00, 0xdf, 0xff, 0xd5, 0xff, 0x09, 0x00, 0x2b, 0x00, 0x32, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x19, 0x00, 0xd8, 0xff, 0xa0, 0xff, 0x89, 0xff, 0x9c, 0xff, 0x98, 0xff, 0xad, 0xff, 0x92, 0xff, 0x2b, 0xff, 0xe7, 0xfe, 0x13, 0xff, 0x23, 0xff, 0xef, 0xfe, 0xd0, 0xfe, 0xf8, 0xfe, 0x0b, 0xff, 0x14, 0xff, 0x71, 0xff, 0x18, 0x00, 0xc4, 0x00, 0x70, 0x01, 0xf0, 0x01, 0x53, 0x02, 0x28, 0x02, 0xe5, 0x01, 0x87, 0x01, 0x04, 0x01, 0xbe, 0x00, 0xc1, 0x00, 0xc8, 0x00, 0xa8, 0x00, 0x5a, 0x00, 0xec, 0xff, 0xc4, 0xff, 0xc7, 0xff, 0xe8, 0xff, 0x16, 0x00, 0x66, 0x00, 0xb6, 0x00, 0xc4, 0x00, 0xe6, 0x00, 0xf5, 0x00, 0xfd, 0x00, 0xcd, 0x00, 0x6c, 0x00, 0xea, 0xff, 0x5c, 0xff, 0xde, 0xfe, 0x8e, 0xfe, 0x61, 0xfe, 0x2a, 0xfe, 0xcf, 0xfd, 0x98, 0xfd, 0x84, 0xfd, 0x5b, 0xfd, 0x41, 0xfd, 0x29, 0xfd, 0x30, 0xfd, 0x70, 0xfd, 0xd7, 0xfd, 0x3a, 0xfe, 0x31, 0xfe, 0x72, 0xfe, 0xfd, 0xfe, 0x9a, 0xff, 0x5b, 0x00, 0x30, 0x01, 0x0f, 0x02, 0x9a, 0x02, 0xe4, 0x02, 0xd2, 0x02, 0xa5, 0x02, 0x6c, 0x02, 0x31, 0x02, 0x35, 0x02, 0x17, 0x02, 0xb0, 0x01, 0x3d, 0x01, 0xdb, 0x00, 0x88, 0x00, 0x38, 0x00, 0xf7, 0xff, 0x73, 0xff, 0x3f, 0xff, 0x0b, 0xff, 0xe9, 0xfe, 0x0d, 0xff, 0x43, 0xff, 0x75, 0xff, 0xa5, 0xff, 0xd7, 0xff, 0x75, 0x00, 0x3f, 0x01, 0xcd, 0x01, 0xfa, 0x01, 0xc0, 0x01, 0x3a, 0x01, 0xbf, 0x00, 0x51, 0x00, 0xff, 0xff, 0xb7, 0xff, 0x45, 0xff, 0xa8, 0xfe, 0x18, 0xfe, 0x9e, 0xfd, 0x57, 0xfd, 0x33, 0xfd, 0x2e, 0xfd, 0x83, 0xfd, 0xf8, 0xfd, 0x7e, 0xfe, 0xe3, 0xfe, 0x09, 0xff, 0x09, 0xff, 0x5a, 0xff, 0xe3, 0xff, 0x2a, 0x00, 0xb9, 0x00, 0x44, 0x01, 0xd5, 0x01, 0xed, 0x01, 0x0b, 0x02, 0xfa, 0x01, 0x90, 0x01, 0x28, 0x01, 0xf1, 0x00, 0x12, 0x01, 0x30, 0x01, 0x18, 0x01, 0x87, 0x00, 0x49, 0x00, 0x2a, 0x00, 0x04, 0x00, 0x24, 0x00, 0x37, 0x00, 0x54, 0x00, 0x5d, 0x00, 0x41, 0x00, 0x52, 0x00, 0x5c, 0x00, 0x35, 0x00, 0xf6, 0xff, 0xbe, 0xff, 0xd3, 0xff, 0x21, 0x00, 0x63, 0x00, 0x69, 0x00, 0x2a, 0x00, 0xe3, 0xff, 0x92, 0xff, 0x80, 0xff, 0xb9, 0xff, 0xc4, 0xff, 0x96, 0xff, 0x39, 0xff, 0xe1, 0xfe, 0xb1, 0xfe, 0xbd, 0xfe, 0xf5, 0xfe, 0x50, 0xff, 0xcc, 0xff, 0x4d, 0x00, 0x72, 0x00, 0x24, 0x00, 0xc3, 0xff, 0x6e, 0xff, 0x45, 0xff, 0x2b, 0xff, 0x26, 0xff, 0x52, 0xff, 0x8d, 0xff, 0xe9, 0xff, 0x31, 0x00, 0x84, 0x00, 0xf9, 0x00, 0x53, 0x01, 0x70, 0x01, 0x42, 0x01, 0xeb, 0x00, 0x90, 0x00, 0x3e, 0x00, 0x31, 0x00, 0x50, 0x00, 0x7b, 0x00, 0x5d, 0x00, 0x8b, 0x00, 0xb2, 0x00, 0xdd, 0x00, 0x67, 0x01, 0xcc, 0x01, 0xbf, 0x01, 0x7e, 0x01, 0x48, 0x01, 0x0e, 0x01, 0xdf, 0x00, 0x7b, 0x00, 0xf7, 0xff, 0x98, 0xff, 0x0a, 0xff, 0x8e, 0xfe, 0x61, 0xfe, 0x81, 0xfe, 0x9f, 0xfe, 0x9f, 0xfe, 0xa3, 0xfe, 0x90, 0xfe, 0x79, 0xfe, 0x53, 0xfe, 0x49, 0xfe, 0x39, 0xfe, 0x50, 0xfe, 0x44, 0xfe, 0x7f, 0xfe, 0xb1, 0xfe, 0xee, 0xfe, 0x2e, 0xff, 0x50, 0xff, 0xa1, 0xff, 0xa6, 0xff, 0x7f, 0xff, 0x47, 0xff, 0x53, 0xff, 0x69, 0xff, 0x70, 0xff, 0x8d, 0xff, 0xb9, 0xff, 0x01, 0x00, 0x84, 0x00, 0xea, 0x00, 0x5d, 0x01, 0xeb, 0x01, 0x7f, 0x02, 0x24, 0x03, 0xb0, 0x03, 0x15, 0x04, 0x2c, 0x04, 0x01, 0x04, 0xbf, 0x03, 0x75, 0x03, 0x05, 0x03, 0xac, 0x02, 0x1b, 0x02, 0x63, 0x01, 0xad, 0x00, 0xa3, 0xff, 0x79, 0xfe, 0x8f, 0xfd, 0xea, 0xfc, 0x4c, 0xfc, 0xd1, 0xfb, 0xbc, 0xfb, 0xab, 0xfb, 0xb0, 0xfb, 0xb4, 0xfb, 0xec, 0xfb, 0x2f, 0xfc, 0x61, 0xfc, 0xfd, 0xfc, 0xcd, 0xfd, 0x9a, 0xfe, 0x64, 0xff, 0x31, 0x00, 0xf5, 0x00, 0xb8, 0x01, 0x59, 0x02, 0xb3, 0x02, 0x09, 0x03, 0xc4, 0x02, 0x46, 0x02, 0xc3, 0x01, 0x5d, 0x01, 0xfc, 0x00, 0xcf, 0x00, 0xdc, 0x00, 0x1d, 0x01, 0x95, 0x01, 0xe9, 0x01, 0xfb, 0x01, 0xb8, 0x01, 0x9f, 0x01, 0x4d, 0x01, 0x04, 0x01, 0xe5, 0x00, 0xf7, 0x00, 0xd1, 0x00, 0x9b, 0x00, 0x3b, 0x00, 0xa8, 0xff, 0x33, 0xff, 0xd8, 0xfe, 0xf1, 0xfe, 0x2a, 0xff, 0x7d, 0xff, 0x91, 0xff, 0xac, 0xff, 0xb3, 0xff, 0x9a, 0xff, 0xaa, 0xff, 0xca, 0xff, 0xe8, 0xff, 0xb6, 0xff, 0x63, 0xff, 0x0a, 0xff, 0xf4, 0xfe, 0xfc, 0xfe, 0xf6, 0xfe, 0x1f, 0xff, 0x0b, 0xff, 0x0d, 0xff, 0x44, 0xff, 0x15, 0xff, 0xdd, 0xfe, 0xdd, 0xfe, 0x0d, 0xff, 0x75, 0xff, 0xe9, 0xff, 0x45, 0x00, 0x63, 0x00, 0x56, 0x00, 0x73, 0x00, 0x89, 0x00, 0xa1, 0x00, 0xc9, 0x00, 0xb6, 0x00, 0x7b, 0x00, 0x3b, 0x00, 0x21, 0x00, 0x1a, 0x00, 0x1b, 0x00, 0x12, 0x00, 0xfe, 0xff, 0xd7, 0xff, 0x87, 0xff, 0x70, 0xff, 0x66, 0xff, 0xff, 0xfe, 0xb6, 0xfe, 0x79, 0xfe, 0x1e, 0xfe, 0xdc, 0xfd, 0xf8, 0xfd, 0x3d, 0xfe, 0x83, 0xfe, 0xdd, 0xfe, 0x1b, 0xff, 0x5c, 0xff, 0x67, 0xff, 0xa3, 0xff, 0xfa, 0xff, 0x5a, 0x00, 0x48, 0x00, 0x23, 0x00, 0x42, 0x00, 0x7a, 0x00, 0x9c, 0x00, 0x9c, 0x00, 0x99, 0x00, 0x72, 0x00, 0x97, 0x00, 0x14, 0x01, 0xaa, 0x01, 0x27, 0x02, 0x96, 0x02, 0x19, 0x03, 0x47, 0x03, 0x49, 0x03, 0x50, 0x03, 0x51, 0x03, 0x46, 0x03, 0xd0, 0x02, 0x1d, 0x02, 0x53, 0x01, 0x9c, 0x00, 0x1d, 0x00, 0x9e, 0xff, 0x0c, 0xff, 0x8e, 0xfe, 0x46, 0xfe, 0x08, 0xfe, 0xfc, 0xfd, 0x0c, 0xfe, 0x2b, 0xfe, 0x42, 0xfe, 0x2c, 0xfe, 0x25, 0xfe, 0x5c, 0xfe, 0xaa, 0xfe, 0x00, 0xff, 0x71, 0xff, 0x9c, 0xff, 0x9c, 0xff, 0x9c, 0xff, 0xb8, 0xff, 0xbc, 0xff, 0xd6, 0xff, 0xf1, 0xff, 0x06, 0x00, 0xfb, 0xff, 0xf7, 0xff, 0xec, 0xff, 0xda, 0xff, 0xc2, 0xff, 0x76, 0xff, 0x42, 0xff, 0x44, 0xff, 0x88, 0xff, 0xa0, 0xff, 0x69, 0xff, 0x48, 0xff, 0x31, 0xff, 0x4c, 0xff, 0x51, 0xff, 0x2f, 0xff, 0x29, 0xff, 0x24, 0xff, 0x00, 0xff, 0x27, 0xff, 0x7a, 0xff, 0xe8, 0xff, 0xa8, 0x00, 0x50, 0x01, 0xc7, 0x01, 0x05, 0x02, 0x1f, 0x02, 0x0a, 0x02, 0xce, 0x01, 0xad, 0x01, 0x54, 0x01, 0xcb, 0x00, 0x66, 0x00, 0xfd, 0xff, 0xc7, 0xff, 0xaf, 0xff, 0xa5, 0xff, 0x9c, 0xff, 0x66, 0xff, 0x56, 0xff, 0x71, 0xff, 0x7d, 0xff, 0x52, 0xff, 0x13, 0xff, 0xff, 0xfe, 0xf2, 0xfe, 0xdf, 0xfe, 0xc4, 0xfe, 0xbf, 0xfe, 0xa3, 0xfe, 0xba, 0xfe, 0xe0, 0xfe, 0x24, 0xff, 0x76, 0xff, 0xca, 0xff, 0x1a, 0x00, 0x4d, 0x00, 0x59, 0x00, 0x64, 0x00, 0x46, 0x00, 0x10, 0x00, 0x52, 0x00, 0x87, 0x00, 0x97, 0x00, 0xdd, 0x00, 0x2f, 0x01, 0x16, 0x01, 0xd0, 0x00, 0x8d, 0x00, 0x88, 0x00, 0x94, 0x00, 0x6b, 0x00, 0x73, 0x00, 0x84, 0x00, 0xa4, 0x00, 0xb4, 0x00, 0xae, 0x00, 0x9b, 0x00, 0x81, 0x00, 0x50, 0x00, 0xf5, 0xff, 0xd4, 0xff, 0x98, 0xff, 0x90, 0xff, 0xdd, 0xff, 0x3a, 0x00, 0xc1, 0x00, 0x48, 0x01, 0x83, 0x01, 0x51, 0x01, 0xfe, 0x00, 0x99, 0x00, 0x50, 0x00, 0x3b, 0x00, 0x39, 0x00, 0x2d, 0x00, 0x10, 0x00, 0xd5, 0xff, 0x71, 0xff, 0x12, 0xff, 0xba, 0xfe, 0xb4, 0xfe, 0xb2, 0xfe, 0x7a, 0xfe, 0x2e, 0xfe, 0x07, 0xfe, 0xce, 0xfd, 0xc2, 0xfd, 0xc7, 0xfd, 0xe2, 0xfd, 0x44, 0xfe, 0xd1, 0xfe, 0x7f, 0xff, 0x1f, 0x00, 0xe6, 0x00, 0xdd, 0x01, 0x6d, 0x02, 0xc0, 0x02, 0xc5, 0x02, 0x9c, 0x02, 0x7e, 0x02, 0x5e, 0x02, 0x2d, 0x02, 0xe1, 0x01, 0xa0, 0x01, 0x68, 0x01, 0x5e, 0x01, 0x86, 0x01, 0xb7, 0x01, 0xbf, 0x01, 0xc1, 0x01, 0x99, 0x01, 0x47, 0x01, 0xdc, 0x00, 0x61, 0x00, 0xd4, 0xff, 0x62, 0xff, 0xf2, 0xfe, 0x89, 0xfe, 0x46, 0xfe, 0xf5, 0xfd, 0x9a, 0xfd, 0x52, 0xfd, 0x21, 0xfd, 0xe1, 0xfc, 0xbe, 0xfc, 0xba, 0xfc, 0xbc, 0xfc, 0x13, 0xfd, 0x78, 0xfd, 0xf7, 0xfd, 0xa4, 0xfe, 0x2f, 0xff, 0x88, 0xff, 0xfe, 0xff, 0x50, 0x00, 0x77, 0x00, 0x8d, 0x00, 0xa2, 0x00, 0xc5, 0x00, 0xd6, 0x00, 0x14, 0x01, 0x5d, 0x01, 0x8a, 0x01, 0x9b, 0x01, 0xc5, 0x01, 0x27, 0x02, 0x44, 0x02, 0x1a, 0x02, 0x9d, 0x01, 0x1b, 0x01, 0xb6, 0x00, 0x37, 0x00, 0xc5, 0xff, 0x60, 0xff, 0x18, 0xff, 0xc3, 0xfe, 0x8a, 0xfe, 0x3f, 0xfe, 0xde, 0xfd, 0x8f, 0xfd, 0x68, 0xfd, 0x87, 0xfd, 0xf0, 0xfd, 0x6a, 0xfe, 0x0f, 0xff, 0xd1, 0xff, 0x5b, 0x00, 0x63, 0x00, 0x69, 0x00, 0x6b, 0x00, 0x81, 0x00, 0xb4, 0x00, 0xdf, 0x00, 0x0e, 0x01, 0x31, 0x01, 0x30, 0x01, 0x3d, 0x01, 0x6c, 0x01, 0xb6, 0x01, 0x3d, 0x02, 0xd3, 0x02, 0x69, 0x03, 0xd0, 0x03, 0xc0, 0x03, 0x5d, 0x03, 0x20, 0x03, 0xd2, 0x02, 0x53, 0x02, 0xbf, 0x01, 0x46, 0x01, 0xd4, 0x00, 0x84, 0x00, 0x0f, 0x00, 0x66, 0xff, 0xb6, 0xfe, 0x41, 0xfe, 0xeb, 0xfd, 0x85, 0xfd, 0x36, 0xfd, 0x07, 0xfd, 0xed, 0xfc, 0x1c, 0xfd, 0x55, 0xfd, 0x80, 0xfd, 0x96, 0xfd, 0xad, 0xfd, 0xd1, 0xfd, 0x15, 0xfe, 0x87, 0xfe, 0xe1, 0xfe, 0x02, 0xff, 0x27, 0xff, 0x40, 0xff, 0x4e, 0xff, 0x3a, 0xff, 0xf2, 0xfe, 0xe5, 0xfe, 0xcc, 0xfe, 0xd2, 0xfe, 0xb7, 0xfe, 0xa8, 0xfe, 0xa7, 0xfe, 0xc6, 0xfe, 0xfe, 0xfe, 0x06, 0xff, 0x39, 0xff, 0x8c, 0xff, 0x0a, 0x00, 0xd1, 0x00, 0x87, 0x01, 0x39, 0x02, 0x2f, 0x03, 0xf5, 0x03, 0x24, 0x04, 0x40, 0x04, 0x2f, 0x04, 0xe2, 0x03, 0x57, 0x03, 0x7d, 0x02, 0x77, 0x01, 0x76, 0x00, 0xb9, 0xff, 0x36, 0xff, 0xd3, 0xfe, 0x90, 0xfe, 0x35, 0xfe, 0xc8, 0xfd, 0x7f, 0xfd, 0x7d, 0xfd, 0xac, 0xfd, 0x0c, 0xfe, 0xa8, 0xfe, 0xfd, 0xfe, 0x35, 0xff, 0x3e, 0xff, 0x2b, 0xff, 0x18, 0xff, 0x12, 0xff, 0x2f, 0xff, 0x63, 0xff, 0x9f, 0xff, 0x02, 0x00, 0x62, 0x00, 0xa0, 0x00, 0xd3, 0x00, 0xdb, 0x00, 0xf5, 0x00, 0x0f, 0x01, 0x43, 0x01, 0x8b, 0x01, 0xc5, 0x01, 0xee, 0x01, 0xe3, 0x01, 0xa0, 0x01, 0x4d, 0x01, 0x26, 0x01, 0x15, 0x01, 0xf9, 0x00, 0xdc, 0x00, 0xd5, 0x00, 0xbe, 0x00, 0x89, 0x00, 0x53, 0x00, 0x07, 0x00, 0xf5, 0xff, 0xf2, 0xff, 0xce, 0xff, 0xab, 0xff, 0xcd, 0xff, 0xf2, 0xff, 0xed, 0xff, 0xdc, 0xff, 0xc0, 0xff, 0xab, 0xff, 0x98, 0xff, 0xba, 0xff, 0xc4, 0xff, 0xfb, 0xff, 0x5a, 0x00, 0xd2, 0x00, 0x34, 0x01, 0x1a, 0x01, 0xbf, 0x00, 0x67, 0x00, 0x1f, 0x00, 0xe5, 0xff, 0xad, 0xff, 0x81, 0xff, 0x43, 0xff, 0xd7, 0xfe, 0x75, 0xfe, 0x2c, 0xfe, 0x05, 0xfe, 0xe3, 0xfd, 0xed, 0xfd, 0x13, 0xfe, 0x3e, 0xfe, 0x8d, 0xfe, 0x9b, 0xfe, 0x8c, 0xfe, 0x88, 0xfe, 0x86, 0xfe, 0x74, 0xfe, 0x5c, 0xfe, 0x4a, 0xfe, 0x63, 0xfe, 0x7a, 0xfe, 0xae, 0xfe, 0x1f, 0xff, 0xa5, 0xff, 0x32, 0x00, 0xb2, 0x00, 0x11, 0x01, 0x6e, 0x01, 0xe0, 0x01, 0x2f, 0x02, 0x49, 0x02, 0x6b, 0x02, 0xcf, 0x02, 0x2c, 0x03, 0x50, 0x03, 0x4f, 0x03, 0x35, 0x03, 0x09, 0x03, 0xce, 0x02, 0x87, 0x02, 0x29, 0x02, 0xbe, 0x01, 0x53, 0x01, 0xf1, 0x00, 0xb5, 0x00, 0x64, 0x00, 0x1e, 0x00, 0xb8, 0xff, 0x6e, 0xff, 0x1a, 0xff, 0xc5, 0xfe, 0x6d, 0xfe, 0x50, 0xfe, 0x6e, 0xfe, 0x9a, 0xfe, 0xd7, 0xfe, 0xed, 0xfe, 0xc5, 0xfe, 0x66, 0xfe, 0xec, 0xfd, 0x97, 0xfd, 0x43, 0xfd, 0x28, 0xfd, 0x74, 0xfd, 0xee, 0xfd, 0x4d, 0xfe, 0x7a, 0xfe, 0x96, 0xfe, 0xb1, 0xfe, 0xc4, 0xfe, 0xdf, 0xfe, 0xee, 0xfe, 0xf9, 0xfe, 0xe8, 0xfe, 0xed, 0xfe, 0x36, 0xff, 0x95, 0xff, 0xee, 0xff, 0x3c, 0x00, 0x8c, 0x00, 0xdd, 0x00, 0x40, 0x01, 0x7d, 0x01, 0xa4, 0x01, 0xb6, 0x01, 0xbe, 0x01, 0x9b, 0x01, 0x58, 0x01, 0x25, 0x01, 0x10, 0x01, 0x2d, 0x01, 0x47, 0x01, 0x5d, 0x01, 0x57, 0x01, 0x4e, 0x01, 0x0d, 0x01, 0x8d, 0x00, 0x2b, 0x00, 0xd7, 0xff, 0x86, 0xff, 0x3b, 0xff, 0x24, 0xff, 0xff, 0xfe, 0xca, 0xfe, 0x87, 0xfe, 0x3e, 0xfe, 0x22, 0xfe, 0x1b, 0xfe, 0x35, 0xfe, 0x62, 0xfe, 0xc2, 0xfe, 0x3e, 0xff, 0xb5, 0xff, 0xfe, 0xff, 0x37, 0x00, 0x83, 0x00, 0xbe, 0x00, 0xeb, 0x00, 0x1a, 0x01, 0x6a, 0x01, 0x9a, 0x01, 0x94, 0x01, 0x73, 0x01, 0x37, 0x01, 0xbe, 0x00, 0x17, 0x00, 0x7d, 0xff, 0x00, 0xff, 0xc9, 0xfe, 0xc7, 0xfe, 0xc8, 0xfe, 0xe9, 0xfe, 0xfc, 0xfe, 0xfd, 0xfe, 0x0a, 0xff, 0x2e, 0xff, 0x52, 0xff, 0x70, 0xff, 0x7a, 0xff, 0x8c, 0xff, 0xc4, 0xff, 0x1a, 0x00, 0x94, 0x00, 0xe7, 0x00, 0xfc, 0x00, 0x04, 0x01, 0x25, 0x01, 0x2f, 0x01, 0x68, 0x01, 0xb1, 0x01, 0xd2, 0x01, 0x9a, 0x01, 0x4f, 0x01, 0xf9, 0x00, 0xb2, 0x00, 0x56, 0x00, 0xef, 0xff, 0xb3, 0xff, 0xb1, 0xff, 0xac, 0xff, 0x9c, 0xff, 0x81, 0xff, 0x71, 0xff, 0x70, 0xff, 0x8f, 0xff, 0x8e, 0xff, 0x7b, 0xff, 0x47, 0xff, 0x39, 0xff, 0x61, 0xff, 0x90, 0xff, 0xb7, 0xff, 0xc8, 0xff, 0xe4, 0xff, 0x26, 0x00, 0x4c, 0x00, 0x9d, 0x00, 0x34, 0x01, 0x01, 0x02, 0xc2, 0x02, 0x53, 0x03, 0xc6, 0x03, 0xc1, 0x03, 0x5f, 0x03, 0xe4, 0x02, 0x78, 0x02, 0xf6, 0x01, 0x7b, 0x01, 0xd3, 0x00, 0x0b, 0x00, 0x3e, 0xff, 0x98, 0xfe, 0x1f, 0xfe, 0xaa, 0xfd, 0x58, 0xfd, 0x14, 0xfd, 0xd0, 0xfc, 0xb2, 0xfc, 0xa1, 0xfc, 0xa1, 0xfc, 0xcf, 0xfc, 0x18, 0xfd, 0x70, 0xfd, 0xa9, 0xfd, 0x19, 0xfe, 0x99, 0xfe, 0x1c, 0xff, 0x95, 0xff, 0xf3, 0xff, 0x29, 0x00, 0x27, 0x00, 0x2c, 0x00, 0x4e, 0x00, 0x44, 0x00, 0x10, 0x00, 0xe9, 0xff, 0xd2, 0xff, 0xe1, 0xff, 0xf2, 0xff, 0xd1, 0xff, 0x89, 0xff, 0x4d, 0xff, 0x59, 0xff, 0xd1, 0xff, 0x7b, 0x00, 0x2d, 0x01, 0xb6, 0x01, 0x31, 0x02, 0x97, 0x02, 0xfb, 0x02, 0x86, 0x03, 0x1a, 0x04, 0x74, 0x04, 0x55, 0x04, 0xbf, 0x03, 0xf8, 0x02, 0x1c, 0x02, 0x69, 0x01, 0xcf, 0x00, 0x41, 0x00, 0xa3, 0xff, 0xf3, 0xfe, 0x5d, 0xfe, 0x03, 0xfe, 0x21, 0xfe, 0x67, 0xfe, 0xb3, 0xfe, 0xe5, 0xfe, 0x27, 0xff, 0x52, 0xff, 0x57, 0xff, 0x3a, 0xff, 0x01, 0xff, 0xc4, 0xfe, 0x80, 0xfe, 0x47, 0xfe, 0x2c, 0xfe, 0x32, 0xfe, 0x3a, 0xfe, 0x26, 0xfe, 0x34, 0xfe, 0x73, 0xfe, 0xa3, 0xfe, 0xd5, 0xfe, 0x04, 0xff, 0x56, 0xff, 0xaa, 0xff, 0xca, 0xff, 0xe7, 0xff, 0x0f, 0x00, 0x44, 0x00, 0x57, 0x00, 0x80, 0x00, 0xac, 0x00, 0xf1, 0x00, 0x3c, 0x01, 0xa2, 0x01, 0x21, 0x02, 0xa9, 0x02, 0xd3, 0x02, 0xe0, 0x02, 0x09, 0x03, 0xed, 0x02, 0x90, 0x02, 0xee, 0x01, 0x42, 0x01, 0xb6, 0x00, 0x55, 0x00, 0xfa, 0xff, 0x9a, 0xff, 0x44, 0xff, 0x0a, 0xff, 0xe5, 0xfe, 0xcc, 0xfe, 0xbd, 0xfe, 0xae, 0xfe, 0xca, 0xfe, 0x09, 0xff, 0x3b, 0xff, 0x30, 0xff, 0xfa, 0xfe, 0xaf, 0xfe, 0x69, 0xfe, 0x2c, 0xfe, 0x02, 0xfe, 0xf2, 0xfd, 0x19, 0xfe, 0x64, 0xfe, 0x99, 0xfe, 0xbd, 0xfe, 0xc8, 0xfe, 0xef, 0xfe, 0x2f, 0xff, 0x7f, 0xff, 0xa6, 0xff, 0xcb, 0xff, 0xe3, 0xff, 0xef, 0xff, 0xe1, 0xff, 0xe7, 0xff, 0xe7, 0xff, 0xdd, 0xff, 0xbb, 0xff, 0x9f, 0xff, 0xb1, 0xff, 0x0b, 0x00, 0x5c, 0x00, 0x97, 0x00, 0xc5, 0x00, 0x17, 0x01, 0x63, 0x01, 0x91, 0x01, 0xa8, 0x01, 0xc2, 0x01, 0xfb, 0x01, 0x4b, 0x02, 0xaf, 0x02, 0x26, 0x03, 0x7a, 0x03, 0x7b, 0x03, 0x58, 0x03, 0xf4, 0x02, 0x81, 0x02, 0xfc, 0x01, 0x48, 0x01, 0x98, 0x00, 0x06, 0x00, 0x88, 0xff, 0x25, 0xff, 0xb7, 0xfe, 0x6b, 0xfe, 0x13, 0xfe, 0xc6, 0xfd, 0xa7, 0xfd, 0xb1, 0xfd, 0xd5, 0xfd, 0x09, 0xfe, 0x58, 0xfe, 0x90, 0xfe, 0xef, 0xfe, 0x4e, 0xff, 0xa1, 0xff, 0x73, 0xff, 0x12, 0xff, 0x9e, 0xfe, 0x52, 0xfe, 0x52, 0xfe, 0x7d, 0xfe, 0xc0, 0xfe, 0xcf, 0xfe, 0xe7, 0xfe, 0xdc, 0xfe, 0xac, 0xfe, 0x87, 0xfe, 0x72, 0xfe, 0x7d, 0xfe, 0xa0, 0xfe, 0xe6, 0xfe, 0x57, 0xff, 0xd4, 0xff, 0x43, 0x00, 0x9d, 0x00, 0x10, 0x01, 0xb9, 0x01, 0x41, 0x02, 0x87, 0x02, 0x90, 0x02, 0x5f, 0x02, 0xfd, 0x01, 0x9c, 0x01, 0x41, 0x01, 0xf0, 0x00, 0xab, 0x00, 0x7c, 0x00, 0x7d, 0x00, 0xc7, 0x00, 0x1d, 0x01, 0x49, 0x01, 0x61, 0x01, 0x63, 0x01, 0x63, 0x01, 0x56, 0x01, 0x2a, 0x01, 0xd1, 0x00, 0x40, 0x00, 0x92, 0xff, 0xdf, 0xfe, 0x43, 0xfe, 0xcd, 0xfd, 0x8c, 0xfd, 0x8b, 0xfd, 0xb9, 0xfd, 0xf4, 0xfd, 0x29, 0xfe, 0x56, 0xfe, 0x81, 0xfe, 0x9c, 0xfe, 0xd9, 0xfe, 0x10, 0xff, 0x40, 0xff, 0x54, 0xff, 0x5b, 0xff, 0x4e, 0xff, 0x67, 0xff, 0xc8, 0xff, 0x2c, 0x00, 0x8e, 0x00, 0xde, 0x00, 0x08, 0x01, 0x0f, 0x01, 0xf7, 0x00, 0xcd, 0x00, 0x83, 0x00, 0x59, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x74, 0x00, 0xa7, 0x00, 0xe1, 0x00, 0x25, 0x01, 0x61, 0x01, 0x60, 0x01, 0x5d, 0x01, 0x42, 0x01, 0x1b, 0x01, 0x20, 0x01, 0x0b, 0x01, 0xf3, 0x00, 0xcb, 0x00, 0xab, 0x00, 0x91, 0x00, 0x9d, 0x00, 0xe0, 0x00, 0xdd, 0x00, 0xb6, 0x00, 0xa1, 0x00, 0x86, 0x00, 0x80, 0x00, 0x69, 0x00, 0x01, 0x00, 0x77, 0xff, 0x0c, 0xff, 0xbe, 0xfe, 0x8e, 0xfe, 0x71, 0xfe, 0x57, 0xfe, 0x6e, 0xfe, 0x9d, 0xfe, 0xd2, 0xfe, 0x10, 0xff, 0x54, 0xff, 0x73, 0xff, 0xa0, 0xff, 0xb2, 0xff, 0xbb, 0xff, 0xd9, 0xff, 0xe2, 0xff, 0xde, 0xff, 0xe5, 0xff, 0xf7, 0xff, 0x12, 0x00, 0x17, 0x00, 0xe3, 0xff, 0xa3, 0xff, 0x51, 0xff, 0x0d, 0xff, 0xf0, 0xfe, 0x02, 0xff, 0x18, 0xff, 0x56, 0xff, 0x91, 0xff, 0xc4, 0xff, 0xd1, 0xff, 0xad, 0xff, 0x6f, 0xff, 0x34, 0xff, 0x01, 0xff, 0xd3, 0xfe, 0xa8, 0xfe, 0x9d, 0xfe, 0xa3, 0xfe, 0xc1, 0xfe, 0x04, 0xff, 0x6d, 0xff, 0xfa, 0xff, 0xb4, 0x00, 0x68, 0x01, 0xf3, 0x01, 0x9b, 0x02, 0x4f, 0x03, 0xb5, 0x03, 0xd3, 0x03, 0xc7, 0x03, 0xa9, 0x03, 0x7a, 0x03, 0x20, 0x03, 0xa9, 0x02, 0x18, 0x02, 0xa6, 0x01, 0x35, 0x01, 0xb6, 0x00, 0x46, 0x00, 0xd3, 0xff, 0x76, 0xff, 0xea, 0xfe, 0x77, 0xfe, 0x2f, 0xfe, 0xfc, 0xfd, 0xce, 0xfd, 0x8e, 0xfd, 0x5a, 0xfd, 0x1e, 0xfd, 0x02, 0xfd, 0xf9, 0xfc, 0x17, 0xfd, 0x59, 0xfd, 0x8b, 0xfd, 0xa9, 0xfd, 0xb4, 0xfd, 0xe8, 0xfd, 0x1e, 0xfe, 0x54, 0xfe, 0x84, 0xfe, 0xec, 0xfe, 0x60, 0xff, 0xe8, 0xff, 0x7e, 0x00, 0x2e, 0x01, 0xd6, 0x01, 0x62, 0x02, 0xe7, 0x02, 0x53, 0x03, 0xa8, 0x03, 0xbf, 0x03, 0x9a, 0x03, 0x6e, 0x03, 0x3d, 0x03, 0xff, 0x02, 0xc8, 0x02, 0x98, 0x02, 0x67, 0x02, 0x38, 0x02, 0xf8, 0x01, 0x93, 0x01, 0x3b, 0x01, 0xef, 0x00, 0xab, 0x00, 0x47, 0x00, 0xce, 0xff, 0x70, 0xff, 0xf3, 0xfe, 0x6b, 0xfe, 0x02, 0xfe, 0xb5, 0xfd, 0x90, 0xfd, 0x9b, 0xfd, 0xc9, 0xfd, 0xda, 0xfd, 0xf2, 0xfd, 0xff, 0xfd, 0xea, 0xfd, 0xe8, 0xfd, 0xfa, 0xfd, 0x3c, 0xfe, 0x55, 0xfe, 0x64, 0xfe, 0x71, 0xfe, 0x8b, 0xfe, 0xb6, 0xfe, 0x1d, 0xff, 0x7e, 0xff, 0xb7, 0xff, 0xc0, 0xff, 0xaa, 0xff, 0x8f, 0xff, 0x8f, 0xff, 0xa6, 0xff, 0xcb, 0xff, 0x17, 0x00, 0x46, 0x00, 0x7e, 0x00, 0xac, 0x00, 0xf0, 0x00, 0x2d, 0x01, 0x56, 0x01, 0x9a, 0x01, 0xc8, 0x01, 0xef, 0x01, 0x0e, 0x02, 0x1d, 0x02, 0x43, 0x02, 0x90, 0x02, 0xa5, 0x02, 0xa7, 0x02, 0x7e, 0x02, 0x29, 0x02, 0xd2, 0x01, 0x48, 0x01, 0xae, 0x00, 0x04, 0x00, 0x3a, 0xff, 0x88, 0xfe, 0xf4, 0xfd, 0x99, 0xfd, 0x39, 0xfd, 0x14, 0xfd, 0xfd, 0xfc, 0x06, 0xfd, 0x39, 0xfd, 0x86, 0xfd, 0xae, 0xfd, 0xe1, 0xfd, 0x2f, 0xfe, 0xa3, 0xfe, 0x10, 0xff, 0x83, 0xff, 0xf1, 0xff, 0x67, 0x00, 0xd3, 0x00, 0x55, 0x01, 0xe6, 0x01, 0x88, 0x02, 0x13, 0x03, 0x5b, 0x03, 0x65, 0x03, 0x74, 0x03, 0x5c, 0x03, 0x1e, 0x03, 0xbf, 0x02, 0x59, 0x02, 0xc9, 0x01, 0x4a, 0x01, 0xe7, 0x00, 0x8c, 0x00, 0x5a, 0x00, 0x2a, 0x00, 0xff, 0xff, 0xdb, 0xff, 0x96, 0xff, 0x30, 0xff, 0xb6, 0xfe, 0x60, 0xfe, 0x2a, 0xfe, 0x1d, 0xfe, 0x1f, 0xfe, 0x42, 0xfe, 0x62, 0xfe, 0x89, 0xfe, 0xb9, 0xfe, 0xc1, 0xfe, 0x97, 0xfe, 0x64, 0xfe, 0x37, 0xfe, 0x27, 0xfe, 0x0b, 0xfe, 0x05, 0xfe, 0xf2, 0xfd, 0xe0, 0xfd, 0xd6, 0xfd, 0xd4, 0xfd, 0xeb, 0xfd, 0x3e, 0xfe, 0xc4, 0xfe, 0x50, 0xff, 0xcf, 0xff, 0x21, 0x00, 0x63, 0x00, 0xb8, 0x00, 0x53, 0x01, 0x03, 0x02, 0x6b, 0x02, 0x86, 0x02, 0x8e, 0x02, 0xa1, 0x02, 0xac, 0x02, 0x8d, 0x02, 0x74, 0x02, 0x6f, 0x02, 0x79, 0x02, 0x73, 0x02, 0x4e, 0x02, 0x08, 0x02, 0xbe, 0x01, 0x76, 0x01, 0xf4, 0x00, 0x53, 0x00, 0xa0, 0xff, 0x0c, 0xff, 0x84, 0xfe, 0xff, 0xfd, 0x86, 0xfd, 0x25, 0xfd, 0x00, 0xfd, 0xed, 0xfc, 0x02, 0xfd, 0x2a, 0xfd, 0x6f, 0xfd, 0xb2, 0xfd, 0x1f, 0xfe, 0xa1, 0xfe, 0x1d, 0xff, 0x98, 0xff, 0x26, 0x00, 0xb0, 0x00, 0x31, 0x01, 0xc2, 0x01, 0x1d, 0x02, 0x3e, 0x02, 0x39, 0x02, 0x12, 0x02, 0xdf, 0x01, 0x96, 0x01, 0x53, 0x01, 0x10, 0x01, 0xd1, 0x00, 0xaa, 0x00, 0x9f, 0x00, 0xb0, 0x00, 0xb1, 0x00, 0x97, 0x00, 0x73, 0x00, 0x3f, 0x00, 0x01, 0x00, 0xd4, 0xff, 0xb5, 0xff, 0x7e, 0xff, 0x4e, 0xff, 0x2a, 0xff, 0x35, 0xff, 0x73, 0xff, 0x96, 0xff, 0xa0, 0xff, 0xa9, 0xff, 0x9c, 0xff, 0x91, 0xff, 0x69, 0xff, 0x3c, 0xff, 0x2e, 0xff, 0x39, 0xff, 0x5c, 0xff, 0x64, 0xff, 0x6c, 0xff, 0x86, 0xff, 0xa6, 0xff, 0xa2, 0xff, 0xa2, 0xff, 0xb4, 0xff, 0xc9, 0xff, 0xca, 0xff, 0xce, 0xff, 0xb4, 0xff, 0x79, 0xff, 0x48, 0xff, 0x1e, 0xff, 0x07, 0xff, 0xf8, 0xfe, 0xd9, 0xfe, 0xab, 0xfe, 0x94, 0xfe, 0xa3, 0xfe, 0xb3, 0xfe, 0xd2, 0xfe, 0xf2, 0xfe, 0x41, 0xff, 0x9e, 0xff, 0xe0, 0xff, 0xfa, 0xff, 0x21, 0x00, 0x5d, 0x00, 0xaa, 0x00, 0xe1, 0x00, 0xf8, 0x00, 0x01, 0x01, 0xd0, 0x00, 0x9e, 0x00, 0x77, 0x00, 0x71, 0x00, 0x9c, 0x00, 0xd9, 0x00, 0x0f, 0x01, 0x3c, 0x01, 0x88, 0x01, 0xec, 0x01, 0x68, 0x02, 0xc9, 0x02, 0xf1, 0x02, 0xe2, 0x02, 0xa5, 0x02, 0x3e, 0x02, 0xd3, 0x01, 0x66, 0x01, 0x1a, 0x01, 0xac, 0x00, 0xf8, 0xff, 0x3e, 0xff, 0xac, 0xfe, 0x35, 0xfe, 0xf7, 0xfd, 0xc9, 0xfd, 0xc1, 0xfd, 0xd8, 0xfd, 0x00, 0xfe, 0x1d, 0xfe, 0x13, 0xfe, 0xee, 0xfd, 0xd2, 0xfd, 0xe5, 0xfd, 0x42, 0xfe, 0xae, 0xfe, 0x15, 0xff, 0x5f, 0xff, 0xad, 0xff, 0xf5, 0xff, 0x3a, 0x00, 0x89, 0x00, 0xec, 0x00, 0x50, 0x01, 0xb2, 0x01, 0xe7, 0x01, 0xda, 0x01, 0xc8, 0x01, 0xa3, 0x01, 0x92, 0x01, 0x5a, 0x01, 0x27, 0x01, 0xf9, 0x00, 0xc5, 0x00, 0xc1, 0x00, 0xda, 0x00, 0x92, 0x00, 0x24, 0x00, 0x9d, 0xff, 0x3e, 0xff, 0xe6, 0xfe, 0x86, 0xfe, 0x55, 0xfe, 0x38, 0xfe, 0x1a, 0xfe, 0x06, 0xfe, 0xfc, 0xfd, 0xed, 0xfd, 0x19, 0xfe, 0x63, 0xfe, 0xa6, 0xfe, 0xc5, 0xfe, 0x11, 0xff, 0x57, 0xff, 0x99, 0xff, 0x14, 0x00, 0x59, 0x00, 0x9d, 0x00, 0xe4, 0x00, 0x03, 0x01, 0x2d, 0x01, 0x5b, 0x01, 0xa2, 0x01, 0xfb, 0x01, 0x1d, 0x02, 0x07, 0x02, 0xfd, 0x01, 0x19, 0x02, 0x3d, 0x02, 0x8b, 0x02, 0xe4, 0x02, 0x19, 0x03, 0x1b, 0x03, 0x08, 0x03, 0xf2, 0x02, 0xa6, 0x02, 0x35, 0x02, 0xa8, 0x01, 0x27, 0x01, 0xbe, 0x00, 0x7e, 0x00, 0x4d, 0x00, 0xe2, 0xff, 0x54, 0xff, 0xaf, 0xfe, 0x3e, 0xfe, 0xd4, 0xfd, 0x98, 0xfd, 0x50, 0xfd, 0x29, 0xfd, 0x24, 0xfd, 0x0c, 0xfd, 0x03, 0xfd, 0xfa, 0xfc, 0x1e, 0xfd, 0x5f, 0xfd, 0x9f, 0xfd, 0xd1, 0xfd, 0xdd, 0xfd, 0xde, 0xfd, 0x04, 0xfe, 0x2c, 0xfe, 0x77, 0xfe, 0xd5, 0xfe, 0x4e, 0xff, 0xb2, 0xff, 0x06, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x20, 0x00, 0x29, 0x00, 0x3c, 0x00, 0x9f, 0x00, 0x53, 0x01, 0x04, 0x02, 0xb1, 0x02, 0x2c, 0x03, 0x6c, 0x03, 0xc5, 0x03, 0xf1, 0x03, 0x04, 0x04, 0xec, 0x03, 0x76, 0x03, 0xb1, 0x02, 0xff, 0x01, 0x50, 0x01, 0xc9, 0x00, 0x5d, 0x00, 0x0c, 0x00, 0xaa, 0xff, 0x38, 0xff, 0xc2, 0xfe, 0x4a, 0xfe, 0xd7, 0xfd, 0x71, 0xfd, 0x2a, 0xfd, 0x05, 0xfd, 0x11, 0xfd, 0x45, 0xfd, 0x91, 0xfd, 0xee, 0xfd, 0x3e, 0xfe, 0x64, 0xfe, 0xc3, 0xfe, 0x1d, 0xff, 0x65, 0xff, 0xa7, 0xff, 0xf7, 0xff, 0x69, 0x00, 0xdb, 0x00, 0x33, 0x01, 0x75, 0x01, 0x8d, 0x01, 0x86, 0x01, 0x7e, 0x01, 0x39, 0x01, 0xec, 0x00, 0xa9, 0x00, 0x68, 0x00, 0x19, 0x00, 0xe0, 0xff, 0x8d, 0xff, 0x34, 0xff, 0xe3, 0xfe, 0xb7, 0xfe, 0x9b, 0xfe, 0x88, 0xfe, 0xa8, 0xfe, 0xf8, 0xfe, 0x60, 0xff, 0xc5, 0xff, 0x24, 0x00, 0x90, 0x00, 0xea, 0x00, 0x11, 0x01, 0x32, 0x01, 0x2b, 0x01, 0x08, 0x01, 0xbb, 0x00, 0x66, 0x00, 0x09, 0x00, 0xbb, 0xff, 0x8c, 0xff, 0x8e, 0xff, 0xa6, 0xff, 0xc4, 0xff, 0xf3, 0xff, 0xf9, 0xff, 0xe0, 0xff, 0xcf, 0xff, 0xc8, 0xff, 0xd6, 0xff, 0xdb, 0xff, 0xc6, 0xff, 0xbd, 0xff, 0xad, 0xff, 0xa0, 0xff, 0x9b, 0xff, 0x9a, 0xff, 0x81, 0xff, 0x34, 0xff, 0xfb, 0xfe, 0xfb, 0xfe, 0x39, 0xff, 0x87, 0xff, 0xe0, 0xff, 0x5c, 0x00, 0xf6, 0x00, 0xa3, 0x01, 0x3d, 0x02, 0xa4, 0x02, 0xea, 0x02, 0x1e, 0x03, 0x20, 0x03, 0xe0, 0x02, 0x43, 0x02, 0x73, 0x01, 0x8e, 0x00, 0xb4, 0xff, 0xeb, 0xfe, 0x4a, 0xfe, 0xcd, 0xfd, 0x69, 0xfd, 0x38, 0xfd, 0x40, 0xfd, 0x6c, 0xfd, 0x9f, 0xfd, 0xec, 0xfd, 0x2d, 0xfe, 0x6a, 0xfe, 0xab, 0xfe, 0xe5, 0xfe, 0x27, 0xff, 0x57, 0xff, 0x95, 0xff, 0xe8, 0xff, 0x28, 0x00, 0xb3, 0x00, 0x49, 0x01, 0xdc, 0x01, 0x40, 0x02, 0x88, 0x02, 0x9c, 0x02, 0x82, 0x02, 0x77, 0x02, 0x8b, 0x02, 0xac, 0x02, 0x95, 0x02, 0x59, 0x02, 0xfd, 0x01, 0xbd, 0x01, 0xaa, 0x01, 0x84, 0x01, 0x3b, 0x01, 0xc1, 0x00, 0x35, 0x00, 0xbf, 0xff, 0x48, 0xff, 0xbb, 0xfe, 0x29, 0xfe, 0x9e, 0xfd, 0x36, 0xfd, 0x1b, 0xfd, 0x30, 0xfd, 0x4f, 0xfd, 0x76, 0xfd, 0x88, 0xfd, 0x8e, 0xfd, 0x8f, 0xfd, 0xad, 0xfd, 0xe2, 0xfd, 0x3b, 0xfe, 0x7d, 0xfe, 0xc1, 0xfe, 0x1a, 0xff, 0x63, 0xff, 0x9d, 0xff, 0x13, 0x00, 0x6a, 0x00, 0x82, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x78, 0x00, 0xa3, 0x00, 0xdd, 0x00, 0xfe, 0x00, 0x06, 0x01, 0x2f, 0x01, 0x35, 0x01, 0x24, 0x01, 0xf7, 0x00, 0xaa, 0x00, 0x50, 0x00, 0x17, 0x00, 0x11, 0x00, 0x22, 0x00, 0x44, 0x00, 0x6e, 0x00, 0xb3, 0x00, 0xc0, 0x00, 0xa5, 0x00, 0xaa, 0x00, 0xdf, 0x00, 0xff, 0x00, 0x2e, 0x01, 0x44, 0x01, 0x61, 0x01, 0x61, 0x01, 0x3c, 0x01, 0xf3, 0x00, 0x9e, 0x00, 0x3d, 0x00, 0xe4, 0xff, 0x78, 0xff, 0x23, 0xff, 0xef, 0xfe, 0xbc, 0xfe, 0x7e, 0xfe, 0x51, 0xfe, 0x45, 0xfe, 0x4d, 0xfe, 0x7b, 0xfe, 0xba, 0xfe, 0x29, 0xff, 0xc3, 0xff, 0x4f, 0x00, 0xb0, 0x00, 0x00, 0x01, 0x32, 0x01, 0x2b, 0x01, 0x1e, 0x01, 0x04, 0x01, 0xd9, 0x00, 0xa9, 0x00, 0x59, 0x00, 0x0a, 0x00, 0xd4, 0xff, 0x98, 0xff, 0x99, 0xff, 0x85, 0xff, 0x6d, 0xff, 0x60, 0xff, 0x33, 0xff, 0x18, 0xff, 0x11, 0xff, 0x11, 0xff, 0x04, 0xff, 0x05, 0xff, 0x0e, 0xff, 0x4d, 0xff, 0xa4, 0xff, 0xe8, 0xff, 0x05, 0x00, 0x0a, 0x00, 0x33, 0x00, 0x4f, 0x00, 0x70, 0x00, 0x95, 0x00, 0xac, 0x00, 0xc2, 0x00, 0xc8, 0x00, 0xdc, 0x00, 0x0e, 0x01, 0x1e, 0x01, 0xf9, 0x00, 0xa9, 0x00, 0x43, 0x00, 0xe9, 0xff, 0x9e, 0xff, 0x86, 0xff, 0x73, 0xff, 0x7d, 0xff, 0x97, 0xff, 0xc0, 0xff, 0xeb, 0xff, 0x28, 0x00, 0x49, 0x00, 0x6e, 0x00, 0xa4, 0x00, 0xfb, 0x00, 0x63, 0x01, 0x9b, 0x01, 0xbb, 0x01, 0xe1, 0x01, 0x0c, 0x02, 0xdf, 0x01, 0x7d, 0x01, 0x00, 0x01, 0x97, 0x00, 0x57, 0x00, 0x34, 0x00, 0x2f, 0x00, 0x23, 0x00, 0x01, 0x00, 0xee, 0xff, 0xc8, 0xff, 0xab, 0xff, 0xc5, 0xff, 0xc6, 0xff, 0x9f, 0xff, 0x7d, 0xff, 0x65, 0xff, 0x5a, 0xff, 0x4d, 0xff, 0x40, 0xff, 0x27, 0xff, 0xf4, 0xfe, 0xdc, 0xfe, 0xc8, 0xfe, 0xbb, 0xfe, 0x9b, 0xfe, 0x67, 0xfe, 0x49, 0xfe, 0x40, 0xfe, 0x3d, 0xfe, 0x32, 0xfe, 0x22, 0xfe, 0x15, 0xfe, 0xf8, 0xfd, 0xe1, 0xfd, 0xda, 0xfd, 0xfc, 0xfd, 0x43, 0xfe, 0x96, 0xfe, 0xe8, 0xfe, 0x14, 0xff, 0x41, 0xff, 0x74, 0xff, 0xda, 0xff, 0x46, 0x00, 0xbf, 0x00, 0x30, 0x01, 0x8f, 0x01, 0xd9, 0x01, 0x29, 0x02, 0x61, 0x02, 0x8c, 0x02, 0x9f, 0x02, 0x74, 0x02, 0x2f, 0x02, 0xc6, 0x01, 0x6c, 0x01, 0x0a, 0x01, 0x9b, 0x00, 0x4f, 0x00, 0x05, 0x00, 0xbd, 0xff, 0x96, 0xff, 0x8b, 0xff, 0x90, 0xff, 0xb0, 0xff, 0xf1, 0xff, 0x20, 0x00, 0x55, 0x00, 0x80, 0x00, 0xa2, 0x00, 0xa9, 0x00, 0xa3, 0x00, 0x7b, 0x00, 0x49, 0x00, 0x53, 0x00, 0x84, 0x00, 0xbc, 0x00, 0xc7, 0x00, 0xa4, 0x00, 0x64, 0x00, 0x32, 0x00, 0x0a, 0x00, 0xf9, 0xff, 0xd3, 0xff, 0xb5, 0xff, 0x7c, 0xff, 0x4d, 0xff, 0xfd, 0xfe, 0xec, 0xfe, 0x07, 0xff, 0x3e, 0xff, 0x92, 0xff, 0xed, 0xff, 0x58, 0x00, 0xc5, 0x00, 0x30, 0x01, 0x85, 0x01, 0x80, 0x01, 0x48, 0x01, 0x1e, 0x01, 0x11, 0x01, 0xfa, 0x00, 0xd1, 0x00, 0x95, 0x00, 0x36, 0x00, 0xb7, 0xff, 0x3c, 0xff, 0xf5, 0xfe, 0xb3, 0xfe, 0x86, 0xfe, 0x76, 0xfe, 0x89, 0xfe, 0xce, 0xfe, 0x1c, 0xff, 0x5f, 0xff, 0x91, 0xff, 0xbb, 0xff, 0xc5, 0xff, 0xb6, 0xff, 0x9b, 0xff, 0x82, 0xff, 0x77, 0xff, 0x4a, 0xff, 0x31, 0xff, 0x2f, 0xff, 0x27, 0xff, 0x1a, 0xff, 0x0d, 0xff, 0x0b, 0xff, 0xfe, 0xfe, 0x14, 0xff, 0x3b, 0xff, 0x65, 0xff, 0x94, 0xff, 0xd8, 0xff, 0x36, 0x00, 0x8f, 0x00, 0xe4, 0x00, 0x21, 0x01, 0x6e, 0x01, 0xb3, 0x01, 0xc4, 0x01, 0xcf, 0x01, 0xae, 0x01, 0x9e, 0x01, 0x69, 0x01, 0x25, 0x01, 0xd8, 0x00, 0x92, 0x00, 0x56, 0x00, 0x2a, 0x00, 0xda, 0xff, 0x9f, 0xff, 0x87, 0xff, 0x9e, 0xff, 0xb4, 0xff, 0x95, 0xff, 0x70, 0xff, 0x6f, 0xff, 0x94, 0xff, 0xc5, 0xff, 0x01, 0x00, 0x15, 0x00, 0xee, 0xff, 0xb8, 0xff, 0x7a, 0xff, 0x4d, 0xff, 0x25, 0xff, 0x0e, 0xff, 0x10, 0xff, 0x19, 0xff, 0x1d, 0xff, 0x1c, 0xff, 0x5b, 0xff, 0xc1, 0xff, 0x5b, 0x00, 0xe3, 0x00, 0x3e, 0x01, 0x79, 0x01, 0x97, 0x01, 0x92, 0x01, 0x60, 0x01, 0x38, 0x01, 0x10, 0x01, 0xcf, 0x00, 0x6b, 0x00, 0xfe, 0xff, 0xab, 0xff, 0x54, 0xff, 0x0d, 0xff, 0xd0, 0xfe, 0xae, 0xfe, 0xc0, 0xfe, 0xe7, 0xfe, 0x22, 0xff, 0x67, 0xff, 0x96, 0xff, 0x9c, 0xff, 0x7f, 0xff, 0x55, 0xff, 0x2d, 0xff, 0x24, 0xff, 0x40, 0xff, 0x66, 0xff, 0xac, 0xff, 0xfa, 0xff, 0x48, 0x00, 0x77, 0x00, 0x86, 0x00, 0x8a, 0x00, 0xa4, 0x00, 0xc8, 0x00, 0xd5, 0x00, 0x01, 0x01, 0x2f, 0x01, 0x21, 0x01, 0xe8, 0x00, 0xb7, 0x00, 0x93, 0x00, 0x75, 0x00, 0x44, 0x00, 0x0c, 0x00, 0xef, 0xff, 0xe0, 0xff, 0xe2, 0xff, 0xc2, 0xff, 0x91, 0xff, 0x80, 0xff, 0x80, 0xff, 0x7c, 0xff, 0x97, 0xff, 0xb5, 0xff, 0xd3, 0xff, 0xeb, 0xff, 0xe3, 0xff, 0xcb, 0xff, 0xd6, 0xff, 0xe9, 0xff, 0xf8, 0xff, 0xdc, 0xff, 0xab, 0xff, 0x67, 0xff, 0x45, 0xff, 0x37, 0xff, 0x40, 0xff, 0x5b, 0xff, 0x61, 0xff, 0x76, 0xff, 0x77, 0xff, 0x9d, 0xff, 0xb5, 0xff, 0xcd, 0xff, 0xd9, 0xff, 0x00, 0x00, 0x3f, 0x00, 0x62, 0x00, 0x86, 0x00, 0x99, 0x00, 0xbf, 0x00, 0x02, 0x01, 0x56, 0x01, 0xb9, 0x01, 0x2f, 0x02, 0x8b, 0x02, 0xb6, 0x02, 0xa1, 0x02, 0x4f, 0x02, 0x01, 0x02, 0xbe, 0x01, 0x6a, 0x01, 0x04, 0x01, 0x95, 0x00, 0x30, 0x00, 0xf1, 0xff, 0xc6, 0xff, 0xa7, 0xff, 0x9e, 0xff, 0xc0, 0xff, 0xea, 0xff, 0xf8, 0xff, 0xe7, 0xff, 0xcf, 0xff, 0x94, 0xff, 0x43, 0xff, 0xd2, 0xfe, 0x68, 0xfe, 0x0e, 0xfe, 0xd4, 0xfd, 0xb5, 0xfd, 0xba, 0xfd, 0xd5, 0xfd, 0xe3, 0xfd, 0xf7, 0xfd, 0x0d, 0xfe, 0x16, 0xfe, 0x09, 0xfe, 0xf9, 0xfd, 0x06, 0xfe, 0x2f, 0xfe, 0x66, 0xfe, 0xdc, 0xfe, 0x66, 0xff, 0x15, 0x00, 0xdd, 0x00, 0xcf, 0x01, 0xaa, 0x02, 0x57, 0x03, 0xb6, 0x03, 0x08, 0x04, 0x31, 0x04, 0x0e, 0x04, 0xd2, 0x03, 0x68, 0x03, 0xea, 0x02, 0x6e, 0x02, 0xe0, 0x01, 0x58, 0x01, 0xc3, 0x00, 0x46, 0x00, 0xba, 0xff, 0x31, 0xff, 0xc1, 0xfe, 0x43, 0xfe, 0xd2, 0xfd, 0x82, 0xfd, 0x6c, 0xfd, 0x6d, 0xfd, 0x6a, 0xfd, 0x82, 0xfd, 0x92, 0xfd, 0x96, 0xfd, 0x98, 0xfd, 0xb1, 0xfd, 0x01, 0xfe, 0x5c, 0xfe, 0xa4, 0xfe, 0xe9, 0xfe, 0x30, 0xff, 0xa1, 0xff, 0x16, 0x00, 0x91, 0x00, 0x0e, 0x01, 0x7e, 0x01, 0xf6, 0x01, 0x61, 0x02, 0xb5, 0x02, 0xaf, 0x02, 0xa0, 0x02, 0x97, 0x02, 0xb2, 0x02, 0xf5, 0x02, 0x18, 0x03, 0xf1, 0x02, 0xa9, 0x02, 0x4a, 0x02, 0xd2, 0x01, 0x22, 0x01, 0x6d, 0x00, 0xcb, 0xff, 0x23, 0xff, 0x98, 0xfe, 0x1f, 0xfe, 0xc9, 0xfd, 0x9f, 0xfd, 0x94, 0xfd, 0x9f, 0xfd, 0xc5, 0xfd, 0xde, 0xfd, 0xfc, 0xfd, 0x1e, 0xfe, 0x4f, 0xfe, 0x88, 0xfe, 0xdc, 0xfe, 0x42, 0xff, 0x94, 0xff, 0xbb, 0xff, 0xba, 0xff, 0xd5, 0xff, 0x02, 0x00, 0x51, 0x00, 0x82, 0x00, 0x90, 0x00, 0x8d, 0x00, 0x6f, 0x00, 0x5f, 0x00, 0x46, 0x00, 0x1f, 0x00, 0xff, 0xff, 0xe1, 0xff, 0xc5, 0xff, 0xa8, 0xff, 0xac, 0xff, 0xbf, 0xff, 0xd1, 0xff, 0xe8, 0xff, 0x03, 0x00, 0xfe, 0xff, 0xf4, 0xff, 0x14, 0x00, 0x34, 0x00, 0x40, 0x00, 0x4c, 0x00, 0x43, 0x00, 0x37, 0x00, 0x29, 0x00, 0x3b, 0x00, 0x3a, 0x00, 0x42, 0x00, 0x19, 0x00, 0xe6, 0xff, 0xab, 0xff, 0x73, 0xff, 0x39, 0xff, 0x21, 0xff, 0x07, 0xff, 0x0f, 0xff, 0x4b, 0xff, 0xb5, 0xff, 0xfe, 0xff, 0x40, 0x00, 0xb7, 0x00, 0x59, 0x01, 0xd4, 0x01, 0x2c, 0x02, 0x55, 0x02, 0x93, 0x02, 0xdd, 0x02, 0x04, 0x03, 0xb3, 0x02, 0x11, 0x02, 0x79, 0x01, 0x05, 0x01, 0xab, 0x00, 0x43, 0x00, 0xcf, 0xff, 0x5e, 0xff, 0xf2, 0xfe, 0x87, 0xfe, 0x20, 0xfe, 0xbd, 0xfd, 0x78, 0xfd, 0x45, 0xfd, 0x43, 0xfd, 0x68, 0xfd, 0x9a, 0xfd, 0xb5, 0xfd, 0xdb, 0xfd, 0x23, 0xfe, 0x86, 0xfe, 0x05, 0xff, 0x8c, 0xff, 0x09, 0x00, 0x8b, 0x00, 0x01, 0x01, 0x60, 0x01, 0x9d, 0x01, 0xca, 0x01, 0xe8, 0x01, 0xb1, 0x01, 0x3f, 0x01, 0xba, 0x00, 0x5e, 0x00, 0x12, 0x00, 0xe2, 0xff, 0xbc, 0xff, 0xd2, 0xff, 0xf2, 0xff, 0x1b, 0x00, 0x45, 0x00, 0x72, 0x00, 0xa2, 0x00, 0xac, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x9b, 0x00, 0x77, 0x00, 0x41, 0x00, 0x0c, 0x00, 0xe2, 0xff, 0xea, 0xff, 0xf2, 0xff, 0x27, 0x00, 0x49, 0x00, 0x6c, 0x00, 0x6a, 0x00, 0x5d, 0x00, 0x34, 0x00, 0xfa, 0xff, 0xbb, 0xff, 0x6c, 0xff, 0x34, 0xff, 0x06, 0xff, 0xfc, 0xfe, 0xf3, 0xfe, 0xf0, 0xfe, 0xe5, 0xfe, 0xe0, 0xfe, 0xd4, 0xfe, 0xdf, 0xfe, 0xff, 0xfe, 0x1e, 0xff, 0x49, 0xff, 0x78, 0xff, 0xb7, 0xff, 0xfd, 0xff, 0x8b, 0x00, 0x0b, 0x01, 0x5c, 0x01, 0x77, 0x01, 0x87, 0x01, 0x6f, 0x01, 0x25, 0x01, 0xda, 0x00, 0x9a, 0x00, 0xae, 0x00, 0x8c, 0x00, 0x5b, 0x00, 0x2a, 0x00, 0xff, 0xff, 0xf1, 0xff, 0xd9, 0xff, 0xad, 0xff, 0x75, 0xff, 0x63, 0xff, 0x6f, 0xff, 0x8c, 0xff, 0xab, 0xff, 0xd4, 0xff, 0xdb, 0xff, 0xbf, 0xff, 0xa0, 0xff, 0x79, 0xff, 0x51, 0xff, 0x2c, 0xff, 0x13, 0xff, 0x1d, 0xff, 0x24, 0xff, 0x3b, 0xff, 0x59, 0xff, 0x95, 0xff, 0xcb, 0xff, 0xfa, 0xff, 0x24, 0x00, 0x49, 0x00, 0x5e, 0x00, 0x64, 0x00, 0x7b, 0x00, 0x94, 0x00, 0xa4, 0x00, 0x94, 0x00, 0x7b, 0x00, 0x38, 0x00, 0xe1, 0xff, 0x7f, 0xff, 0x61, 0xff, 0x4d, 0xff, 0x4c, 0xff, 0x59, 0xff, 0x62, 0xff, 0x7b, 0xff, 0xa0, 0xff, 0xbb, 0xff, 0xda, 0xff, 0x07, 0x00, 0x23, 0x00, 0x3a, 0x00, 0x5a, 0x00, 0x9d, 0x00, 0x06, 0x01, 0x55, 0x01, 0x6f, 0x01, 0x5a, 0x01, 0x35, 0x01, 0x22, 0x01, 0x0c, 0x01, 0xee, 0x00, 0xc7, 0x00, 0xa2, 0x00, 0x71, 0x00, 0x4e, 0x00, 0x2a, 0x00, 0x03, 0x00, 0xf6, 0xff, 0xeb, 0xff, 0xe2, 0xff, 0xd7, 0xff, 0xb6, 0xff, 0x8b, 0xff, 0x51, 0xff, 0x27, 0xff, 0x0a, 0xff, 0x10, 0xff, 0x1e, 0xff, 0x20, 0xff, 0x22, 0xff, 0x45, 0xff, 0x76, 0xff, 0x96, 0xff, 0xb1, 0xff, 0xd0, 0xff, 0xf9, 0xff, 0x23, 0x00, 0x48, 0x00, 0x7b, 0x00, 0xa3, 0x00, 0xda, 0x00, 0xd5, 0x00, 0xc8, 0x00, 0xcc, 0x00, 0xf0, 0x00, 0x18, 0x01, 0xf0, 0x00, 0x8f, 0x00, 0x42, 0x00, 0x17, 0x00, 0x13, 0x00, 0x0d, 0x00, 0x16, 0x00, 0x2b, 0x00, 0x46, 0x00, 0x3d, 0x00, 0x30, 0x00, 0x29, 0x00, 0x24, 0x00, 0x2f, 0x00, 0x22, 0x00, 0x0c, 0x00, 0xc3, 0xff, 0x83, 0xff, 0x5a, 0xff, 0x2a, 0xff, 0x18, 0xff, 0x0e, 0xff, 0x25, 0xff, 0x42, 0xff, 0x6a, 0xff, 0x83, 0xff, 0x66, 0xff, 0x3e, 0xff, 0x13, 0xff, 0x22, 0xff, 0x43, 0xff, 0x63, 0xff, 0x76, 0xff, 0xa3, 0xff, 0xb8, 0xff, 0xdd, 0xff, 0x12, 0x00, 0x50, 0x00, 0x76, 0x00, 0x8a, 0x00, 0x87, 0x00, 0x7e, 0x00, 0x81, 0x00, 0x9d, 0x00, 0x9d, 0x00, 0xa2, 0x00, 0x8c, 0x00, 0x60, 0x00, 0x27, 0x00, 0x1c, 0x00, 0x2c, 0x00, 0x5a, 0x00, 0x82, 0x00, 0x74, 0x00, 0x64, 0x00, 0x2d, 0x00, 0xf9, 0xff, 0xb5, 0xff, 0x92, 0xff, 0x89, 0xff, 0xa2, 0xff, 0xcf, 0xff, 0x05, 0x00, 0x2d, 0x00, 0x37, 0x00, 0x5d, 0x00, 0x9d, 0x00, 0xe7, 0x00, 0x0e, 0x01, 0x0e, 0x01, 0xf3, 0x00, 0xe3, 0x00, 0xdd, 0x00, 0xaf, 0x00, 0x5b, 0x00, 0x19, 0x00, 0xd2, 0xff, 0x8d, 0xff, 0x47, 0xff, 0x36, 0xff, 0x36, 0xff, 0x3a, 0xff, 0x22, 0xff, 0x06, 0xff, 0xf7, 0xfe, 0xeb, 0xfe, 0xe0, 0xfe, 0xe3, 0xfe, 0xef, 0xfe, 0xfc, 0xfe, 0x2a, 0xff, 0x50, 0xff, 0xbe, 0xff, 0x2c, 0x00, 0x6b, 0x00, 0x81, 0x00, 0x95, 0x00, 0xba, 0x00, 0xcd, 0x00, 0xd3, 0x00, 0xbc, 0x00, 0xb8, 0x00, 0xe0, 0x00, 0x05, 0x01, 0x1d, 0x01, 0xec, 0x00, 0x97, 0x00, 0x39, 0x00, 0x02, 0x00, 0xe1, 0xff, 0xdb, 0xff, 0xe0, 0xff, 0x06, 0x00, 0x2d, 0x00, 0x48, 0x00, 0x42, 0x00, 0x23, 0x00, 0x21, 0x00, 0x20, 0x00, 0x25, 0x00, 0x29, 0x00, 0x3e, 0x00, 0x56, 0x00, 0x62, 0x00, 0x69, 0x00, 0x8e, 0x00, 0x99, 0x00, 0x84, 0x00, 0x4f, 0x00, 0xf9, 0xff, 0xa3, 0xff, 0x57, 0xff, 0x32, 0xff, 0x20, 0xff, 0x24, 0xff, 0x37, 0xff, 0x45, 0xff, 0x44, 0xff, 0x28, 0xff, 0x06, 0xff, 0xf1, 0xfe, 0x00, 0xff, 0x0f, 0xff, 0x33, 0xff, 0x2d, 0xff, 0x46, 0xff, 0x58, 0xff, 0x7f, 0xff, 0xb0, 0xff, 0xff, 0xff, 0x3d, 0x00, 0x6d, 0x00, 0x92, 0x00, 0x8c, 0x00, 0x71, 0x00, 0x4b, 0x00, 0x1b, 0x00, 0xf1, 0xff, 0xdc, 0xff, 0xe1, 0xff, 0xc8, 0xff, 0x9e, 0xff, 0x71, 0xff, 0x64, 0xff, 0x6d, 0xff, 0x7c, 0xff, 0xa1, 0xff, 0xc3, 0xff, 0xc2, 0xff, 0xb7, 0xff, 0x9e, 0xff, 0x97, 0xff, 0x7d, 0xff, 0x8f, 0xff, 0xa5, 0xff, 0xb9, 0xff, 0xef, 0xff, 0x45, 0x00, 0xba, 0x00, 0xfb, 0x00, 0x1a, 0x01, 0x47, 0x01, 0x8e, 0x01, 0xc6, 0x01, 0xfc, 0x01, 0x0a, 0x02, 0xfc, 0x01, 0xf3, 0x01, 0xf8, 0x01, 0xfb, 0x01, 0xe4, 0x01, 0xc9, 0x01, 0xb6, 0x01, 0xa6, 0x01, 0x70, 0x01, 0x30, 0x01, 0xde, 0x00, 0x84, 0x00, 0x3a, 0x00, 0xde, 0xff, 0x7f, 0xff, 0x49, 0xff, 0x1d, 0xff, 0xf0, 0xfe, 0xc3, 0xfe, 0xc2, 0xfe, 0xe7, 0xfe, 0x26, 0xff, 0x55, 0xff, 0x7d, 0xff, 0xa6, 0xff, 0x9b, 0xff, 0x9c, 0xff, 0xb3, 0xff, 0xc1, 0xff, 0xbe, 0xff, 0xa4, 0xff, 0x7a, 0xff, 0x55, 0xff, 0x59, 0xff, 0x4f, 0xff, 0x3f, 0xff, 0x32, 0xff, 0x3e, 0xff, 0x55, 0xff, 0x35, 0xff, 0x27, 0xff, 0x31, 0xff, 0x3d, 0xff, 0x29, 0xff, 0x07, 0xff, 0x05, 0xff, 0x0a, 0xff, 0x06, 0xff, 0xf6, 0xfe, 0xec, 0xfe, 0xf7, 0xfe, 0xf4, 0xfe, 0xed, 0xfe, 0xd7, 0xfe, 0xd8, 0xfe, 0x03, 0xff, 0x4c, 0xff, 0x9b, 0xff, 0xeb, 0xff, 0x07, 0x00, 0x14, 0x00, 0x1a, 0x00, 0x23, 0x00, 0x28, 0x00, 0x50, 0x00, 0x8d, 0x00, 0xde, 0x00, 0x41, 0x01, 0xa9, 0x01, 0x1f, 0x02, 0x94, 0x02, 0xcb, 0x02, 0xc2, 0x02, 0x98, 0x02, 0x4c, 0x02, 0xed, 0x01, 0xca, 0x01, 0xc1, 0x01, 0xa5, 0x01, 0x81, 0x01, 0x63, 0x01, 0x26, 0x01, 0xf7, 0x00, 0xc4, 0x00, 0x81, 0x00, 0x2f, 0x00, 0xe2, 0xff, 0x70, 0xff, 0x09, 0xff, 0xc9, 0xfe, 0xb1, 0xfe, 0xb6, 0xfe, 0xbd, 0xfe, 0xcf, 0xfe, 0xf2, 0xfe, 0x10, 0xff, 0x25, 0xff, 0x3e, 0xff, 0x45, 0xff, 0x5a, 0xff, 0x41, 0xff, 0x1d, 0xff, 0xf8, 0xfe, 0xed, 0xfe, 0xe4, 0xfe, 0xf7, 0xfe, 0x28, 0xff, 0x48, 0xff, 0x64, 0xff, 0x6a, 0xff, 0x86, 0xff, 0xba, 0xff, 0xfc, 0xff, 0x42, 0x00, 0x6e, 0x00, 0x9d, 0x00, 0xd5, 0x00, 0x06, 0x01, 0x14, 0x01, 0x20, 0x01, 0x1b, 0x01, 0x0d, 0x01, 0x0a, 0x01, 0x1d, 0x01, 0x36, 0x01, 0x2e, 0x01, 0xe5, 0x00, 0x98, 0x00, 0x32, 0x00, 0xe1, 0xff, 0x92, 0xff, 0x4f, 0xff, 0x17, 0xff, 0xfa, 0xfe, 0xe0, 0xfe, 0xcf, 0xfe, 0xd5, 0xfe, 0xd9, 0xfe, 0xe0, 0xfe, 0xde, 0xfe, 0xe3, 0xfe, 0xf0, 0xfe, 0x15, 0xff, 0x35, 0xff, 0x72, 0xff, 0xaa, 0xff, 0xfd, 0xff, 0x6f, 0x00, 0xd1, 0x00, 0x24, 0x01, 0x68, 0x01, 0x68, 0x01, 0x54, 0x01, 0x37, 0x01, 0x2c, 0x01, 0x4a, 0x01, 0x63, 0x01, 0x64, 0x01, 0x35, 0x01, 0xf4, 0x00, 0xa7, 0x00, 0x5e, 0x00, 0x00, 0x00, 0xaa, 0xff, 0x65, 0xff, 0x39, 0xff, 0x18, 0xff, 0x05, 0xff, 0x25, 0xff, 0x5d, 0xff, 0xa3, 0xff, 0xcf, 0xff, 0xe1, 0xff, 0xde, 0xff, 0xb1, 0xff, 0x86, 0xff, 0x68, 0xff, 0x5e, 0xff, 0x67, 0xff, 0x8b, 0xff, 0xb9, 0xff, 0xe8, 0xff, 0x20, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x9e, 0x00, 0x99, 0x00, 0xa0, 0x00, 0xc4, 0x00, 0xed, 0x00, 0xf2, 0x00, 0xf2, 0x00, 0xdc, 0x00, 0xb0, 0x00, 0x91, 0x00, 0x83, 0x00, 0x71, 0x00, 0x25, 0x00, 0xbb, 0xff, 0x40, 0xff, 0xe2, 0xfe, 0x8e, 0xfe, 0x6a, 0xfe, 0x6a, 0xfe, 0x85, 0xfe, 0xb3, 0xfe, 0xec, 0xfe, 0x21, 0xff, 0x44, 0xff, 0x61, 0xff, 0x75, 0xff, 0x85, 0xff, 0x9b, 0xff, 0xd0, 0xff, 0x10, 0x00, 0x36, 0x00, 0x3e, 0x00, 0x14, 0x00, 0x0e, 0x00, 0x2a, 0x00, 0x6c, 0x00, 0xa6, 0x00, 0xd9, 0x00, 0xfb, 0x00, 0x41, 0x01, 0x83, 0x01, 0x94, 0x01, 0x9b, 0x01, 0x85, 0x01, 0x66, 0x01, 0x46, 0x01, 0x5a, 0x01, 0x45, 0x01, 0x33, 0x01, 0xf4, 0x00, 0xb6, 0x00, 0x62, 0x00, 0x2b, 0x00, 0xfa, 0xff, 0xcf, 0xff, 0x9e, 0xff, 0x88, 0xff, 0x66, 0xff, 0x54, 0xff, 0x2d, 0xff, 0xe6, 0xfe, 0xa8, 0xfe, 0x71, 0xfe, 0x41, 0xfe, 0x39, 0xfe, 0x38, 0xfe, 0x4e, 0xfe, 0x82, 0xfe, 0xca, 0xfe, 0x18, 0xff, 0x49, 0xff, 0x58, 0xff, 0x7f, 0xff, 0x97, 0xff, 0xa3, 0xff, 0xb9, 0xff, 0xd1, 0xff, 0xd4, 0xff, 0xe0, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xd7, 0xff, 0xcf, 0xff, 0xf5, 0xff, 0x2d, 0x00, 0x79, 0x00, 0xb4, 0x00, 0xec, 0x00, 0x08, 0x01, 0x1b, 0x01, 0x2b, 0x01, 0x1f, 0x01, 0x29, 0x01, 0x53, 0x01, 0x64, 0x01, 0x46, 0x01, 0x25, 0x01, 0x16, 0x01, 0xea, 0x00, 0xc0, 0x00, 0x79, 0x00, 0x30, 0x00, 0xe6, 0xff, 0xae, 0xff, 0x84, 0xff, 0x53, 0xff, 0x22, 0xff, 0x03, 0xff, 0xf3, 0xfe, 0xec, 0xfe, 0xf1, 0xfe, 0xe9, 0xfe, 0xe4, 0xfe, 0xdb, 0xfe, 0xcd, 0xfe, 0xc7, 0xfe, 0xdd, 0xfe, 0x11, 0xff, 0x52, 0xff, 0xcc, 0xff, 0x80, 0x00, 0x2b, 0x01, 0xa8, 0x01, 0xf5, 0x01, 0x19, 0x02, 0x0b, 0x02, 0xe4, 0x01, 0xda, 0x01, 0xe1, 0x01, 0xb2, 0x01, 0x67, 0x01, 0x1f, 0x01, 0xe4, 0x00, 0xa9, 0x00, 0x4e, 0x00, 0x00, 0x00, 0xb3, 0xff, 0x92, 0xff, 0x86, 0xff, 0x8a, 0xff, 0xa5, 0xff, 0x94, 0xff, 0x60, 0xff, 0x3f, 0xff, 0x17, 0xff, 0xfc, 0xfe, 0xd8, 0xfe, 0xcf, 0xfe, 0xc8, 0xfe, 0xcb, 0xfe, 0xdc, 0xfe, 0x07, 0xff, 0x38, 0xff, 0x70, 0xff, 0xca, 0xff, 0x15, 0x00, 0x48, 0x00, 0x57, 0x00, 0x47, 0x00, 0x64, 0x00, 0x75, 0x00, 0x82, 0x00, 0x82, 0x00, 0x7f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x60, 0x00, 0x6f, 0x00, 0x97, 0x00, 0xba, 0x00, 0xa4, 0x00, 0x6f, 0x00, 0x30, 0x00, 0xe9, 0xff, 0xb8, 0xff, 0x8d, 0xff, 0x68, 0xff, 0x41, 0xff, 0x28, 0xff, 0x1e, 0xff, 0x19, 0xff, 0x28, 0xff, 0x3c, 0xff, 0x49, 0xff, 0x59, 0xff, 0x64, 0xff, 0x76, 0xff, 0x98, 0xff, 0xc6, 0xff, 0xed, 0xff, 0x16, 0x00, 0x33, 0x00, 0x34, 0x00, 0x0f, 0x00, 0xdb, 0xff, 0xb1, 0xff, 0xad, 0xff, 0xb9, 0xff, 0xc0, 0xff, 0xc6, 0xff, 0xce, 0xff, 0xe9, 0xff, 0xef, 0xff, 0x04, 0x00, 0x42, 0x00, 0x9e, 0x00, 0x04, 0x01, 0x50, 0x01, 0x5e, 0x01, 0x54, 0x01, 0x49, 0x01, 0x30, 0x01, 0xfd, 0x00, 0xd4, 0x00, 0xc2, 0x00, 0xa0, 0x00, 0x99, 0x00, 0x9f, 0x00, 0xa7, 0x00, 0xa1, 0x00, 0x8d, 0x00, 0x54, 0x00, 0x21, 0x00, 0xf9, 0xff, 0xe4, 0xff, 0xc2, 0xff, 0xb2, 0xff, 0x97, 0xff, 0x72, 0xff, 0x4f, 0xff, 0x46, 0xff, 0x59, 0xff, 0x66, 0xff, 0x4e, 0xff, 0x39, 0xff, 0x2c, 0xff, 0x20, 0xff, 0x11, 0xff, 0x09, 0xff, 0xed, 0xfe, 0xd8, 0xfe, 0xd8, 0xfe, 0xd2, 0xfe, 0xd0, 0xfe, 0xcc, 0xfe, 0xd1, 0xfe, 0xd2, 0xfe, 0xe0, 0xfe, 0x00, 0xff, 0x4d, 0xff, 0xa3, 0xff, 0xf7, 0xff, 0x36, 0x00, 0x66, 0x00, 0x8c, 0x00, 0xb0, 0x00, 0x03, 0x01, 0x58, 0x01, 0xb1, 0x01, 0x07, 0x02, 0x5c, 0x02, 0x76, 0x02, 0x5c, 0x02, 0x33, 0x02, 0x17, 0x02, 0x1f, 0x02, 0x05, 0x02, 0x0a, 0x02, 0x1a, 0x02, 0x11, 0x02, 0xc8, 0x01, 0x64, 0x01, 0xf9, 0x00, 0x99, 0x00, 0x65, 0x00, 0x30, 0x00, 0xe5, 0xff, 0x93, 0xff, 0x4b, 0xff, 0xef, 0xfe, 0xa5, 0xfe, 0x5e, 0xfe, 0x36, 0xfe, 0x14, 0xfe, 0xf7, 0xfd, 0xd7, 0xfd, 0xcb, 0xfd, 0xd9, 0xfd, 0xfc, 0xfd, 0x20, 0xfe, 0x51, 0xfe, 0x79, 0xfe, 0xa7, 0xfe, 0xbe, 0xfe, 0xe1, 0xfe, 0xf0, 0xfe, 0x12, 0xff, 0x36, 0xff, 0x73, 0xff, 0xb6, 0xff, 0xf5, 0xff, 0x27, 0x00, 0x61, 0x00, 0xa5, 0x00, 0xde, 0x00, 0x06, 0x01, 0x25, 0x01, 0x3e, 0x01, 0x75, 0x01, 0xc4, 0x01, 0x17, 0x02, 0x60, 0x02, 0x79, 0x02, 0x8c, 0x02, 0x86, 0x02, 0xa1, 0x02, 0x8a, 0x02, 0x0e, 0x02, 0x61, 0x01, 0x9b, 0x00, 0xe8, 0xff, 0x64, 0xff, 0x10, 0xff, 0xc2, 0xfe, 0x77, 0xfe, 0x3a, 0xfe, 0x25, 0xfe, 0x2b, 0xfe, 0x58, 0xfe, 0x89, 0xfe, 0xbd, 0xfe, 0xeb, 0xfe, 0x23, 0xff, 0x47, 0xff, 0x6f, 0xff, 0x78, 0xff, 0x7e, 0xff, 0x98, 0xff, 0xb4, 0xff, 0xf9, 0xff, 0x48, 0x00, 0x82, 0x00, 0xc1, 0x00, 0xed, 0x00, 0x03, 0x01, 0x00, 0x01, 0x05, 0x01, 0x15, 0x01, 0x2e, 0x01, 0x22, 0x01, 0x02, 0x01, 0xc4, 0x00, 0x7a, 0x00, 0x29, 0x00, 0xd2, 0xff, 0x88, 0xff, 0x64, 0xff, 0x49, 0xff, 0x3c, 0xff, 0x16, 0xff, 0xf9, 0xfe, 0xf1, 0xfe, 0x01, 0xff, 0x09, 0xff, 0x07, 0xff, 0xee, 0xfe, 0xdc, 0xfe, 0xcb, 0xfe, 0xd0, 0xfe, 0xd8, 0xfe, 0xf0, 0xfe, 0x1c, 0xff, 0x46, 0xff, 0x8e, 0xff, 0xc8, 0xff, 0x12, 0x00, 0x51, 0x00, 0x9c, 0x00, 0xd9, 0x00, 0x0f, 0x01, 0x0e, 0x01, 0x05, 0x01, 0x0a, 0x01, 0x12, 0x01, 0x09, 0x01, 0xfd, 0x00, 0xfc, 0x00, 0xe5, 0x00, 0xcb, 0x00, 0xba, 0x00, 0xc2, 0x00, 0xb3, 0x00, 0x9d, 0x00, 0x76, 0x00, 0x42, 0x00, 0x07, 0x00, 0xcf, 0xff, 0xa4, 0xff, 0x6a, 0xff, 0x3e, 0xff, 0x23, 0xff, 0x17, 0xff, 0x23, 0xff, 0x2b, 0xff, 0x2e, 0xff, 0x25, 0xff, 0x1e, 0xff, 0x2d, 0xff, 0x32, 0xff, 0x3d, 0xff, 0x49, 0xff, 0x5e, 0xff, 0x78, 0xff, 0x91, 0xff, 0x92, 0xff, 0x8b, 0xff, 0x80, 0xff, 0x8e, 0xff, 0xb4, 0xff, 0xdd, 0xff, 0x02, 0x00, 0x0e, 0x00, 0x2b, 0x00, 0x4e, 0x00, 0x7c, 0x00, 0xbb, 0x00, 0xd8, 0x00, 0xcc, 0x00, 0x9a, 0x00, 0x7a, 0x00, 0x63, 0x00, 0x66, 0x00, 0x5e, 0x00, 0x5e, 0x00, 0x59, 0x00, 0x42, 0x00, 0x2a, 0x00, 0x23, 0x00, 0x2c, 0x00, 0x16, 0x00, 0x00, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x54, 0x00, 0x52, 0x00, 0x4a, 0x00, 0x63, 0x00, 0x87, 0x00, 0x97, 0x00, 0xb4, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe3, 0x00, 0xf0, 0x00, 0xf2, 0x00, 0xf6, 0x00, 0xe5, 0x00, 0xa5, 0x00, 0x4a, 0x00, 0xdd, 0xff, 0x7e, 0xff, 0x3b, 0xff, 0x1c, 0xff, 0xef, 0xfe, 0xdb, 0xfe, 0xc6, 0xfe, 0xd0, 0xfe, 0xf2, 0xfe, 0x1c, 0xff, 0x46, 0xff, 0x5a, 0xff, 0x57, 0xff, 0x5b, 0xff, 0x5b, 0xff, 0x80, 0xff, 0xdf, 0xff, 0x38, 0x00, 0x79, 0x00, 0x95, 0x00, 0xba, 0x00, 0xbe, 0x00, 0xb7, 0x00, 0x8d, 0x00, 0x55, 0x00, 0x34, 0x00, 0x3b, 0x00, 0x4b, 0x00, 0x58, 0x00, 0x48, 0x00, 0x3c, 0x00, 0x41, 0x00, 0x54, 0x00, 0x65, 0x00, 0x67, 0x00, 0x45, 0x00, 0x07, 0x00, 0xcf, 0xff, 0xbb, 0xff, 0xaf, 0xff, 0x9e, 0xff, 0x96, 0xff, 0xa2, 0xff, 0xc0, 0xff, 0xe1, 0xff, 0xd8, 0xff, 0xc5, 0xff, 0xbf, 0xff, 0xbd, 0xff, 0xbc, 0xff, 0x8c, 0xff, 0x51, 0xff, 0x31, 0xff, 0x3f, 0xff, 0x85, 0xff, 0xd6, 0xff, 0x15, 0x00, 0x42, 0x00, 0x64, 0x00, 0x8b, 0x00, 0x80, 0x00, 0x7d, 0x00, 0x71, 0x00, 0x62, 0x00, 0x69, 0x00, 0x8d, 0x00, 0xc3, 0x00, 0x02, 0x01, 0x1f, 0x01, 0x19, 0x01, 0x0f, 0x01, 0x17, 0x01, 0x22, 0x01, 0x23, 0x01, 0x04, 0x01, 0xe5, 0x00, 0x9f, 0x00, 0x55, 0x00, 0xf9, 0xff, 0xa4, 0xff, 0x46, 0xff, 0xf8, 0xfe, 0xb4, 0xfe, 0x8a, 0xfe, 0x60, 0xfe, 0x35, 0xfe, 0x0d, 0xfe, 0xfe, 0xfd, 0xf9, 0xfd, 0x18, 0xfe, 0x65, 0xfe, 0xc6, 0xfe, 0x33, 0xff, 0x6f, 0xff, 0x94, 0xff, 0xa3, 0xff, 0xc3, 0xff, 0xf1, 0xff, 0x0a, 0x00, 0xff, 0xff, 0xf9, 0xff, 0x0a, 0x00, 0x47, 0x00, 0x7d, 0x00, 0xab, 0x00, 0xb3, 0x00, 0xb1, 0x00, 0x9a, 0x00, 0x97, 0x00, 0x9b, 0x00, 0x9e, 0x00, 0xaa, 0x00, 0xb6, 0x00, 0x9d, 0x00, 0x91, 0x00, 0x92, 0x00, 0xa2, 0x00, 0xc2, 0x00, 0x01, 0x01, 0x4e, 0x01, 0x8f, 0x01, 0xb8, 0x01, 0xb2, 0x01, 0x9b, 0x01, 0x57, 0x01, 0x0d, 0x01, 0xc6, 0x00, 0x90, 0x00, 0x5c, 0x00, 0x2d, 0x00, 0x0d, 0x00, 0xee, 0xff, 0xb4, 0xff, 0x6a, 0xff, 0x1c, 0xff, 0xcd, 0xfe, 0x8a, 0xfe, 0x5a, 0xfe, 0x3f, 0xfe, 0x35, 0xfe, 0x38, 0xfe, 0x41, 0xfe, 0x3c, 0xfe, 0x38, 0xfe, 0x52, 0xfe, 0x90, 0xfe, 0xe7, 0xfe, 0x30, 0xff, 0x75, 0xff, 0xb5, 0xff, 0xff, 0xff, 0x63, 0x00, 0xcd, 0x00, 0x37, 0x01, 0x96, 0x01, 0xe6, 0x01, 0x32, 0x02, 0x7d, 0x02, 0xba, 0x02, 0xe5, 0x02, 0xde, 0x02, 0xcf, 0x02, 0xa7, 0x02, 0x57, 0x02, 0xe4, 0x01, 0x83, 0x01, 0x22, 0x01, 0xb7, 0x00, 0x5c, 0x00, 0x05, 0x00, 0xc3, 0xff, 0x86, 0xff, 0x4d, 0xff, 0x04, 0xff, 0xc7, 0xfe, 0x9c, 0xfe, 0x6a, 0xfe, 0x4e, 0xfe, 0x3f, 0xfe, 0x28, 0xfe, 0x0b, 0xfe, 0xdb, 0xfd, 0xc2, 0xfd, 0xbb, 0xfd, 0xca, 0xfd, 0xdb, 0xfd, 0xf3, 0xfd, 0xf9, 0xfd, 0x12, 0xfe, 0x42, 0xfe, 0x82, 0xfe, 0xd6, 0xfe, 0x28, 0xff, 0x70, 0xff, 0xc4, 0xff, 0x30, 0x00, 0xb5, 0x00, 0x29, 0x01, 0x8e, 0x01, 0xea, 0x01, 0x52, 0x02, 0xbd, 0x02, 0xfe, 0x02, 0x1b, 0x03, 0x09, 0x03, 0xf8, 0x02, 0xe0, 0x02, 0xa0, 0x02, 0x51, 0x02, 0x10, 0x02, 0xe9, 0x01, 0x7a, 0x01, 0x01, 0x01, 0x93, 0x00, 0x23, 0x00, 0xc7, 0xff, 0x66, 0xff, 0xf6, 0xfe, 0xa7, 0xfe, 0x87, 0xfe, 0x6b, 0xfe, 0x74, 0xfe, 0x74, 0xfe, 0x81, 0xfe, 0x85, 0xfe, 0x83, 0xfe, 0x87, 0xfe, 0x99, 0xfe, 0xc1, 0xfe, 0xea, 0xfe, 0x1e, 0xff, 0x6c, 0xff, 0xce, 0xff, 0x29, 0x00, 0x68, 0x00, 0xaf, 0x00, 0xed, 0x00, 0x2c, 0x01, 0x3d, 0x01, 0x46, 0x01, 0x1e, 0x01, 0xd8, 0x00, 0x72, 0x00, 0x1d, 0x00, 0xef, 0xff, 0xba, 0xff, 0x8b, 0xff, 0x3e, 0xff, 0x07, 0xff, 0xcf, 0xfe, 0xb8, 0xfe, 0xb0, 0xfe, 0xc7, 0xfe, 0xd9, 0xfe, 0xe2, 0xfe, 0xd1, 0xfe, 0xc6, 0xfe, 0xb4, 0xfe, 0xba, 0xfe, 0xca, 0xfe, 0xf5, 0xfe, 0x02, 0xff, 0x0a, 0xff, 0x27, 0xff, 0x43, 0xff, 0x50, 0xff, 0x6a, 0xff, 0xbc, 0xff, 0x20, 0x00, 0x97, 0x00, 0x06, 0x01, 0x7c, 0x01, 0xf7, 0x01, 0x38, 0x02, 0x66, 0x02, 0x80, 0x02, 0x81, 0x02, 0x71, 0x02, 0x58, 0x02, 0x50, 0x02, 0x4f, 0x02, 0x30, 0x02, 0xe4, 0x01, 0x85, 0x01, 0x15, 0x01, 0xa1, 0x00, 0x1c, 0x00, 0x99, 0xff, 0x33, 0xff, 0xe6, 0xfe, 0xb5, 0xfe, 0xa7, 0xfe, 0x96, 0xfe, 0x70, 0xfe, 0x39, 0xfe, 0x2a, 0xfe, 0x27, 0xfe, 0x2f, 0xfe, 0x44, 0xfe, 0x5f, 0xfe, 0x78, 0xfe, 0x98, 0xfe, 0xaf, 0xfe, 0xbf, 0xfe, 0xe1, 0xfe, 0x0c, 0xff, 0x34, 0xff, 0x59, 0xff, 0x7c, 0xff, 0xa6, 0xff, 0xd8, 0xff, 0x09, 0x00, 0x3d, 0x00, 0x6d, 0x00, 0xa6, 0x00, 0xb3, 0x00, 0xac, 0x00, 0xc3, 0x00, 0xe7, 0x00, 0x35, 0x01, 0x7f, 0x01, 0xa6, 0x01, 0xdd, 0x01, 0x29, 0x02, 0x7f, 0x02, 0xad, 0x02, 0x96, 0x02, 0x62, 0x02, 0x20, 0x02, 0xcb, 0x01, 0x71, 0x01, 0x2a, 0x01, 0xee, 0x00, 0xa4, 0x00, 0x2b, 0x00, 0xb0, 0xff, 0x35, 0xff, 0xc6, 0xfe, 0x76, 0xfe, 0x31, 0xfe, 0x14, 0xfe, 0x09, 0xfe, 0x22, 0xfe, 0x56, 0xfe, 0x9f, 0xfe, 0xd4, 0xfe, 0x1e, 0xff, 0x4f, 0xff, 0x75, 0xff, 0x80, 0xff, 0x82, 0xff, 0x8b, 0xff, 0x9e, 0xff, 0xbf, 0xff, 0xda, 0xff, 0xf5, 0xff, 0xf3, 0xff, 0xe3, 0xff, 0xdc, 0xff, 0xec, 0xff, 0xe9, 0xff, 0xdb, 0xff, 0xce, 0xff, 0xc5, 0xff, 0xbf, 0xff, 0xcf, 0xff, 0xe9, 0xff, 0x0e, 0x00, 0x4a, 0x00, 0x8b, 0x00, 0xc8, 0x00, 0xf3, 0x00, 0x17, 0x01, 0x20, 0x01, 0x18, 0x01, 0x26, 0x01, 0x38, 0x01, 0x37, 0x01, 0x17, 0x01, 0xd5, 0x00, 0x7c, 0x00, 0x2b, 0x00, 0xf7, 0xff, 0xc2, 0xff, 0x87, 0xff, 0x40, 0xff, 0xeb, 0xfe, 0xa5, 0xfe, 0x78, 0xfe, 0x64, 0xfe, 0x54, 0xfe, 0x63, 0xfe, 0x5b, 0xfe, 0x61, 0xfe, 0x81, 0xfe, 0x8f, 0xfe, 0x97, 0xfe, 0x9e, 0xfe, 0xc5, 0xfe, 0xfe, 0xfe, 0x29, 0xff, 0x4f, 0xff, 0x81, 0xff, 0xc6, 0xff, 0x21, 0x00, 0x80, 0x00, 0xd4, 0x00, 0x2a, 0x01, 0x62, 0x01, 0x8e, 0x01, 0xd2, 0x01, 0x25, 0x02, 0x69, 0x02, 0x95, 0x02, 0x75, 0x02, 0x35, 0x02, 0x0b, 0x02, 0xdc, 0x01, 0xc4, 0x01, 0x8b, 0x01, 0x33, 0x01, 0xdd, 0x00, 0x84, 0x00, 0x3f, 0x00, 0xfd, 0xff, 0xd4, 0xff, 0xa4, 0xff, 0x7d, 0xff, 0x35, 0xff, 0xf9, 0xfe, 0xcc, 0xfe, 0xaa, 0xfe, 0x9c, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x80, 0xfe, 0xa8, 0xfe, 0xcf, 0xfe, 0x14, 0xff, 0x3f, 0xff, 0x77, 0xff, 0xa4, 0xff, 0xd8, 0xff, 0xf0, 0xff, 0x03, 0x00, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0xfd, 0xff, 0xf9, 0xff, 0xfe, 0xff, 0x30, 0x00, 0x73, 0x00, 0xa8, 0x00, 0xc6, 0x00, 0xcc, 0x00, 0xf6, 0x00, 0x22, 0x01, 0x65, 0x01, 0x94, 0x01, 0x9a, 0x01, 0x7b, 0x01, 0x21, 0x01, 0xb9, 0x00, 0x5d, 0x00, 0x26, 0x00, 0xd9, 0xff, 0x97, 0xff, 0x64, 0xff, 0x3c, 0xff, 0x1b, 0xff, 0x0c, 0xff, 0x32, 0xff, 0x62, 0xff, 0x89, 0xff, 0xa4, 0xff, 0xc2, 0xff, 0xdc, 0xff, 0xee, 0xff, 0xfb, 0xff, 0x02, 0x00, 0x05, 0x00, 0xed, 0xff, 0xd3, 0xff, 0xab, 0xff, 0x77, 0xff, 0x2f, 0xff, 0xec, 0xfe, 0xcf, 0xfe, 0xcb, 0xfe, 0xec, 0xfe, 0x09, 0xff, 0x31, 0xff, 0x4f, 0xff, 0x85, 0xff, 0xb4, 0xff, 0xc8, 0xff, 0xcb, 0xff, 0xc6, 0xff, 0xe6, 0xff, 0x2a, 0x00, 0x6d, 0x00, 0xa2, 0x00, 0xda, 0x00, 0xd5, 0x00, 0xce, 0x00, 0xdb, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xe1, 0x00, 0xa1, 0x00, 0x55, 0x00, 0x11, 0x00, 0xed, 0xff, 0xe7, 0xff, 0xc5, 0xff, 0xa3, 0xff, 0x6c, 0xff, 0x48, 0xff, 0x3e, 0xff, 0x47, 0xff, 0x5d, 0xff, 0x6a, 0xff, 0x84, 0xff, 0xa7, 0xff, 0xfb, 0xff, 0x29, 0x00, 0x45, 0x00, 0x44, 0x00, 0x38, 0x00, 0x39, 0x00, 0x2f, 0x00, 0x12, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x02, 0x00, 0x14, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0xfb, 0xff, 0x20, 0x00, 0x43, 0x00, 0x5e, 0x00, 0x61, 0x00, 0x51, 0x00, 0x49, 0x00, 0x47, 0x00, 0x3f, 0x00, 0x4c, 0x00, 0x4e, 0x00, 0x50, 0x00, 0x50, 0x00, 0x3f, 0x00, 0x1a, 0x00, 0xf7, 0xff, 0xed, 0xff, 0xf8, 0xff, 0xfe, 0xff, 0xe8, 0xff, 0xb8, 0xff, 0x7c, 0xff, 0x41, 0xff, 0x12, 0xff, 0xea, 0xfe, 0xbe, 0xfe, 0x95, 0xfe, 0x7b, 0xfe, 0x5b, 0xfe, 0x5e, 0xfe, 0x72, 0xfe, 0xb1, 0xfe, 0x10, 0xff, 0x86, 0xff, 0xf1, 0xff, 0x50, 0x00, 0xc4, 0x00, 0x34, 0x01, 0xae, 0x01, 0xff, 0x01, 0x37, 0x02, 0x68, 0x02, 0x6d, 0x02, 0x48, 0x02, 0xf5, 0x01, 0x9e, 0x01, 0x48, 0x01, 0x1d, 0x01, 0x17, 0x01, 0x15, 0x01, 0x04, 0x01, 0xed, 0x00, 0xcb, 0x00, 0xc9, 0x00, 0xc4, 0x00, 0xc2, 0x00, 0xaa, 0x00, 0x7a, 0x00, 0x4a, 0x00, 0x19, 0x00, 0xf1, 0xff, 0xd5, 0xff, 0xc1, 0xff, 0xa6, 0xff, 0x71, 0xff, 0x29, 0xff, 0xea, 0xfe, 0xb6, 0xfe, 0x96, 0xfe, 0x8a, 0xfe, 0x85, 0xfe, 0x98, 0xfe, 0xa9, 0xfe, 0xcf, 0xfe, 0xfa, 0xfe, 0x38, 0xff, 0x8e, 0xff, 0xda, 0xff, 0x0d, 0x00, 0x47, 0x00, 0x7d, 0x00, 0xa4, 0x00, 0xbc, 0x00, 0xd1, 0x00, 0x02, 0x01, 0x32, 0x01, 0x8a, 0x01, 0xc3, 0x01, 0xd8, 0x01, 0xca, 0x01, 0xa5, 0x01, 0x8f, 0x01, 0x73, 0x01, 0x43, 0x01, 0xeb, 0x00, 0x8e, 0x00, 0x2c, 0x00, 0xda, 0xff, 0x7b, 0xff, 0x37, 0xff, 0xf0, 0xfe, 0xc2, 0xfe, 0x96, 0xfe, 0x87, 0xfe, 0x81, 0xfe, 0x7e, 0xfe, 0x5f, 0xfe, 0x4e, 0xfe, 0x44, 0xfe, 0x45, 0xfe, 0x50, 0xfe, 0x5a, 0xfe, 0x59, 0xfe, 0x66, 0xfe, 0x73, 0xfe, 0x82, 0xfe, 0xa3, 0xfe, 0xd3, 0xfe, 0x08, 0xff, 0x3d, 0xff, 0x76, 0xff, 0xc5, 0xff, 0x16, 0x00, 0x77, 0x00, 0xc9, 0x00, 0x10, 0x01, 0x27, 0x01, 0x32, 0x01, 0x2f, 0x01, 0x47, 0x01, 0x75, 0x01, 0x91, 0x01, 0x96, 0x01, 0x8e, 0x01, 0x84, 0x01, 0x9e, 0x01, 0x92, 0x01, 0x6e, 0x01, 0x4b, 0x01, 0x13, 0x01, 0xdb, 0x00, 0x82, 0x00, 0x3a, 0x00, 0x02, 0x00, 0xda, 0xff, 0xc6, 0xff, 0xad, 0xff, 0xa3, 0xff, 0x86, 0xff, 0x9a, 0xff, 0xd7, 0xff, 0x1f, 0x00, 0x2f, 0x00, 0x19, 0x00, 0xec, 0xff, 0xac, 0xff, 0x5e, 0xff, 0x1c, 0xff, 0xed, 0xfe, 0xcf, 0xfe, 0xb6, 0xfe, 0xc9, 0xfe, 0xe0, 0xfe, 0x10, 0xff, 0x36, 0xff, 0x4f, 0xff, 0x85, 0xff, 0xd5, 0xff, 0x38, 0x00, 0x6f, 0x00, 0x96, 0x00, 0xb7, 0x00, 0xc8, 0x00, 0xe1, 0x00, 0xf8, 0x00, 0xfd, 0x00, 0xee, 0x00, 0xdb, 0x00, 0xb9, 0x00, 0x7b, 0x00, 0x51, 0x00, 0x16, 0x00, 0xe5, 0xff, 0xab, 0xff, 0x78, 0xff, 0x68, 0xff, 0x70, 0xff, 0x77, 0xff, 0x54, 0xff, 0x16, 0xff, 0xf6, 0xfe, 0xf3, 0xfe, 0xfc, 0xfe, 0xf3, 0xfe, 0x03, 0xff, 0x05, 0xff, 0x2a, 0xff, 0x6b, 0xff, 0xab, 0xff, 0xe4, 0xff, 0x33, 0x00, 0x73, 0x00, 0x94, 0x00, 0xa9, 0x00, 0xca, 0x00, 0xf3, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfd, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xf8, 0x00, 0x0c, 0x01, 0x1e, 0x01, 0x0c, 0x01, 0x12, 0x01, 0x11, 0x01, 0x09, 0x01, 0xe3, 0x00, 0x99, 0x00, 0x61, 0x00, 0x21, 0x00, 0xe4, 0xff, 0x8d, 0xff, 0x55, 0xff, 0x20, 0xff, 0xf7, 0xfe, 0xc1, 0xfe, 0x92, 0xfe, 0x75, 0xfe, 0x60, 0xfe, 0x4e, 0xfe, 0x56, 0xfe, 0x60, 0xfe, 0x76, 0xfe, 0x95, 0xfe, 0xc3, 0xfe, 0xeb, 0xfe, 0x19, 0xff, 0x5c, 0xff, 0x80, 0xff, 0xa9, 0xff, 0xcd, 0xff, 0x00, 0x00, 0x3f, 0x00, 0x59, 0x00, 0x67, 0x00, 0x6d, 0x00, 0xa7, 0x00, 0xe2, 0x00, 0x15, 0x01, 0x56, 0x01, 0xa2, 0x01, 0xc1, 0x01, 0xb6, 0x01, 0x90, 0x01, 0x60, 0x01, 0x17, 0x01, 0xc8, 0x00, 0x5e, 0x00, 0x02, 0x00, 0xbb, 0xff, 0x94, 0xff, 0x89, 0xff, 0x9c, 0xff, 0xae, 0xff, 0xd2, 0xff, 0x07, 0x00, 0x3e, 0x00, 0x72, 0x00, 0x93, 0x00, 0x9b, 0x00, 0xc4, 0x00, 0xf1, 0x00, 0x15, 0x01, 0x40, 0x01, 0x63, 0x01, 0x6c, 0x01, 0x38, 0x01, 0xeb, 0x00, 0x98, 0x00, 0x4e, 0x00, 0x01, 0x00, 0xd6, 0xff, 0xb3, 0xff, 0xa6, 0xff, 0x98, 0xff, 0x6b, 0xff, 0x41, 0xff, 0x2b, 0xff, 0x11, 0xff, 0xf5, 0xfe, 0xec, 0xfe, 0xeb, 0xfe, 0xe6, 0xfe, 0xe6, 0xfe, 0xd9, 0xfe, 0xd4, 0xfe, 0xd0, 0xfe, 0xc9, 0xfe, 0xd1, 0xfe, 0xd6, 0xfe, 0xe3, 0xfe, 0xfe, 0xfe, 0x1a, 0xff, 0x55, 0xff, 0xa4, 0xff, 0x0a, 0x00, 0x6c, 0x00, 0xc8, 0x00, 0x2a, 0x01, 0x70, 0x01, 0x8b, 0x01, 0x79, 0x01, 0x5d, 0x01, 0x55, 0x01, 0x50, 0x01, 0x53, 0x01, 0x3f, 0x01, 0x37, 0x01, 0x17, 0x01, 0xe2, 0x00, 0x9e, 0x00, 0x61, 0x00, 0x1e, 0x00, 0xe5, 0xff, 0x9a, 0xff, 0x5c, 0xff, 0x19, 0xff, 0xf6, 0xfe, 0xdf, 0xfe, 0xdc, 0xfe, 0xdd, 0xfe, 0xda, 0xfe, 0xc7, 0xfe, 0xe0, 0xfe, 0xfb, 0xfe, 0x31, 0xff, 0x55, 0xff, 0x82, 0xff, 0xa9, 0xff, 0xd1, 0xff, 0xe5, 0xff, 0xf5, 0xff, 0x01, 0x00, 0x16, 0x00, 0x35, 0x00, 0x4d, 0x00, 0x60, 0x00, 0x73, 0x00, 0x73, 0x00, 0x77, 0x00, 0x81, 0x00, 0x76, 0x00, 0x55, 0x00, 0x1f, 0x00, 0xf5, 0xff, 0xcb, 0xff, 0xae, 0xff, 0xa5, 0xff, 0x9a, 0xff, 0x8f, 0xff, 0x89, 0xff, 0x73, 0xff, 0x68, 0xff, 0x58, 0xff, 0x50, 0xff, 0x4d, 0xff, 0x5a, 0xff, 0x66, 0xff, 0x75, 0xff, 0x95, 0xff, 0xc4, 0xff, 0xe6, 0xff, 0x02, 0x00, 0x1a, 0x00, 0x2f, 0x00, 0x44, 0x00, 0x51, 0x00, 0x5d, 0x00, 0x6f, 0x00, 0x8a, 0x00, 0x99, 0x00, 0xa4, 0x00, 0xc7, 0x00, 0xed, 0x00, 0x06, 0x01, 0x10, 0x01, 0x11, 0x01, 0x0c, 0x01, 0xf6, 0x00, 0xf1, 0x00, 0xda, 0x00, 0xda, 0x00, 0xbb, 0x00, 0x99, 0x00, 0x82, 0x00, 0x78, 0x00, 0x67, 0x00, 0x4c, 0x00, 0x10, 0x00, 0x13, 0x00, 0x05, 0x00, 0x08, 0x00, 0x03, 0x00, 0x21, 0x00, 0x39, 0x00, 0x56, 0x00, 0x68, 0x00, 0x4c, 0x00, 0x29, 0x00, 0xee, 0xff, 0xc2, 0xff, 0x95, 0xff, 0x7c, 0xff, 0x50, 0xff, 0x25, 0xff, 0xf2, 0xfe, 0xd9, 0xfe, 0xdd, 0xfe, 0xf3, 0xfe, 0xfc, 0xfe, 0x17, 0xff, 0x33, 0xff, 0x3c, 0xff, 0x48, 0xff, 0x42, 0xff, 0x40, 0xff, 0x50, 0xff, 0x7d, 0xff, 0xbc, 0xff, 0x19, 0x00, 0x78, 0x00, 0xe3, 0x00, 0x6c, 0x01, 0xee, 0x01, 0x36, 0x02, 0x58, 0x02, 0x54, 0x02, 0x22, 0x02, 0xd6, 0x01, 0x84, 0x01, 0x39, 0x01, 0xe5, 0x00, 0x97, 0x00, 0x3d, 0x00, 0xe9, 0xff, 0x90, 0xff, 0x3c, 0xff, 0xe3, 0xfe, 0x9a, 0xfe, 0x79, 0xfe, 0x7c, 0xfe, 0x82, 0xfe, 0x87, 0xfe, 0x8d, 0xfe, 0x8f, 0xfe, 0x9b, 0xfe, 0xb6, 0xfe, 0xe2, 0xfe, 0x14, 0xff, 0x37, 0xff, 0x61, 0xff, 0x80, 0xff, 0x94, 0xff, 0xaa, 0xff, 0xcc, 0xff, 0xf7, 0xff, 0x2c, 0x00, 0x46, 0x00, 0x4e, 0x00, 0x56, 0x00, 0x8e, 0x00, 0xf2, 0x00, 0x37, 0x01, 0x67, 0x01, 0x5a, 0x01, 0x39, 0x01, 0x01, 0x01, 0xd5, 0x00, 0xa3, 0x00, 0x7a, 0x00, 0x5d, 0x00, 0x5d, 0x00, 0x50, 0x00, 0x48, 0x00, 0x4d, 0x00, 0x63, 0x00, 0x85, 0x00, 0x90, 0x00, 0x8a, 0x00, 0x5b, 0x00, 0x33, 0x00, 0x12, 0x00, 0xef, 0xff, 0xc9, 0xff, 0xa4, 0xff, 0x79, 0xff, 0x55, 0xff, 0x35, 0xff, 0x04, 0xff, 0xf2, 0xfe, 0xd3, 0xfe, 0xdb, 0xfe, 0xdb, 0xfe, 0xf7, 0xfe, 0x25, 0xff, 0x61, 0xff, 0xb6, 0xff, 0x07, 0x00, 0x5f, 0x00, 0xa8, 0x00, 0xe7, 0x00, 0x1b, 0x01, 0x33, 0x01, 0x32, 0x01, 0x26, 0x01, 0x1a, 0x01, 0xf6, 0x00, 0xbd, 0x00, 0x86, 0x00, 0x4c, 0x00, 0x2c, 0x00, 0x0d, 0x00, 0xe2, 0xff, 0xd1, 0xff, 0xb6, 0xff, 0xaf, 0xff, 0x90, 0xff, 0x75, 0xff, 0x59, 0xff, 0x48, 0xff, 0x48, 0xff, 0x40, 0xff, 0x2f, 0xff, 0x0f, 0xff, 0xf5, 0xfe, 0xe3, 0xfe, 0xed, 0xfe, 0x00, 0xff, 0x2e, 0xff, 0x88, 0xff, 0xed, 0xff, 0x55, 0x00, 0xbf, 0x00, 0xff, 0x00, 0x18, 0x01, 0xf4, 0x00, 0xb5, 0x00, 0x59, 0x00, 0x0c, 0x00, 0xb8, 0xff, 0x78, 0xff, 0x56, 0xff, 0x33, 0xff, 0x2e, 0xff, 0x41, 0xff, 0x64, 0xff, 0xaa, 0xff, 0xe7, 0xff, 0x27, 0x00, 0x4e, 0x00, 0x73, 0x00, 0x8e, 0x00, 0xae, 0x00, 0xd0, 0x00, 0xea, 0x00, 0xee, 0x00, 0xea, 0x00, 0xe7, 0x00, 0xe9, 0x00, 0xca, 0x00, 0xbe, 0x00, 0xa1, 0x00, 0x93, 0x00, 0x82, 0x00, 0x71, 0x00, 0x54, 0x00, 0x3b, 0x00, 0x1e, 0x00, 0xf0, 0xff, 0xc5, 0xff, 0x86, 0xff, 0x47, 0xff, 0x18, 0xff, 0x07, 0xff, 0x0b, 0xff, 0x11, 0xff, 0x16, 0xff, 0x27, 0xff, 0x2f, 0xff, 0x48, 0xff, 0x62, 0xff, 0xa5, 0xff, 0xfe, 0xff, 0x74, 0x00, 0xd8, 0x00, 0x33, 0x01, 0x64, 0x01, 0x98, 0x01, 0xa7, 0x01, 0x9c, 0x01, 0x74, 0x01, 0x3a, 0x01, 0xfb, 0x00, 0xb4, 0x00, 0x7a, 0x00, 0x43, 0x00, 0x05, 0x00, 0xc3, 0xff, 0x82, 0xff, 0x4e, 0xff, 0x29, 0xff, 0xfb, 0xfe, 0xe4, 0xfe, 0xcf, 0xfe, 0xc0, 0xfe, 0xc8, 0xfe, 0xcf, 0xfe, 0xf2, 0xfe, 0x03, 0xff, 0x19, 0xff, 0x47, 0xff, 0x74, 0xff, 0xb0, 0xff, 0xc8, 0xff, 0xed, 0xff, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, 0x11, 0x00, 0x24, 0x00, 0x33, 0x00, 0x4c, 0x00, 0x7c, 0x00, 0xb2, 0x00, 0xea, 0x00, 0x1f, 0x01, 0x42, 0x01, 0x6c, 0x01, 0x6d, 0x01, 0x6c, 0x01, 0x3d, 0x01, 0x13, 0x01, 0xcf, 0x00, 0x74, 0x00, 0x18, 0x00, 0xc4, 0xff, 0x86, 0xff, 0x4d, 0xff, 0x13, 0xff, 0xdc, 0xfe, 0xb1, 0xfe, 0xa6, 0xfe, 0x99, 0xfe, 0x91, 0xfe, 0x82, 0xfe, 0x85, 0xfe, 0x98, 0xfe, 0xa6, 0xfe, 0xbe, 0xfe, 0xdc, 0xfe, 0x07, 0xff, 0x40, 0xff, 0x88, 0xff, 0xf4, 0xff, 0x3c, 0x00, 0x8b, 0x00, 0xcd, 0x00, 0xff, 0x00, 0x28, 0x01, 0x50, 0x01, 0x77, 0x01, 0x94, 0x01, 0xb0, 0x01, 0xaf, 0x01, 0x91, 0x01, 0x5c, 0x01, 0x32, 0x01, 0xf1, 0x00, 0xaa, 0x00, 0x6b, 0x00, 0x41, 0x00, 0x10, 0x00, 0xeb, 0xff, 0xc1, 0xff, 0xc0, 0xff, 0xb7, 0xff, 0xb6, 0xff, 0xbe, 0xff, 0xc9, 0xff, 0xb3, 0xff, 0x98, 0xff, 0x71, 0xff, 0x5b, 0xff, 0x47, 0xff, 0x23, 0xff, 0x0f, 0xff, 0x06, 0xff, 0x19, 0xff, 0x4a, 0xff, 0x80, 0xff, 0xaa, 0xff, 0xc8, 0xff, 0xdb, 0xff, 0xfc, 0xff, 0x0c, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x98, 0x00, 0xbb, 0x00, 0xda, 0x00, 0xe9, 0x00, 0x03, 0x01, 0x11, 0x01, 0x11, 0x01, 0x05, 0x01, 0x05, 0x01, 0xdc, 0x00, 0xb2, 0x00, 0x70, 0x00, 0x22, 0x00, 0xd6, 0xff, 0x82, 0xff, 0x4e, 0xff, 0x22, 0xff, 0x08, 0xff, 0xeb, 0xfe, 0xcd, 0xfe, 0xbc, 0xfe, 0xbd, 0xfe, 0xf5, 0xfe, 0x39, 0xff, 0x8b, 0xff, 0xd4, 0xff, 0x1e, 0x00, 0x5a, 0x00, 0xa5, 0x00, 0xe4, 0x00, 0x06, 0x01, 0x14, 0x01, 0x03, 0x01, 0xf6, 0x00, 0xea, 0x00, 0xcd, 0x00, 0x9d, 0x00, 0x5d, 0x00, 0x2f, 0x00, 0xf0, 0xff, 0xc6, 0xff, 0x95, 0xff, 0x84, 0xff, 0x8d, 0xff, 0x87, 0xff, 0x8e, 0xff, 0xab, 0xff, 0xc9, 0xff, 0xf0, 0xff, 0x26, 0x00, 0x44, 0x00, 0x50, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x13, 0x00, 0xd3, 0xff, 0x81, 0xff, 0x2e, 0xff, 0xf0, 0xfe, 0xc7, 0xfe, 0xa6, 0xfe, 0xba, 0xfe, 0xcf, 0xfe, 0xf5, 0xfe, 0x09, 0xff, 0x3a, 0xff, 0x6e, 0xff, 0xd3, 0xff, 0x25, 0x00, 0x5c, 0x00, 0x7d, 0x00, 0x91, 0x00, 0x9c, 0x00, 0xa2, 0x00, 0xb4, 0x00, 0xd3, 0x00, 0xf9, 0x00, 0x1a, 0x01, 0x3c, 0x01, 0x4f, 0x01, 0x50, 0x01, 0x3f, 0x01, 0x29, 0x01, 0x04, 0x01, 0xc9, 0x00, 0x82, 0x00, 0x37, 0x00, 0x02, 0x00, 0xd4, 0xff, 0xc1, 0xff, 0xb2, 0xff, 0xa2, 0xff, 0x97, 0xff, 0x92, 0xff, 0x8b, 0xff, 0x9a, 0xff, 0xa4, 0xff, 0xc2, 0xff, 0xc3, 0xff, 0xc8, 0xff, 0xc8, 0xff, 0xcf, 0xff, 0xc3, 0xff, 0xcd, 0xff, 0xae, 0xff, 0x8e, 0xff, 0x66, 0xff, 0x44, 0xff, 0x29, 0xff, 0x28, 0xff, 0x30, 0xff, 0x30, 0xff, 0x4d, 0xff, 0x70, 0xff, 0xa8, 0xff, 0x02, 0x00, 0x1a, 0x00, 0x31, 0x00, 0x18, 0x00, 0x12, 0x00, 0xfe, 0xff, 0x14, 0x00, 0x3d, 0x00, 0x73, 0x00, 0x96, 0x00, 0xb2, 0x00, 0xdd, 0x00, 0x10, 0x01, 0x31, 0x01, 0x24, 0x01, 0x0d, 0x01, 0xde, 0x00, 0xaf, 0x00, 0x87, 0x00, 0x84, 0x00, 0x72, 0x00, 0x74, 0x00, 0x76, 0x00, 0x72, 0x00, 0x70, 0x00, 0x74, 0x00, 0x85, 0x00, 0x7f, 0x00, 0x69, 0x00, 0x48, 0x00, 0x32, 0x00, 0x0b, 0x00, 0xf2, 0xff, 0xc1, 0xff, 0x91, 0xff, 0x53, 0xff, 0x0a, 0xff, 0xcc, 0xfe, 0x8b, 0xfe, 0x67, 0xfe, 0x54, 0xfe, 0x54, 0xfe, 0x55, 0xfe, 0x6d, 0xfe, 0x93, 0xfe, 0xd6, 0xfe, 0x05, 0xff, 0x5a, 0xff, 0x83, 0xff, 0xd3, 0xff, 0x17, 0x00, 0x51, 0x00, 0x90, 0x00, 0xc3, 0x00, 0x10, 0x01, 0x4a, 0x01, 0x9a, 0x01, 0xc1, 0x01, 0xd0, 0x01, 0xa8, 0x01, 0x62, 0x01, 0xf8, 0x00, 0x8d, 0x00, 0x2b, 0x00, 0xd6, 0xff, 0x9e, 0xff, 0x7d, 0xff, 0x5f, 0xff, 0x56, 0xff, 0x5e, 0xff, 0x69, 0xff, 0x75, 0xff, 0x6c, 0xff, 0x6b, 0xff, 0x5a, 0xff, 0x6f, 0xff, 0x91, 0xff, 0xcb, 0xff, 0x18, 0x00, 0x69, 0x00, 0xb0, 0x00, 0xda, 0x00, 0xf5, 0x00, 0x02, 0x01, 0xfa, 0x00, 0xe8, 0x00, 0xce, 0x00, 0xbd, 0x00, 0xa6, 0x00, 0x84, 0x00, 0x54, 0x00, 0x17, 0x00, 0xc8, 0xff, 0x82, 0xff, 0x50, 0xff, 0x30, 0xff, 0x0f, 0xff, 0x01, 0xff, 0x09, 0xff, 0x27, 0xff, 0x6a, 0xff, 0xaf, 0xff, 0xf6, 0xff, 0x21, 0x00, 0x40, 0x00, 0x77, 0x00, 0x8f, 0x00, 0xa2, 0x00, 0x88, 0x00, 0x58, 0x00, 0x1f, 0x00, 0xe6, 0xff, 0xb8, 0xff, 0x99, 0xff, 0x81, 0xff, 0x7d, 0xff, 0x92, 0xff, 0xc9, 0xff, 0xfa, 0xff, 0x06, 0x00, 0x09, 0x00, 0xea, 0xff, 0xdb, 0xff, 0xc9, 0xff, 0xb0, 0xff, 0xa9, 0xff, 0xc1, 0xff, 0xe5, 0xff, 0x11, 0x00, 0x46, 0x00, 0x7f, 0x00, 0xb6, 0x00, 0xcb, 0x00, 0xca, 0x00, 0xc5, 0x00, 0xc1, 0x00, 0xc3, 0x00, 0xc3, 0x00, 0xae, 0x00, 0x97, 0x00, 0x84, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x61, 0x00, 0x4b, 0x00, 0x32, 0x00, 0x0b, 0x00, 0xe0, 0xff, 0xc8, 0xff, 0xb5, 0xff, 0x94, 0xff, 0x6d, 0xff, 0x34, 0xff, 0x0b, 0xff, 0xe1, 0xfe, 0xd3, 0xfe, 0xd3, 0xfe, 0xec, 0xfe, 0x11, 0xff, 0x48, 0xff, 0x78, 0xff, 0xa0, 0xff, 0xbe, 0xff, 0xc6, 0xff, 0xcc, 0xff, 0xc9, 0xff, 0xd9, 0xff, 0xed, 0xff, 0x05, 0x00, 0x1b, 0x00, 0x36, 0x00, 0x50, 0x00, 0x54, 0x00, 0x5d, 0x00, 0x78, 0x00, 0x91, 0x00, 0x8a, 0x00, 0x86, 0x00, 0x81, 0x00, 0x86, 0x00, 0x66, 0x00, 0x3f, 0x00, 0x28, 0x00, 0x1a, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0xf4, 0xff, 0xdc, 0xff, 0xb6, 0xff, 0xa5, 0xff, 0xa0, 0xff, 0xa3, 0xff, 0xb4, 0xff, 0xd3, 0xff, 0xef, 0xff, 0x0c, 0x00, 0x2d, 0x00, 0x3d, 0x00, 0x52, 0x00, 0x61, 0x00, 0x84, 0x00, 0xae, 0x00, 0xb5, 0x00, 0xb1, 0x00, 0x86, 0x00, 0x73, 0x00, 0x38, 0x00, 0xf7, 0xff, 0xb6, 0xff, 0x81, 0xff, 0x56, 0xff, 0x3b, 0xff, 0x35, 0xff, 0x2e, 0xff, 0x39, 0xff, 0x40, 0xff, 0x40, 0xff, 0x56, 0xff, 0x64, 0xff, 0x69, 0xff, 0x69, 0xff, 0x67, 0xff, 0x57, 0xff, 0x54, 0xff, 0x3b, 0xff, 0x4c, 0xff, 0x6c, 0xff, 0x9b, 0xff, 0xd2, 0xff, 0x0d, 0x00, 0x63, 0x00, 0xc3, 0x00, 0x12, 0x01, 0x45, 0x01, 0x7d, 0x01, 0xb4, 0x01, 0xd7, 0x01, 0xf9, 0x01, 0x0b, 0x02, 0xe8, 0x01, 0xcd, 0x01, 0xad, 0x01, 0x7f, 0x01, 0x3f, 0x01, 0x01, 0x01, 0xb6, 0x00, 0x5d, 0x00, 0xeb, 0xff, 0x81, 0xff, 0x09, 0xff, 0xa9, 0xfe, 0x62, 0xfe, 0x43, 0xfe, 0x38, 0xfe, 0x48, 0xfe, 0x72, 0xfe, 0x9d, 0xfe, 0xe2, 0xfe, 0x33, 0xff, 0x90, 0xff, 0xf1, 0xff, 0x39, 0x00, 0x5a, 0x00, 0x53, 0x00, 0x43, 0x00, 0x37, 0x00, 0x39, 0x00, 0x52, 0x00, 0x75, 0x00, 0xa2, 0x00, 0xb5, 0x00, 0xbc, 0x00, 0xa6, 0x00, 0x87, 0x00, 0x53, 0x00, 0x23, 0x00, 0x1d, 0x00, 0x2c, 0x00, 0x31, 0x00, 0x1c, 0x00, 0xef, 0xff, 0xbb, 0xff, 0x96, 0xff, 0x7d, 0xff, 0x77, 0xff, 0x87, 0xff, 0x8d, 0xff, 0x9b, 0xff, 0xac, 0xff, 0xda, 0xff, 0x0c, 0x00, 0x43, 0x00, 0x54, 0x00, 0x41, 0x00, 0x01, 0x00, 0xb3, 0xff, 0x94, 0xff, 0x8a, 0xff, 0x99, 0xff, 0xa3, 0xff, 0xa6, 0xff, 0xbc, 0xff, 0xd1, 0xff, 0xf2, 0xff, 0x0e, 0x00, 0x13, 0x00, 0x1b, 0x00, 0x12, 0x00, 0x0e, 0x00, 0x1a, 0x00, 0x26, 0x00, 0x27, 0x00, 0x29, 0x00, 0x29, 0x00, 0x3e, 0x00, 0x57, 0x00, 0x7c, 0x00, 0xab, 0x00, 0xd5, 0x00, 0xf0, 0x00, 0xf7, 0x00, 0xf1, 0x00, 0xe6, 0x00, 0xc0, 0x00, 0x92, 0x00, 0x53, 0x00, 0x1d, 0x00, 0xf7, 0xff, 0xd6, 0xff, 0xa3, 0xff, 0x7f, 0xff, 0x59, 0xff, 0x3c, 0xff, 0x36, 0xff, 0x3d, 0xff, 0x4f, 0xff, 0x50, 0xff, 0x4c, 0xff, 0x43, 0xff, 0x3a, 0xff, 0x29, 0xff, 0x26, 0xff, 0x39, 0xff, 0x5f, 0xff, 0x81, 0xff, 0xa6, 0xff, 0xc1, 0xff, 0xe1, 0xff, 0x1c, 0x00, 0x5b, 0x00, 0xb0, 0x00, 0xeb, 0x00, 0xff, 0x00, 0x02, 0x01, 0xf7, 0x00, 0xdb, 0x00, 0xab, 0x00, 0x97, 0x00, 0x90, 0x00, 0x81, 0x00, 0x5e, 0x00, 0x2f, 0x00, 0x11, 0x00, 0xf9, 0xff, 0xe9, 0xff, 0xf3, 0xff, 0x0f, 0x00, 0x25, 0x00, 0xff, 0xff, 0xe1, 0xff, 0xbe, 0xff, 0xa0, 0xff, 0x80, 0xff, 0x6b, 0xff, 0x59, 0xff, 0x44, 0xff, 0x2b, 0xff, 0x19, 0xff, 0x1c, 0xff, 0x28, 0xff, 0x42, 0xff, 0x3f, 0xff, 0x5d, 0xff, 0x83, 0xff, 0x9d, 0xff, 0xbc, 0xff, 0xd7, 0xff, 0x05, 0x00, 0x18, 0x00, 0x1e, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x21, 0x00, 0x2e, 0x00, 0x2f, 0x00, 0x28, 0x00, 0x23, 0x00, 0x35, 0x00, 0x34, 0x00, 0x22, 0x00, 0xf4, 0xff, 0xd0, 0xff, 0xca, 0xff, 0xdd, 0xff, 0x0b, 0x00, 0x2d, 0x00, 0x59, 0x00, 0x82, 0x00, 0xae, 0x00, 0xdf, 0x00, 0x13, 0x01, 0x65, 0x01, 0xb5, 0x01, 0xe8, 0x01, 0x03, 0x02, 0x02, 0x02, 0xdd, 0x01, 0x9f, 0x01, 0x5a, 0x01, 0x0c, 0x01, 0xab, 0x00, 0x3e, 0x00, 0xd9, 0xff, 0x7b, 0xff, 0x25, 0xff, 0xd9, 0xfe, 0x9e, 0xfe, 0x7c, 0xfe, 0x68, 0xfe, 0x56, 0xfe, 0x51, 0xfe, 0x60, 0xfe, 0x72, 0xfe, 0x9a, 0xfe, 0xd2, 0xfe, 0x0d, 0xff, 0x3a, 0xff, 0x6b, 0xff, 0x94, 0xff, 0xba, 0xff, 0xd7, 0xff, 0xee, 0xff, 0x10, 0x00, 0x12, 0x00, 0x2c, 0x00, 0x32, 0x00, 0x33, 0x00, 0x3f, 0x00, 0x5a, 0x00, 0x86, 0x00, 0xc3, 0x00, 0xef, 0x00, 0x02, 0x01, 0xef, 0x00, 0xd5, 0x00, 0xb7, 0x00, 0xa1, 0x00, 0x91, 0x00, 0x7e, 0x00, 0x61, 0x00, 0x3c, 0x00, 0x14, 0x00, 0xf9, 0xff, 0xde, 0xff, 0xcc, 0xff, 0xc3, 0xff, 0xb2, 0xff, 0xa1, 0xff, 0x9e, 0xff, 0x8d, 0xff, 0x8a, 0xff, 0x85, 0xff, 0x80, 0xff, 0x8d, 0xff, 0xa1, 0xff, 0xb8, 0xff, 0xdf, 0xff, 0x03, 0x00, 0x24, 0x00, 0x52, 0x00, 0x63, 0x00, 0x6e, 0x00, 0x68, 0x00, 0x49, 0x00, 0x17, 0x00, 0xe2, 0xff, 0xb5, 0xff, 0x9b, 0xff, 0x8e, 0xff, 0x91, 0xff, 0x82, 0xff, 0x7a, 0xff, 0x86, 0xff, 0x9d, 0xff, 0xc5, 0xff, 0xda, 0xff, 0xfe, 0xff, 0x2d, 0x00, 0x62, 0x00, 0xa6, 0x00, 0xdb, 0x00, 0x07, 0x01, 0x17, 0x01, 0x11, 0x01, 0x0c, 0x01, 0xf4, 0x00, 0xcf, 0x00, 0x9a, 0x00, 0x5d, 0x00, 0x23, 0x00, 0xe1, 0xff, 0xba, 0xff, 0x9f, 0xff, 0xa8, 0xff, 0xa0, 0xff, 0xa8, 0xff, 0x8a, 0xff, 0x6e, 0xff, 0x5c, 0xff, 0x5d, 0xff, 0x7a, 0xff, 0xa0, 0xff, 0xd2, 0xff, 0x15, 0x00, 0x56, 0x00, 0x87, 0x00, 0xac, 0x00, 0xa8, 0x00, 0x78, 0x00, 0x45, 0x00, 0x24, 0x00, 0x13, 0x00, 0x21, 0x00, 0x28, 0x00, 0x11, 0x00, 0xf2, 0xff, 0xca, 0xff, 0xa5, 0xff, 0x81, 0xff, 0x71, 0xff, 0x6a, 0xff, 0x60, 0xff, 0x5a, 0xff, 0x5b, 0xff, 0x7c, 0xff, 0x94, 0xff, 0xbf, 0xff, 0xf4, 0xff, 0x03, 0x00, 0x11, 0x00, 0x00, 0x00, 0xfa, 0xff, 0xe7, 0xff, 0xe6, 0xff, 0xf8, 0xff, 0x05, 0x00, 0x1a, 0x00, 0x33, 0x00, 0x5a, 0x00, 0x84, 0x00, 0xa5, 0x00, 0xb5, 0x00, 0xc2, 0x00, 0xba, 0x00, 0xa6, 0x00, 0x79, 0x00, 0x3d, 0x00, 0x0d, 0x00, 0xd9, 0xff, 0xbb, 0xff, 0x92, 0xff, 0x79, 0xff, 0x62, 0xff, 0x4f, 0xff, 0x39, 0xff, 0x29, 0xff, 0x2e, 0xff, 0x48, 0xff, 0x6d, 0xff, 0x85, 0xff, 0xa8, 0xff, 0xc7, 0xff, 0xf8, 0xff, 0x1c, 0x00, 0x38, 0x00, 0x6e, 0x00, 0xba, 0x00, 0x15, 0x01, 0x5d, 0x01, 0x92, 0x01, 0xa4, 0x01, 0xc5, 0x01, 0xb0, 0x01, 0x81, 0x01, 0x3b, 0x01, 0xe9, 0x00, 0x85, 0x00, 0x25, 0x00, 0xd7, 0xff, 0xa0, 0xff, 0x7f, 0xff, 0x60, 0xff, 0x5d, 0xff, 0x60, 0xff, 0x68, 0xff, 0x69, 0xff, 0x67, 0xff, 0x6a, 0xff, 0x7c, 0xff, 0x83, 0xff, 0x9f, 0xff, 0xc0, 0xff, 0xd6, 0xff, 0xe0, 0xff, 0xf5, 0xff, 0x18, 0x00, 0x3e, 0x00, 0x5e, 0x00, 0x76, 0x00, 0x9a, 0x00, 0xab, 0x00, 0xc4, 0x00, 0xe0, 0x00, 0xe6, 0x00, 0xf4, 0x00, 0xe4, 0x00, 0xd3, 0x00, 0xaa, 0x00, 0x75, 0x00, 0x2e, 0x00, 0xf0, 0xff, 0xa9, 0xff, 0x79, 0xff, 0x3a, 0xff, 0x16, 0xff, 0xfc, 0xfe, 0xf6, 0xfe, 0x03, 0xff, 0x1e, 0xff, 0x1e, 0xff, 0x27, 0xff, 0x1e, 0xff, 0x26, 0xff, 0x2a, 0xff, 0x42, 0xff, 0x51, 0xff, 0x68, 0xff, 0x68, 0xff, 0x67, 0xff, 0x59, 0xff, 0x52, 0xff, 0x55, 0xff, 0x67, 0xff, 0x66, 0xff, 0x5b, 0xff, 0x58, 0xff, 0x54, 0xff, 0x52, 0xff, 0x53, 0xff, 0x4f, 0xff, 0x68, 0xff, 0x87, 0xff, 0xa5, 0xff, 0xca, 0xff, 0xea, 0xff, 0xfd, 0xff, 0x02, 0x00, 0x0d, 0x00, 0x13, 0x00, 0x20, 0x00, 0x3a, 0x00, 0x5d, 0x00, 0x73, 0x00, 0x7a, 0x00, 0x97, 0x00, 0xc1, 0x00, 0x02, 0x01, 0x2b, 0x01, 0x47, 0x01, 0x70, 0x01, 0x7b, 0x01, 0x7a, 0x01, 0x64, 0x01, 0x59, 0x01, 0x5f, 0x01, 0x7d, 0x01, 0x93, 0x01, 0x92, 0x01, 0x8e, 0x01, 0x88, 0x01, 0x73, 0x01, 0x5a, 0x01, 0x48, 0x01, 0x33, 0x01, 0xee, 0x00, 0x86, 0x00, 0x2d, 0x00, 0xe5, 0xff, 0x92, 0xff, 0x42, 0xff, 0xf5, 0xfe, 0xc3, 0xfe, 0xad, 0xfe, 0x90, 0xfe, 0x89, 0xfe, 0x72, 0xfe, 0x6d, 0xfe, 0x6f, 0xfe, 0x77, 0xfe, 0x96, 0xfe, 0xac, 0xfe, 0xc3, 0xfe, 0xd9, 0xfe, 0xf0, 0xfe, 0xfb, 0xfe, 0x0e, 0xff, 0x09, 0xff, 0x1c, 0xff, 0x34, 0xff, 0x6d, 0xff, 0x9c, 0xff, 0xd0, 0xff, 0x0a, 0x00, 0x36, 0x00, 0x63, 0x00, 0x7a, 0x00, 0x7e, 0x00, 0x8d, 0x00, 0xa7, 0x00, 0xbd, 0x00, 0xbe, 0x00, 0xbd, 0x00, 0xc6, 0x00, 0xd5, 0x00, 0xf5, 0x00, 0x27, 0x01, 0x2f, 0x01, 0x18, 0x01, 0xd1, 0x00, 0x8f, 0x00, 0x52, 0x00, 0x24, 0x00, 0xeb, 0xff, 0xcb, 0xff, 0x9c, 0xff, 0x7e, 0xff, 0x55, 0xff, 0x28, 0xff, 0x0b, 0xff, 0xfe, 0xfe, 0x0d, 0xff, 0x2d, 0xff, 0x5a, 0xff, 0xa0, 0xff, 0xe7, 0xff, 0x38, 0x00, 0x74, 0x00, 0x9e, 0x00, 0xc1, 0x00, 0xe2, 0x00, 0xf0, 0x00, 0xe5, 0x00, 0xc1, 0x00, 0x99, 0x00, 0x74, 0x00, 0x62, 0x00, 0x69, 0x00, 0x7d, 0x00, 0xa2, 0x00, 0xb2, 0x00, 0x94, 0x00, 0x6b, 0x00, 0x4b, 0x00, 0x1f, 0x00, 0xff, 0xff, 0xe2, 0xff, 0xc8, 0xff, 0xb5, 0xff, 0x90, 0xff, 0x62, 0xff, 0x2d, 0xff, 0x04, 0xff, 0xef, 0xfe, 0xeb, 0xfe, 0xfc, 0xfe, 0x11, 0xff, 0x2f, 0xff, 0x4c, 0xff, 0x62, 0xff, 0x6f, 0xff, 0x87, 0xff, 0x86, 0xff, 0xa9, 0xff, 0xba, 0xff, 0xcf, 0xff, 0xe2, 0xff, 0x04, 0x00, 0x23, 0x00, 0x47, 0x00, 0x58, 0x00, 0x65, 0x00, 0x66, 0x00, 0x64, 0x00, 0x7b, 0x00, 0x99, 0x00, 0xb1, 0x00, 0xb4, 0x00, 0xbd, 0x00, 0xb2, 0x00, 0xa4, 0x00, 0x92, 0x00, 0x6e, 0x00, 0x3f, 0x00, 0x08, 0x00, 0xe3, 0xff, 0xb7, 0xff, 0xb2, 0xff, 0xc2, 0xff, 0xea, 0xff, 0x24, 0x00, 0x55, 0x00, 0x7d, 0x00, 0x83, 0x00, 0x88, 0x00, 0x5f, 0x00, 0x37, 0x00, 0x12, 0x00, 0xfb, 0xff, 0xfa, 0xff, 0x06, 0x00, 0x21, 0x00, 0x2f, 0x00, 0x27, 0x00, 0x13, 0x00, 0xfe, 0xff, 0xf9, 0xff, 0xe4, 0xff, 0xce, 0xff, 0xbc, 0xff, 0xc7, 0xff, 0xdf, 0xff, 0x04, 0x00, 0x31, 0x00, 0x36, 0x00, 0x46, 0x00, 0x4b, 0x00, 0x4c, 0x00, 0x3a, 0x00, 0x2d, 0x00, 0x11, 0x00, 0xe9, 0xff, 0xca, 0xff, 0xa0, 0xff, 0x78, 0xff, 0x51, 0xff, 0x3c, 0xff, 0x2e, 0xff, 0x33, 0xff, 0x2d, 0xff, 0x29, 0xff, 0x3c, 0xff, 0x57, 0xff, 0x64, 0xff, 0x6b, 0xff, 0x74, 0xff, 0x77, 0xff, 0x9a, 0xff, 0xb3, 0xff, 0xd7, 0xff, 0xf3, 0xff, 0x1e, 0x00, 0x65, 0x00, 0xae, 0x00, 0x02, 0x01, 0x3d, 0x01, 0x67, 0x01, 0x74, 0x01, 0x59, 0x01, 0x2e, 0x01, 0xfa, 0x00, 0xc5, 0x00, 0x9e, 0x00, 0x83, 0x00, 0x58, 0x00, 0x25, 0x00, 0xef, 0xff, 0xc8, 0xff, 0x95, 0xff, 0x5d, 0xff, 0x16, 0xff, 0xdb, 0xfe, 0xb2, 0xfe, 0x9c, 0xfe, 0xa9, 0xfe, 0xc6, 0xfe, 0xe8, 0xfe, 0x24, 0xff, 0x53, 0xff, 0x84, 0xff, 0xb4, 0xff, 0xee, 0xff, 0x1e, 0x00, 0x49, 0x00, 0x5b, 0x00, 0x75, 0x00, 0x88, 0x00, 0xa5, 0x00, 0xc9, 0x00, 0xee, 0x00, 0x21, 0x01, 0x3f, 0x01, 0x4a, 0x01, 0x34, 0x01, 0x0b, 0x01, 0xb9, 0x00, 0x72, 0x00, 0x2f, 0x00, 0x03, 0x00, 0xe6, 0xff, 0xcd, 0xff, 0xcb, 0xff, 0xc2, 0xff, 0xcd, 0xff, 0xb8, 0xff, 0xa3, 0xff, 0x83, 0xff, 0x7d, 0xff, 0x78, 0xff, 0x80, 0xff, 0x8e, 0xff, 0xab, 0xff, 0xc3, 0xff, 0xe3, 0xff, 0x02, 0x00, 0x21, 0x00, 0x30, 0x00, 0x27, 0x00, 0x10, 0x00, 0xe5, 0xff, 0xcb, 0xff, 0xc3, 0xff, 0xc9, 0xff, 0xe8, 0xff, 0xfd, 0xff, 0x01, 0x00, 0x06, 0x00, 0xe9, 0xff, 0xc8, 0xff, 0x98, 0xff, 0x75, 0xff, 0x61, 0xff, 0x65, 0xff, 0x84, 0xff, 0xaa, 0xff, 0xe4, 0xff, 0x27, 0x00, 0x4e, 0x00, 0x6a, 0x00, 0x9f, 0x00, 0xd0, 0x00, 0xe6, 0x00, 0xde, 0x00, 0xc3, 0x00, 0xa4, 0x00, 0x79, 0x00, 0x5d, 0x00, 0x4d, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4d, 0x00, 0x52, 0x00, 0x4e, 0x00, 0x34, 0x00, 0x16, 0x00, 0xff, 0xff, 0xe6, 0xff, 0xcd, 0xff, 0xc2, 0xff, 0xc7, 0xff, 0xbe, 0xff, 0xb0, 0xff, 0x90, 0xff, 0x71, 0xff, 0x4c, 0xff, 0x29, 0xff, 0x1b, 0xff, 0x26, 0xff, 0x3b, 0xff, 0x4f, 0xff, 0x5c, 0xff, 0x68, 0xff, 0x87, 0xff, 0xac, 0xff, 0xe3, 0xff, 0xfe, 0xff, 0x12, 0x00, 0x2d, 0x00, 0x36, 0x00, 0x35, 0x00, 0x22, 0x00, 0x22, 0x00, 0x18, 0x00, 0x2e, 0x00, 0x41, 0x00, 0x61, 0x00, 0x7a, 0x00, 0x91, 0x00, 0xa8, 0x00, 0xa9, 0x00, 0xa7, 0x00, 0x99, 0x00, 0x8c, 0x00, 0x72, 0x00, 0x5d, 0x00, 0x3c, 0x00, 0x10, 0x00, 0xf3, 0xff, 0xcc, 0xff, 0xbb, 0xff, 0xb0, 0xff, 0xb2, 0xff, 0xc0, 0xff, 0xd5, 0xff, 0xf7, 0xff, 0x00, 0x00, 0x08, 0x00, 0xfc, 0xff, 0xe9, 0xff, 0xe5, 0xff, 0xf0, 0xff, 0xf9, 0xff, 0xf0, 0xff, 0xdf, 0xff, 0xd4, 0xff, 0xde, 0xff, 0xee, 0xff, 0xea, 0xff, 0xd8, 0xff, 0xba, 0xff, 0x9f, 0xff, 0x83, 0xff, 0x7e, 0xff, 0x99, 0xff, 0xd1, 0xff, 0x05, 0x00, 0x26, 0x00, 0x35, 0x00, 0x29, 0x00, 0x25, 0x00, 0x27, 0x00, 0x39, 0x00, 0x70, 0x00, 0xaf, 0x00, 0xed, 0x00, 0x17, 0x01, 0x3e, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x4e, 0x01, 0x1a, 0x01, 0xe5, 0x00, 0xa1, 0x00, 0x6d, 0x00, 0x3a, 0x00, 0x0e, 0x00, 0xda, 0xff, 0xb5, 0xff, 0x8b, 0xff, 0x6a, 0xff, 0x61, 0xff, 0x5e, 0xff, 0x4f, 0xff, 0x3e, 0xff, 0x26, 0xff, 0x19, 0xff, 0x1c, 0xff, 0x1d, 0xff, 0x1a, 0xff, 0x1f, 0xff, 0x31, 0xff, 0x42, 0xff, 0x59, 0xff, 0x7c, 0xff, 0xa3, 0xff, 0xbe, 0xff, 0xbd, 0xff, 0xca, 0xff, 0xd3, 0xff, 0xf6, 0xff, 0x14, 0x00, 0x2d, 0x00, 0x36, 0x00, 0x3e, 0x00, 0x52, 0x00, 0x5a, 0x00, 0x59, 0x00, 0x52, 0x00, 0x53, 0x00, 0x6b, 0x00, 0x80, 0x00, 0xab, 0x00, 0xbb, 0x00, 0xc3, 0x00, 0xe6, 0x00, 0x0f, 0x01, 0x0f, 0x01, 0x0a, 0x01, 0xfc, 0x00, 0xe8, 0x00, 0xb3, 0x00, 0x68, 0x00, 0x20, 0x00, 0xe2, 0xff, 0xb4, 0xff, 0x9c, 0xff, 0x89, 0xff, 0x87, 0xff, 0xa3, 0xff, 0xb7, 0xff, 0xb6, 0xff, 0xa7, 0xff, 0xab, 0xff, 0xaa, 0xff, 0xb3, 0xff, 0xa0, 0xff, 0x99, 0xff, 0x7b, 0xff, 0x75, 0xff, 0x6b, 0xff, 0x64, 0xff, 0x4f, 0xff, 0x4c, 0xff, 0x3f, 0xff, 0x35, 0xff, 0x41, 0xff, 0x5d, 0xff, 0x6d, 0xff, 0x79, 0xff, 0x73, 0xff, 0x80, 0xff, 0x9e, 0xff, 0xb7, 0xff, 0xe1, 0xff, 0x06, 0x00, 0x2a, 0x00, 0x48, 0x00, 0x5d, 0x00, 0x7e, 0x00, 0xa1, 0x00, 0xb9, 0x00, 0xe5, 0x00, 0xee, 0x00, 0x05, 0x01, 0x0c, 0x01, 0x01, 0x01, 0x0b, 0x01, 0x0c, 0x01, 0x02, 0x01, 0xf9, 0x00, 0x01, 0x01, 0xe8, 0x00, 0xcc, 0x00, 0x8f, 0x00, 0x6b, 0x00, 0x3c, 0x00, 0x15, 0x00, 0xeb, 0xff, 0xda, 0xff, 0xb5, 0xff, 0x8d, 0xff, 0x65, 0xff, 0x37, 0xff, 0x05, 0xff, 0xd9, 0xfe, 0xb1, 0xfe, 0xa2, 0xfe, 0xb2, 0xfe, 0xc4, 0xfe, 0xdb, 0xfe, 0xe5, 0xfe, 0xec, 0xfe, 0xfb, 0xfe, 0x12, 0xff, 0x38, 0xff, 0x6e, 0xff, 0x9d, 0xff, 0xdf, 0xff, 0x1b, 0x00, 0x52, 0x00, 0x90, 0x00, 0xe7, 0x00, 0x37, 0x01, 0x82, 0x01, 0xc1, 0x01, 0xf6, 0x01, 0x32, 0x02, 0x58, 0x02, 0x6c, 0x02, 0x5b, 0x02, 0x1d, 0x02, 0xbe, 0x01, 0x4a, 0x01, 0xc8, 0x00, 0x47, 0x00, 0xda, 0xff, 0x8d, 0xff, 0x4f, 0xff, 0x23, 0xff, 0xf6, 0xfe, 0xd9, 0xfe, 0xd2, 0xfe, 0xc6, 0xfe, 0xc4, 0xfe, 0xc1, 0xfe, 0xc5, 0xfe, 0xd3, 0xfe, 0xea, 0xfe, 0x06, 0xff, 0x1f, 0xff, 0x33, 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x53, 0xff, 0x60, 0xff, 0x81, 0xff, 0x9c, 0xff, 0xb1, 0xff, 0xde, 0xff, 0xfd, 0xff, 0x24, 0x00, 0x37, 0x00, 0x3d, 0x00, 0x4a, 0x00, 0x5f, 0x00, 0x74, 0x00, 0x8d, 0x00, 0xa1, 0x00, 0xa3, 0x00, 0xa5, 0x00, 0xa1, 0x00, 0x85, 0x00, 0x65, 0x00, 0x51, 0x00, 0x2e, 0x00, 0x06, 0x00, 0xe5, 0xff, 0xd7, 0xff, 0xe2, 0xff, 0xea, 0xff, 0xeb, 0xff, 0xee, 0xff, 0xdb, 0xff, 0xd5, 0xff, 0xd0, 0xff, 0xea, 0xff, 0xf0, 0xff, 0x0a, 0x00, 0x09, 0x00, 0x16, 0x00, 0x25, 0x00, 0x27, 0x00, 0x2d, 0x00, 0x20, 0x00, 0x03, 0x00, 0xd4, 0xff, 0xa8, 0xff, 0x8b, 0xff, 0x66, 0xff, 0x5b, 0xff, 0x56, 0xff, 0x59, 0xff, 0x6b, 0xff, 0x6c, 0xff, 0x79, 0xff, 0x87, 0xff, 0x95, 0xff, 0x99, 0xff, 0x8e, 0xff, 0x93, 0xff, 0x95, 0xff, 0x94, 0xff, 0xb1, 0xff, 0xd0, 0xff, 0xf9, 0xff, 0x0b, 0x00, 0x26, 0x00, 0x37, 0x00, 0x49, 0x00, 0x69, 0x00, 0xa4, 0x00, 0xe4, 0x00, 0x0c, 0x01, 0x31, 0x01, 0x49, 0x01, 0x64, 0x01, 0x69, 0x01, 0x53, 0x01, 0x2a, 0x01, 0xf1, 0x00, 0xb3, 0x00, 0x85, 0x00, 0x5e, 0x00, 0x56, 0x00, 0x33, 0x00, 0x15, 0x00, 0xe1, 0xff, 0xb1, 0xff, 0x84, 0xff, 0x62, 0xff, 0x4e, 0xff, 0x48, 0xff, 0x35, 0xff, 0x27, 0xff, 0x24, 0xff, 0x3b, 0xff, 0x60, 0xff, 0x94, 0xff, 0xbb, 0xff, 0xe2, 0xff, 0x00, 0x00, 0x19, 0x00, 0x3f, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x6d, 0x00, 0x74, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x58, 0x00, 0x53, 0x00, 0x60, 0x00, 0x70, 0x00, 0x73, 0x00, 0x79, 0x00, 0x86, 0x00, 0x87, 0x00, 0x7c, 0x00, 0x7d, 0x00, 0x90, 0x00, 0xac, 0x00, 0xba, 0x00, 0xc0, 0x00, 0xa9, 0x00, 0xa6, 0x00, 0x8e, 0x00, 0x7f, 0x00, 0x64, 0x00, 0x39, 0x00, 0x0b, 0x00, 0xc3, 0xff, 0x71, 0xff, 0x25, 0xff, 0xd7, 0xfe, 0x9d, 0xfe, 0x6e, 0xfe, 0x40, 0xfe, 0x32, 0xfe, 0x27, 0xfe, 0x33, 0xfe, 0x4d, 0xfe, 0x75, 0xfe, 0x9c, 0xfe, 0xc2, 0xfe, 0xe1, 0xfe, 0x15, 0xff, 0x56, 0xff, 0x8e, 0xff, 0xd6, 0xff, 0x16, 0x00, 0x52, 0x00, 0xb1, 0x00, 0x17, 0x01, 0x74, 0x01, 0xba, 0x01, 0xe4, 0x01, 0xdd, 0x01, 0xca, 0x01, 0x96, 0x01, 0x66, 0x01, 0x3b, 0x01, 0x29, 0x01, 0xfc, 0x00, 0xc7, 0x00, 0x90, 0x00, 0x59, 0x00, 0x20, 0x00, 0xea, 0xff, 0xad, 0xff, 0x88, 0xff, 0x70, 0xff, 0x66, 0xff, 0x5e, 0xff, 0x4d, 0xff, 0x4b, 0xff, 0x42, 0xff, 0x46, 0xff, 0x53, 0xff, 0x58, 0xff, 0x53, 0xff, 0x4d, 0xff, 0x53, 0xff, 0x57, 0xff, 0x64, 0xff, 0x70, 0xff, 0x74, 0xff, 0x84, 0xff, 0x96, 0xff, 0xb4, 0xff, 0xc6, 0xff, 0xef, 0xff, 0x2b, 0x00, 0x6d, 0x00, 0x8a, 0x00, 0x97, 0x00, 0x91, 0x00, 0x9d, 0x00, 0xb0, 0x00, 0xca, 0x00, 0xdc, 0x00, 0xe8, 0x00, 0xe8, 0x00, 0xe4, 0x00, 0xc9, 0x00, 0x9d, 0x00, 0x6a, 0x00, 0x41, 0x00, 0x27, 0x00, 0x15, 0x00, 0x0a, 0x00, 0x07, 0x00, 0xee, 0xff, 0xef, 0xff, 0xe7, 0xff, 0xe2, 0xff, 0xb9, 0xff, 0x83, 0xff, 0x4c, 0xff, 0x26, 0xff, 0x14, 0xff, 0x21, 0xff, 0x48, 0xff, 0x6b, 0xff, 0x90, 0xff, 0xb1, 0xff, 0xd0, 0xff, 0xfe, 0xff, 0x2c, 0x00, 0x4a, 0x00, 0x5e, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x52, 0x00, 0x3d, 0x00, 0x25, 0x00, 0x06, 0x00, 0xf1, 0xff, 0xd4, 0xff, 0xb1, 0xff, 0x8f, 0xff, 0x77, 0xff, 0x7d, 0xff, 0x8c, 0xff, 0x92, 0xff, 0x96, 0xff, 0x85, 0xff, 0x82, 0xff, 0x87, 0xff, 0x99, 0xff, 0xa6, 0xff, 0xb1, 0xff, 0xa6, 0xff, 0xa7, 0xff, 0xaa, 0xff, 0xb0, 0xff, 0xca, 0xff, 0xfb, 0xff, 0x38, 0x00, 0x57, 0x00, 0x7b, 0x00, 0xab, 0x00, 0xe6, 0x00, 0x1a, 0x01, 0x4f, 0x01, 0x84, 0x01, 0xc3, 0x01, 0xdd, 0x01, 0xda, 0x01, 0xbe, 0x01, 0x80, 0x01, 0x44, 0x01, 0x0b, 0x01, 0xd3, 0x00, 0x8f, 0x00, 0x54, 0x00, 0x09, 0x00, 0xc6, 0xff, 0x74, 0xff, 0x3b, 0xff, 0x0e, 0xff, 0xf9, 0xfe, 0xf2, 0xfe, 0xf5, 0xfe, 0x01, 0xff, 0x00, 0xff, 0xf6, 0xfe, 0xe9, 0xfe, 0xdd, 0xfe, 0xd9, 0xfe, 0xf1, 0xfe, 0x0d, 0xff, 0x3d, 0xff, 0x79, 0xff, 0xb3, 0xff, 0xea, 0xff, 0x05, 0x00, 0x28, 0x00, 0x38, 0x00, 0x4e, 0x00, 0x63, 0x00, 0x6e, 0x00, 0x5f, 0x00, 0x4a, 0x00, 0x30, 0x00, 0x09, 0x00, 0xf5, 0xff, 0xec, 0xff, 0xec, 0xff, 0x06, 0x00, 0x14, 0x00, 0x37, 0x00, 0x4f, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x3f, 0x00, 0x28, 0x00, 0x26, 0x00, 0x28, 0x00, 0x3b, 0x00, 0x42, 0x00, 0x30, 0x00, 0x16, 0x00, 0xf8, 0xff, 0xe3, 0xff, 0xd1, 0xff, 0xd9, 0xff, 0xe8, 0xff, 0xfe, 0xff, 0x13, 0x00, 0x18, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x05, 0x00, 0xeb, 0xff, 0xcc, 0xff, 0xbf, 0xff, 0xbf, 0xff, 0xd2, 0xff, 0xe6, 0xff, 0xef, 0xff, 0xeb, 0xff, 0xe6, 0xff, 0xe9, 0xff, 0xf1, 0xff, 0x0e, 0x00, 0x25, 0x00, 0x23, 0x00, 0x0e, 0x00, 0xf2, 0xff, 0xe0, 0xff, 0xc8, 0xff, 0xc0, 0xff, 0xa5, 0xff, 0xa6, 0xff, 0xab, 0xff, 0xd5, 0xff, 0xf9, 0xff, 0x2e, 0x00, 0x5c, 0x00, 0x8d, 0x00, 0xa7, 0x00, 0xb0, 0x00, 0x9c, 0x00, 0x83, 0x00, 0x64, 0x00, 0x36, 0x00, 0xfc, 0xff, 0xc8, 0xff, 0xb8, 0xff, 0xab, 0xff, 0xa8, 0xff, 0xa1, 0xff, 0x96, 0xff, 0x93, 0xff, 0x83, 0xff, 0x8e, 0xff, 0x98, 0xff, 0xa2, 0xff, 0xa8, 0xff, 0xb2, 0xff, 0xce, 0xff, 0xe3, 0xff, 0xed, 0xff, 0xf1, 0xff, 0xf1, 0xff, 0xeb, 0xff, 0xf7, 0xff, 0xfd, 0xff, 0x03, 0x00, 0xed, 0xff, 0xea, 0xff, 0xec, 0xff, 0xed, 0xff, 0xf0, 0xff, 0xf5, 0xff, 0xff, 0xff, 0x09, 0x00, 0x13, 0x00, 0x19, 0x00, 0x34, 0x00, 0x3d, 0x00, 0x54, 0x00, 0x53, 0x00, 0x60, 0x00, 0x5b, 0x00, 0x4a, 0x00, 0x40, 0x00, 0x41, 0x00, 0x5a, 0x00, 0x51, 0x00, 0x3c, 0x00, 0x18, 0x00, 0xfe, 0xff, 0xd3, 0xff, 0xc6, 0xff, 0xa7, 0xff, 0xa2, 0xff, 0xa3, 0xff, 0xb1, 0xff, 0xc3, 0xff, 0xd0, 0xff, 0xe2, 0xff, 0xf9, 0xff, 0x0d, 0x00, 0x18, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x24, 0x00, 0x22, 0x00, 0x32, 0x00, 0x42, 0x00, 0x44, 0x00, 0x5e, 0x00, 0x6e, 0x00, 0x81, 0x00, 0x84, 0x00, 0x9b, 0x00, 0x96, 0x00, 0x90, 0x00, 0x7b, 0x00, 0x70, 0x00, 0x63, 0x00, 0x48, 0x00, 0x2f, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x23, 0x00, 0x3b, 0x00, 0x3d, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x3e, 0x00, 0x30, 0x00, 0x20, 0x00, 0x1b, 0x00, 0x10, 0x00, 0x10, 0x00, 0x17, 0x00, 0x0b, 0x00, 0x06, 0x00, 0xfa, 0xff, 0xea, 0xff, 0xd9, 0xff, 0xc5, 0xff, 0xac, 0xff, 0x8b, 0xff, 0x6d, 0xff, 0x52, 0xff, 0x42, 0xff, 0x3a, 0xff, 0x4d, 0xff, 0x54, 0xff, 0x68, 0xff, 0x69, 0xff, 0x6f, 0xff, 0x7f, 0xff, 0x94, 0xff, 0xbd, 0xff, 0xde, 0xff, 0xf5, 0xff, 0xf8, 0xff, 0xf9, 0xff, 0xf3, 0xff, 0xe7, 0xff, 0xd6, 0xff, 0xbc, 0xff, 0xba, 0xff, 0xb3, 0xff, 0xba, 0xff, 0xbe, 0xff, 0xcc, 0xff, 0xc9, 0xff, 0xd4, 0xff, 0xd8, 0xff, 0xe4, 0xff, 0xf1, 0xff, 0xe9, 0xff, 0xe4, 0xff, 0xd1, 0xff, 0xcc, 0xff, 0xd1, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x1e, 0x00, 0x40, 0x00, 0x5a, 0x00, 0x63, 0x00, 0x74, 0x00, 0x79, 0x00, 0x7d, 0x00, 0x62, 0x00, 0x4d, 0x00, 0x38, 0x00, 0x2a, 0x00, 0x1b, 0x00, 0x12, 0x00, 0x0e, 0x00, 0x17, 0x00, 0x20, 0x00, 0x1c, 0x00, 0x26, 0x00, 0x1b, 0x00, 0x29, 0x00, 0x24, 0x00, 0x29, 0x00, 0x25, 0x00, 0x2c, 0x00, 0x36, 0x00, 0x39, 0x00, 0x30, 0x00, 0x36, 0x00, 0x42, 0x00, 0x50, 0x00, 0x4a, 0x00, 0x4c, 0x00, 0x52, 0x00, 0x55, 0x00, 0x41, 0x00, 0x39, 0x00, 0x3d, 0x00, 0x43, 0x00, 0x48, 0x00, 0x46, 0x00, 0x46, 0x00, 0x59, 0x00, 0x6e, 0x00, 0x7f, 0x00, 0x82, 0x00, 0x5e, 0x00, 0x45, 0x00, 0x20, 0x00, 0x03, 0x00, 0xe2, 0xff, 0xce, 0xff, 0xd4, 0xff, 0xda, 0xff, 0xe2, 0xff, 0xd9, 0xff, 0xbd, 0xff, 0xa4, 0xff, 0x91, 0xff, 0x83, 0xff, 0x7e, 0xff, 0x89, 0xff, 0x90, 0xff, 0x9d, 0xff, 0x94, 0xff, 0xa0, 0xff, 0x8e, 0xff, 0x85, 0xff, 0x7e, 0xff, 0x83, 0xff, 0x81, 0xff, 0x8c, 0xff, 0x89, 0xff, 0x91, 0xff, 0x98, 0xff, 0x98, 0xff, 0xa0, 0xff, 0x91, 0xff, 0x8c, 0xff, 0x81, 0xff, 0x8b, 0xff, 0x99, 0xff, 0xad, 0xff, 0xca, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x17, 0x00, 0x3c, 0x00, 0x59, 0x00, 0x7d, 0x00, 0xb4, 0x00, 0xdf, 0x00, 0x07, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x34, 0x01, 0x37, 0x01, 0x21, 0x01, 0x0b, 0x01, 0xe6, 0x00, 0xcc, 0x00, 0xb1, 0x00, 0xa8, 0x00, 0xa0, 0x00, 0x9e, 0x00, 0x8d, 0x00, 0x77, 0x00, 0x53, 0x00, 0x1f, 0x00, 0xe5, 0xff, 0xa7, 0xff, 0x77, 0xff, 0x4d, 0xff, 0x31, 0xff, 0x1c, 0xff, 0x0b, 0xff, 0xfa, 0xfe, 0xe8, 0xfe, 0xe2, 0xfe, 0xea, 0xfe, 0xf5, 0xfe, 0x06, 0xff, 0x19, 0xff, 0x32, 0xff, 0x53, 0xff, 0x8b, 0xff, 0xd8, 0xff, 0x33, 0x00, 0x82, 0x00, 0xd1, 0x00, 0x0c, 0x01, 0x42, 0x01, 0x6e, 0x01, 0x6a, 0x01, 0x59, 0x01, 0x26, 0x01, 0xfd, 0x00, 0xd3, 0x00, 0xa9, 0x00, 0x82, 0x00, 0x59, 0x00, 0x37, 0x00, 0x10, 0x00, 0xe2, 0xff, 0xc4, 0xff, 0x9e, 0xff, 0x93, 0xff, 0x73, 0xff, 0x6c, 0xff, 0x68, 0xff, 0x72, 0xff, 0x76, 0xff, 0x7f, 0xff, 0x9b, 0xff, 0xcc, 0xff, 0xf2, 0xff, 0x21, 0x00, 0x4c, 0x00, 0x66, 0x00, 0x6e, 0x00, 0x62, 0x00, 0x44, 0x00, 0x27, 0x00, 0x0f, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xf9, 0xff, 0xe9, 0xff, 0xd6, 0xff, 0xbf, 0xff, 0x9c, 0xff, 0x6f, 0xff, 0x59, 0xff, 0x43, 0xff, 0x33, 0xff, 0x35, 0xff, 0x42, 0xff, 0x59, 0xff, 0x83, 0xff, 0xac, 0xff, 0xb6, 0xff, 0xc1, 0xff, 0xc6, 0xff, 0xea, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xf0, 0xff, 0xe5, 0xff, 0xdd, 0xff, 0xe5, 0xff, 0xf8, 0xff, 0x11, 0x00, 0x30, 0x00, 0x56, 0x00, 0x62, 0x00, 0x71, 0x00, 0x7b, 0x00, 0x8b, 0x00, 0x99, 0x00, 0xa8, 0x00, 0xbe, 0x00, 0xb1, 0x00, 0x86, 0x00, 0x55, 0x00, 0x20, 0x00, 0xe7, 0xff, 0xbf, 0xff, 0x99, 0xff, 0x78, 0xff, 0x51, 0xff, 0x1d, 0xff, 0x07, 0xff, 0xf1, 0xfe, 0xed, 0xfe, 0xfb, 0xfe, 0x0c, 0xff, 0x3e, 0xff, 0x70, 0xff, 0xb7, 0xff, 0x01, 0x00, 0x38, 0x00, 0x6e, 0x00, 0x90, 0x00, 0xab, 0x00, 0xcd, 0x00, 0xf0, 0x00, 0x18, 0x01, 0x4b, 0x01, 0x63, 0x01, 0x65, 0x01, 0x50, 0x01, 0x3b, 0x01, 0x0c, 0x01, 0xd6, 0x00, 0xa3, 0x00, 0x79, 0x00, 0x5a, 0x00, 0x3e, 0x00, 0x0f, 0x00, 0xed, 0xff, 0xd2, 0xff, 0xbc, 0xff, 0xbb, 0xff, 0xbe, 0xff, 0xb1, 0xff, 0x96, 0xff, 0x78, 0xff, 0x59, 0xff, 0x46, 0xff, 0x49, 0xff, 0x5b, 0xff, 0x78, 0xff, 0x8f, 0xff, 0xa0, 0xff, 0xaf, 0xff, 0xa7, 0xff, 0x9d, 0xff, 0x88, 0xff, 0x91, 0xff, 0xa1, 0xff, 0xb9, 0xff, 0xce, 0xff, 0xe0, 0xff, 0x04, 0x00, 0x30, 0x00, 0x6e, 0x00, 0x82, 0x00, 0x90, 0x00, 0x98, 0x00, 0x95, 0x00, 0x8b, 0x00, 0x85, 0x00, 0x83, 0x00, 0x84, 0x00, 0x94, 0x00, 0x96, 0x00, 0xa0, 0x00, 0x8e, 0x00, 0x75, 0x00, 0x58, 0x00, 0x3a, 0x00, 0x25, 0x00, 0x10, 0x00, 0xf7, 0xff, 0xe0, 0xff, 0xd8, 0xff, 0xcd, 0xff, 0xd7, 0xff, 0xdc, 0xff, 0xc9, 0xff, 0xb5, 0xff, 0x8c, 0xff, 0x68, 0xff, 0x3f, 0xff, 0x30, 0xff, 0x24, 0xff, 0x21, 0xff, 0x1b, 0xff, 0x29, 0xff, 0x24, 0xff, 0x21, 0xff, 0x17, 0xff, 0x29, 0xff, 0x42, 0xff, 0x6a, 0xff, 0x86, 0xff, 0xb2, 0xff, 0xe1, 0xff, 0x02, 0x00, 0x1b, 0x00, 0x34, 0x00, 0x61, 0x00, 0x7d, 0x00, 0xa4, 0x00, 0xcd, 0x00, 0xf6, 0x00, 0x21, 0x01, 0x2d, 0x01, 0x4c, 0x01, 0x72, 0x01, 0xa0, 0x01, 0xab, 0x01, 0x8d, 0x01, 0x66, 0x01, 0x3b, 0x01, 0xf5, 0x00, 0xa1, 0x00, 0x3c, 0x00, 0xe9, 0xff, 0xa3, 0xff, 0x6d, 0xff, 0x2f, 0xff, 0xfa, 0xfe, 0xd2, 0xfe, 0xaf, 0xfe, 0x9e, 0xfe, 0x92, 0xfe, 0x95, 0xfe, 0xa5, 0xfe, 0xbe, 0xfe, 0xd3, 0xfe, 0xd9, 0xfe, 0xd3, 0xfe, 0xcd, 0xfe, 0xd6, 0xfe, 0xf4, 0xfe, 0x24, 0xff, 0x4f, 0xff, 0x85, 0xff, 0xbb, 0xff, 0x0f, 0x00, 0x5d, 0x00, 0xa6, 0x00, 0xec, 0x00, 0x47, 0x01, 0x96, 0x01, 0xcf, 0x01, 0xfd, 0x01, 0x1e, 0x02, 0x28, 0x02, 0x19, 0x02, 0x05, 0x02, 0x08, 0x02, 0xf7, 0x01, 0xe7, 0x01, 0xcb, 0x01, 0xa0, 0x01, 0x75, 0x01, 0x25, 0x01, 0xcb, 0x00, 0x63, 0x00, 0x07, 0x00, 0xb1, 0xff, 0x55, 0xff, 0x15, 0xff, 0xcc, 0xfe, 0x9f, 0xfe, 0x6a, 0xfe, 0x50, 0xfe, 0x3f, 0xfe, 0x38, 0xfe, 0x38, 0xfe, 0x4e, 0xfe, 0x6b, 0xfe, 0x96, 0xfe, 0xb9, 0xfe, 0xd3, 0xfe, 0xef, 0xfe, 0xfb, 0xfe, 0x03, 0xff, 0x20, 0xff, 0x26, 0xff, 0x52, 0xff, 0x7e, 0xff, 0xc5, 0xff, 0x08, 0x00, 0x3b, 0x00, 0x62, 0x00, 0x88, 0x00, 0xab, 0x00, 0xbe, 0x00, 0xc1, 0x00, 0xd1, 0x00, 0xe7, 0x00, 0xfc, 0x00, 0x0a, 0x01, 0x0f, 0x01, 0x1a, 0x01, 0x09, 0x01, 0x06, 0x01, 0xfb, 0x00, 0xe3, 0x00, 0xd2, 0x00, 0xd6, 0x00, 0xcb, 0x00, 0xd6, 0x00, 0xba, 0x00, 0xac, 0x00, 0x85, 0x00, 0x63, 0x00, 0x39, 0x00, 0xfc, 0xff, 0xbd, 0xff, 0x78, 0xff, 0x45, 0xff, 0x1d, 0xff, 0xfe, 0xfe, 0xf9, 0xfe, 0xef, 0xfe, 0xf5, 0xfe, 0xf6, 0xfe, 0x09, 0xff, 0x28, 0xff, 0x4a, 0xff, 0x5a, 0xff, 0x7b, 0xff, 0x8d, 0xff, 0xb8, 0xff, 0xee, 0xff, 0x19, 0x00, 0x39, 0x00, 0x37, 0x00, 0x23, 0x00, 0x06, 0x00, 0xe4, 0xff, 0xc3, 0xff, 0xb7, 0xff, 0xad, 0xff, 0xba, 0xff, 0xcf, 0xff, 0xf1, 0xff, 0x17, 0x00, 0x41, 0x00, 0x71, 0x00, 0x8a, 0x00, 0xa1, 0x00, 0xa4, 0x00, 0x9b, 0x00, 0x8e, 0x00, 0x81, 0x00, 0x6b, 0x00, 0x53, 0x00, 0x3d, 0x00, 0x1b, 0x00, 0xf3, 0xff, 0xc9, 0xff, 0xa0, 0xff, 0x72, 0xff, 0x57, 0xff, 0x40, 0xff, 0x34, 0xff, 0x27, 0xff, 0x32, 0xff, 0x3b, 0xff, 0x5c, 0xff, 0x8b, 0xff, 0xbf, 0xff, 0x02, 0x00, 0x3d, 0x00, 0x69, 0x00, 0x71, 0x00, 0x6b, 0x00, 0x57, 0x00, 0x52, 0x00, 0x30, 0x00, 0x0e, 0x00, 0xf0, 0xff, 0xde, 0xff, 0xce, 0xff, 0xc0, 0xff, 0xaf, 0xff, 0xa1, 0xff, 0xa9, 0xff, 0xae, 0xff, 0xca, 0xff, 0xdf, 0xff, 0x00, 0x00, 0x30, 0x00, 0x69, 0x00, 0xa8, 0x00, 0xc5, 0x00, 0xd0, 0x00, 0xc4, 0x00, 0xb3, 0x00, 0x83, 0x00, 0x4e, 0x00, 0x11, 0x00, 0xec, 0xff, 0xd4, 0xff, 0xca, 0xff, 0xd4, 0xff, 0xe3, 0xff, 0xe5, 0xff, 0xdb, 0xff, 0xc6, 0xff, 0xaa, 0xff, 0x97, 0xff, 0x8f, 0xff, 0x9c, 0xff, 0xb9, 0xff, 0xcf, 0xff, 0xe3, 0xff, 0xe8, 0xff, 0xea, 0xff, 0xe5, 0xff, 0xeb, 0xff, 0xe6, 0xff, 0xde, 0xff, 0xdf, 0xff, 0xe7, 0xff, 0xfc, 0xff, 0x1f, 0x00, 0x28, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x58, 0x00, 0x78, 0x00, 0x9f, 0x00, 0xbd, 0x00, 0xd3, 0x00, 0xe2, 0x00, 0xcb, 0x00, 0xa6, 0x00, 0x80, 0x00, 0x5e, 0x00, 0x41, 0x00, 0x2c, 0x00, 0x25, 0x00, 0x19, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x11, 0x00, 0xfe, 0xff, 0xf0, 0xff, 0xc3, 0xff, 0xa2, 0xff, 0x79, 0xff, 0x53, 0xff, 0x27, 0xff, 0x16, 0xff, 0x01, 0xff, 0x04, 0xff, 0x07, 0xff, 0x23, 0xff, 0x54, 0xff, 0x6a, 0xff, 0x98, 0xff, 0xb0, 0xff, 0xda, 0xff, 0x03, 0x00, 0x1e, 0x00, 0x48, 0x00, 0x79, 0x00, 0xb4, 0x00, 0xf4, 0x00, 0x17, 0x01, 0x34, 0x01, 0x36, 0x01, 0x22, 0x01, 0xf8, 0x00, 0xb8, 0x00, 0x7d, 0x00, 0x40, 0x00, 0x14, 0x00, 0xe9, 0xff, 0xcb, 0xff, 0xa5, 0xff, 0x8a, 0xff, 0x77, 0xff, 0x64, 0xff, 0x63, 0xff, 0x6c, 0xff, 0x66, 0xff, 0x74, 0xff, 0x63, 0xff, 0x6d, 0xff, 0x6e, 0xff, 0x7f, 0xff, 0x92, 0xff, 0xae, 0xff, 0xbc, 0xff, 0xc8, 0xff, 0xd3, 0xff, 0xe0, 0xff, 0xf5, 0xff, 0x0c, 0x00, 0x28, 0x00, 0x4a, 0x00, 0x6d, 0x00, 0x95, 0x00, 0xb9, 0x00, 0xdb, 0x00, 0xd7, 0x00, 0xcb, 0x00, 0xb9, 0x00, 0xbb, 0x00, 0xc1, 0x00, 0xb6, 0x00, 0xa2, 0x00, 0x75, 0x00, 0x41, 0x00, 0x09, 0x00, 0xea, 0xff, 0xcd, 0xff, 0xae, 0xff, 0x86, 0xff, 0x5e, 0xff, 0x3d, 0xff, 0x1f, 0xff, 0x19, 0xff, 0x0e, 0xff, 0x1d, 0xff, 0x25, 0xff, 0x43, 0xff, 0x5a, 0xff, 0x6e, 0xff, 0x86, 0xff, 0x92, 0xff, 0xaf, 0xff, 0xd1, 0xff, 0xed, 0xff, 0x02, 0x00, 0x2f, 0x00, 0x40, 0x00, 0x50, 0x00, 0x40, 0x00, 0x3f, 0x00, 0x4a, 0x00, 0x5a, 0x00, 0x68, 0x00, 0x7b, 0x00, 0x89, 0x00, 0xa1, 0x00, 0xb7, 0x00, 0xbb, 0x00, 0xa9, 0x00, 0x93, 0x00, 0x84, 0x00, 0x71, 0x00, 0x66, 0x00, 0x5b, 0x00, 0x53, 0x00, 0x48, 0x00, 0x3e, 0x00, 0x45, 0x00, 0x5a, 0x00, 0x7a, 0x00, 0x9c, 0x00, 0xba, 0x00, 0xce, 0x00, 0xc6, 0x00, 0xb6, 0x00, 0x86, 0x00, 0x57, 0x00, 0x2b, 0x00, 0x13, 0x00, 0xf7, 0xff, 0xcc, 0xff, 0xae, 0xff, 0x75, 0xff, 0x4b, 0xff, 0x15, 0xff, 0xfe, 0xfe, 0xda, 0xfe, 0xd2, 0xfe, 0xce, 0xfe, 0xcf, 0xfe, 0xcf, 0xfe, 0xcd, 0xfe, 0xe2, 0xfe, 0x02, 0xff, 0x29, 0xff, 0x5c, 0xff, 0x85, 0xff, 0xb9, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0x26, 0x00, 0x5b, 0x00, 0x8a, 0x00, 0xad, 0x00, 0xc5, 0x00, 0xcb, 0x00, 0xc0, 0x00, 0xcf, 0x00, 0xcb, 0x00, 0xba, 0x00, 0xac, 0x00, 0xa9, 0x00, 0xb5, 0x00, 0xb2, 0x00, 0x89, 0x00, 0x6a, 0x00, 0x37, 0x00, 0x22, 0x00, 0xfa, 0xff, 0xcd, 0xff, 0xa6, 0xff, 0x80, 0xff, 0x68, 0xff, 0x67, 0xff, 0x6b, 0xff, 0x7a, 0xff, 0x83, 0xff, 0x80, 0xff, 0x79, 0xff, 0x79, 0xff, 0x81, 0xff, 0x89, 0xff, 0x8f, 0xff, 0xa1, 0xff, 0xcd, 0xff, 0x09, 0x00, 0x4e, 0x00, 0x7f, 0x00, 0xa0, 0x00, 0xbe, 0x00, 0xd0, 0x00, 0xe7, 0x00, 0xff, 0x00, 0x0a, 0x01, 0x0a, 0x01, 0xf6, 0x00, 0xd3, 0x00, 0x9b, 0x00, 0x68, 0x00, 0x40, 0x00, 0x0e, 0x00, 0xe7, 0xff, 0xba, 0xff, 0xa7, 0xff, 0x8e, 0xff, 0x84, 0xff, 0x7e, 0xff, 0x7e, 0xff, 0x7d, 0xff, 0x6c, 0xff, 0x65, 0xff, 0x64, 0xff, 0x71, 0xff, 0x8e, 0xff, 0xb6, 0xff, 0xd3, 0xff, 0xda, 0xff, 0xdb, 0xff, 0xd0, 0xff, 0xca, 0xff, 0xc9, 0xff, 0xc2, 0xff, 0xcd, 0xff, 0xc8, 0xff, 0xc2, 0xff, 0xa6, 0xff, 0x9c, 0xff, 0x83, 0xff, 0x72, 0xff, 0x60, 0xff, 0x54, 0xff, 0x51, 0xff, 0x4b, 0xff, 0x5b, 0xff, 0x73, 0xff, 0xa3, 0xff, 0xd0, 0xff, 0x04, 0x00, 0x2b, 0x00, 0x49, 0x00, 0x6a, 0x00, 0x94, 0x00, 0xb3, 0x00, 0xbb, 0x00, 0xb2, 0x00, 0xaf, 0x00, 0xa8, 0x00, 0xb3, 0x00, 0xc9, 0x00, 0xfa, 0x00, 0x2d, 0x01, 0x63, 0x01, 0x95, 0x01, 0xc1, 0x01, 0xca, 0x01, 0xb9, 0x01, 0x81, 0x01, 0x3e, 0x01, 0xe3, 0x00, 0x73, 0x00, 0x1d, 0x00, 0xce, 0xff, 0x86, 0xff, 0x42, 0xff, 0x06, 0xff, 0xd8, 0xfe, 0xc3, 0xfe, 0xb4, 0xfe, 0xc4, 0xfe, 0xd8, 0xfe, 0x05, 0xff, 0x1d, 0xff, 0x4a, 0xff, 0x62, 0xff, 0x86, 0xff, 0xa0, 0xff, 0xba, 0xff, 0xcd, 0xff, 0xe4, 0xff, 0xf2, 0xff, 0x15, 0x00, 0x2a, 0x00, 0x46, 0x00, 0x59, 0x00, 0x73, 0x00, 0x8f, 0x00, 0x8a, 0x00, 0x85, 0x00, 0x55, 0x00, 0x36, 0x00, 0x03, 0x00, 0xe8, 0xff, 0xca, 0xff, 0xb6, 0xff, 0xab, 0xff, 0xa4, 0xff, 0xa8, 0xff, 0x9d, 0xff, 0x9a, 0xff, 0x9b, 0xff, 0xab, 0xff, 0xb7, 0xff, 0xb5, 0xff, 0xb8, 0xff, 0xbd, 0xff, 0xca, 0xff, 0xce, 0xff, 0xd0, 0xff, 0xd5, 0xff, 0xe5, 0xff, 0xf7, 0xff, 0x15, 0x00, 0x33, 0x00, 0x4c, 0x00, 0x5a, 0x00, 0x60, 0x00, 0x5d, 0x00, 0x59, 0x00, 0x53, 0x00, 0x4c, 0x00, 0x44, 0x00, 0x2d, 0x00, 0x0f, 0x00, 0xf2, 0xff, 0xe3, 0xff, 0xcf, 0xff, 0xc1, 0xff, 0xb0, 0xff, 0xa5, 0xff, 0xa7, 0xff, 0xa1, 0xff, 0xa9, 0xff, 0xbe, 0xff, 0xca, 0xff, 0xca, 0xff, 0xd3, 0xff, 0xe0, 0xff, 0xf4, 0xff, 0x0b, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x11, 0x00, 0x0e, 0x00, 0x1e, 0x00, 0x1a, 0x00, 0x19, 0x00, 0xfe, 0xff, 0xf5, 0xff, 0xe3, 0xff, 0xf2, 0xff, 0xf2, 0xff, 0x06, 0x00, 0x14, 0x00, 0x39, 0x00, 0x41, 0x00, 0x56, 0x00, 0x63, 0x00, 0x70, 0x00, 0x61, 0x00, 0x5e, 0x00, 0x56, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x7a, 0x00, 0x7d, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x31, 0x00, 0x1c, 0x00, 0xf9, 0xff, 0xdf, 0xff, 0xcb, 0xff, 0xaf, 0xff, 0x8a, 0xff, 0x67, 0xff, 0x48, 0xff, 0x3e, 0xff, 0x40, 0xff, 0x55, 0xff, 0x63, 0xff, 0x78, 0xff, 0x87, 0xff, 0xa9, 0xff, 0xcd, 0xff, 0x04, 0x00, 0x37, 0x00, 0x5d, 0x00, 0x6a, 0x00, 0x63, 0x00, 0x56, 0x00, 0x4c, 0x00, 0x30, 0x00, 0x22, 0x00, 0x00, 0x00, 0xfa, 0xff, 0xe7, 0xff, 0xf3, 0xff, 0x01, 0x00, 0x1e, 0x00, 0x45, 0x00, 0x75, 0x00, 0x93, 0x00, 0xb1, 0x00, 0xb4, 0x00, 0xab, 0x00, 0x99, 0x00, 0x84, 0x00, 0x70, 0x00, 0x64, 0x00, 0x4f, 0x00, 0x4c, 0x00, 0x3d, 0x00, 0x26, 0x00, 0x04, 0x00, 0xdd, 0xff, 0xbc, 0xff, 0x97, 0xff, 0x7c, 0xff, 0x6c, 0xff, 0x64, 0xff, 0x66, 0xff, 0x6b, 0xff, 0x64, 0xff, 0x58, 0xff, 0x44, 0xff, 0x37, 0xff, 0x22, 0xff, 0x19, 0xff, 0x14, 0xff, 0x21, 0xff, 0x38, 0xff, 0x66, 0xff, 0x85, 0xff, 0x96, 0xff, 0xaf, 0xff, 0xc0, 0xff, 0xd3, 0xff, 0xe9, 0xff, 0x09, 0x00, 0x28, 0x00, 0x47, 0x00, 0x60, 0x00, 0x75, 0x00, 0x8a, 0x00, 0x9a, 0x00, 0xa8, 0x00, 0xbb, 0x00, 0xd4, 0x00, 0xdf, 0x00, 0xdd, 0x00, 0xda, 0x00, 0xb9, 0x00, 0x97, 0x00, 0x80, 0x00, 0x6d, 0x00, 0x73, 0x00, 0x75, 0x00, 0x76, 0x00, 0x63, 0x00, 0x53, 0x00, 0x3e, 0x00, 0x44, 0x00, 0x42, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x45, 0x00, 0x48, 0x00, 0x44, 0x00, 0x36, 0x00, 0x11, 0x00, 0xe6, 0xff, 0xbe, 0xff, 0x91, 0xff, 0x70, 0xff, 0x52, 0xff, 0x4b, 0xff, 0x57, 0xff, 0x6a, 0xff, 0x85, 0xff, 0x99, 0xff, 0xaa, 0xff, 0xba, 0xff, 0xc3, 0xff, 0xe0, 0xff, 0xe9, 0xff, 0xf7, 0xff, 0xeb, 0xff, 0xdb, 0xff, 0xb8, 0xff, 0x9b, 0xff, 0x8c, 0xff, 0x89, 0xff, 0x87, 0xff, 0x91, 0xff, 0xa4, 0xff, 0xbb, 0xff, 0xc8, 0xff, 0xd8, 0xff, 0xd9, 0xff, 0xdd, 0xff, 0xdb, 0xff, 0xe1, 0xff, 0xe7, 0xff, 0xe3, 0xff, 0xe0, 0xff, 0xd9, 0xff, 0xdc, 0xff, 0xf5, 0xff, 0x11, 0x00, 0x4c, 0x00, 0x7c, 0x00, 0xaf, 0x00, 0xbf, 0x00, 0xce, 0x00, 0xe0, 0x00, 0xe2, 0x00, 0xd3, 0x00, 0xd0, 0x00, 0xb6, 0x00, 0x93, 0x00, 0x79, 0x00, 0x58, 0x00, 0x3c, 0x00, 0x21, 0x00, 0x03, 0x00, 0xfa, 0xff, 0xed, 0xff, 0xf0, 0xff, 0xf4, 0xff, 0xec, 0xff, 0xef, 0xff, 0xe4, 0xff, 0xd7, 0xff, 0xc6, 0xff, 0xb9, 0xff, 0x9e, 0xff, 0x94, 0xff, 0x81, 0xff, 0x77, 0xff, 0x7b, 0xff, 0x82, 0xff, 0x89, 0xff, 0x95, 0xff, 0x9d, 0xff, 0x9f, 0xff, 0xa4, 0xff, 0xa8, 0xff, 0xb9, 0xff, 0xd4, 0xff, 0xea, 0xff, 0xe7, 0xff, 0xe4, 0xff, 0xdd, 0xff, 0xe2, 0xff, 0xe9, 0xff, 0xf3, 0xff, 0xf9, 0xff, 0x07, 0x00, 0xf4, 0xff, 0xea, 0xff, 0xe8, 0xff, 0xf5, 0xff, 0xf9, 0xff, 0x0b, 0x00, 0x1f, 0x00, 0x44, 0x00, 0x6a, 0x00, 0x93, 0x00, 0xa5, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xba, 0x00, 0xb4, 0x00, 0xa3, 0x00, 0x9b, 0x00, 0x8d, 0x00, 0x7c, 0x00, 0x54, 0x00, 0x46, 0x00, 0x1d, 0x00, 0x06, 0x00, 0xee, 0xff, 0xe7, 0xff, 0xd5, 0xff, 0xcc, 0xff, 0xb9, 0xff, 0xa7, 0xff, 0x88, 0xff, 0x70, 0xff, 0x5e, 0xff, 0x53, 0xff, 0x61, 0xff, 0x7b, 0xff, 0x9e, 0xff, 0xd5, 0xff, 0xf8, 0xff, 0x23, 0x00, 0x46, 0x00, 0x5d, 0x00, 0x6b, 0x00, 0x5a, 0x00, 0x61, 0x00, 0x64, 0x00, 0x74, 0x00, 0x7e, 0x00, 0x8a, 0x00, 0x9f, 0x00, 0xaf, 0x00, 0xba, 0x00, 0xab, 0x00, 0x90, 0x00, 0x6c, 0x00, 0x43, 0x00, 0x0f, 0x00, 0xd2, 0xff, 0x9d, 0xff, 0x75, 0xff, 0x55, 0xff, 0x48, 0xff, 0x45, 0xff, 0x48, 0xff, 0x4b, 0xff, 0x47, 0xff, 0x40, 0xff, 0x3a, 0xff, 0x29, 0xff, 0x21, 0xff, 0x1c, 0xff, 0x30, 0xff, 0x3e, 0xff, 0x4d, 0xff, 0x5e, 0xff, 0x72, 0xff, 0x79, 0xff, 0x90, 0xff, 0xaa, 0xff, 0xe0, 0xff, 0x0a, 0x00, 0x3a, 0x00, 0x75, 0x00, 0xb3, 0x00, 0xfa, 0x00, 0x2a, 0x01, 0x46, 0x01, 0x6a, 0x01, 0x87, 0x01, 0x95, 0x01, 0x9d, 0x01, 0x71, 0x01, 0x3d, 0x01, 0xfc, 0x00, 0xc0, 0x00, 0x77, 0x00, 0x37, 0x00, 0xf6, 0xff, 0xb5, 0xff, 0x7c, 0xff, 0x50, 0xff, 0x2d, 0xff, 0x0e, 0xff, 0xf3, 0xfe, 0xeb, 0xfe, 0xe8, 0xfe, 0xf7, 0xfe, 0x10, 0xff, 0x2d, 0xff, 0x55, 0xff, 0x8a, 0xff, 0xb2, 0xff, 0xdf, 0xff, 0xf1, 0xff, 0x11, 0x00, 0x29, 0x00, 0x49, 0x00, 0x59, 0x00, 0x4e, 0x00, 0x56, 0x00, 0x52, 0x00, 0x5f, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x5b, 0x00, 0x53, 0x00, 0x4f, 0x00, 0x60, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x5d, 0x00, 0x42, 0x00, 0x29, 0x00, 0x1c, 0x00, 0x12, 0x00, 0x06, 0x00, 0xed, 0xff, 0xca, 0xff, 0xc4, 0xff, 0xbc, 0xff, 0xad, 0xff, 0xa2, 0xff, 0x92, 0xff, 0x84, 0xff, 0x80, 0xff, 0x79, 0xff, 0x7a, 0xff, 0x91, 0xff, 0x9b, 0xff, 0xb7, 0xff, 0xc8, 0xff, 0xde, 0xff, 0x01, 0x00, 0x1d, 0x00, 0x3c, 0x00, 0x54, 0x00, 0x51, 0x00, 0x51, 0x00, 0x4c, 0x00, 0x43, 0x00, 0x30, 0x00, 0x33, 0x00, 0x39, 0x00, 0x43, 0x00, 0x41, 0x00, 0x43, 0x00, 0x3c, 0x00, 0x27, 0x00, 0x0e, 0x00, 0x03, 0x00, 0xf3, 0xff, 0xe2, 0xff, 0xca, 0xff, 0xa6, 0xff, 0x97, 0xff, 0x89, 0xff, 0x86, 0xff, 0x77, 0xff, 0x72, 0xff, 0x65, 0xff, 0x64, 0xff, 0x63, 0xff, 0x78, 0xff, 0x8c, 0xff, 0xc0, 0xff, 0xf2, 0xff, 0x49, 0x00, 0x9d, 0x00, 0xdc, 0x00, 0x0c, 0x01, 0x38, 0x01, 0x55, 0x01, 0x52, 0x01, 0x2b, 0x01, 0x1a, 0x01, 0xf9, 0x00, 0xe2, 0x00, 0xc6, 0x00, 0xa7, 0x00, 0x82, 0x00, 0x58, 0x00, 0x30, 0x00, 0xfd, 0xff, 0xcf, 0xff, 0xaa, 0xff, 0x79, 0xff, 0x5d, 0xff, 0x40, 0xff, 0x34, 0xff, 0x2a, 0xff, 0x2b, 0xff, 0x30, 0xff, 0x2b, 0xff, 0x43, 0xff, 0x53, 0xff, 0x69, 0xff, 0x7f, 0xff, 0x88, 0xff, 0xac, 0xff, 0xc9, 0xff, 0xe7, 0xff, 0xfe, 0xff, 0x0e, 0x00, 0x12, 0x00, 0x09, 0x00, 0x00, 0x00, 0xf3, 0xff, 0xef, 0xff, 0xf3, 0xff, 0x00, 0x00, 0x05, 0x00, 0x10, 0x00, 0x03, 0x00, 0x14, 0x00, 0x13, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x35, 0x00, 0x66, 0x00, 0x7b, 0x00, 0x94, 0x00, 0x8f, 0x00, 0x8a, 0x00, 0x78, 0x00, 0x6f, 0x00, 0x56, 0x00, 0x56, 0x00, 0x47, 0x00, 0x37, 0x00, 0x27, 0x00, 0x1f, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x06, 0x00, 0xfd, 0xff, 0xeb, 0xff, 0xca, 0xff, 0x9f, 0xff, 0x7f, 0xff, 0x50, 0xff, 0x44, 0xff, 0x36, 0xff, 0x37, 0xff, 0x2e, 0xff, 0x26, 0xff, 0x3a, 0xff, 0x4f, 0xff, 0x64, 0xff, 0x72, 0xff, 0x8f, 0xff, 0xae, 0xff, 0xd5, 0xff, 0xf9, 0xff, 0x15, 0x00, 0x2f, 0x00, 0x34, 0x00, 0x2f, 0x00, 0x2e, 0x00, 0x26, 0x00, 0x2b, 0x00, 0x34, 0x00, 0x4c, 0x00, 0x71, 0x00, 0xab, 0x00, 0xda, 0x00, 0xf2, 0x00, 0xf5, 0x00, 0xea, 0x00, 0xde, 0x00, 0xb7, 0x00, 0x86, 0x00, 0x60, 0x00, 0x2f, 0x00, 0x04, 0x00, 0xda, 0xff, 0xba, 0xff, 0xa9, 0xff, 0x9d, 0xff, 0x97, 0xff, 0x8e, 0xff, 0x96, 0xff, 0x8c, 0xff, 0x93, 0xff, 0x9a, 0xff, 0x97, 0xff, 0x96, 0xff, 0xa2, 0xff, 0xb0, 0xff, 0xce, 0xff, 0xe7, 0xff, 0x04, 0x00, 0x15, 0x00, 0x24, 0x00, 0x1a, 0x00, 0x17, 0x00, 0x10, 0x00, 0x02, 0x00, 0xf9, 0xff, 0xe3, 0xff, 0xc7, 0xff, 0xa6, 0xff, 0x97, 0xff, 0x97, 0xff, 0xa8, 0xff, 0xb9, 0xff, 0xcf, 0xff, 0x01, 0x00, 0x32, 0x00, 0x68, 0x00, 0xaf, 0x00, 0xfe, 0x00, 0x3e, 0x01, 0x54, 0x01, 0x5c, 0x01, 0x5a, 0x01, 0x49, 0x01, 0x10, 0x01, 0xce, 0x00, 0x7a, 0x00, 0x3a, 0x00, 0xfe, 0xff, 0xc4, 0xff, 0x9a, 0xff, 0x76, 0xff, 0x5c, 0xff, 0x37, 0xff, 0x23, 0xff, 0x1a, 0xff, 0x03, 0xff, 0x00, 0xff, 0xeb, 0xfe, 0xf7, 0xfe, 0x00, 0xff, 0x18, 0xff, 0x3b, 0xff, 0x67, 0xff, 0x8a, 0xff, 0xb6, 0xff, 0xe0, 0xff, 0x0d, 0x00, 0x3b, 0x00, 0x6b, 0x00, 0xa9, 0x00, 0xd9, 0x00, 0x0a, 0x01, 0x30, 0x01, 0x3c, 0x01, 0x26, 0x01, 0xf9, 0x00, 0xd3, 0x00, 0xa3, 0x00, 0x7b, 0x00, 0x60, 0x00, 0x42, 0x00, 0x2a, 0x00, 0x13, 0x00, 0xf7, 0xff, 0xe3, 0xff, 0xe1, 0xff, 0xf1, 0xff, 0x11, 0x00, 0x23, 0x00, 0x22, 0x00, 0x06, 0x00, 0xd9, 0xff, 0xab, 0xff, 0x72, 0xff, 0x42, 0xff, 0x20, 0xff, 0x0c, 0xff, 0x05, 0xff, 0x08, 0xff, 0x11, 0xff, 0x30, 0xff, 0x51, 0xff, 0x73, 0xff, 0xa5, 0xff, 0xc3, 0xff, 0xd7, 0xff, 0xf5, 0xff, 0x10, 0x00, 0x31, 0x00, 0x44, 0x00, 0x56, 0x00, 0x65, 0x00, 0x5f, 0x00, 0x64, 0x00, 0x68, 0x00, 0x84, 0x00, 0xb5, 0x00, 0xe5, 0x00, 0x0e, 0x01, 0x08, 0x01, 0xfb, 0x00, 0xe0, 0x00, 0xd0, 0x00, 0xaa, 0x00, 0x80, 0x00, 0x4d, 0x00, 0x18, 0x00, 0xee, 0xff, 0xc6, 0xff, 0xa3, 0xff, 0x87, 0xff, 0x6f, 0xff, 0x5d, 0xff, 0x3d, 0xff, 0x37, 0xff, 0x3a, 0xff, 0x4f, 0xff, 0x54, 0xff, 0x5b, 0xff, 0x64, 0xff, 0x6f, 0xff, 0x8c, 0xff, 0xa0, 0xff, 0xb9, 0xff, 0xc4, 0xff, 0xd6, 0xff, 0xe5, 0xff, 0xf4, 0xff, 0x0d, 0x00, 0x11, 0x00, 0x1c, 0x00, 0x26, 0x00, 0x2f, 0x00, 0x26, 0x00, 0x1e, 0x00, 0x09, 0x00, 0xf6, 0xff, 0xe4, 0xff, 0xe9, 0xff, 0xed, 0xff, 0xf8, 0xff, 0xf3, 0xff, 0xfb, 0xff, 0x0f, 0x00, 0x27, 0x00, 0x5b, 0x00, 0x85, 0x00, 0xab, 0x00, 0xcd, 0x00, 0xef, 0x00, 0x10, 0x01, 0x22, 0x01, 0x35, 0x01, 0x4c, 0x01, 0x47, 0x01, 0x22, 0x01, 0xfe, 0x00, 0xc7, 0x00, 0x8f, 0x00, 0x58, 0x00, 0x22, 0x00, 0x05, 0x00, 0xe4, 0xff, 0xd7, 0xff, 0xc2, 0xff, 0x9e, 0xff, 0x74, 0xff, 0x4e, 0xff, 0x2b, 0xff, 0x0d, 0xff, 0xfa, 0xfe, 0xe5, 0xfe, 0xdf, 0xfe, 0xdf, 0xfe, 0xe5, 0xfe, 0xe8, 0xfe, 0xf0, 0xfe, 0x05, 0xff, 0x1b, 0xff, 0x2f, 0xff, 0x45, 0xff, 0x59, 0xff, 0x63, 0xff, 0x70, 0xff, 0x79, 0xff, 0x9e, 0xff, 0xc5, 0xff, 0xf6, 0xff, 0x23, 0x00, 0x4c, 0x00, 0x65, 0x00, 0x79, 0x00, 0x81, 0x00, 0x92, 0x00, 0x90, 0x00, 0x92, 0x00, 0x7d, 0x00, 0x67, 0x00, 0x53, 0x00, 0x5a, 0x00, 0x6e, 0x00, 0x8f, 0x00, 0xc0, 0x00, 0xd1, 0x00, 0xd0, 0x00, 0xcb, 0x00, 0xb3, 0x00, 0x99, 0x00, 0x84, 0x00, 0x78, 0x00, 0x67, 0x00, 0x3e, 0x00, 0x25, 0x00, 0x0c, 0x00, 0xf4, 0xff, 0xcd, 0xff, 0xaf, 0xff, 0x91, 0xff, 0x7f, 0xff, 0x7b, 0xff, 0x78, 0xff, 0x75, 0xff, 0x6c, 0xff, 0x5c, 0xff, 0x53, 0xff, 0x57, 0xff, 0x5c, 0xff, 0x63, 0xff, 0x6e, 0xff, 0x70, 0xff, 0x87, 0xff, 0x82, 0xff, 0x8d, 0xff, 0x86, 0xff, 0x7a, 0xff, 0x86, 0xff, 0x9f, 0xff, 0xbb, 0xff, 0xd8, 0xff, 0xef, 0xff, 0x12, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x8a, 0x00, 0xaf, 0x00, 0xc5, 0x00, 0xdf, 0x00, 0x0b, 0x01, 0x2f, 0x01, 0x50, 0x01, 0x65, 0x01, 0x52, 0x01, 0x31, 0x01, 0x04, 0x01, 0xd4, 0x00, 0x9d, 0x00, 0x5e, 0x00, 0x2e, 0x00, 0xf2, 0xff, 0xce, 0xff, 0xa4, 0xff, 0x94, 0xff, 0x79, 0xff, 0x63, 0xff, 0x47, 0xff, 0x42, 0xff, 0x3b, 0xff, 0x4a, 0xff, 0x53, 0xff, 0x61, 0xff, 0x74, 0xff, 0x89, 0xff, 0xa5, 0xff, 0xc0, 0xff, 0xd5, 0xff, 0xd1, 0xff, 0xdd, 0xff, 0xde, 0xff, 0xec, 0xff, 0xfa, 0xff, 0x19, 0x00, 0x3a, 0x00, 0x4b, 0x00, 0x50, 0x00, 0x43, 0x00, 0x32, 0x00, 0x16, 0x00, 0xf9, 0xff, 0xe8, 0xff, 0xd3, 0xff, 0xc9, 0xff, 0xb5, 0xff, 0xac, 0xff, 0x9e, 0xff, 0x92, 0xff, 0x9a, 0xff, 0x94, 0xff, 0x8b, 0xff, 0x82, 0xff, 0x84, 0xff, 0x8b, 0xff, 0x98, 0xff, 0xa4, 0xff, 0xb1, 0xff, 0xd1, 0xff, 0xf7, 0xff, 0x2e, 0x00, 0x5a, 0x00, 0x88, 0x00, 0xb1, 0x00, 0xc9, 0x00, 0xec, 0x00, 0xf4, 0x00, 0xfc, 0x00, 0xf0, 0x00, 0xe0, 0x00, 0xcb, 0x00, 0xaa, 0x00, 0x7f, 0x00, 0x55, 0x00, 0x27, 0x00, 0x05, 0x00, 0xd8, 0xff, 0xc2, 0xff, 0x9e, 0xff, 0x83, 0xff, 0x62, 0xff, 0x47, 0xff, 0x44, 0xff, 0x3f, 0xff, 0x40, 0xff, 0x4b, 0xff, 0x5b, 0xff, 0x79, 0xff, 0xa5, 0xff, 0xcf, 0xff, 0xf2, 0xff, 0x0d, 0x00, 0x26, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x28, 0x00, 0x25, 0x00, 0x2b, 0x00, 0x16, 0x00, 0x15, 0x00, 0x0c, 0x00, 0x12, 0x00, 0x06, 0x00, 0xf1, 0xff, 0xe5, 0xff, 0xea, 0xff, 0x09, 0x00, 0x2a, 0x00, 0x4b, 0x00, 0x62, 0x00, 0x75, 0x00, 0x71, 0x00, 0x73, 0x00, 0x70, 0x00, 0x63, 0x00, 0x4f, 0x00, 0x31, 0x00, 0x1a, 0x00, 0xf6, 0xff, 0xd9, 0xff, 0xb6, 0xff, 0xab, 0xff, 0x99, 0xff, 0x94, 0xff, 0x8d, 0xff, 0x91, 0xff, 0x93, 0xff, 0xa7, 0xff, 0xc2, 0xff, 0xdb, 0xff, 0xf4, 0xff, 0x14, 0x00, 0x32, 0x00, 0x69, 0x00, 0x8e, 0x00, 0xb4, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xae, 0x00, 0x94, 0x00, 0x72, 0x00, 0x53, 0x00, 0x33, 0x00, 0x21, 0x00, 0x13, 0x00, 0x03, 0x00, 0xec, 0xff, 0xd4, 0xff, 0xbf, 0xff, 0xd1, 0xff, 0xf6, 0xff, 0x00, 0x00, 0xfb, 0xff, 0xdc, 0xff, 0xd0, 0xff, 0xc0, 0xff, 0xba, 0xff, 0xbd, 0xff, 0xbf, 0xff, 0xd7, 0xff, 0xdd, 0xff, 0xe1, 0xff, 0xdd, 0xff, 0xe3, 0xff, 0xd8, 0xff, 0xde, 0xff, 0xc6, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xbf, 0xff, 0xb7, 0xff, 0xa8, 0xff, 0xad, 0xff, 0xb9, 0xff, 0xd1, 0xff, 0xde, 0xff, 0xe2, 0xff, 0xe9, 0xff, 0xfd, 0xff, 0x03, 0x00, 0x17, 0x00, 0x14, 0x00, 0x12, 0x00, 0x17, 0x00, 0x22, 0x00, 0x25, 0x00, 0x2f, 0x00, 0x20, 0x00, 0x23, 0x00, 0x1e, 0x00, 0x17, 0x00, 0x0a, 0x00, 0xfc, 0xff, 0xe0, 0xff, 0xd0, 0xff, 0xb5, 0xff, 0xb3, 0xff, 0xb7, 0xff, 0xaf, 0xff, 0xad, 0xff, 0xb5, 0xff, 0xcd, 0xff, 0xe8, 0xff, 0xf6, 0xff, 0x0d, 0x00, 0x22, 0x00, 0x2c, 0x00, 0x38, 0x00, 0x3e, 0x00, 0x45, 0x00, 0x4f, 0x00, 0x3e, 0x00, 0x33, 0x00, 0x30, 0x00, 0x2b, 0x00, 0x29, 0x00, 0x28, 0x00, 0x27, 0x00, 0x28, 0x00, 0x30, 0x00, 0x23, 0x00, 0x14, 0x00, 0x0a, 0x00, 0x18, 0x00, 0x29, 0x00, 0x2b, 0x00, 0x28, 0x00, 0x2e, 0x00, 0x35, 0x00, 0x47, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x3d, 0x00, 0x26, 0x00, 0x0b, 0x00, 0xf2, 0xff, 0xd7, 0xff, 0xc0, 0xff, 0xaa, 0xff, 0x92, 0xff, 0x9b, 0xff, 0xb1, 0xff, 0xcd, 0xff, 0xd9, 0xff, 0xeb, 0xff, 0xdc, 0xff, 0xcf, 0xff, 0xaf, 0xff, 0x99, 0xff, 0x86, 0xff, 0x76, 0xff, 0x6a, 0xff, 0x63, 0xff, 0x72, 0xff, 0x83, 0xff, 0xa4, 0xff, 0xcd, 0xff, 0xf2, 0xff, 0x0e, 0x00, 0x2f, 0x00, 0x4e, 0x00, 0x7a, 0x00, 0xa0, 0x00, 0xc0, 0x00, 0xd4, 0x00, 0xdd, 0x00, 0xde, 0x00, 0xc8, 0x00, 0xb5, 0x00, 0x9d, 0x00, 0x9e, 0x00, 0x9e, 0x00, 0xa6, 0x00, 0x93, 0x00, 0x79, 0x00, 0x5c, 0x00, 0x38, 0x00, 0x10, 0x00, 0xde, 0xff, 0xae, 0xff, 0x88, 0xff, 0x7f, 0xff, 0x7e, 0xff, 0x8e, 0xff, 0x8b, 0xff, 0x89, 0xff, 0x82, 0xff, 0x7d, 0xff, 0x6b, 0xff, 0x6d, 0xff, 0x7a, 0xff, 0xa0, 0xff, 0xa5, 0xff, 0xa0, 0xff, 0x9a, 0xff, 0x90, 0xff, 0x9f, 0xff, 0xb2, 0xff, 0xc9, 0xff, 0xe8, 0xff, 0xfb, 0xff, 0x14, 0x00, 0x13, 0x00, 0x2c, 0x00, 0x3f, 0x00, 0x4f, 0x00, 0x66, 0x00, 0x88, 0x00, 0x9a, 0x00, 0x9b, 0x00, 0x82, 0x00, 0x68, 0x00, 0x4d, 0x00, 0x3e, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x27, 0x00, 0x23, 0x00, 0x13, 0x00, 0x02, 0x00, 0xe5, 0xff, 0xcc, 0xff, 0xb5, 0xff, 0xa6, 0xff, 0x95, 0xff, 0x8a, 0xff, 0x77, 0xff, 0x74, 0xff, 0x84, 0xff, 0x9a, 0xff, 0xba, 0xff, 0xce, 0xff, 0xeb, 0xff, 0x08, 0x00, 0x28, 0x00, 0x43, 0x00, 0x52, 0x00, 0x59, 0x00, 0x4c, 0x00, 0x48, 0x00, 0x38, 0x00, 0x37, 0x00, 0x1c, 0x00, 0x03, 0x00, 0xdf, 0xff, 0xba, 0xff, 0xab, 0xff, 0xa2, 0xff, 0xb1, 0xff, 0xb3, 0xff, 0xc8, 0xff, 0xd4, 0xff, 0xef, 0xff, 0x17, 0x00, 0x4a, 0x00, 0x71, 0x00, 0x93, 0x00, 0x9b, 0x00, 0xb4, 0x00, 0xae, 0x00, 0xae, 0x00, 0x91, 0x00, 0x88, 0x00, 0x73, 0x00, 0x64, 0x00, 0x46, 0x00, 0x23, 0x00, 0x00, 0x00, 0xd7, 0xff, 0xb7, 0xff, 0x99, 0xff, 0x89, 0xff, 0x85, 0xff, 0x80, 0xff, 0x80, 0xff, 0x9d, 0xff, 0xc5, 0xff, 0xef, 0xff, 0x15, 0x00, 0x26, 0x00, 0x25, 0x00, 0x17, 0x00, 0xfc, 0xff, 0xec, 0xff, 0xca, 0xff, 0xb2, 0xff, 0x98, 0xff, 0x92, 0xff, 0x7e, 0xff, 0x72, 0xff, 0x67, 0xff, 0x65, 0xff, 0x81, 0xff, 0x8b, 0xff, 0xb5, 0xff, 0xd6, 0xff, 0xf4, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x02, 0x00, 0xf4, 0xff, 0xe7, 0xff, 0xec, 0xff, 0x04, 0x00, 0x1b, 0x00, 0x36, 0x00, 0x4e, 0x00, 0x67, 0x00, 0xa1, 0x00, 0xd4, 0x00, 0x03, 0x01, 0x1f, 0x01, 0x24, 0x01, 0x08, 0x01, 0xe1, 0x00, 0xaf, 0x00, 0x92, 0x00, 0x7e, 0x00, 0x67, 0x00, 0x4d, 0x00, 0x30, 0x00, 0x1a, 0x00, 0xfb, 0xff, 0xd4, 0xff, 0xa3, 0xff, 0x84, 0xff, 0x62, 0xff, 0x4a, 0xff, 0x3d, 0xff, 0x36, 0xff, 0x31, 0xff, 0x2c, 0xff, 0x31, 0xff, 0x41, 0xff, 0x4b, 0xff, 0x5d, 0xff, 0x70, 0xff, 0x7d, 0xff, 0x80, 0xff, 0x8e, 0xff, 0xa2, 0xff, 0xbe, 0xff, 0xeb, 0xff, 0x08, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x32, 0x00, 0x34, 0x00, 0x37, 0x00, 0x2f, 0x00, 0x2b, 0x00, 0x26, 0x00, 0x19, 0x00, 0x06, 0x00, 0xf6, 0xff, 0xf0, 0xff, 0xf4, 0xff, 0xfc, 0xff, 0xf8, 0xff, 0x13, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x3e, 0x00, 0x5d, 0x00, 0x86, 0x00, 0xaf, 0x00, 0xc2, 0x00, 0xe6, 0x00, 0xf5, 0x00, 0xf6, 0x00, 0xeb, 0x00, 0xd9, 0x00, 0xae, 0x00, 0x7e, 0x00, 0x4a, 0x00, 0x19, 0x00, 0xec, 0xff, 0xc6, 0xff, 0xa0, 0xff, 0x8e, 0xff, 0x86, 0xff, 0x85, 0xff, 0x8d, 0xff, 0x8d, 0xff, 0x9f, 0xff, 0x9e, 0xff, 0xab, 0xff, 0x97, 0xff, 0x90, 0xff, 0x95, 0xff, 0x8d, 0xff, 0x8e, 0xff, 0x8e, 0xff, 0x91, 0xff, 0x87, 0xff, 0x7f, 0xff, 0x6c, 0xff, 0x74, 0xff, 0x92, 0xff, 0xcc, 0xff, 0x09, 0x00, 0x42, 0x00, 0x6f, 0x00, 0xae, 0x00, 0xd3, 0x00, 0xf7, 0x00, 0xf3, 0x00, 0xee, 0x00, 0xdf, 0x00, 0xd3, 0x00, 0xb1, 0x00, 0x95, 0x00, 0x6d, 0x00, 0x3c, 0x00, 0x0e, 0x00, 0xea, 0xff, 0xd2, 0xff, 0xb7, 0xff, 0xae, 0xff, 0xad, 0xff, 0xb1, 0xff, 0xbd, 0xff, 0xce, 0xff, 0xd9, 0xff, 0xd9, 0xff, 0xd3, 0xff, 0xc7, 0xff, 0xb7, 0xff, 0xaa, 0xff, 0x9b, 0xff, 0x99, 0xff, 0x9e, 0xff, 0xa0, 0xff, 0xad, 0xff, 0xcc, 0xff, 0xd0, 0xff, 0xee, 0xff, 0x00, 0x00, 0x25, 0x00, 0x3f, 0x00, 0x4a, 0x00, 0x5f, 0x00, 0x65, 0x00, 0x66, 0x00, 0x6a, 0x00, 0x63, 0x00, 0x52, 0x00, 0x29, 0x00, 0xfe, 0xff, 0xd0, 0xff, 0xb2, 0xff, 0x9a, 0xff, 0x87, 0xff, 0x73, 0xff, 0x70, 0xff, 0x82, 0xff, 0x8c, 0xff, 0x9d, 0xff, 0xb9, 0xff, 0xc7, 0xff, 0xd7, 0xff, 0xdc, 0xff, 0xe3, 0xff, 0xe5, 0xff, 0xf1, 0xff, 0x0b, 0x00, 0x24, 0x00, 0x4f, 0x00, 0x98, 0x00, 0xd9, 0x00, 0x25, 0x01, 0x5c, 0x01, 0x6c, 0x01, 0x5d, 0x01, 0x3a, 0x01, 0x11, 0x01, 0xdd, 0x00, 0xb5, 0x00, 0x7e, 0x00, 0x39, 0x00, 0x08, 0x00, 0xd2, 0xff, 0xa5, 0xff, 0x78, 0xff, 0x4d, 0xff, 0x25, 0xff, 0x06, 0xff, 0xf4, 0xfe, 0xf8, 0xfe, 0xf2, 0xfe, 0xfb, 0xfe, 0x07, 0xff, 0x1b, 0xff, 0x34, 0xff, 0x6d, 0xff, 0x9d, 0xff, 0xd1, 0xff, 0x00, 0x00, 0x26, 0x00, 0x31, 0x00, 0x39, 0x00, 0x24, 0x00, 0x1a, 0x00, 0x18, 0x00, 0x2b, 0x00, 0x33, 0x00, 0x50, 0x00, 0x58, 0x00, 0x5e, 0x00, 0x66, 0x00, 0x53, 0x00, 0x41, 0x00, 0x1e, 0x00, 0x04, 0x00, 0xe8, 0xff, 0xd6, 0xff, 0xd2, 0xff, 0xc0, 0xff, 0xc3, 0xff, 0xb7, 0xff, 0xac, 0xff, 0xa3, 0xff, 0x9c, 0xff, 0xa0, 0xff, 0xa8, 0xff, 0xb2, 0xff, 0xb8, 0xff, 0xc8, 0xff, 0xdc, 0xff, 0xf0, 0xff, 0xf5, 0xff, 0xe5, 0xff, 0xd1, 0xff, 0xbe, 0xff, 0xac, 0xff, 0xae, 0xff, 0xbb, 0xff, 0xcc, 0xff, 0xec, 0xff, 0xfc, 0xff, 0x27, 0x00, 0x4b, 0x00, 0x6e, 0x00, 0x81, 0x00, 0xa3, 0x00, 0xdf, 0x00, 0x17, 0x01, 0x4d, 0x01, 0x65, 0x01, 0x62, 0x01, 0x44, 0x01, 0x29, 0x01, 0xfc, 0x00, 0xdd, 0x00, 0x95, 0x00, 0x69, 0x00, 0x32, 0x00, 0x0a, 0x00, 0xd3, 0xff, 0xb7, 0xff, 0x92, 0xff, 0x7a, 0xff, 0x69, 0xff, 0x56, 0xff, 0x47, 0xff, 0x40, 0xff, 0x3e, 0xff, 0x4e, 0xff, 0x62, 0xff, 0x76, 0xff, 0x78, 0xff, 0x7a, 0xff, 0x7c, 0xff, 0x88, 0xff, 0x95, 0xff, 0xa0, 0xff, 0xa4, 0xff, 0xab, 0xff, 0xc0, 0xff, 0xe2, 0xff, 0x15, 0x00, 0x42, 0x00, 0x60, 0x00, 0x84, 0x00, 0x9e, 0x00, 0xa9, 0x00, 0xb3, 0x00, 0xaa, 0x00, 0x98, 0x00, 0x8a, 0x00, 0x7a, 0x00, 0x69, 0x00, 0x53, 0x00, 0x3c, 0x00, 0x1f, 0x00, 0xff, 0xff, 0xd7, 0xff, 0xc7, 0xff, 0xbb, 0xff, 0xa3, 0xff, 0x95, 0xff, 0x76, 0xff, 0x6c, 0xff, 0x58, 0xff, 0x4b, 0xff, 0x31, 0xff, 0x25, 0xff, 0x0c, 0xff, 0xff, 0xfe, 0x08, 0xff, 0x13, 0xff, 0x25, 0xff, 0x45, 0xff, 0x6b, 0xff, 0xa7, 0xff, 0xeb, 0xff, 0x0f, 0x00, 0x2e, 0x00, 0x41, 0x00, 0x60, 0x00, 0x7b, 0x00, 0x80, 0x00, 0x81, 0x00, 0x81, 0x00, 0x84, 0x00, 0x85, 0x00, 0x94, 0x00, 0xae, 0x00, 0xb6, 0x00, 0xb2, 0x00, 0x9b, 0x00, 0x91, 0x00, 0x82, 0x00, 0x6d, 0x00, 0x6a, 0x00, 0x6c, 0x00, 0x80, 0x00, 0x7a, 0x00, 0x76, 0x00, 0x5a, 0x00, 0x3f, 0x00, 0x33, 0x00, 0x29, 0x00, 0x20, 0x00, 0x1b, 0x00, 0x23, 0x00, 0x0c, 0x00, 0x07, 0x00, 0xe9, 0xff, 0xce, 0xff, 0xac, 0xff, 0x90, 0xff, 0x6f, 0xff, 0x60, 0xff, 0x61, 0xff, 0x6a, 0xff, 0x6a, 0xff, 0x6d, 0xff, 0x79, 0xff, 0x86, 0xff, 0x84, 0xff, 0x7c, 0xff, 0x73, 0xff, 0x66, 0xff, 0x5a, 0xff, 0x4f, 0xff, 0x52, 0xff, 0x65, 0xff, 0x69, 0xff, 0x86, 0xff, 0x8f, 0xff, 0xc3, 0xff, 0xf5, 0xff, 0x30, 0x00, 0x65, 0x00, 0x8a, 0x00, 0xb9, 0x00, 0xd9, 0x00, 0xed, 0x00, 0xf5, 0x00, 0xef, 0x00, 0xfc, 0x00, 0xfb, 0x00, 0x01, 0x01, 0xe5, 0x00, 0xd0, 0x00, 0xaa, 0x00, 0x7d, 0x00, 0x47, 0x00, 0x19, 0x00, 0xeb, 0xff, 0xd5, 0xff, 0xbd, 0xff, 0xaf, 0xff, 0xbe, 0xff, 0xc3, 0xff, 0xe5, 0xff, 0xee, 0xff, 0xf9, 0xff, 0x0f, 0x00, 0x28, 0x00, 0x3c, 0x00, 0x4d, 0x00, 0x54, 0x00, 0x53, 0x00, 0x4a, 0x00, 0x45, 0x00, 0x1e, 0x00, 0xfe, 0xff, 0xda, 0xff, 0xc2, 0xff, 0xba, 0xff, 0xa4, 0xff, 0xa4, 0xff, 0x9b, 0xff, 0xa2, 0xff, 0x9d, 0xff, 0x9f, 0xff, 0x85, 0xff, 0x78, 0xff, 0x5c, 0xff, 0x47, 0xff, 0x36, 0xff, 0x49, 0xff, 0x4a, 0xff, 0x62, 0xff, 0x72, 0xff, 0x8e, 0xff, 0xab, 0xff, 0xc5, 0xff, 0xe3, 0xff, 0xfe, 0xff, 0x0f, 0x00, 0x1e, 0x00, 0x29, 0x00, 0x25, 0x00, 0x27, 0x00, 0x26, 0x00, 0x2c, 0x00, 0x29, 0x00, 0x1f, 0x00, 0x18, 0x00, 0x1b, 0x00, 0x1b, 0x00, 0x1b, 0x00, 0x1b, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x1d, 0x00, 0x2f, 0x00, 0x55, 0x00, 0x6a, 0x00, 0x66, 0x00, 0x67, 0x00, 0x5a, 0x00, 0x61, 0x00, 0x69, 0x00, 0x51, 0x00, 0x47, 0x00, 0x31, 0x00, 0x22, 0x00, 0x0b, 0x00, 0x04, 0x00, 0xf7, 0xff, 0xdf, 0xff, 0xd1, 0xff, 0xd7, 0xff, 0xda, 0xff, 0xea, 0xff, 0xde, 0xff, 0xe6, 0xff, 0xd8, 0xff, 0xe4, 0xff, 0xe4, 0xff, 0xf2, 0xff, 0xf8, 0xff, 0xf8, 0xff, 0xf5, 0xff, 0xe6, 0xff, 0xdd, 0xff, 0xe2, 0xff, 0xed, 0xff, 0x05, 0x00, 0x13, 0x00, 0x1f, 0x00, 0x24, 0x00, 0x34, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x3b, 0x00, 0x4d, 0x00, 0x62, 0x00, 0x69, 0x00, 0x6a, 0x00, 0x59, 0x00, 0x49, 0x00, 0x32, 0x00, 0x17, 0x00, 0xfc, 0xff, 0xda, 0xff, 0xc2, 0xff, 0xa9, 0xff, 0x93, 0xff, 0x7f, 0xff, 0x6e, 0xff, 0x6a, 0xff, 0x67, 0xff, 0x69, 0xff, 0x65, 0xff, 0x73, 0xff, 0x77, 0xff, 0x82, 0xff, 0x8c, 0xff, 0x9a, 0xff, 0xa7, 0xff, 0xc8, 0xff, 0xe1, 0xff, 0xf0, 0xff, 0x17, 0x00, 0x40, 0x00, 0x69, 0x00, 0x7f, 0x00, 0x8c, 0x00, 0x99, 0x00, 0x95, 0x00, 0x92, 0x00, 0x77, 0x00, 0x5e, 0x00, 0x36, 0x00, 0x0c, 0x00, 0xf5, 0xff, 0xde, 0xff, 0xdb, 0xff, 0xcd, 0xff, 0xc7, 0xff, 0xba, 0xff, 0xb2, 0xff, 0xb4, 0xff, 0xbd, 0xff, 0xb7, 0xff, 0xbb, 0xff, 0xb8, 0xff, 0xb8, 0xff, 0xc8, 0xff, 0xce, 0xff, 0xda, 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x56, 0x00, 0x80, 0x00, 0x91, 0x00, 0xa8, 0x00, 0xb4, 0x00, 0xb8, 0x00, 0xb1, 0x00, 0xa1, 0x00, 0x8c, 0x00, 0x72, 0x00, 0x4e, 0x00, 0x30, 0x00, 0x09, 0x00, 0x02, 0x00, 0xfe, 0xff, 0xf6, 0xff, 0xe3, 0xff, 0xca, 0xff, 0xbe, 0xff, 0xaf, 0xff, 0x9d, 0xff, 0x8e, 0xff, 0x7d, 0xff, 0x72, 0xff, 0x5a, 0xff, 0x48, 0xff, 0x3a, 0xff, 0x3b, 0xff, 0x4c, 0xff, 0x5b, 0xff, 0x74, 0xff, 0x84, 0xff, 0xa6, 0xff, 0xc9, 0xff, 0xee, 0xff, 0x06, 0x00, 0x22, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x8a, 0x00, 0xa9, 0x00, 0xce, 0x00, 0xe3, 0x00, 0xef, 0x00, 0xe9, 0x00, 0xe7, 0x00, 0xe6, 0x00, 0xd7, 0x00, 0xbd, 0x00, 0x9a, 0x00, 0x84, 0x00, 0x53, 0x00, 0x3e, 0x00, 0x25, 0x00, 0x13, 0x00, 0xff, 0xff, 0xdc, 0xff, 0xc3, 0xff, 0x9b, 0xff, 0x82, 0xff, 0x6e, 0xff, 0x5f, 0xff, 0x5b, 0xff, 0x50, 0xff, 0x4e, 0xff, 0x4b, 0xff, 0x53, 0xff, 0x69, 0xff, 0x81, 0xff, 0xaa, 0xff, 0xc6, 0xff, 0xcf, 0xff, 0xeb, 0xff, 0xfe, 0xff, 0x1a, 0x00, 0x28, 0x00, 0x2e, 0x00, 0x39, 0x00, 0x35, 0x00, 0x43, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x44, 0x00, 0x4a, 0x00, 0x4d, 0x00, 0x50, 0x00, 0x54, 0x00, 0x64, 0x00, 0x70, 0x00, 0x72, 0x00, 0x70, 0x00, 0x67, 0x00, 0x69, 0x00, 0x60, 0x00, 0x55, 0x00, 0x43, 0x00, 0x2b, 0x00, 0x19, 0x00, 0x01, 0x00, 0xe3, 0xff, 0xbf, 0xff, 0xa3, 0xff, 0x8c, 0xff, 0x70, 0xff, 0x5b, 0xff, 0x47, 0xff, 0x3d, 0xff, 0x2c, 0xff, 0x33, 0xff, 0x46, 0xff, 0x54, 0xff, 0x65, 0xff, 0x75, 0xff, 0x85, 0xff, 0x9c, 0xff, 0xbe, 0xff, 0xdc, 0xff, 0xf2, 0xff, 0x09, 0x00, 0x18, 0x00, 0x1e, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x1c, 0x00, 0x18, 0x00, 0x07, 0x00, 0xf6, 0xff, 0xdc, 0xff, 0xd0, 0xff, 0xcc, 0xff, 0xc9, 0xff, 0xbc, 0xff, 0xac, 0xff, 0xa1, 0xff, 0x98, 0xff, 0xb0, 0xff, 0xcb, 0xff, 0xe6, 0xff, 0x0a, 0x00, 0x1f, 0x00, 0x34, 0x00, 0x47, 0x00, 0x5f, 0x00, 0x6b, 0x00, 0x7a, 0x00, 0x8c, 0x00, 0x99, 0x00, 0xad, 0x00, 0xbd, 0x00, 0xd7, 0x00, 0xd7, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xf4, 0x00, 0x04, 0x01, 0x15, 0x01, 0xfd, 0x00, 0xdf, 0x00, 0xaa, 0x00, 0x7c, 0x00, 0x49, 0x00, 0x1a, 0x00, 0xf5, 0xff, 0xcd, 0xff, 0xb5, 0xff, 0x98, 0xff, 0x99, 0xff, 0x95, 0xff, 0x99, 0xff, 0x8d, 0xff, 0x81, 0xff, 0x77, 0xff, 0x72, 0xff, 0x71, 0xff, 0x64, 0xff, 0x5c, 0xff, 0x4a, 0xff, 0x4d, 0xff, 0x50, 0xff, 0x6a, 0xff, 0x87, 0xff, 0xa4, 0xff, 0xb1, 0xff, 0xbf, 0xff, 0xd7, 0xff, 0xdd, 0xff, 0xf4, 0xff, 0x04, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x1e, 0x00, 0x11, 0x00, 0x22, 0x00, 0x1e, 0x00, 0x33, 0x00, 0x37, 0x00, 0x53, 0x00, 0x55, 0x00, 0x64, 0x00, 0x56, 0x00, 0x4c, 0x00, 0x37, 0x00, 0x37, 0x00, 0x21, 0x00, 0x1a, 0x00, 0x04, 0x00, 0xfd, 0xff, 0xed, 0xff, 0xd9, 0xff, 0xcb, 0xff, 0xcc, 0xff, 0xd1, 0xff, 0xe5, 0xff, 0xeb, 0xff, 0xf6, 0xff, 0xeb, 0xff, 0xeb, 0xff, 0xe3, 0xff, 0xe4, 0xff, 0xce, 0xff, 0xbf, 0xff, 0xb6, 0xff, 0xb3, 0xff, 0xb1, 0xff, 0xa9, 0xff, 0xae, 0xff, 0xb0, 0xff, 0xba, 0xff, 0xb0, 0xff, 0xae, 0xff, 0xa1, 0xff, 0x96, 0xff, 0x95, 0xff, 0x9c, 0xff, 0xa3, 0xff, 0xb0, 0xff, 0xb2, 0xff, 0xc4, 0xff, 0xcf, 0xff, 0x00, 0x00, 0x1e, 0x00, 0x42, 0x00, 0x56, 0x00, 0x61, 0x00, 0x75, 0x00, 0x7c, 0x00, 0x7f, 0x00, 0x80, 0x00, 0x8b, 0x00, 0x99, 0x00, 0xa4, 0x00, 0xb8, 0x00, 0xc1, 0x00, 0xd0, 0x00, 0xd9, 0x00, 0xdd, 0x00, 0xd5, 0x00, 0xcc, 0x00, 0xae, 0x00, 0x8a, 0x00, 0x67, 0x00, 0x39, 0x00, 0x01, 0x00, 0xcf, 0xff, 0x9e, 0xff, 0x70, 0xff, 0x59, 0xff, 0x41, 0xff, 0x46, 0xff, 0x4b, 0xff, 0x49, 0xff, 0x4e, 0xff, 0x49, 0xff, 0x5e, 0xff, 0x7a, 0xff, 0xaa, 0xff, 0xe3, 0xff, 0x0b, 0x00, 0x3c, 0x00, 0x72, 0x00, 0xad, 0x00, 0xcd, 0x00, 0xe4, 0x00, 0xf0, 0x00, 0xe2, 0x00, 0xcb, 0x00, 0x9b, 0x00, 0x6a, 0x00, 0x42, 0x00, 0x22, 0x00, 0x03, 0x00, 0xf5, 0xff, 0xdb, 0xff, 0xc6, 0xff, 0xad, 0xff, 0xa1, 0xff, 0x9e, 0xff, 0x9b, 0xff, 0x87, 0xff, 0x88, 0xff, 0x86, 0xff, 0x88, 0xff, 0x7c, 0xff, 0x85, 0xff, 0x82, 0xff, 0x8b, 0xff, 0x8a, 0xff, 0x86, 0xff, 0x8a, 0xff, 0x8d, 0xff, 0x9b, 0xff, 0xa8, 0xff, 0xb5, 0xff, 0xcd, 0xff, 0xe8, 0xff, 0xfd, 0xff, 0x1a, 0x00, 0x32, 0x00, 0x49, 0x00, 0x56, 0x00, 0x73, 0x00, 0x8e, 0x00, 0xae, 0x00, 0xc8, 0x00, 0xdf, 0x00, 0xd2, 0x00, 0xc5, 0x00, 0xae, 0x00, 0x8c, 0x00, 0x66, 0x00, 0x34, 0x00, 0x15, 0x00, 0xec, 0xff, 0xcc, 0xff, 0xb1, 0xff, 0x96, 0xff, 0x78, 0xff, 0x67, 0xff, 0x52, 0xff, 0x52, 0xff, 0x52, 0xff, 0x58, 0xff, 0x51, 0xff, 0x54, 0xff, 0x59, 0xff, 0x68, 0xff, 0x73, 0xff, 0x83, 0xff, 0x8a, 0xff, 0x97, 0xff, 0xa6, 0xff, 0xbc, 0xff, 0xd6, 0xff, 0xf2, 0xff, 0x0d, 0x00, 0x37, 0x00, 0x5d, 0x00, 0x7e, 0x00, 0x95, 0x00, 0x95, 0x00, 0x9b, 0x00, 0x8c, 0x00, 0x88, 0x00, 0x88, 0x00, 0x6d, 0x00, 0x4d, 0x00, 0x25, 0x00, 0x05, 0x00, 0xef, 0xff, 0xe1, 0xff, 0xd4, 0xff, 0xcc, 0xff, 0xd9, 0xff, 0xde, 0xff, 0xf0, 0xff, 0xf0, 0xff, 0x00, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x29, 0x00, 0x36, 0x00, 0x48, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x6a, 0x00, 0x6d, 0x00, 0x5f, 0x00, 0x5a, 0x00, 0x48, 0x00, 0x43, 0x00, 0x37, 0x00, 0x23, 0x00, 0x13, 0x00, 0xf6, 0xff, 0xde, 0xff, 0xc1, 0xff, 0xa8, 0xff, 0x9e, 0xff, 0x8e, 0xff, 0x8c, 0xff, 0x8f, 0xff, 0x9c, 0xff, 0xbb, 0xff, 0xbe, 0xff, 0xbf, 0xff, 0xbb, 0xff, 0xab, 0xff, 0xb1, 0xff, 0xbb, 0xff, 0xdb, 0xff, 0x01, 0x00, 0x37, 0x00, 0x52, 0x00, 0x7a, 0x00, 0x86, 0x00, 0x9a, 0x00, 0x98, 0x00, 0x9f, 0x00, 0x8e, 0x00, 0x86, 0x00, 0x69, 0x00, 0x42, 0x00, 0x17, 0x00, 0xee, 0xff, 0xcb, 0xff, 0xa2, 0xff, 0x87, 0xff, 0x5e, 0xff, 0x4d, 0xff, 0x44, 0xff, 0x4f, 0xff, 0x53, 0xff, 0x66, 0xff, 0x6e, 0xff, 0x81, 0xff, 0x8b, 0xff, 0xa8, 0xff, 0xcf, 0xff, 0xf1, 0xff, 0x17, 0x00, 0x32, 0x00, 0x48, 0x00, 0x56, 0x00, 0x5e, 0x00, 0x69, 0x00, 0x72, 0x00, 0x6a, 0x00, 0x73, 0x00, 0x7a, 0x00, 0x80, 0x00, 0x70, 0x00, 0x7c, 0x00, 0x7d, 0x00, 0x79, 0x00, 0x72, 0x00, 0x5a, 0x00, 0x48, 0x00, 0x24, 0x00, 0x0c, 0x00, 0xf4, 0xff, 0xe6, 0xff, 0xe1, 0xff, 0xe5, 0xff, 0xea, 0xff, 0xdf, 0xff, 0xda, 0xff, 0xcd, 0xff, 0xcb, 0xff, 0xc5, 0xff, 0xbf, 0xff, 0xb0, 0xff, 0x98, 0xff, 0x7d, 0xff, 0x6b, 0xff, 0x74, 0xff, 0x70, 0xff, 0x8c, 0xff, 0x9d, 0xff, 0xb7, 0xff, 0xdd, 0xff, 0xf1, 0xff, 0x19, 0x00, 0x3d, 0x00, 0x69, 0x00, 0x78, 0x00, 0x8c, 0x00, 0x99, 0x00, 0xa7, 0x00, 0x9f, 0x00, 0x81, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x4f, 0x00, 0x44, 0x00, 0x2b, 0x00, 0x17, 0x00, 0x0a, 0x00, 0x07, 0x00, 0x05, 0x00, 0xf2, 0xff, 0xe6, 0xff, 0xe3, 0xff, 0xce, 0xff, 0xbd, 0xff, 0xa8, 0xff, 0x95, 0xff, 0x8c, 0xff, 0x8b, 0xff, 0x91, 0xff, 0x94, 0xff, 0x9c, 0xff, 0xaf, 0xff, 0xc4, 0xff, 0xd6, 0xff, 0xea, 0xff, 0xe4, 0xff, 0xf3, 0xff, 0xfa, 0xff, 0x0d, 0x00, 0x1b, 0x00, 0x29, 0x00, 0x29, 0x00, 0x26, 0x00, 0x13, 0x00, 0x03, 0x00, 0x0c, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0xfd, 0xff, 0xff, 0xff, 0x02, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x16, 0x00, 0x16, 0x00, 0x05, 0x00, 0x00, 0x00, 0xed, 0xff, 0xea, 0xff, 0xe9, 0xff, 0xeb, 0xff, 0xe9, 0xff, 0xee, 0xff, 0xf1, 0xff, 0xf8, 0xff, 0x04, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x13, 0x00, 0x1a, 0x00, 0x15, 0x00, 0x0e, 0x00, 0xff, 0xff, 0xf0, 0xff, 0xe6, 0xff, 0xeb, 0xff, 0xf3, 0xff, 0xf5, 0xff, 0xf8, 0xff, 0xf6, 0xff, 0x01, 0x00, 0x01, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0xfe, 0xff, 0x00, 0x00, 0xf4, 0xff, 0xe6, 0xff, 0xdc, 0xff, 0xca, 0xff, 0xca, 0xff, 0xca, 0xff, 0xc7, 0xff, 0xc7, 0xff, 0xc8, 0xff, 0xcf, 0xff, 0xf1, 0xff, 0x15, 0x00, 0x34, 0x00, 0x4a, 0x00, 0x59, 0x00, 0x54, 0x00, 0x4b, 0x00, 0x31, 0x00, 0x22, 0x00, 0x0f, 0x00, 0x03, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x1f, 0x00, 0x1d, 0x00, 0x18, 0x00, 0xf7, 0xff, 0xe7, 0xff, 0xd1, 0xff, 0xc4, 0xff, 0xb9, 0xff, 0xa9, 0xff, 0xa3, 0xff, 0x9a, 0xff, 0x92, 0xff, 0x8c, 0xff, 0x91, 0xff, 0xad, 0xff, 0xd2, 0xff, 0xf4, 0xff, 0x15, 0x00, 0x27, 0x00, 0x3f, 0x00, 0x62, 0x00, 0x8b, 0x00, 0x97, 0x00, 0xa5, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xba, 0x00, 0xb4, 0x00, 0xb1, 0x00, 0x9e, 0x00, 0x91, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x41, 0x00, 0x1d, 0x00, 0xfd, 0xff, 0xd0, 0xff, 0xbd, 0xff, 0xa8, 0xff, 0x8d, 0xff, 0x78, 0xff, 0x6a, 0xff, 0x5a, 0xff, 0x4c, 0xff, 0x4c, 0xff, 0x3b, 0xff, 0x3e, 0xff, 0x2c, 0xff, 0x2e, 0xff, 0x3d, 0xff, 0x49, 0xff, 0x56, 0xff, 0x70, 0xff, 0x93, 0xff, 0xb1, 0xff, 0xcd, 0xff, 0xe5, 0xff, 0xf1, 0xff, 0x05, 0x00, 0x1b, 0x00, 0x2c, 0x00, 0x43, 0x00, 0x67, 0x00, 0x9b, 0x00, 0xc7, 0x00, 0xed, 0x00, 0x0e, 0x01, 0x32, 0x01, 0x55, 0x01, 0x64, 0x01, 0x5b, 0x01, 0x54, 0x01, 0x47, 0x01, 0x28, 0x01, 0xfd, 0x00, 0xd3, 0x00, 0xa2, 0x00, 0x58, 0x00, 0x18, 0x00, 0xd5, 0xff, 0xa8, 0xff, 0x6f, 0xff, 0x48, 0xff, 0x21, 0xff, 0x10, 0xff, 0xff, 0xfe, 0xf6, 0xfe, 0xf1, 0xfe, 0xf4, 0xfe, 0xf5, 0xfe, 0xf5, 0xfe, 0xf7, 0xfe, 0xfb, 0xfe, 0x03, 0xff, 0x16, 0xff, 0x36, 0xff, 0x5e, 0xff, 0x8a, 0xff, 0xd7, 0xff, 0x1b, 0x00, 0x6d, 0x00, 0xc1, 0x00, 0x02, 0x01, 0x49, 0x01, 0x89, 0x01, 0xbf, 0x01, 0xcb, 0x01, 0xbd, 0x01, 0x93, 0x01, 0x64, 0x01, 0x31, 0x01, 0xe5, 0x00, 0x98, 0x00, 0x4a, 0x00, 0x05, 0x00, 0xcf, 0xff, 0x9e, 0xff, 0x75, 0xff, 0x57, 0xff, 0x40, 0xff, 0x32, 0xff, 0x27, 0xff, 0x1d, 0xff, 0x1f, 0xff, 0x1e, 0xff, 0x29, 0xff, 0x3f, 0xff, 0x52, 0xff, 0x63, 0xff, 0x6d, 0xff, 0x72, 0xff, 0x78, 0xff, 0x7d, 0xff, 0x84, 0xff, 0x8b, 0xff, 0x9f, 0xff, 0xb2, 0xff, 0xcd, 0xff, 0xd5, 0xff, 0xe1, 0xff, 0xea, 0xff, 0xf8, 0xff, 0xf8, 0xff, 0x08, 0x00, 0x0a, 0x00, 0x18, 0x00, 0x20, 0x00, 0x20, 0x00, 0x27, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x4f, 0x00, 0x5b, 0x00, 0x70, 0x00, 0x87, 0x00, 0xa1, 0x00, 0xa2, 0x00, 0x97, 0x00, 0x77, 0x00, 0x54, 0x00, 0x2f, 0x00, 0xff, 0xff, 0xd7, 0xff, 0xb2, 0xff, 0x94, 0xff, 0x7f, 0xff, 0x5f, 0xff, 0x52, 0xff, 0x39, 0xff, 0x2a, 0xff, 0x33, 0xff, 0x43, 0xff, 0x54, 0xff, 0x6c, 0xff, 0x8d, 0xff, 0xaa, 0xff, 0xc9, 0xff, 0xdf, 0xff, 0x09, 0x00, 0x1b, 0x00, 0x3a, 0x00, 0x43, 0x00, 0x57, 0x00, 0x6b, 0x00, 0x79, 0x00, 0x7f, 0x00, 0x94, 0x00, 0xa7, 0x00, 0xcd, 0x00, 0xe7, 0x00, 0xf9, 0x00, 0xf8, 0x00, 0xdf, 0x00, 0xce, 0x00, 0xbc, 0x00, 0xa3, 0x00, 0x93, 0x00, 0x7f, 0x00, 0x77, 0x00, 0x68, 0x00, 0x53, 0x00, 0x3f, 0x00, 0x28, 0x00, 0x13, 0x00, 0x02, 0x00, 0xea, 0xff, 0xd4, 0xff, 0xbc, 0xff, 0xab, 0xff, 0x8d, 0xff, 0x7b, 0xff, 0x5e, 0xff, 0x4d, 0xff, 0x44, 0xff, 0x42, 0xff, 0x48, 0xff, 0x53, 0xff, 0x5f, 0xff, 0x6c, 0xff, 0x78, 0xff, 0x8d, 0xff, 0xa7, 0xff, 0xc5, 0xff, 0xe0, 0xff, 0xfc, 0xff, 0x0f, 0x00, 0x2c, 0x00, 0x31, 0x00, 0x3e, 0x00, 0x2d, 0x00, 0x2a, 0x00, 0x0b, 0x00, 0xfd, 0xff, 0xe1, 0xff, 0xca, 0xff, 0xb6, 0xff, 0xa5, 0xff, 0x9e, 0xff, 0x98, 0xff, 0x98, 0xff, 0xa2, 0xff, 0xb5, 0xff, 0xbc, 0xff, 0xc4, 0xff, 0xc3, 0xff, 0xc4, 0xff, 0xc4, 0xff, 0xce, 0xff, 0xd1, 0xff, 0xd5, 0xff, 0xd0, 0xff, 0xe1, 0xff, 0xf3, 0xff, 0x17, 0x00, 0x1e, 0x00, 0x28, 0x00, 0x21, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x22, 0x00, 0x32, 0x00, 0x42, 0x00, 0x4f, 0x00, 0x58, 0x00, 0x54, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x53, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x5b, 0x00, 0x57, 0x00, 0x4d, 0x00, 0x4b, 0x00, 0x47, 0x00, 0x41, 0x00, 0x2f, 0x00, 0x10, 0x00, 0xf2, 0xff, 0xcf, 0xff, 0xad, 0xff, 0x91, 0xff, 0x77, 0xff, 0x6a, 0xff, 0x6c, 0xff, 0x6e, 0xff, 0x7c, 0xff, 0x83, 0xff, 0xa1, 0xff, 0xc6, 0xff, 0xdd, 0xff, 0xf9, 0xff, 0x0c, 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x42, 0x00, 0x5a, 0x00, 0x5f, 0x00, 0x58, 0x00, 0x4c, 0x00, 0x44, 0x00, 0x3b, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x1a, 0x00, 0x13, 0x00, 0x14, 0x00, 0x1b, 0x00, 0x20, 0x00, 0x1d, 0x00, 0x21, 0x00, 0x24, 0x00, 0x37, 0x00, 0x50, 0x00, 0x5d, 0x00, 0x6a, 0x00, 0x5f, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x35, 0x00, 0x24, 0x00, 0x04, 0x00, 0xe7, 0xff, 0xd2, 0xff, 0xc5, 0xff, 0xc4, 0xff, 0xc5, 0xff, 0xd0, 0xff, 0xcb, 0xff, 0xc4, 0xff, 0xb1, 0xff, 0xb0, 0xff, 0xb5, 0xff, 0xb6, 0xff, 0xcc, 0xff, 0xce, 0xff, 0xe6, 0xff, 0xe9, 0xff, 0xed, 0xff, 0xf2, 0xff, 0xf6, 0xff, 0x00, 0x00, 0x08, 0x00, 0xf8, 0xff, 0xed, 0xff, 0xe0, 0xff, 0xc4, 0xff, 0xc0, 0xff, 0xae, 0xff, 0xb0, 0xff, 0xa6, 0xff, 0xa8, 0xff, 0xb5, 0xff, 0xbb, 0xff, 0xc5, 0xff, 0xc6, 0xff, 0xc9, 0xff, 0xc6, 0xff, 0xd4, 0xff, 0xe5, 0xff, 0x03, 0x00, 0x24, 0x00, 0x59, 0x00, 0x84, 0x00, 0x9e, 0x00, 0xa0, 0x00, 0x89, 0x00, 0x73, 0x00, 0x5a, 0x00, 0x42, 0x00, 0x2c, 0x00, 0x1d, 0x00, 0x1c, 0x00, 0x1f, 0x00, 0x1a, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0x12, 0x00, 0x05, 0x00, 0xf9, 0xff, 0xf3, 0xff, 0xf3, 0xff, 0x00, 0x00, 0x08, 0x00, 0x16, 0x00, 0x19, 0x00, 0x10, 0x00, 0x02, 0x00, 0xf2, 0xff, 0xe9, 0xff, 0xea, 0xff, 0xef, 0xff, 0xfb, 0xff, 0xfc, 0xff, 0x06, 0x00, 0x01, 0x00, 0xf8, 0xff, 0xf5, 0xff, 0xf2, 0xff, 0xf7, 0xff, 0xe2, 0xff, 0xd9, 0xff, 0xc2, 0xff, 0xab, 0xff, 0x93, 0xff, 0x8b, 0xff, 0x89, 0xff, 0x8f, 0xff, 0x9f, 0xff, 0xb5, 0xff, 0xcc, 0xff, 0xe9, 0xff, 0xf7, 0xff, 0xf3, 0xff, 0xf6, 0xff, 0xee, 0xff, 0xef, 0xff, 0xed, 0xff, 0xf1, 0xff, 0x02, 0x00, 0x25, 0x00, 0x40, 0x00, 0x5e, 0x00, 0x74, 0x00, 0x7a, 0x00, 0x88, 0x00, 0x7a, 0x00, 0x73, 0x00, 0x64, 0x00, 0x56, 0x00, 0x39, 0x00, 0x1f, 0x00, 0x00, 0x00, 0xec, 0xff, 0xcc, 0xff, 0xc6, 0xff, 0xac, 0xff, 0x9a, 0xff, 0x91, 0xff, 0x73, 0xff, 0x60, 0xff, 0x57, 0xff, 0x4d, 0xff, 0x52, 0xff, 0x55, 0xff, 0x61, 0xff, 0x6d, 0xff, 0x7e, 0xff, 0x8f, 0xff, 0xa6, 0xff, 0xbe, 0xff, 0xda, 0xff, 0xff, 0xff, 0x24, 0x00, 0x4d, 0x00, 0x72, 0x00, 0x96, 0x00, 0xb8, 0x00, 0xe3, 0x00, 0xf6, 0x00, 0x04, 0x01, 0x02, 0x01, 0xfd, 0x00, 0x0f, 0x01, 0x16, 0x01, 0x26, 0x01, 0x1d, 0x01, 0x08, 0x01, 0xe1, 0x00, 0xb5, 0x00, 0x7f, 0x00, 0x46, 0x00, 0x19, 0x00, 0xf5, 0xff, 0xcd, 0xff, 0xa9, 0xff, 0x77, 0xff, 0x57, 0xff, 0x3c, 0xff, 0x2e, 0xff, 0x26, 0xff, 0x22, 0xff, 0x1d, 0xff, 0x1e, 0xff, 0x16, 0xff, 0x1f, 0xff, 0x22, 0xff, 0x43, 0xff, 0x5e, 0xff, 0x83, 0xff, 0x94, 0xff, 0xa7, 0xff, 0xa5, 0xff, 0xb0, 0xff, 0xc2, 0xff, 0xcc, 0xff, 0xed, 0xff, 0x06, 0x00, 0x29, 0x00, 0x3d, 0x00, 0x51, 0x00, 0x65, 0x00, 0x8c, 0x00, 0xb5, 0x00, 0xd6, 0x00, 0xf6, 0x00, 0x0d, 0x01, 0x22, 0x01, 0x15, 0x01, 0x08, 0x01, 0xd2, 0x00, 0xa4, 0x00, 0x77, 0x00, 0x4c, 0x00, 0x23, 0x00, 0xf6, 0xff, 0xc2, 0xff, 0xa1, 0xff, 0x7e, 0xff, 0x68, 0xff, 0x59, 0xff, 0x54, 0xff, 0x57, 0xff, 0x67, 0xff, 0x80, 0xff, 0x9d, 0xff, 0xc1, 0xff, 0xe2, 0xff, 0x06, 0x00, 0x25, 0x00, 0x33, 0x00, 0x44, 0x00, 0x57, 0x00, 0x67, 0x00, 0x69, 0x00, 0x6a, 0x00, 0x66, 0x00, 0x5c, 0x00, 0x44, 0x00, 0x1b, 0x00, 0xff, 0xff, 0xec, 0xff, 0xd7, 0xff, 0xc4, 0xff, 0xb8, 0xff, 0xbd, 0xff, 0xb1, 0xff, 0xb2, 0xff, 0xa4, 0xff, 0x9c, 0xff, 0x97, 0xff, 0x8b, 0xff, 0x7c, 0xff, 0x74, 0xff, 0x6e, 0xff, 0x76, 0xff, 0x89, 0xff, 0x96, 0xff, 0x92, 0xff, 0x94, 0xff, 0xa0, 0xff, 0xa4, 0xff, 0xba, 0xff, 0xc9, 0xff, 0xd7, 0xff, 0xe6, 0xff, 0xea, 0xff, 0xee, 0xff, 0xf1, 0xff, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x2b, 0x00, 0x3e, 0x00, 0x54, 0x00, 0x61, 0x00, 0x71, 0x00, 0x98, 0x00, 0xbd, 0x00, 0xd0, 0x00, 0xe5, 0x00, 0xea, 0x00, 0xe4, 0x00, 0xdb, 0x00, 0xc7, 0x00, 0xbe, 0x00, 0xaf, 0x00, 0xa6, 0x00, 0xb4, 0x00, 0xb6, 0x00, 0xaf, 0x00, 0x96, 0x00, 0x72, 0x00, 0x41, 0x00, 0x0c, 0x00, 0xcc, 0xff, 0x8c, 0xff, 0x58, 0xff, 0x32, 0xff, 0x09, 0xff, 0xf8, 0xfe, 0xe6, 0xfe, 0xdc, 0xfe, 0xcf, 0xfe, 0xd2, 0xfe, 0xd2, 0xfe, 0xea, 0xfe, 0xfd, 0xfe, 0x1c, 0xff, 0x35, 0xff, 0x5e, 0xff, 0x9a, 0xff, 0xd7, 0xff, 0x18, 0x00, 0x69, 0x00, 0xad, 0x00, 0xee, 0x00, 0x17, 0x01, 0x44, 0x01, 0x73, 0x01, 0x96, 0x01, 0xa8, 0x01, 0x8e, 0x01, 0x70, 0x01, 0x33, 0x01, 0x00, 0x01, 0xc6, 0x00, 0x89, 0x00, 0x4c, 0x00, 0x16, 0x00, 0xe4, 0xff, 0xcf, 0xff, 0xbf, 0xff, 0xb5, 0xff, 0xa5, 0xff, 0xa0, 0xff, 0x95, 0xff, 0x95, 0xff, 0x9c, 0xff, 0x8b, 0xff, 0x76, 0xff, 0x74, 0xff, 0x74, 0xff, 0x7d, 0xff, 0x7e, 0xff, 0x86, 0xff, 0x79, 0xff, 0x71, 0xff, 0x63, 0xff, 0x62, 0xff, 0x60, 0xff, 0x6e, 0xff, 0x83, 0xff, 0x83, 0xff, 0x8f, 0xff, 0x84, 0xff, 0x86, 0xff, 0x8c, 0xff, 0xa1, 0xff, 0xb3, 0xff, 0xcf, 0xff, 0xd8, 0xff, 0xd9, 0xff, 0xd7, 0xff, 0xe4, 0xff, 0xec, 0xff, 0x0d, 0x00, 0x0d, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x18, 0x00, 0x38, 0x00, 0x4b, 0x00, 0x63, 0x00, 0x63, 0x00, 0x5f, 0x00, 0x57, 0x00, 0x58, 0x00, 0x57, 0x00, 0x67, 0x00, 0x5f, 0x00, 0x5a, 0x00, 0x4a, 0x00, 0x54, 0x00, 0x54, 0x00, 0x59, 0x00, 0x5b, 0x00, 0x59, 0x00, 0x48, 0x00, 0x39, 0x00, 0x2f, 0x00, 0x22, 0x00, 0xff, 0xff, 0xed, 0xff, 0xdc, 0xff, 0xd9, 0xff, 0xda, 0xff, 0xd3, 0xff, 0xcf, 0xff, 0xc4, 0xff, 0xbc, 0xff, 0xb0, 0xff, 0xad, 0xff, 0xa7, 0xff, 0xa0, 0xff, 0x9f, 0xff, 0x9f, 0xff, 0x9c, 0xff, 0x92, 0xff, 0x95, 0xff, 0x83, 0xff, 0x7e, 0xff, 0x72, 0xff, 0x7a, 0xff, 0x81, 0xff, 0x98, 0xff, 0xb2, 0xff, 0xd7, 0xff, 0xec, 0xff, 0x0b, 0x00, 0x12, 0x00, 0x1d, 0x00, 0x1c, 0x00, 0x23, 0x00, 0x1f, 0x00, 0x31, 0x00, 0x47, 0x00, 0x5d, 0x00, 0x5c, 0x00, 0x5b, 0x00, 0x4d, 0x00, 0x44, 0x00, 0x2f, 0x00, 0x26, 0x00, 0x1e, 0x00, 0x28, 0x00, 0x2f, 0x00, 0x49, 0x00, 0x53, 0x00, 0x6c, 0x00, 0x7d, 0x00, 0x8e, 0x00, 0x97, 0x00, 0x91, 0x00, 0x81, 0x00, 0x61, 0x00, 0x4b, 0x00, 0x2f, 0x00, 0x1e, 0x00, 0xff, 0xff, 0xe4, 0xff, 0xcd, 0xff, 0xae, 0xff, 0xa4, 0xff, 0x8d, 0xff, 0x89, 0xff, 0x82, 0xff, 0x87, 0xff, 0x8b, 0xff, 0x9e, 0xff, 0xab, 0xff, 0xc1, 0xff, 0xd2, 0xff, 0xdf, 0xff, 0xf1, 0xff, 0xf9, 0xff, 0xfd, 0xff, 0x01, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x12, 0x00, 0x07, 0x00, 0x13, 0x00, 0x1b, 0x00, 0x20, 0x00, 0x21, 0x00, 0x0f, 0x00, 0x12, 0x00, 0x0e, 0x00, 0x0b, 0x00, 0x13, 0x00, 0x2a, 0x00, 0x48, 0x00, 0x5d, 0x00, 0x67, 0x00, 0x6a, 0x00, 0x73, 0x00, 0x70, 0x00, 0x5e, 0x00, 0x49, 0x00, 0x22, 0x00, 0x03, 0x00, 0xe4, 0xff, 0xcf, 0xff, 0xb8, 0xff, 0xa2, 0xff, 0x89, 0xff, 0x7d, 0xff, 0x6d, 0xff, 0x68, 0xff, 0x56, 0xff, 0x53, 0xff, 0x44, 0xff, 0x3b, 0xff, 0x48, 0xff, 0x56, 0xff, 0x5f, 0xff, 0x70, 0xff, 0x7a, 0xff, 0x7f, 0xff, 0x9a, 0xff, 0xb6, 0xff, 0xcf, 0xff, 0xec, 0xff, 0x1b, 0x00, 0x50, 0x00, 0x90, 0x00, 0xbe, 0x00, 0xec, 0x00, 0x0a, 0x01, 0x1f, 0x01, 0x30, 0x01, 0x2f, 0x01, 0x29, 0x01, 0x13, 0x01, 0xfa, 0x00, 0xc4, 0x00, 0x8f, 0x00, 0x52, 0x00, 0x1f, 0x00, 0xf9, 0xff, 0xd9, 0xff, 0xb1, 0xff, 0x96, 0xff, 0x6b, 0xff, 0x5d, 0xff, 0x4f, 0xff, 0x45, 0xff, 0x3d, 0xff, 0x2d, 0xff, 0x27, 0xff, 0x2c, 0xff, 0x41, 0xff, 0x56, 0xff, 0x76, 0xff, 0x8d, 0xff, 0xad, 0xff, 0xc7, 0xff, 0xe1, 0xff, 0x07, 0x00, 0x1d, 0x00, 0x3e, 0x00, 0x59, 0x00, 0x80, 0x00, 0x9f, 0x00, 0xbd, 0x00, 0xc2, 0x00, 0xb6, 0x00, 0x93, 0x00, 0x74, 0x00, 0x58, 0x00, 0x4e, 0x00, 0x3e, 0x00, 0x2e, 0x00, 0x2f, 0x00, 0x14, 0x00, 0x0f, 0x00, 0xec, 0xff, 0xea, 0xff, 0xe5, 0xff, 0xf2, 0xff, 0xf1, 0xff, 0xe9, 0xff, 0xed, 0xff, 0xf4, 0xff, 0x04, 0x00, 0xfa, 0xff, 0xf7, 0xff, 0xfd, 0xff, 0x06, 0x00, 0x05, 0x00, 0xf8, 0xff, 0xed, 0xff, 0xe1, 0xff, 0xe3, 0xff, 0xdd, 0xff, 0xe8, 0xff, 0xe4, 0xff, 0xf3, 0xff, 0xf0, 0xff, 0xfd, 0xff, 0x0f, 0x00, 0x1f, 0x00, 0x21, 0x00, 0x25, 0x00, 0x26, 0x00, 0x23, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x01, 0x00, 0xf4, 0xff, 0xdb, 0xff, 0xd8, 0xff, 0xbb, 0xff, 0xa8, 0xff, 0x93, 0xff, 0x7f, 0xff, 0x82, 0xff, 0x89, 0xff, 0x92, 0xff, 0x82, 0xff, 0x7f, 0xff, 0x81, 0xff, 0x82, 0xff, 0x85, 0xff, 0x8d, 0xff, 0x9a, 0xff, 0xb2, 0xff, 0xce, 0xff, 0xe6, 0xff, 0x03, 0x00, 0x14, 0x00, 0x26, 0x00, 0x30, 0x00, 0x47, 0x00, 0x49, 0x00, 0x48, 0x00, 0x47, 0x00, 0x4d, 0x00, 0x56, 0x00, 0x5a, 0x00, 0x6a, 0x00, 0x69, 0x00, 0x70, 0x00, 0x73, 0x00, 0x77, 0x00, 0x76, 0x00, 0x79, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x62, 0x00, 0x5b, 0x00, 0x42, 0x00, 0x2e, 0x00, 0x16, 0x00, 0x08, 0x00, 0xfe, 0xff, 0xf4, 0xff, 0xdd, 0xff, 0xcf, 0xff, 0xbf, 0xff, 0xbd, 0xff, 0xbc, 0xff, 0xb4, 0xff, 0xb2, 0xff, 0xb0, 0xff, 0xad, 0xff, 0xab, 0xff, 0xa8, 0xff, 0xb8, 0xff, 0xbc, 0xff, 0xb7, 0xff, 0xae, 0xff, 0x9d, 0xff, 0x98, 0xff, 0x89, 0xff, 0x8c, 0xff, 0x8b, 0xff, 0x97, 0xff, 0xac, 0xff, 0xbc, 0xff, 0xd0, 0xff, 0xe2, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x27, 0x00, 0x44, 0x00, 0x5d, 0x00, 0x6d, 0x00, 0x87, 0x00, 0xaa, 0x00, 0xd1, 0x00, 0xe7, 0x00, 0xf1, 0x00, 0xe9, 0x00, 0xe1, 0x00, 0xce, 0x00, 0xac, 0x00, 0x92, 0x00, 0x5a, 0x00, 0x36, 0x00, 0x04, 0x00, 0xe2, 0xff, 0xb9, 0xff, 0x9a, 0xff, 0x87, 0xff, 0x8c, 0xff, 0x97, 0xff, 0x95, 0xff, 0xa8, 0xff, 0xab, 0xff, 0xaf, 0xff, 0xab, 0xff, 0xaa, 0xff, 0xab, 0xff, 0xa4, 0xff, 0xa9, 0xff, 0xa1, 0xff, 0xb4, 0xff, 0xb5, 0xff, 0xb7, 0xff, 0xb7, 0xff, 0xc3, 0xff, 0xd1, 0xff, 0xd5, 0xff, 0xe2, 0xff, 0xe5, 0xff, 0xf2, 0xff, 0xec, 0xff, 0x0b, 0x00, 0x1b, 0x00, 0x3c, 0x00, 0x4a, 0x00, 0x5f, 0x00, 0x57, 0x00, 0x57, 0x00, 0x4f, 0x00, 0x5d, 0x00, 0x59, 0x00, 0x6e, 0x00, 0x78, 0x00, 0x88, 0x00, 0x93, 0x00, 0x8e, 0x00, 0x78, 0x00, 0x66, 0x00, 0x48, 0x00, 0x2c, 0x00, 0x00, 0x00, 0xda, 0xff, 0xb6, 0xff, 0xa2, 0xff, 0x8e, 0xff, 0x7c, 0xff, 0x76, 0xff, 0x73, 0xff, 0x87, 0xff, 0x7d, 0xff, 0x92, 0xff, 0x9d, 0xff, 0xb6, 0xff, 0xae, 0xff, 0xb8, 0xff, 0xac, 0xff, 0xae, 0xff, 0x9e, 0xff, 0x92, 0xff, 0x93, 0xff, 0x95, 0xff, 0xa9, 0xff, 0xae, 0xff, 0xc2, 0xff, 0xc6, 0xff, 0xc4, 0xff, 0xd0, 0xff, 0xe7, 0xff, 0x1b, 0x00, 0x61, 0x00, 0xab, 0x00, 0xc9, 0x00, 0xe8, 0x00, 0xdc, 0x00, 0xce, 0x00, 0xb3, 0x00, 0x94, 0x00, 0x84, 0x00, 0x63, 0x00, 0x4c, 0x00, 0x39, 0x00, 0x35, 0x00, 0x21, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x2a, 0x00, 0x40, 0x00, 0x4a, 0x00, 0x4d, 0x00, 0x48, 0x00, 0x41, 0x00, 0x43, 0x00, 0x37, 0x00, 0x22, 0x00, 0x0d, 0x00, 0x03, 0x00, 0xec, 0xff, 0xe3, 0xff, 0xd1, 0xff, 0xc5, 0xff, 0xb7, 0xff, 0xa0, 0xff, 0x85, 0xff, 0x6d, 0xff, 0x51, 0xff, 0x4f, 0xff, 0x47, 0xff, 0x57, 0xff, 0x6e, 0xff, 0x7e, 0xff, 0x90, 0xff, 0x9e, 0xff, 0xb2, 0xff, 0xbf, 0xff, 0xc0, 0xff, 0xca, 0xff, 0xc4, 0xff, 0xce, 0xff, 0xdc, 0xff, 0xec, 0xff, 0xf8, 0xff, 0xef, 0xff, 0xee, 0xff, 0xec, 0xff, 0xee, 0xff, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00, 0x21, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x21, 0x00, 0x30, 0x00, 0x37, 0x00, 0x3b, 0x00, 0x31, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x38, 0x00, 0x31, 0x00, 0x3d, 0x00, 0x45, 0x00, 0x50, 0x00, 0x65, 0x00, 0x77, 0x00, 0x8c, 0x00, 0x90, 0x00, 0x95, 0x00, 0x89, 0x00, 0x79, 0x00, 0x5e, 0x00, 0x3b, 0x00, 0x23, 0x00, 0x04, 0x00, 0xec, 0xff, 0xcf, 0xff, 0xbc, 0xff, 0xb1, 0xff, 0xb2, 0xff, 0xb0, 0xff, 0xb2, 0xff, 0xa2, 0xff, 0x9a, 0xff, 0x96, 0xff, 0x91, 0xff, 0x8d, 0xff, 0x8b, 0xff, 0x79, 0xff, 0x79, 0xff, 0x71, 0xff, 0x77, 0xff, 0x7b, 0xff, 0x84, 0xff, 0x88, 0xff, 0x83, 0xff, 0x8d, 0xff, 0x9e, 0xff, 0xb2, 0xff, 0xd8, 0xff, 0x0b, 0x00, 0x34, 0x00, 0x60, 0x00, 0x74, 0x00, 0x8d, 0x00, 0x9c, 0x00, 0xac, 0x00, 0xad, 0x00, 0xa7, 0x00, 0xa4, 0x00, 0x91, 0x00, 0x88, 0x00, 0x70, 0x00, 0x5f, 0x00, 0x43, 0x00, 0x2d, 0x00, 0x03, 0x00, 0xe5, 0xff, 0xbd, 0xff, 0xac, 0xff, 0x95, 0xff, 0x86, 0xff, 0x73, 0xff, 0x69, 0xff, 0x66, 0xff, 0x70, 0xff, 0x87, 0xff, 0x9b, 0xff, 0xbb, 0xff, 0xeb, 0xff, 0x15, 0x00, 0x45, 0x00, 0x7a, 0x00, 0xa5, 0x00, 0xc7, 0x00, 0xdb, 0x00, 0xdd, 0x00, 0xd3, 0x00, 0xc0, 0x00, 0xa3, 0x00, 0x92, 0x00, 0x78, 0x00, 0x63, 0x00, 0x4f, 0x00, 0x33, 0x00, 0x21, 0x00, 0x1a, 0x00, 0x19, 0x00, 0x0c, 0x00, 0xfc, 0xff, 0xf4, 0xff, 0xdf, 0xff, 0xd9, 0xff, 0xd2, 0xff, 0xc6, 0xff, 0xa8, 0xff, 0x96, 0xff, 0x80, 0xff, 0x6f, 0xff, 0x58, 0xff, 0x4a, 0xff, 0x3f, 0xff, 0x3e, 0xff, 0x3a, 0xff, 0x3b, 0xff, 0x4a, 0xff, 0x4e, 0xff, 0x59, 0xff, 0x62, 0xff, 0x6e, 0xff, 0x7d, 0xff, 0x9a, 0xff, 0xb7, 0xff, 0xd9, 0xff, 0xdd, 0xff, 0xf2, 0xff, 0xf1, 0xff, 0x04, 0x00, 0x19, 0x00, 0x32, 0x00, 0x50, 0x00, 0x67, 0x00, 0x7b, 0x00, 0x98, 0x00, 0xb7, 0x00, 0xdc, 0x00, 0xf1, 0x00, 0xfd, 0x00, 0x0b, 0x01, 0x0c, 0x01, 0xfe, 0x00, 0xd9, 0x00, 0xb2, 0x00, 0x87, 0x00, 0x64, 0x00, 0x4a, 0x00, 0x31, 0x00, 0x22, 0x00, 0x04, 0x00, 0xed, 0xff, 0xcd, 0xff, 0xaf, 0xff, 0xa0, 0xff, 0x9d, 0xff, 0x9a, 0xff, 0x99, 0xff, 0x8d, 0xff, 0x88, 0xff, 0x7e, 0xff, 0x85, 0xff, 0x83, 0xff, 0x93, 0xff, 0x92, 0xff, 0x95, 0xff, 0x9c, 0xff, 0xae, 0xff, 0xc9, 0xff, 0xd9, 0xff, 0xf9, 0xff, 0x0d, 0x00, 0x31, 0x00, 0x35, 0x00, 0x43, 0x00, 0x45, 0x00, 0x40, 0x00, 0x2d, 0x00, 0x15, 0x00, 0xf2, 0xff, 0xd5, 0xff, 0xba, 0xff, 0xa6, 0xff, 0x9a, 0xff, 0x96, 0xff, 0x94, 0xff, 0x90, 0xff, 0x92, 0xff, 0x99, 0xff, 0x94, 0xff, 0xa8, 0xff, 0xb3, 0xff, 0xc6, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0x28, 0x00, 0x54, 0x00, 0x81, 0x00, 0x90, 0x00, 0x8d, 0x00, 0x93, 0x00, 0x8d, 0x00, 0x95, 0x00, 0x8f, 0x00, 0x80, 0x00, 0x7a, 0x00, 0x77, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x5b, 0x00, 0x4d, 0x00, 0x3e, 0x00, 0x30, 0x00, 0x18, 0x00, 0x09, 0x00, 0xf5, 0xff, 0xd5, 0xff, 0xc2, 0xff, 0xa7, 0xff, 0x9f, 0xff, 0x88, 0xff, 0x7d, 0xff, 0x68, 0xff, 0x5e, 0xff, 0x55, 0xff, 0x51, 0xff, 0x57, 0xff, 0x5c, 0xff, 0x5f, 0xff, 0x67, 0xff, 0x68, 0xff, 0x73, 0xff, 0x80, 0xff, 0x91, 0xff, 0xa4, 0xff, 0xc9, 0xff, 0xec, 0xff, 0x1f, 0x00, 0x52, 0x00, 0x6b, 0x00, 0x7e, 0x00, 0x91, 0x00, 0x9f, 0x00, 0xa3, 0x00, 0x97, 0x00, 0x84, 0x00, 0x76, 0x00, 0x66, 0x00, 0x5a, 0x00, 0x47, 0x00, 0x2f, 0x00, 0x12, 0x00, 0x01, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0xfa, 0xff, 0xf2, 0xff, 0xe2, 0xff, 0xe2, 0xff, 0xd9, 0xff, 0xec, 0xff, 0xe1, 0xff, 0xf7, 0xff, 0x06, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x1f, 0x00, 0x15, 0x00, 0x02, 0x00, 0xf1, 0xff, 0xd7, 0xff, 0xbf, 0xff, 0xba, 0xff, 0xb6, 0xff, 0xbb, 0xff, 0xc2, 0xff, 0xcb, 0xff, 0xdc, 0xff, 0xe3, 0xff, 0xee, 0xff, 0xe9, 0xff, 0xf1, 0xff, 0xf8, 0xff, 0xfb, 0xff, 0x07, 0x00, 0x12, 0x00, 0x2a, 0x00, 0x42, 0x00, 0x55, 0x00, 0x79, 0x00, 0x7c, 0x00, 0x8f, 0x00, 0x89, 0x00, 0x8e, 0x00, 0x81, 0x00, 0x76, 0x00, 0x75, 0x00, 0x61, 0x00, 0x5a, 0x00, 0x4c, 0x00, 0x40, 0x00, 0x2f, 0x00, 0x1f, 0x00, 0x07, 0x00, 0xfd, 0xff, 0xf2, 0xff, 0xdb, 0xff, 0xcf, 0xff, 0xa7, 0xff, 0xa0, 0xff, 0x89, 0xff, 0x7b, 0xff, 0x6d, 0xff, 0x69, 0xff, 0x6b, 0xff, 0x65, 0xff, 0x70, 0xff, 0x78, 0xff, 0x96, 0xff, 0xa5, 0xff, 0xb5, 0xff, 0xbd, 0xff, 0xbc, 0xff, 0xbf, 0xff, 0xb5, 0xff, 0xc2, 0xff, 0xca, 0xff, 0xe3, 0xff, 0xfd, 0xff, 0x0c, 0x00, 0x22, 0x00, 0x29, 0x00, 0x38, 0x00, 0x32, 0x00, 0x28, 0x00, 0x26, 0x00, 0x1f, 0x00, 0x1b, 0x00, 0x04, 0x00, 0x01, 0x00, 0xfc, 0xff, 0xfa, 0xff, 0xf8, 0xff, 0x05, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x06, 0x00, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0x09, 0x00, 0x0f, 0x00, 0x15, 0x00, 0x1b, 0x00, 0x16, 0x00, 0x1b, 0x00, 0x1a, 0x00, 0x17, 0x00, 0x13, 0x00, 0x11, 0x00, 0x15, 0x00, 0x25, 0x00, 0x23, 0x00, 0x1d, 0x00, 0x11, 0x00, 0x08, 0x00, 0x02, 0x00, 0xea, 0xff, 0xe1, 0xff, 0xc7, 0xff, 0xc3, 0xff, 0xb5, 0xff, 0xb8, 0xff, 0xba, 0xff, 0xc1, 0xff, 0xc6, 0xff, 0xd0, 0xff, 0xd5, 0xff, 0xe8, 0xff, 0xfa, 0xff, 0x10, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x21, 0x00, 0x28, 0x00, 0x37, 0x00, 0x50, 0x00, 0x71, 0x00, 0x81, 0x00, 0x90, 0x00, 0x93, 0x00, 0x9b, 0x00, 0x96, 0x00, 0x8e, 0x00, 0x7b, 0x00, 0x6c, 0x00, 0x70, 0x00, 0x69, 0x00, 0x63, 0x00, 0x59, 0x00, 0x42, 0x00, 0x20, 0x00, 0x05, 0x00, 0xe3, 0xff, 0xd2, 0xff, 0xc2, 0xff, 0xbb, 0xff, 0xb0, 0xff, 0xa1, 0xff, 0x93, 0xff, 0x89, 0xff, 0x7e, 0xff, 0x76, 0xff, 0x72, 0xff, 0x75, 0xff, 0x71, 0xff, 0x6c, 0xff, 0x6d, 0xff, 0x70, 0xff, 0x82, 0xff, 0x95, 0xff, 0xa3, 0xff, 0xac, 0xff, 0xc2, 0xff, 0xd8, 0xff, 0xef, 0xff, 0x08, 0x00, 0x1a, 0x00, 0x2b, 0x00, 0x40, 0x00, 0x4c, 0x00, 0x5a, 0x00, 0x57, 0x00, 0x62, 0x00, 0x62, 0x00, 0x64, 0x00, 0x4c, 0x00, 0x35, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfb, 0xff, 0xe6, 0xff, 0xe4, 0xff, 0xd3, 0xff, 0xcc, 0xff, 0xcb, 0xff, 0xd7, 0xff, 0xda, 0xff, 0xe6, 0xff, 0xeb, 0xff, 0xf4, 0xff, 0xfa, 0xff, 0x11, 0x00, 0x19, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x22, 0x00, 0x1f, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x15, 0x00, 0x12, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x03, 0x00, 0xf0, 0xff, 0xe8, 0xff, 0xea, 0xff, 0xec, 0xff, 0xe5, 0xff, 0xf1, 0xff, 0xe4, 0xff, 0xe2, 0xff, 0xd6, 0xff, 0xd4, 0xff, 0xca, 0xff, 0xcc, 0xff, 0xce, 0xff, 0xd7, 0xff, 0xd2, 0xff, 0xd0, 0xff, 0xba, 0xff, 0xb3, 0xff, 0xa6, 0xff, 0xa1, 0xff, 0x9e, 0xff, 0xa0, 0xff, 0xac, 0xff, 0xc2, 0xff, 0xd5, 0xff, 0xf5, 0xff, 0x15, 0x00, 0x3f, 0x00, 0x62, 0x00, 0x77, 0x00, 0x86, 0x00, 0x96, 0x00, 0xa5, 0x00, 0xab, 0x00, 0xb9, 0x00, 0xbc, 0x00, 0xc5, 0x00, 0xd0, 0x00, 0xd8, 0x00, 0xda, 0x00, 0xc0, 0x00, 0xa6, 0x00, 0x7f, 0x00, 0x5c, 0x00, 0x41, 0x00, 0x20, 0x00, 0x07, 0x00, 0xec, 0xff, 0xd0, 0xff, 0xbc, 0xff, 0xa4, 0xff, 0x98, 0xff, 0x8c, 0xff, 0x8e, 0xff, 0x8a, 0xff, 0x81, 0xff, 0x7c, 0xff, 0x7b, 0xff, 0x7a, 0xff, 0x7c, 0xff, 0x79, 0xff, 0x83, 0xff, 0x88, 0xff, 0x93, 0xff, 0xa1, 0xff, 0xab, 0xff, 0xb3, 0xff, 0xbe, 0xff, 0xcb, 0xff, 0xcf, 0xff, 0xca, 0xff, 0xc8, 0xff, 0xb4, 0xff, 0xb5, 0xff, 0xb4, 0xff, 0xc4, 0xff, 0xdf, 0xff, 0xef, 0xff, 0x12, 0x00, 0x2f, 0x00, 0x64, 0x00, 0x7f, 0x00, 0xab, 0x00, 0xc0, 0x00, 0xd9, 0x00, 0xe6, 0x00, 0xde, 0x00, 0xc8, 0x00, 0xa9, 0x00, 0x8a, 0x00, 0x73, 0x00, 0x4d, 0x00, 0x2b, 0x00, 0x11, 0x00, 0xf4, 0xff, 0xdd, 0xff, 0xb9, 0xff, 0xab, 0xff, 0x98, 0xff, 0x90, 0xff, 0x82, 0xff, 0x79, 0xff, 0x72, 0xff, 0x7f, 0xff, 0x90, 0xff, 0x99, 0xff, 0xa9, 0xff, 0xb3, 0xff, 0xb1, 0xff, 0xb4, 0xff, 0xa8, 0xff, 0xaa, 0xff, 0xa3, 0xff, 0xb5, 0xff, 0xd2, 0xff, 0xeb, 0xff, 0x05, 0x00, 0x22, 0x00, 0x30, 0x00, 0x43, 0x00, 0x5d, 0x00, 0x74, 0x00, 0x96, 0x00, 0xb5, 0x00, 0xd1, 0x00, 0xe1, 0x00, 0xea, 0x00, 0xdd, 0x00, 0xd5, 0x00, 0xc5, 0x00, 0xbc, 0x00, 0xac, 0x00, 0x82, 0x00, 0x5d, 0x00, 0x2e, 0x00, 0x03, 0x00, 0xdc, 0xff, 0xbb, 0xff, 0xa3, 0xff, 0x87, 0xff, 0x6e, 0xff, 0x53, 0xff, 0x40, 0xff, 0x33, 0xff, 0x2f, 0xff, 0x2e, 0xff, 0x35, 0xff, 0x33, 0xff, 0x2d, 0xff, 0x3c, 0xff, 0x45, 0xff, 0x68, 0xff, 0x87, 0xff, 0x99, 0xff, 0xb4, 0xff, 0xbc, 0xff, 0xda, 0xff, 0xea, 0xff, 0x11, 0x00, 0x3d, 0x00, 0x6e, 0x00, 0x8c, 0x00, 0x9c, 0x00, 0xa8, 0x00, 0xac, 0x00, 0xa8, 0x00, 0xa8, 0x00, 0xb6, 0x00, 0xc5, 0x00, 0xce, 0x00, 0xd1, 0x00, 0xc6, 0x00, 0xa0, 0x00, 0x71, 0x00, 0x39, 0x00, 0x0f, 0x00, 0xe2, 0xff, 0xbc, 0xff, 0x9c, 0xff, 0x7d, 0xff, 0x6c, 0xff, 0x5b, 0xff, 0x53, 0xff, 0x57, 0xff, 0x57, 0xff, 0x6a, 0xff, 0x7d, 0xff, 0x85, 0xff, 0xa0, 0xff, 0xae, 0xff, 0xcb, 0xff, 0xdb, 0xff, 0xf3, 0xff, 0x08, 0x00, 0x2b, 0x00, 0x51, 0x00, 0x61, 0x00, 0x6a, 0x00, 0x61, 0x00, 0x54, 0x00, 0x3b, 0x00, 0x25, 0x00, 0x15, 0x00, 0x07, 0x00, 0xea, 0xff, 0xd7, 0xff, 0xb4, 0xff, 0xa1, 0xff, 0x8a, 0xff, 0x7d, 0xff, 0x77, 0xff, 0x74, 0xff, 0x72, 0xff, 0x73, 0xff, 0x82, 0xff, 0x96, 0xff, 0xab, 0xff, 0xbc, 0xff, 0xdb, 0xff, 0xfe, 0xff, 0x36, 0x00, 0x60, 0x00, 0x8d, 0x00, 0x96, 0x00, 0x97, 0x00, 0x7f, 0x00, 0x6a, 0x00, 0x4e, 0x00, 0x2f, 0x00, 0x22, 0x00, 0x0a, 0x00, 0x05, 0x00, 0xff, 0xff, 0x0b, 0x00, 0x25, 0x00, 0x39, 0x00, 0x54, 0x00, 0x51, 0x00, 0x52, 0x00, 0x52, 0x00, 0x4d, 0x00, 0x43, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x31, 0x00, 0x27, 0x00, 0x0b, 0x00, 0x00, 0x00, 0xe9, 0xff, 0xd5, 0xff, 0xd3, 0xff, 0xce, 0xff, 0xc1, 0xff, 0xc6, 0xff, 0xc0, 0xff, 0xc3, 0xff, 0xd0, 0xff, 0xdd, 0xff, 0xed, 0xff, 0xf0, 0xff, 0xf4, 0xff, 0xf9, 0xff, 0xf8, 0xff, 0x09, 0x00, 0x27, 0x00, 0x2e, 0x00, 0x3b, 0x00, 0x37, 0x00, 0x2e, 0x00, 0x21, 0x00, 0x0e, 0x00, 0x04, 0x00, 0xfe, 0xff, 0xf3, 0xff, 0xe1, 0xff, 0xd9, 0xff, 0xb9, 0xff, 0xb7, 0xff, 0x93, 0xff, 0x8e, 0xff, 0x85, 0xff, 0x7d, 0xff, 0x87, 0xff, 0x7f, 0xff, 0x84, 0xff, 0x88, 0xff, 0x8f, 0xff, 0x99, 0xff, 0x9c, 0xff, 0x98, 0xff, 0x91, 0xff, 0x8c, 0xff, 0x9d, 0xff, 0xa6, 0xff, 0xc8, 0xff, 0xe2, 0xff, 0x05, 0x00, 0x0b, 0x00, 0x18, 0x00, 0x23, 0x00, 0x3b, 0x00, 0x57, 0x00, 0x7d, 0x00, 0x9e, 0x00, 0xbc, 0x00, 0xc9, 0x00, 0xcb, 0x00, 0xc8, 0x00, 0xcb, 0x00, 0xc1, 0x00, 0xc4, 0x00, 0xc1, 0x00, 0xac, 0x00, 0x98, 0x00, 0x7d, 0x00, 0x5f, 0x00, 0x4b, 0x00, 0x4a, 0x00, 0x31, 0x00, 0x1d, 0x00, 0x16, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe3, 0xff, 0xd7, 0xff, 0xc5, 0xff, 0xb6, 0xff, 0xa2, 0xff, 0x84, 0xff, 0x70, 0xff, 0x60, 0xff, 0x54, 0xff, 0x51, 0xff, 0x58, 0xff, 0x5d, 0xff, 0x6b, 0xff, 0x7d, 0xff, 0x8a, 0xff, 0x9d, 0xff, 0xa5, 0xff, 0xb6, 0xff, 0xcb, 0xff, 0xda, 0xff, 0xfa, 0xff, 0x18, 0x00, 0x32, 0x00, 0x45, 0x00, 0x50, 0x00, 0x5d, 0x00, 0x61, 0x00, 0x79, 0x00, 0x83, 0x00, 0x92, 0x00, 0x94, 0x00, 0x9a, 0x00, 0x88, 0x00, 0x80, 0x00, 0x74, 0x00, 0x75, 0x00, 0x73, 0x00, 0x5b, 0x00, 0x31, 0x00, 0x0b, 0x00, 0xeb, 0xff, 0xcc, 0xff, 0xbc, 0xff, 0xa9, 0xff, 0x9f, 0xff, 0x89, 0xff, 0x86, 0xff, 0x84, 0xff, 0x7f, 0xff, 0x7d, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x89, 0xff, 0x8b, 0xff, 0x99, 0xff, 0xa7, 0xff, 0xba, 0xff, 0xd8, 0xff, 0xea, 0xff, 0x02, 0x00, 0x0b, 0x00, 0x12, 0x00, 0x16, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x14, 0x00, 0x0b, 0x00, 0xff, 0xff, 0xfc, 0xff, 0xf3, 0xff, 0xef, 0xff, 0xf0, 0xff, 0xfe, 0xff, 0x26, 0x00, 0x4b, 0x00, 0x6c, 0x00, 0x89, 0x00, 0x97, 0x00, 0x9c, 0x00, 0x96, 0x00, 0x85, 0x00, 0x6f, 0x00, 0x52, 0x00, 0x36, 0x00, 0x14, 0x00, 0xea, 0xff, 0xbe, 0xff, 0x9f, 0xff, 0x7b, 0xff, 0x6d, 0xff, 0x5c, 0xff, 0x62, 0xff, 0x71, 0xff, 0x86, 0xff, 0x9d, 0xff, 0xcc, 0xff, 0xe1, 0xff, 0xfa, 0xff, 0x15, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x18, 0x00, 0x23, 0x00, 0x29, 0x00, 0x2e, 0x00, 0x46, 0x00, 0x53, 0x00, 0x55, 0x00, 0x49, 0x00, 0x43, 0x00, 0x3f, 0x00, 0x40, 0x00, 0x48, 0x00, 0x45, 0x00, 0x37, 0x00, 0x24, 0x00, 0x0e, 0x00, 0xf8, 0xff, 0xe2, 0xff, 0xc3, 0xff, 0xa8, 0xff, 0x91, 0xff, 0x84, 0xff, 0x75, 0xff, 0x67, 0xff, 0x62, 0xff, 0x54, 0xff, 0x4e, 0xff, 0x50, 0xff, 0x60, 0xff, 0x80, 0xff, 0x93, 0xff, 0xa6, 0xff, 0xb6, 0xff, 0xd0, 0xff, 0xf4, 0xff, 0x1b, 0x00, 0x2c, 0x00, 0x40, 0x00, 0x45, 0x00, 0x56, 0x00, 0x5c, 0x00, 0x70, 0x00, 0x75, 0x00, 0x7b, 0x00, 0x84, 0x00, 0x7d, 0x00, 0x6e, 0x00, 0x5a, 0x00, 0x41, 0x00, 0x2a, 0x00, 0x1c, 0x00, 0x1a, 0x00, 0x25, 0x00, 0x1e, 0x00, 0x1b, 0x00, 0x17, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x24, 0x00, 0x3b, 0x00, 0x4e, 0x00, 0x59, 0x00, 0x62, 0x00, 0x56, 0x00, 0x47, 0x00, 0x2d, 0x00, 0x1c, 0x00, 0xfe, 0xff, 0xec, 0xff, 0xe2, 0xff, 0xd6, 0xff, 0xc9, 0xff, 0xba, 0xff, 0xb5, 0xff, 0xa8, 0xff, 0xa1, 0xff, 0x9d, 0xff, 0xa3, 0xff, 0xa7, 0xff, 0xb6, 0xff, 0xc9, 0xff, 0xe2, 0xff, 0xed, 0xff, 0xf6, 0xff, 0xeb, 0xff, 0xeb, 0xff, 0xe1, 0xff, 0xed, 0xff, 0xf5, 0xff, 0x06, 0x00, 0x20, 0x00, 0x33, 0x00, 0x3c, 0x00, 0x47, 0x00, 0x4d, 0x00, 0x3d, 0x00, 0x31, 0x00, 0x1b, 0x00, 0x0a, 0x00, 0xfa, 0xff, 0xe0, 0xff, 0xcb, 0xff, 0xb1, 0xff, 0xa5, 0xff, 0x91, 0xff, 0x91, 0xff, 0x8f, 0xff, 0x94, 0xff, 0xa0, 0xff, 0xa4, 0xff, 0xb5, 0xff, 0xcd, 0xff, 0xe1, 0xff, 0x07, 0x00, 0x2f, 0x00, 0x5d, 0x00, 0x6f, 0x00, 0x7e, 0x00, 0x80, 0x00, 0x83, 0x00, 0x7b, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x5d, 0x00, 0x51, 0x00, 0x3f, 0x00, 0x36, 0x00, 0x1c, 0x00, 0x07, 0x00, 0xec, 0xff, 0xe0, 0xff, 0xcf, 0xff, 0xc7, 0xff, 0xb5, 0xff, 0xad, 0xff, 0xa5, 0xff, 0xa1, 0xff, 0xa0, 0xff, 0x95, 0xff, 0x94, 0xff, 0x86, 0xff, 0x89, 0xff, 0x82, 0xff, 0x94, 0xff, 0xaf, 0xff, 0xd0, 0xff, 0xfb, 0xff, 0x19, 0x00, 0x33, 0x00, 0x3d, 0x00, 0x41, 0x00, 0x43, 0x00, 0x3e, 0x00, 0x3d, 0x00, 0x32, 0x00, 0x31, 0x00, 0x26, 0x00, 0x2b, 0x00, 0x26, 0x00, 0x2f, 0x00, 0x1b, 0x00, 0x0f, 0x00, 0x05, 0x00, 0x0f, 0x00, 0x23, 0x00, 0x37, 0x00, 0x41, 0x00, 0x40, 0x00, 0x41, 0x00, 0x35, 0x00, 0x24, 0x00, 0x0c, 0x00, 0xf6, 0xff, 0xe9, 0xff, 0xe9, 0xff, 0xe6, 0xff, 0xdc, 0xff, 0xde, 0xff, 0xde, 0xff, 0xe3, 0xff, 0xe4, 0xff, 0xd3, 0xff, 0xce, 0xff, 0xbd, 0xff, 0xbe, 0xff, 0xbc, 0xff, 0xc4, 0xff, 0xc3, 0xff, 0xc8, 0xff, 0xcc, 0xff, 0xd6, 0xff, 0xe4, 0xff, 0xea, 0xff, 0xf1, 0xff, 0xe3, 0xff, 0xf0, 0xff, 0xeb, 0xff, 0xf4, 0xff, 0xf2, 0xff, 0xef, 0xff, 0xeb, 0xff, 0xe4, 0xff, 0xd6, 0xff, 0xc6, 0xff, 0xba, 0xff, 0xa9, 0xff, 0xa1, 0xff, 0xa9, 0xff, 0xb3, 0xff, 0xba, 0xff, 0xd2, 0xff, 0xda, 0xff, 0xf7, 0xff, 0x0c, 0x00, 0x29, 0x00, 0x42, 0x00, 0x64, 0x00, 0x7d, 0x00, 0x9d, 0x00, 0xa8, 0x00, 0xa4, 0x00, 0x94, 0x00, 0x8d, 0x00, 0x89, 0x00, 0x7d, 0x00, 0x68, 0x00, 0x45, 0x00, 0x25, 0x00, 0x11, 0x00, 0x01, 0x00, 0xf3, 0xff, 0xe0, 0xff, 0xc9, 0xff, 0xb4, 0xff, 0xaf, 0xff, 0xb0, 0xff, 0xaa, 0xff, 0x9c, 0xff, 0xa5, 0xff, 0xa4, 0xff, 0xb6, 0xff, 0xc4, 0xff, 0xc7, 0xff, 0xd1, 0xff, 0xd2, 0xff, 0xd0, 0xff, 0xd4, 0xff, 0xd5, 0xff, 0xe4, 0xff, 0xdf, 0xff, 0xed, 0xff, 0xe6, 0xff, 0xec, 0xff, 0xe9, 0xff, 0xe8, 0xff, 0xf7, 0xff, 0x03, 0x00, 0x08, 0x00, 0x09, 0x00, 0x02, 0x00, 0xfa, 0xff, 0xf3, 0xff, 0xdf, 0xff, 0xe2, 0xff, 0xdf, 0xff, 0xea, 0xff, 0xef, 0xff, 0xf5, 0xff, 0xfb, 0xff, 0x06, 0x00, 0x13, 0x00, 0x2b, 0x00, 0x34, 0x00, 0x55, 0x00, 0x61, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x72, 0x00, 0x70, 0x00, 0x78, 0x00, 0x6b, 0x00, 0x5f, 0x00, 0x45, 0x00, 0x26, 0x00, 0x05, 0x00, 0xec, 0xff, 0xd4, 0xff, 0xd1, 0xff, 0xcf, 0xff, 0xd7, 0xff, 0xe1, 0xff, 0xfd, 0xff, 0x0b, 0x00, 0x32, 0x00, 0x3a, 0x00, 0x43, 0x00, 0x45, 0x00, 0x53, 0x00, 0x4a, 0x00, 0x45, 0x00, 0x31, 0x00, 0x1d, 0x00, 0x02, 0x00, 0xde, 0xff, 0xd0, 0xff, 0xb5, 0xff, 0xac, 0xff, 0xa1, 0xff, 0x97, 0xff, 0x9a, 0xff, 0x95, 0xff, 0x95, 0xff, 0x93, 0xff, 0x8d, 0xff, 0x8d, 0xff, 0x91, 0xff, 0x89, 0xff, 0x9a, 0xff, 0x99, 0xff, 0xa5, 0xff, 0xa8, 0xff, 0xbd, 0xff, 0xd1, 0xff, 0xe5, 0xff, 0x07, 0x00, 0x1a, 0x00, 0x36, 0x00, 0x41, 0x00, 0x56, 0x00, 0x71, 0x00, 0x8f, 0x00, 0xb0, 0x00, 0xb9, 0x00, 0xad, 0x00, 0x99, 0x00, 0x8a, 0x00, 0x7b, 0x00, 0x68, 0x00, 0x58, 0x00, 0x4f, 0x00, 0x43, 0x00, 0x39, 0x00, 0x25, 0x00, 0x1b, 0x00, 0x11, 0x00, 0x06, 0x00, 0xea, 0xff, 0xd3, 0xff, 0xc6, 0xff, 0xb5, 0xff, 0xa4, 0xff, 0x91, 0xff, 0x86, 0xff, 0x80, 0xff, 0x79, 0xff, 0x7e, 0xff, 0x83, 0xff, 0x9c, 0xff, 0xa2, 0xff, 0xad, 0xff, 0xab, 0xff, 0xaf, 0xff, 0xcb, 0xff, 0xda, 0xff, 0xf2, 0xff, 0x06, 0x00, 0x1f, 0x00, 0x39, 0x00, 0x4a, 0x00, 0x72, 0x00, 0x7d, 0x00, 0x99, 0x00, 0xa2, 0x00, 0x9c, 0x00, 0x97, 0x00, 0x7f, 0x00, 0x6a, 0x00, 0x45, 0x00, 0x25, 0x00, 0x06, 0x00, 0xed, 0xff, 0xd8, 0xff, 0xba, 0xff, 0xa9, 0xff, 0x8f, 0xff, 0x7c, 0xff, 0x6b, 0xff, 0x60, 0xff, 0x62, 0xff, 0x60, 0xff, 0x67, 0xff, 0x75, 0xff, 0x8b, 0xff, 0x9f, 0xff, 0xbc, 0xff, 0xcb, 0xff, 0xe5, 0xff, 0x00, 0x00, 0x0f, 0x00, 0x23, 0x00, 0x36, 0x00, 0x41, 0x00, 0x51, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x42, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x51, 0x00, 0x4a, 0x00, 0x3e, 0x00, 0x2e, 0x00, 0x11, 0x00, 0xf8, 0xff, 0xe1, 0xff, 0xd2, 0xff, 0xc4, 0xff, 0xb0, 0xff, 0xa2, 0xff, 0xa0, 0xff, 0xa1, 0xff, 0x9e, 0xff, 0x9d, 0xff, 0xa6, 0xff, 0xaf, 0xff }; constexpr unsigned int cp808_raw_len = 36312; ================================================ FILE: lib/claps/cp909.h ================================================ const uint8_t FLASHMEM cp909_raw[] = { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xa8, 0xff, 0x18, 0x00, 0x8f, 0xff, 0x37, 0x00, 0x7f, 0xff, 0x45, 0x00, 0x59, 0xff, 0x7e, 0x00, 0x1d, 0xff, 0xc4, 0x00, 0xbd, 0xfe, 0x5a, 0x01, 0xc1, 0xfd, 0x33, 0x03, 0xa3, 0xf9, 0xd1, 0x23, 0x11, 0x7b, 0x5b, 0x4f, 0x6a, 0x49, 0x6f, 0x33, 0x47, 0x3a, 0x3f, 0x31, 0xaa, 0x5d, 0x85, 0x70, 0x30, 0x6e, 0x90, 0x3b, 0x5e, 0xe5, 0x61, 0xf8, 0x49, 0xe8, 0x8d, 0xf8, 0xf2, 0xc5, 0x34, 0x8a, 0x46, 0x90, 0x69, 0x8e, 0xfb, 0x8d, 0xcc, 0x95, 0xe2, 0xc5, 0xbb, 0xaa, 0x82, 0xd9, 0xfb, 0xf7, 0xff, 0x06, 0x89, 0xfc, 0xb6, 0xe7, 0x33, 0x35, 0xe0, 0x0e, 0xd0, 0xe3, 0xeb, 0xb5, 0x27, 0xe4, 0x6a, 0x05, 0x4b, 0xfa, 0x82, 0x06, 0x19, 0xe7, 0xc1, 0xe7, 0x1b, 0xf0, 0xb6, 0x01, 0x3f, 0x20, 0x84, 0x15, 0x7e, 0x22, 0x19, 0x19, 0x93, 0x17, 0x44, 0x21, 0x5f, 0x2f, 0x45, 0x46, 0xb1, 0x29, 0x68, 0x11, 0xd7, 0x1f, 0x4c, 0x22, 0x04, 0x27, 0x32, 0x3f, 0xe8, 0x27, 0xfd, 0x2f, 0x33, 0x12, 0xd2, 0x19, 0xab, 0xf7, 0xb8, 0xd0, 0x7e, 0xd5, 0xe1, 0xbe, 0x05, 0xcb, 0x10, 0xc7, 0xa5, 0xd0, 0x00, 0xb8, 0x79, 0xd6, 0xc0, 0xea, 0xfa, 0x09, 0x04, 0x10, 0x20, 0xf1, 0x8e, 0xe7, 0xfb, 0x0b, 0x3f, 0x1a, 0x67, 0x12, 0x55, 0x32, 0x84, 0x09, 0xe0, 0xdf, 0xc6, 0xf4, 0x0a, 0xf0, 0x6f, 0xed, 0x2a, 0xf0, 0xd0, 0xef, 0xa5, 0xf1, 0x63, 0xe9, 0xd7, 0xef, 0x07, 0x07, 0x03, 0x1c, 0x17, 0x16, 0xb0, 0x11, 0x7e, 0x18, 0xa0, 0x07, 0xdc, 0x02, 0x7e, 0x04, 0x08, 0xec, 0xff, 0x01, 0x16, 0x0d, 0x9d, 0x12, 0x00, 0x09, 0x4f, 0x02, 0x61, 0xf3, 0x2a, 0xd7, 0x61, 0xd9, 0xaf, 0xd9, 0x35, 0xe3, 0x41, 0xf5, 0xb7, 0x1f, 0x87, 0x2f, 0x6d, 0x17, 0xdd, 0x22, 0x1b, 0x22, 0x81, 0x09, 0xce, 0x0e, 0x67, 0xeb, 0x55, 0xec, 0x56, 0xdf, 0xe6, 0xeb, 0x78, 0xf4, 0x0f, 0xfc, 0xc6, 0xeb, 0x56, 0xdc, 0xf9, 0xf9, 0x51, 0xfc, 0x66, 0xf9, 0xce, 0xf2, 0xe8, 0xe9, 0x8c, 0x09, 0x15, 0x01, 0x29, 0x02, 0x80, 0xf7, 0xf1, 0xeb, 0x41, 0xec, 0xd2, 0xe4, 0x31, 0xe8, 0x1d, 0xf4, 0xa2, 0x03, 0xbb, 0x09, 0x12, 0x1c, 0x96, 0x2b, 0x73, 0x2c, 0x9b, 0x2a, 0xbd, 0x35, 0x9b, 0x3a, 0x6e, 0x34, 0x24, 0x29, 0xb8, 0x1c, 0xbe, 0x0b, 0x5e, 0x0f, 0x42, 0x0c, 0x78, 0x11, 0x64, 0x06, 0xfd, 0xfc, 0x93, 0xfb, 0x6d, 0xee, 0x2b, 0xe6, 0x67, 0xf3, 0xf3, 0xed, 0x41, 0xf0, 0xfe, 0xf1, 0x8b, 0xdd, 0x1f, 0xe1, 0xec, 0xeb, 0xb6, 0xf2, 0xf4, 0xf4, 0xe7, 0xdf, 0xd2, 0xd9, 0xa8, 0xdd, 0x75, 0xe1, 0xe1, 0xe4, 0x37, 0xe6, 0x5f, 0xf5, 0x3d, 0xfa, 0x84, 0xf5, 0xeb, 0xef, 0x3c, 0xf2, 0x55, 0xf1, 0xb0, 0xf3, 0xd3, 0xf4, 0x45, 0xf9, 0x2d, 0x00, 0x32, 0x05, 0xcc, 0x0a, 0x63, 0x10, 0x06, 0x1c, 0xfb, 0x2a, 0xac, 0x33, 0x9c, 0x2c, 0xff, 0x2c, 0x54, 0x21, 0x40, 0x19, 0x95, 0x0d, 0xd5, 0x09, 0x94, 0x0d, 0x60, 0x10, 0x85, 0x11, 0x8b, 0x04, 0x38, 0xf4, 0x94, 0xfa, 0xab, 0xfd, 0x27, 0xfa, 0xaa, 0xf6, 0xda, 0xef, 0x70, 0xf2, 0x38, 0xf8, 0xe9, 0xf5, 0x42, 0xef, 0x07, 0xf3, 0xf0, 0xf3, 0x7a, 0xf1, 0xa0, 0xe8, 0xb4, 0xe7, 0x20, 0xf2, 0x7f, 0xed, 0x46, 0xed, 0xd1, 0xea, 0xea, 0xef, 0x09, 0xf7, 0x0d, 0xf8, 0xa6, 0x01, 0x11, 0x0a, 0x3a, 0x02, 0x0a, 0xff, 0xcd, 0x01, 0x61, 0x03, 0xa4, 0x03, 0x39, 0x09, 0x97, 0x0c, 0x0f, 0x11, 0x21, 0x10, 0x4b, 0x0d, 0x48, 0x09, 0x76, 0xfe, 0x3d, 0xf8, 0xc2, 0xfa, 0xf3, 0xfe, 0xb9, 0x00, 0x63, 0x02, 0x03, 0x04, 0x10, 0x05, 0x83, 0x00, 0x76, 0xfd, 0xaf, 0xfb, 0x90, 0xfd, 0x2c, 0x04, 0xca, 0x05, 0xcc, 0x06, 0xe2, 0x0b, 0xd9, 0x08, 0x88, 0x0b, 0x9e, 0x0d, 0xd3, 0x11, 0x55, 0x16, 0xe5, 0x11, 0xef, 0x08, 0x93, 0x09, 0xbb, 0x0a, 0x84, 0x07, 0xdf, 0x04, 0x5e, 0x04, 0xec, 0xfe, 0x02, 0xfa, 0x83, 0xfa, 0x0c, 0xf9, 0x61, 0xf3, 0xd6, 0xf4, 0x56, 0xf5, 0xc5, 0xf4, 0x9f, 0xf0, 0x02, 0xf1, 0x49, 0xec, 0x51, 0xe5, 0xee, 0xe8, 0xf2, 0xea, 0xba, 0xed, 0x2e, 0xed, 0x89, 0xef, 0x96, 0xf0, 0xb0, 0xf3, 0xc7, 0xf6, 0x7c, 0xfb, 0x4b, 0xff, 0x22, 0x04, 0x98, 0x06, 0xb5, 0x0a, 0xe9, 0x0e, 0x7e, 0x0d, 0x6d, 0x09, 0xdb, 0x0b, 0xea, 0x11, 0x79, 0x10, 0x53, 0x11, 0x49, 0x0d, 0x04, 0x06, 0xca, 0x04, 0xb3, 0x02, 0x59, 0x03, 0x4a, 0x06, 0x65, 0x04, 0x3b, 0x04, 0xd9, 0x02, 0xe6, 0x00, 0x84, 0x02, 0x6e, 0x04, 0xd6, 0xfe, 0xe4, 0xfb, 0x77, 0xfb, 0xa4, 0xf8, 0x78, 0xf4, 0xcf, 0xf7, 0x30, 0xfb, 0x26, 0x00, 0x1a, 0x03, 0x06, 0xff, 0xc1, 0xfa, 0x33, 0x02, 0x94, 0x03, 0x5c, 0x03, 0x73, 0x03, 0x8b, 0x00, 0xa7, 0xfd, 0x3a, 0xff, 0xf3, 0xfe, 0xc4, 0xff, 0x3a, 0xff, 0x23, 0xfd, 0xcd, 0xff, 0x64, 0xfb, 0x2a, 0xf7, 0x02, 0xf5, 0xb2, 0xf7, 0x4e, 0xf9, 0x87, 0xfa, 0x2b, 0xfd, 0x24, 0x00, 0x7b, 0xfd, 0x8c, 0xff, 0x25, 0x05, 0xcb, 0x03, 0x2d, 0x04, 0x3e, 0x04, 0x97, 0x03, 0x55, 0x05, 0x9a, 0x04, 0xfb, 0x01, 0x61, 0xfc, 0x8d, 0xfb, 0x22, 0xfe, 0x35, 0xfc, 0x96, 0xfb, 0xeb, 0xfd, 0x44, 0xfd, 0x2f, 0xfc, 0x91, 0xfe, 0x1b, 0x00, 0xef, 0xfe, 0x2f, 0xfe, 0x77, 0xfe, 0x11, 0x01, 0x01, 0xff, 0xc3, 0x00, 0x29, 0x03, 0x68, 0xff, 0xd1, 0xfd, 0x2f, 0xfe, 0xc1, 0x00, 0xde, 0x00, 0x38, 0x01, 0x2b, 0x01, 0x64, 0x04, 0x17, 0x05, 0x04, 0x04, 0xc4, 0x00, 0x5a, 0xff, 0xe4, 0xfd, 0x01, 0xfd, 0x98, 0xff, 0x60, 0xfe, 0x97, 0x01, 0xff, 0xfe, 0x9c, 0xfc, 0x7f, 0xfd, 0x21, 0xff, 0xf8, 0xfe, 0x72, 0x01, 0x71, 0x02, 0x47, 0x05, 0xaa, 0x06, 0x2e, 0x06, 0x99, 0x04, 0x0a, 0x05, 0x07, 0x07, 0x72, 0x05, 0x9e, 0x06, 0x61, 0x06, 0x86, 0x03, 0x89, 0x00, 0xfe, 0x00, 0x4f, 0x00, 0xd3, 0xfd, 0x0c, 0xfe, 0x3d, 0xfe, 0x7a, 0xfe, 0xce, 0xfe, 0x97, 0xff, 0xd6, 0xfc, 0xb4, 0xfa, 0x61, 0xfc, 0x10, 0xfc, 0xdc, 0xfb, 0x25, 0xfa, 0xf2, 0xf8, 0xf9, 0xf6, 0x22, 0xf8, 0x8f, 0xf8, 0x16, 0xfa, 0x21, 0xfc, 0x39, 0xfd, 0x72, 0xfe, 0xcd, 0xff, 0xab, 0x00, 0x84, 0x01, 0xcc, 0x02, 0xb1, 0x02, 0x94, 0x02, 0x5d, 0x02, 0xbc, 0x03, 0x54, 0x02, 0xbb, 0x02, 0x6f, 0x01, 0x19, 0x01, 0x5f, 0x01, 0xe2, 0xff, 0xad, 0x00, 0xd7, 0x00, 0xff, 0x01, 0xaf, 0x02, 0x62, 0x02, 0x93, 0x03, 0x12, 0x05, 0x78, 0x05, 0x6e, 0x06, 0x04, 0x08, 0x1c, 0x0a, 0xd1, 0x0a, 0x53, 0x0a, 0x04, 0x0b, 0x02, 0x0b, 0xbd, 0x08, 0x07, 0x07, 0xeb, 0x05, 0x86, 0x03, 0xb6, 0x01, 0x94, 0x00, 0x50, 0xfe, 0x85, 0xfc, 0xbb, 0xfa, 0x23, 0xf9, 0xc7, 0xf7, 0x5f, 0xf6, 0x14, 0xf5, 0x36, 0xf4, 0xd0, 0xf3, 0x31, 0xf4, 0x09, 0xf4, 0x5a, 0xf4, 0x5f, 0xf5, 0x42, 0xf5, 0x61, 0xf5, 0x11, 0xf7, 0x57, 0xf7, 0x29, 0xf7, 0xa3, 0xf7, 0xe6, 0xf7, 0x82, 0xf8, 0x77, 0xfa, 0x88, 0xfb, 0x23, 0xfd, 0xaf, 0xfd, 0x35, 0xff, 0x46, 0x01, 0x84, 0x03, 0x73, 0x05, 0x69, 0x07, 0x3a, 0x09, 0x9a, 0x0a, 0xc6, 0x0b, 0x74, 0x0c, 0x52, 0x0c, 0x0e, 0x0b, 0xd3, 0x0b, 0x61, 0x09, 0x88, 0x07, 0xcd, 0x05, 0x5e, 0x06, 0x1d, 0x05, 0xf4, 0x04, 0xf9, 0x01, 0x02, 0x00, 0xbe, 0xfd, 0xc6, 0xff, 0xaa, 0xfc, 0x1d, 0xfe, 0xf0, 0xf9, 0x36, 0xfc, 0x62, 0xf7, 0xe6, 0xfa, 0x58, 0xfe, 0x0a, 0x62, 0x37, 0x6b, 0x24, 0x63, 0x64, 0x1f, 0xa3, 0xcc, 0xc7, 0xaf, 0xea, 0xd4, 0xfc, 0xd0, 0x2e, 0x86, 0x48, 0x95, 0xd4, 0x89, 0x37, 0x97, 0x7b, 0x95, 0xa1, 0xb1, 0x19, 0xd4, 0x88, 0xb9, 0x29, 0xea, 0x39, 0xfd, 0x59, 0x15, 0xe3, 0x27, 0x75, 0xf5, 0xcc, 0x06, 0x12, 0x26, 0xc7, 0x2b, 0xb1, 0x3e, 0x4c, 0x6e, 0xe7, 0x74, 0x62, 0x75, 0x06, 0x74, 0x33, 0x75, 0x7c, 0x70, 0x1b, 0x5c, 0x02, 0x43, 0x5a, 0x61, 0x78, 0x48, 0x0a, 0x23, 0x40, 0x23, 0xfa, 0x10, 0x93, 0x05, 0x27, 0x07, 0x67, 0x1b, 0x36, 0x1f, 0x9d, 0x27, 0x28, 0x0a, 0x59, 0xed, 0xaf, 0xd3, 0xb0, 0xcd, 0x99, 0xe4, 0xe3, 0xe7, 0xb4, 0xdf, 0xb4, 0xbe, 0xa8, 0x95, 0x13, 0x8e, 0xaf, 0x8f, 0xaf, 0x96, 0x8a, 0xaf, 0x3b, 0xb5, 0x9e, 0xd8, 0xa4, 0xe9, 0xe6, 0xcd, 0x4a, 0xa8, 0x32, 0xa8, 0x70, 0xbc, 0x83, 0xc6, 0xd3, 0xd3, 0xcc, 0xf4, 0xf1, 0xf9, 0xf9, 0xee, 0xc4, 0x05, 0x6d, 0x25, 0xf2, 0x41, 0x46, 0x62, 0xd6, 0x32, 0x36, 0x1b, 0xdd, 0x43, 0xbb, 0x4e, 0xb4, 0x47, 0xf1, 0x4b, 0x37, 0x45, 0xd1, 0x20, 0xe3, 0x20, 0xbf, 0x12, 0xc5, 0x00, 0xb6, 0xe7, 0x78, 0x01, 0xae, 0x20, 0x35, 0x17, 0xf3, 0x0f, 0xe4, 0xf8, 0x3f, 0xec, 0xda, 0xe1, 0xd4, 0xdc, 0x33, 0xc3, 0x48, 0xcf, 0x55, 0xdb, 0x15, 0xf1, 0x08, 0x10, 0x9c, 0x19, 0x34, 0x21, 0xe5, 0x23, 0xa1, 0x1c, 0x84, 0x1f, 0xd4, 0x1e, 0x20, 0xff, 0x24, 0x0d, 0x28, 0xf6, 0x4b, 0x0c, 0xa5, 0xf3, 0x39, 0xe6, 0xd8, 0xd6, 0x1e, 0xb2, 0x8e, 0xb5, 0xb4, 0xc6, 0x94, 0xe4, 0xd5, 0xef, 0xcb, 0x0d, 0x2f, 0x0e, 0xbc, 0x1f, 0xb3, 0x17, 0x5c, 0x19, 0xaf, 0x11, 0x68, 0x1f, 0xfa, 0x30, 0xe4, 0x22, 0x51, 0x18, 0x96, 0x14, 0x28, 0xfe, 0x08, 0xf7, 0xc4, 0xe5, 0x2f, 0xfb, 0xb8, 0xfd, 0x55, 0xfe, 0xa8, 0xf3, 0xa5, 0xd4, 0x0c, 0xdf, 0xb1, 0xe4, 0xbc, 0xeb, 0x15, 0xde, 0x86, 0xdf, 0x41, 0xe5, 0x4a, 0xe5, 0xe0, 0xd9, 0x99, 0xe5, 0x37, 0xf9, 0xc7, 0xff, 0x5c, 0x06, 0x0d, 0x1a, 0x73, 0x2e, 0x70, 0x30, 0x42, 0x2a, 0x61, 0x4c, 0xa5, 0x4a, 0xec, 0x40, 0xe9, 0x3e, 0x7a, 0x43, 0x12, 0x2c, 0xd3, 0x20, 0xab, 0x23, 0x89, 0x0e, 0xe0, 0xf6, 0x6b, 0xec, 0xee, 0xf7, 0xde, 0xf6, 0xcf, 0xf2, 0x39, 0xde, 0x10, 0xd0, 0xc7, 0xdd, 0xf9, 0xd5, 0xd7, 0xca, 0xde, 0xc9, 0xf1, 0xd8, 0x6e, 0xe8, 0x3f, 0xd9, 0x8d, 0xcb, 0x8c, 0xd2, 0x45, 0xd8, 0x3f, 0xd9, 0x52, 0xd3, 0x39, 0xd8, 0x31, 0xdf, 0xca, 0xe8, 0xfa, 0xf3, 0x97, 0x03, 0x3c, 0x14, 0xdf, 0x1a, 0xd8, 0x14, 0x15, 0x30, 0x90, 0x3c, 0xc8, 0x32, 0x80, 0x33, 0x55, 0x2d, 0xb9, 0x26, 0xc7, 0x21, 0x99, 0x2c, 0x8b, 0x24, 0x13, 0x18, 0x98, 0x08, 0x96, 0x0a, 0xef, 0x16, 0x2e, 0x0f, 0x92, 0x07, 0x0b, 0xf4, 0xc0, 0xe9, 0xcb, 0xec, 0xc5, 0xe1, 0xf3, 0xdb, 0x3b, 0xd3, 0xfe, 0xc7, 0x7d, 0xcc, 0x39, 0xd6, 0xa5, 0xdf, 0xf3, 0xf0, 0xf3, 0xf9, 0xb1, 0xff, 0x39, 0x0c, 0x5d, 0x0d, 0x4e, 0x00, 0xb2, 0xf5, 0x47, 0xf6, 0x0d, 0xfc, 0x99, 0x05, 0x60, 0x05, 0xd3, 0xff, 0x7f, 0xf1, 0x9a, 0xfa, 0x43, 0xfd, 0x75, 0xf9, 0x72, 0x00, 0xd6, 0x08, 0xd3, 0x10, 0xef, 0x17, 0x82, 0x1b, 0x7f, 0x09, 0xcb, 0x09, 0x81, 0x12, 0x79, 0x0f, 0xf3, 0x08, 0xd3, 0x0f, 0x2a, 0x0a, 0x3f, 0xfb, 0x31, 0xfa, 0x1d, 0x0d, 0x07, 0x14, 0x39, 0x12, 0x81, 0x0a, 0x09, 0x04, 0xd2, 0x0f, 0x2f, 0x06, 0x88, 0x07, 0xfe, 0xf7, 0xaa, 0xe8, 0x84, 0xea, 0x2f, 0xea, 0x09, 0xee, 0xd3, 0xef, 0xb6, 0xfb, 0x49, 0xf7, 0x7f, 0xf9, 0xb2, 0xfa, 0x94, 0xf8, 0x49, 0x00, 0x47, 0x0d, 0x8f, 0x07, 0x74, 0x06, 0x2b, 0x0a, 0x8b, 0x01, 0xff, 0xf8, 0xe6, 0xf8, 0xe3, 0xf9, 0x8e, 0xfe, 0xbd, 0xf9, 0xe6, 0xf0, 0x35, 0xef, 0x93, 0xee, 0xdf, 0xf0, 0x93, 0xf3, 0xec, 0xfb, 0xb9, 0x06, 0x36, 0x0a, 0xed, 0x0d, 0x4c, 0x14, 0x2c, 0x10, 0xe5, 0x0d, 0xc5, 0x0b, 0x30, 0x00, 0xb0, 0xf8, 0x33, 0x01, 0x0a, 0x09, 0xbe, 0x0d, 0x1c, 0x07, 0xcc, 0x04, 0x36, 0xff, 0xfd, 0xfb, 0x60, 0xf7, 0x81, 0xed, 0x9c, 0xee, 0x9c, 0xef, 0xf7, 0xf6, 0xb3, 0xf9, 0xe0, 0x02, 0xa8, 0xfe, 0x15, 0xf9, 0x83, 0xff, 0x9f, 0x08, 0x28, 0x08, 0xa5, 0x08, 0x75, 0x03, 0x98, 0xff, 0xb5, 0xfd, 0x9b, 0x03, 0xb9, 0x06, 0x6f, 0x0d, 0x16, 0x0a, 0xeb, 0x03, 0xd3, 0x0b, 0xce, 0x0a, 0x2e, 0x07, 0xa3, 0x0a, 0xfd, 0x03, 0xf9, 0x04, 0x44, 0x04, 0x0e, 0x02, 0x3b, 0xff, 0x68, 0xfc, 0x06, 0xfd, 0x0e, 0xf7, 0xea, 0xf2, 0x67, 0xf4, 0x0b, 0xfa, 0x4c, 0xfd, 0xbc, 0xff, 0x83, 0xfd, 0xd4, 0xf6, 0xe5, 0xf9, 0xbe, 0xfc, 0x63, 0xf8, 0x83, 0xfb, 0x0b, 0xfe, 0xea, 0xff, 0x20, 0xfe, 0xb2, 0xfd, 0x4e, 0xfb, 0x53, 0xfb, 0x0f, 0xfa, 0xfd, 0xf5, 0xd0, 0xf8, 0xd7, 0xf8, 0xbf, 0xf7, 0x83, 0xfd, 0x86, 0xfe, 0x0f, 0xff, 0x1b, 0xff, 0x07, 0x01, 0x99, 0x04, 0xb4, 0x03, 0x43, 0x01, 0x57, 0x01, 0x49, 0x06, 0xe9, 0x0a, 0x24, 0x0d, 0x03, 0x10, 0x05, 0x11, 0x4f, 0x0e, 0x5a, 0x0e, 0x6d, 0x0c, 0x3d, 0x09, 0xa6, 0x0a, 0x9e, 0x0b, 0xd3, 0x0b, 0x36, 0x0a, 0xbb, 0x05, 0x06, 0xfe, 0x36, 0xfc, 0x60, 0xfc, 0xe8, 0xfb, 0xc1, 0xfa, 0x42, 0xf7, 0xaf, 0xf6, 0xf2, 0xf2, 0xdc, 0xef, 0xbe, 0xee, 0x3a, 0xf4, 0x8a, 0xf6, 0x28, 0xf6, 0x45, 0xf8, 0xa2, 0xf6, 0x2f, 0xf5, 0x0b, 0xf7, 0xf5, 0xf7, 0x7c, 0xf8, 0x8c, 0xf8, 0xc0, 0xf7, 0x96, 0xf8, 0x74, 0xf8, 0x19, 0xfa, 0x3d, 0xfd, 0xc5, 0x00, 0x5a, 0x05, 0x7b, 0x08, 0x45, 0x0c, 0x0f, 0x0c, 0xc8, 0x08, 0xfd, 0x07, 0x31, 0x07, 0x87, 0x03, 0xa5, 0x03, 0x49, 0x06, 0x3b, 0x09, 0x31, 0x0b, 0x53, 0x09, 0xda, 0x08, 0xdd, 0x04, 0x51, 0x02, 0xde, 0xfe, 0xfd, 0xfd, 0xca, 0xfd, 0xe8, 0xff, 0x6b, 0xff, 0xf5, 0xfd, 0xb7, 0xff, 0x1d, 0xfd, 0x07, 0xfc, 0xbb, 0xfa, 0x00, 0xfc, 0xe9, 0xfc, 0x04, 0xfa, 0xb9, 0xf9, 0x0b, 0xfc, 0x1a, 0xfd, 0xd7, 0xfe, 0xa3, 0x01, 0x61, 0x04, 0xcb, 0x06, 0xd0, 0x06, 0x2b, 0x05, 0x92, 0x05, 0x98, 0x05, 0x32, 0x05, 0x95, 0x05, 0xfe, 0x05, 0x18, 0x03, 0xbf, 0xff, 0xc0, 0xfe, 0x98, 0xfd, 0xb1, 0xfb, 0xb3, 0xfa, 0xf5, 0xf9, 0x0d, 0xfb, 0xff, 0xfb, 0xa5, 0xfa, 0xa8, 0xfb, 0xc9, 0xfb, 0xaa, 0xfc, 0x2a, 0xfd, 0x3e, 0xfc, 0x50, 0xfd, 0x87, 0xfc, 0x58, 0xfd, 0xc7, 0xfe, 0x81, 0x01, 0x61, 0x00, 0x98, 0x01, 0xf1, 0x01, 0x17, 0xfe, 0x86, 0xfd, 0x1a, 0xff, 0xf4, 0xff, 0x33, 0x00, 0x54, 0x00, 0xd1, 0xff, 0xf2, 0xfe, 0x36, 0x00, 0xeb, 0xff, 0xbc, 0x01, 0xb2, 0x01, 0x3f, 0xff, 0x9c, 0xfe, 0x22, 0xfe, 0xf1, 0xfd, 0x82, 0xfd, 0x0d, 0xfe, 0xbf, 0xfd, 0x0e, 0xfd, 0xa3, 0xfe, 0x71, 0xfd, 0x73, 0xfd, 0x4c, 0xfd, 0x08, 0xfe, 0xa6, 0xff, 0x47, 0xfe, 0xd9, 0xfd, 0x6e, 0xfe, 0xbf, 0x00, 0x6c, 0x01, 0x48, 0x03, 0xbe, 0x04, 0x69, 0x07, 0xe4, 0x08, 0x65, 0x0a, 0xde, 0x0a, 0x5f, 0x0c, 0x12, 0x0d, 0x9c, 0x0c, 0x75, 0x0c, 0x87, 0x0b, 0xca, 0x08, 0x05, 0x07, 0x59, 0x04, 0x7e, 0x02, 0xb3, 0x01, 0xe8, 0xff, 0xc1, 0xff, 0xc2, 0xfe, 0x7a, 0xfd, 0x3b, 0xfc, 0x4d, 0xfc, 0x1a, 0xfb, 0xfb, 0xfa, 0x19, 0xfa, 0xf8, 0xf8, 0x46, 0xf8, 0xce, 0xf6, 0xf1, 0xf5, 0x3c, 0xf6, 0xa6, 0xf6, 0x84, 0xf6, 0xdc, 0xf7, 0x4d, 0xf7, 0xf9, 0xf6, 0x64, 0xf8, 0x11, 0xf8, 0x40, 0xf8, 0x07, 0xfa, 0x4d, 0xf9, 0xd8, 0xf9, 0xf9, 0xfa, 0xa3, 0xfc, 0x0c, 0xfe, 0xde, 0xfe, 0x7d, 0x00, 0x39, 0x02, 0x2a, 0x03, 0xc4, 0x02, 0xc3, 0x03, 0xbf, 0x03, 0x64, 0x04, 0xb7, 0x03, 0xf1, 0x03, 0x11, 0x03, 0x78, 0x06, 0x36, 0xc8, 0x93, 0x9c, 0x2c, 0xb5, 0x5b, 0xe6, 0xa4, 0x0b, 0x0b, 0x43, 0x49, 0x4d, 0x6d, 0x30, 0x8d, 0x03, 0x3e, 0x0e, 0x8d, 0xec, 0xf5, 0xd4, 0x9b, 0xde, 0xfb, 0x3f, 0xbe, 0x4e, 0x43, 0x2e, 0xb9, 0x4b, 0x46, 0x61, 0x29, 0x24, 0xd8, 0x47, 0x85, 0x42, 0xea, 0xec, 0xd5, 0xd5, 0xcf, 0x05, 0x40, 0x07, 0xa0, 0xe2, 0x90, 0xd5, 0x9c, 0xf2, 0xcd, 0xde, 0x7a, 0xb6, 0x25, 0xa6, 0xfa, 0xce, 0xcb, 0xe7, 0x53, 0xe9, 0x3f, 0xec, 0x98, 0xfe, 0x14, 0x02, 0xb5, 0xf5, 0x40, 0xf3, 0xba, 0x17, 0x19, 0x1a, 0x49, 0x26, 0xb8, 0x05, 0x11, 0xd6, 0x61, 0xce, 0x8b, 0xe5, 0xad, 0xfc, 0xeb, 0x01, 0xc7, 0xed, 0xdd, 0x00, 0xdc, 0x1c, 0xc7, 0x0b, 0x71, 0x01, 0x62, 0x03, 0x16, 0x0b, 0x8e, 0xf3, 0x5f, 0xfc, 0xcc, 0xf4, 0x88, 0x23, 0xa5, 0x23, 0xaf, 0x24, 0x4b, 0x02, 0x63, 0xed, 0x7d, 0xd0, 0x44, 0xd9, 0xdf, 0xfc, 0xfe, 0x0a, 0x23, 0x07, 0xe5, 0x0f, 0x7e, 0x28, 0xbf, 0x4b, 0x33, 0x46, 0x21, 0x25, 0x54, 0x19, 0x47, 0x4b, 0xee, 0x29, 0x55, 0x14, 0x89, 0xf5, 0xe3, 0xe6, 0x05, 0xbd, 0xec, 0xa9, 0x2b, 0xbb, 0xbb, 0xed, 0xb5, 0x0e, 0xaa, 0x06, 0x47, 0x1e, 0x04, 0x3e, 0xc0, 0x24, 0x98, 0x2a, 0x29, 0x1c, 0xf3, 0xf0, 0x0b, 0xd2, 0x03, 0xba, 0x8b, 0xc6, 0xa5, 0xc8, 0x65, 0xdb, 0x8b, 0xfc, 0x8d, 0xf9, 0x40, 0xe7, 0xc2, 0xfe, 0xcf, 0xff, 0x3b, 0xd2, 0xb7, 0xda, 0xbb, 0xdf, 0x87, 0x04, 0xcd, 0x02, 0xf4, 0x14, 0x60, 0x0b, 0x9f, 0xe1, 0x06, 0xf3, 0xb9, 0xff, 0x44, 0xf4, 0x6c, 0xfb, 0x46, 0x03, 0x3d, 0x21, 0x0c, 0x18, 0x51, 0x1b, 0x3e, 0x24, 0xfe, 0xf3, 0xe3, 0x04, 0x00, 0xef, 0x48, 0xe4, 0xdc, 0xe4, 0x5c, 0xea, 0x66, 0xf7, 0xdc, 0xfd, 0x01, 0x09, 0x53, 0x06, 0x90, 0xec, 0x9f, 0xfd, 0xa2, 0x0f, 0xda, 0x28, 0x67, 0x2d, 0x40, 0x2d, 0xbe, 0x12, 0x6a, 0x18, 0x64, 0x0e, 0x08, 0x0d, 0xa6, 0xfd, 0x2e, 0xfa, 0x18, 0x12, 0x3a, 0x1f, 0x41, 0x13, 0xf6, 0xfc, 0x59, 0x11, 0x51, 0x06, 0x73, 0xf8, 0xd0, 0xfb, 0xa5, 0xf8, 0xe3, 0xed, 0xe3, 0xed, 0x68, 0xf7, 0xc5, 0x05, 0x5b, 0x02, 0xdc, 0x00, 0x37, 0xe1, 0x42, 0xd3, 0x82, 0xeb, 0x56, 0xf5, 0x24, 0x0b, 0xc6, 0xfd, 0x29, 0xed, 0x24, 0xf3, 0x9e, 0xf3, 0x6f, 0xe5, 0xaf, 0xdc, 0x4c, 0xf2, 0x06, 0x07, 0x3d, 0x14, 0x21, 0x0b, 0x0f, 0x1d, 0x2f, 0x1c, 0x81, 0xfd, 0xc7, 0xf9, 0x49, 0x08, 0xd5, 0xff, 0x92, 0x0c, 0x5c, 0x08, 0x0f, 0x12, 0x51, 0x0f, 0xd8, 0x03, 0x51, 0x0d, 0x4f, 0xfb, 0x78, 0xee, 0xa2, 0xfa, 0x09, 0x16, 0x1f, 0x1f, 0x61, 0x2a, 0x8b, 0x17, 0x2e, 0x15, 0x96, 0x0d, 0x9a, 0x0d, 0x9c, 0xf9, 0x7c, 0xe8, 0x81, 0xed, 0x19, 0xdf, 0xfa, 0xdb, 0x07, 0xcf, 0x56, 0xdc, 0x88, 0xdd, 0x76, 0xe0, 0x43, 0xe7, 0x7c, 0xfe, 0x56, 0x08, 0xfe, 0x10, 0xe7, 0x1b, 0x74, 0x1d, 0xe5, 0x1b, 0x04, 0x30, 0xe4, 0x23, 0xb3, 0x17, 0xa6, 0x13, 0x5b, 0x0b, 0xd4, 0x04, 0x54, 0xfb, 0x35, 0x03, 0x71, 0x02, 0xd5, 0xf3, 0x83, 0xf3, 0x1f, 0xef, 0xbb, 0xe8, 0xfd, 0xe7, 0x95, 0xee, 0x2c, 0x00, 0x4b, 0x03, 0xcb, 0xf7, 0x79, 0xf7, 0x3b, 0xf8, 0x17, 0xf6, 0xb6, 0xf8, 0x4d, 0xf6, 0x62, 0xef, 0x1e, 0xf4, 0x4d, 0xef, 0xd7, 0xf5, 0x6c, 0xee, 0xd9, 0xe8, 0xaf, 0xe7, 0xaf, 0xf1, 0x28, 0xf6, 0x1e, 0xf5, 0xbf, 0xfe, 0xac, 0x06, 0xaf, 0x07, 0x99, 0x0b, 0x79, 0x08, 0xbd, 0x0b, 0x21, 0x12, 0x0a, 0x0c, 0x7c, 0x08, 0x88, 0x06, 0x64, 0x0d, 0xe6, 0x0e, 0xcf, 0x0c, 0x61, 0x16, 0x22, 0x19, 0x3b, 0x0d, 0x2e, 0x0e, 0x00, 0x18, 0x1b, 0x1c, 0x5f, 0x17, 0x74, 0x1b, 0x6f, 0x14, 0x97, 0x07, 0xf5, 0x02, 0xfe, 0x03, 0x1d, 0x06, 0x70, 0x02, 0xa7, 0xf9, 0xef, 0xeb, 0x72, 0xeb, 0xe5, 0xee, 0x08, 0xeb, 0x07, 0xec, 0x0b, 0xe5, 0x4f, 0xe3, 0x23, 0xe9, 0x0c, 0xe3, 0x67, 0xe5, 0x2f, 0xe4, 0x57, 0xe6, 0x42, 0xea, 0xd2, 0xe9, 0xe0, 0xf0, 0xe9, 0xf8, 0xa8, 0xfc, 0x1e, 0xff, 0x0b, 0x06, 0x8d, 0x05, 0xa9, 0x05, 0x82, 0x0d, 0x48, 0x10, 0xa0, 0x16, 0x05, 0x19, 0xe8, 0x13, 0xf8, 0x0e, 0x84, 0x0d, 0xc9, 0x13, 0x8a, 0x16, 0x1a, 0x17, 0x3c, 0x15, 0xb5, 0x11, 0x90, 0x08, 0x3b, 0x01, 0x84, 0x03, 0xea, 0x04, 0x04, 0x04, 0xf2, 0xfe, 0x72, 0xf7, 0xf8, 0xf9, 0xef, 0xf6, 0xc3, 0xf0, 0xd7, 0xf5, 0x19, 0xf8, 0x97, 0xfa, 0x10, 0xfa, 0x88, 0xf6, 0x14, 0xf7, 0x22, 0xf5, 0x1f, 0xf2, 0xde, 0xf5, 0x98, 0xf2, 0x1d, 0xf4, 0x19, 0xf9, 0xea, 0xfb, 0xd8, 0xff, 0x0f, 0xfe, 0xe7, 0x01, 0x41, 0x02, 0x2e, 0x02, 0x76, 0x04, 0x42, 0x01, 0xda, 0x00, 0x2f, 0x00, 0xeb, 0xff, 0x2b, 0x01, 0xc9, 0x04, 0x19, 0x02, 0x07, 0x02, 0xfe, 0x02, 0x10, 0x04, 0x1e, 0x05, 0x1b, 0x03, 0x8c, 0x06, 0xf5, 0x07, 0xf0, 0x06, 0x44, 0x07, 0xbc, 0x0a, 0x65, 0x0a, 0x91, 0x08, 0xae, 0x04, 0xf4, 0x00, 0xc3, 0xf8, 0x52, 0xf7, 0x45, 0xf7, 0x72, 0xff, 0x1e, 0x00, 0x65, 0x05, 0x83, 0xfe, 0x14, 0x05, 0x69, 0xf9, 0x62, 0x03, 0x4f, 0xf2, 0xb7, 0x4e, 0x95, 0x09, 0xc4, 0xae, 0x51, 0xd9, 0xbb, 0xb7, 0x02, 0xdd, 0x0d, 0xb3, 0x06, 0xe2, 0xec, 0x15, 0x8e, 0xe4, 0x7b, 0xb3, 0xfa, 0xb8, 0xf9, 0xdf, 0xc3, 0xdf, 0xc2, 0xe3, 0x2c, 0xe6, 0x0a, 0x07, 0x28, 0x14, 0x10, 0x03, 0xbb, 0x13, 0xd0, 0x3d, 0x25, 0x4a, 0xfb, 0x54, 0x7d, 0x60, 0x2c, 0x6a, 0x2f, 0x52, 0x1e, 0x48, 0xb9, 0x44, 0x42, 0x56, 0x9c, 0x66, 0xad, 0x62, 0x6a, 0x51, 0x29, 0x22, 0x85, 0x18, 0x10, 0x08, 0xcd, 0xed, 0x71, 0xc7, 0x4d, 0xcf, 0x41, 0xda, 0x57, 0xe2, 0x69, 0xd5, 0xda, 0xc3, 0xf9, 0xc8, 0x12, 0xcf, 0x15, 0x9e, 0xad, 0xb2, 0x46, 0xd6, 0x93, 0xe1, 0xbd, 0x02, 0xc2, 0x0e, 0x08, 0xed, 0xa3, 0xd4, 0x49, 0xd7, 0xd4, 0xf5, 0xc1, 0x02, 0x3a, 0xea, 0x19, 0xf9, 0x25, 0xc7, 0x6d, 0xc6, 0xc6, 0xe0, 0xa0, 0x1b, 0xf3, 0x2d, 0x81, 0x29, 0x26, 0x38, 0xbe, 0x3e, 0x9e, 0x2b, 0xdd, 0x30, 0x36, 0x26, 0x52, 0x0b, 0xd8, 0xfa, 0x5b, 0xe5, 0xf6, 0xd2, 0x3e, 0xc2, 0x24, 0xd1, 0xfa, 0xe7, 0x45, 0x0b, 0xf6, 0x2a, 0xa3, 0x18, 0xf3, 0x06, 0x23, 0x0c, 0x42, 0xf5, 0x24, 0xdb, 0x2a, 0xd3, 0x7a, 0xed, 0x4c, 0x0c, 0xc0, 0x17, 0xc5, 0x13, 0x69, 0xfe, 0x1f, 0x0c, 0x93, 0x10, 0x52, 0x15, 0xb8, 0x14, 0x85, 0xde, 0x71, 0xf4, 0x1e, 0x00, 0xbd, 0x03, 0xa8, 0xf2, 0x3f, 0xea, 0x9f, 0xf6, 0x05, 0xfd, 0xb5, 0x0e, 0x75, 0x2d, 0x63, 0x14, 0x00, 0x00, 0xca, 0xe0, 0x4a, 0xe2, 0x27, 0x0c, 0x00, 0xfe, 0xc0, 0xff, 0x1b, 0xd9, 0xc5, 0xe4, 0xe0, 0xf8, 0x6a, 0xfa, 0x42, 0x15, 0x12, 0x18, 0xf1, 0x08, 0x44, 0x30, 0xf5, 0x3a, 0xb9, 0x2f, 0x12, 0x3a, 0x04, 0x3a, 0xf3, 0x23, 0x76, 0x0b, 0x93, 0x09, 0xb5, 0x1a, 0x36, 0x1d, 0x14, 0x1c, 0x6f, 0xfe, 0x5f, 0xc2, 0xb3, 0xe7, 0x52, 0xfc, 0xdd, 0xf0, 0xfe, 0xf5, 0x79, 0xb4, 0x22, 0xc8, 0x43, 0xd5, 0x58, 0xc8, 0xbc, 0xc5, 0x11, 0xb3, 0xc7, 0xba, 0x5d, 0xce, 0xb5, 0xd9, 0xbf, 0xed, 0x80, 0xfa, 0xd9, 0xe1, 0x2c, 0xe9, 0x6e, 0x08, 0xe9, 0x08, 0x78, 0x18, 0xf6, 0x1c, 0xcc, 0x17, 0x52, 0x28, 0x0c, 0x36, 0x2b, 0x16, 0xc5, 0x1b, 0xa3, 0x45, 0x7a, 0x57, 0x7b, 0x55, 0xc0, 0x3d, 0xc3, 0x4c, 0xe7, 0x20, 0xf9, 0x09, 0x95, 0xff, 0x0e, 0x05, 0x5e, 0x0a, 0x76, 0x02, 0xbb, 0xf6, 0x13, 0x03, 0xd1, 0x16, 0x1c, 0x02, 0x66, 0x1e, 0xc9, 0x19, 0x7e, 0xea, 0x6a, 0xfe, 0x00, 0xfd, 0xb9, 0xdd, 0x86, 0xf0, 0x88, 0xef, 0x5a, 0xeb, 0x04, 0xbe, 0xc7, 0xd6, 0x5e, 0xfd, 0xf8, 0xd8, 0x90, 0xc4, 0xec, 0xb7, 0x4b, 0xc9, 0xf9, 0xc2, 0x8f, 0xb6, 0xab, 0xc8, 0x33, 0xdb, 0xa7, 0xe4, 0x4b, 0xdb, 0x6b, 0xdc, 0xf8, 0xe0, 0x89, 0xea, 0xe0, 0xfc, 0xe9, 0x15, 0xcf, 0x36, 0xb6, 0x4d, 0x05, 0x4a, 0x15, 0x5a, 0x35, 0x54, 0x1e, 0x4b, 0xe9, 0x40, 0x8e, 0x20, 0x72, 0x12, 0x4c, 0xf2, 0xcb, 0xd9, 0x02, 0xf2, 0x40, 0xf5, 0xfe, 0x0e, 0x11, 0x1e, 0x7b, 0x18, 0xe6, 0xfb, 0x30, 0x0c, 0x08, 0x0a, 0x14, 0x04, 0x57, 0xf0, 0xec, 0xb9, 0x98, 0xba, 0x7b, 0xd4, 0x6d, 0xda, 0xe6, 0xf1, 0xe5, 0x04, 0x9e, 0x32, 0xdf, 0x29, 0xe1, 0x12, 0x77, 0x0e, 0xdc, 0x06, 0x88, 0x03, 0x2f, 0x08, 0x5e, 0xf6, 0xc6, 0xfc, 0x86, 0xfd, 0x9c, 0x06, 0x1c, 0xf3, 0x07, 0xd8, 0x1d, 0xfa, 0x4e, 0x04, 0x19, 0xef, 0x4b, 0xfd, 0x1e, 0x08, 0xa1, 0xda, 0x53, 0xce, 0x2c, 0xe3, 0x70, 0x19, 0xe8, 0x20, 0x61, 0x23, 0x55, 0xf7, 0x1f, 0xf5, 0x0b, 0x0b, 0x6e, 0x0a, 0x82, 0x20, 0xb5, 0x29, 0x62, 0x10, 0x1f, 0xf8, 0x2d, 0x19, 0x92, 0x1e, 0x91, 0xf8, 0xc7, 0xff, 0xdf, 0xfd, 0x8f, 0xf5, 0x3e, 0x02, 0x63, 0x00, 0x86, 0xf2, 0xe2, 0xbc, 0x11, 0xe1, 0x32, 0xdb, 0xaf, 0xd5, 0x7a, 0xbf, 0x90, 0xbf, 0x96, 0xde, 0x64, 0xf6, 0xb6, 0xef, 0xe9, 0x04, 0xec, 0x13, 0xd1, 0x06, 0x8b, 0x00, 0x23, 0x09, 0x75, 0xfb, 0x48, 0x15, 0xf3, 0x27, 0x42, 0x19, 0x59, 0x35, 0x25, 0x3f, 0xca, 0x4a, 0xdd, 0x20, 0x4a, 0x19, 0xd8, 0x10, 0x86, 0xf1, 0xd4, 0xcf, 0xbd, 0xda, 0x77, 0xef, 0x9f, 0xf9, 0x10, 0xfa, 0x84, 0xeb, 0x41, 0xf9, 0x15, 0x0f, 0x30, 0x0c, 0xe4, 0x01, 0x49, 0xf8, 0xdb, 0x2c, 0x78, 0x32, 0x7b, 0x31, 0x26, 0x21, 0xbe, 0x1d, 0x86, 0x1d, 0x60, 0x0d, 0x4c, 0x09, 0x66, 0xf7, 0xf5, 0xda, 0x40, 0xe2, 0xee, 0xed, 0xa2, 0xf6, 0x09, 0x0e, 0xaf, 0x16, 0x0f, 0x0e, 0x21, 0x1d, 0x4b, 0x09, 0x4d, 0xf3, 0xbc, 0xe4, 0xc8, 0xd7, 0xc0, 0xe7, 0x24, 0xd7, 0xab, 0xca, 0xfd, 0xbf, 0x27, 0xd2, 0x5c, 0xe1, 0x99, 0xe1, 0x5e, 0xd9, 0xd2, 0xfd, 0x7d, 0x06, 0x4d, 0xfc, 0xab, 0xe5, 0xbb, 0xff, 0x7a, 0x0f, 0x38, 0x13, 0xd9, 0x0b, 0xf0, 0xf7, 0x18, 0xe1, 0xf3, 0xd7, 0x30, 0xdf, 0x02, 0xec, 0x69, 0x06, 0x75, 0x22, 0x6a, 0x3a, 0x19, 0x55, 0x75, 0x43, 0x9c, 0x2c, 0x4d, 0x1c, 0x58, 0x19, 0xcf, 0x0b, 0x61, 0x12, 0xe6, 0x14, 0x5b, 0x0a, 0xc4, 0x10, 0x9d, 0x0b, 0x29, 0x17, 0x4a, 0x25, 0xf2, 0x11, 0x21, 0xf6, 0x39, 0xf5, 0x6e, 0xe0, 0x47, 0xca, 0x44, 0xce, 0x9f, 0xd7, 0x14, 0xe2, 0x9b, 0xf2, 0x5e, 0x17, 0x3e, 0x18, 0x45, 0xe1, 0x2e, 0xed, 0xcb, 0xf5, 0x9f, 0xda, 0xe8, 0xcd, 0x8d, 0xce, 0xe7, 0xdb, 0x81, 0xda, 0xcc, 0xec, 0x92, 0x01, 0xa0, 0x05, 0xb4, 0xfe, 0x49, 0xfc, 0x89, 0xf6, 0x37, 0x03, 0xdb, 0x08, 0xaf, 0x19, 0x43, 0x2e, 0x63, 0x14, 0x3c, 0xf8, 0x90, 0x0b, 0x53, 0x32, 0xba, 0x3d, 0x68, 0x3a, 0xa6, 0x17, 0x91, 0xf7, 0xb2, 0x02, 0xd6, 0xfe, 0xed, 0xed, 0x33, 0xf3, 0xc7, 0xd7, 0xbf, 0xee, 0xd1, 0xe6, 0xb9, 0xda, 0x9b, 0xe2, 0x61, 0xe9, 0x65, 0xfe, 0xe0, 0x19, 0xb0, 0x14, 0x23, 0x10, 0xd9, 0x25, 0xe7, 0x2e, 0x8e, 0x37, 0x4e, 0x14, 0xab, 0x10, 0xb3, 0xfa, 0x77, 0xec, 0x2f, 0xdd, 0x6d, 0xf1, 0x6f, 0x01, 0xa6, 0xff, 0xa8, 0x01, 0xbb, 0xfe, 0x75, 0xfe, 0x20, 0xed, 0xd7, 0xd7, 0x43, 0xe4, 0x91, 0xe9, 0x4b, 0xf6, 0x39, 0x06, 0xd5, 0x12, 0x72, 0x17, 0x40, 0x18, 0x8d, 0x0f, 0xa1, 0x1d, 0x6e, 0x1e, 0x53, 0x0f, 0xd4, 0x08, 0xcc, 0x0e, 0x4f, 0x1d, 0x4f, 0x20, 0xd3, 0x17, 0x75, 0x19, 0x3d, 0x1c, 0x6f, 0x22, 0x15, 0x16, 0x24, 0x02, 0x77, 0x02, 0x75, 0xfd, 0x94, 0xf1, 0x62, 0xe1, 0x02, 0xf7, 0xb4, 0xf1, 0xd6, 0xe3, 0xc5, 0xe0, 0xa3, 0xd5, 0x2f, 0xcc, 0xeb, 0xea, 0xce, 0xf9, 0xed, 0xf4, 0xe6, 0x04, 0xea, 0x00, 0x72, 0xf6, 0xc9, 0xf3, 0xad, 0xf8, 0xe0, 0xf2, 0x6f, 0xfd, 0xfc, 0x01, 0x5e, 0xeb, 0xd2, 0xd8, 0x8a, 0xd6, 0x45, 0xde, 0x18, 0xc9, 0xbc, 0xcb, 0xd4, 0xe3, 0x81, 0x0f, 0x6a, 0x14, 0xf3, 0x2f, 0xc4, 0x41, 0xce, 0x1c, 0xad, 0x20, 0x5c, 0x2f, 0x43, 0x15, 0xea, 0x16, 0xbf, 0x0f, 0x4b, 0x0b, 0x0c, 0xf4, 0xfd, 0xf1, 0x08, 0x0f, 0xd9, 0x00, 0xf6, 0xe7, 0xe4, 0xde, 0xc0, 0xe4, 0x48, 0xf0, 0x95, 0xeb, 0x56, 0x02, 0x38, 0x05, 0xda, 0xfa, 0x5f, 0xfb, 0x5f, 0xf7, 0x02, 0xda, 0xcc, 0xe4, 0xf5, 0xe8, 0x2f, 0x0a, 0x36, 0x09, 0x86, 0x06, 0xf2, 0x1b, 0x1d, 0x03, 0xe8, 0xfd, 0xa5, 0xfc, 0x76, 0xf9, 0x2e, 0x05, 0x65, 0x22, 0xca, 0x35, 0x10, 0x43, 0x4d, 0x36, 0xab, 0x19, 0xdb, 0x03, 0x00, 0x19, 0xdd, 0x09, 0x47, 0xf9, 0x45, 0xe7, 0x2c, 0xd5, 0x19, 0xcd, 0x62, 0xca, 0x68, 0xdc, 0xf8, 0xf9, 0xa7, 0xfe, 0xf1, 0xfc, 0x4d, 0x0b, 0x29, 0xfd, 0xf1, 0x04, 0xba, 0x14, 0x1b, 0x22, 0x5c, 0x16, 0x31, 0x03, 0x99, 0xfa, 0x3e, 0xec, 0x19, 0xf1, 0x28, 0xeb, 0xc3, 0xe2, 0x04, 0xde, 0xba, 0xe5, 0x2d, 0xe7, 0x49, 0xec, 0x1e, 0xdc, 0x20, 0xd8, 0x46, 0xe7, 0xd5, 0xf2, 0xa5, 0xfa, 0xde, 0x08, 0xd9, 0x11, 0x0f, 0x1d, 0x6d, 0x22, 0xdb, 0x23, 0x50, 0x26, 0x64, 0x37, 0x3b, 0x4f, 0x76, 0x52, 0xa0, 0x5d, 0x0a, 0x4e, 0xa5, 0x34, 0xb0, 0x2e, 0x78, 0x36, 0x81, 0x26, 0x3d, 0x17, 0x01, 0x15, 0x60, 0x10, 0x9f, 0x06, 0x33, 0xfa, 0x58, 0xf9, 0xde, 0xe2, 0xd8, 0xc6, 0xbb, 0xcc, 0x49, 0xdd, 0x60, 0xdc, 0xc2, 0xeb, 0x22, 0xdf, 0x2a, 0xd2, 0xea, 0xd8, 0xc5, 0xd7, 0x68, 0xc6, 0xb4, 0xba, 0xda, 0xc8, 0x7a, 0xed, 0xe8, 0xe2, 0x65, 0xe1, 0x39, 0xda, 0x28, 0xdd, 0xe8, 0xdd, 0x33, 0xcf, 0xc7, 0xdd, 0x42, 0xe4, 0x7f, 0xe9, 0xcd, 0xf3, 0xcd, 0x08, 0xda, 0x0f, 0xe1, 0x13, 0xac, 0x22, 0x60, 0x1d, 0x71, 0x1d, 0xbd, 0x17, 0x11, 0x01, 0x79, 0xf9, 0x7a, 0x00, 0x7a, 0x13, 0x1d, 0x23, 0xe8, 0x3c, 0xfb, 0x43, 0xfb, 0x27, 0xf7, 0x29, 0xa2, 0x38, 0xaa, 0x30, 0xd5, 0x26, 0x9f, 0x07, 0xfb, 0x0b, 0x8d, 0x1e, 0xac, 0x19, 0x3d, 0x10, 0x94, 0x16, 0x08, 0x15, 0x5e, 0x11, 0xef, 0x03, 0xdf, 0xf9, 0xed, 0xeb, 0x5e, 0xea, 0x72, 0xe3, 0x61, 0xce, 0x8f, 0xd2, 0x69, 0xd2, 0xa6, 0xd1, 0x84, 0xdb, 0xb3, 0xee, 0xb5, 0xdf, 0x9b, 0xda, 0x0d, 0xdc, 0x18, 0xc9, 0x72, 0xc5, 0x7a, 0xdb, 0x9b, 0xe8, 0xbc, 0xfa, 0xa1, 0x06, 0x8a, 0x0b, 0xd5, 0x03, 0x50, 0x0c, 0xa0, 0x23, 0xe7, 0x26, 0xf2, 0x1d, 0xfb, 0x12, 0x62, 0x07, 0xde, 0x09, 0xda, 0x0f, 0xe4, 0x19, 0x2c, 0x18, 0xb0, 0x05, 0xa9, 0x07, 0x4f, 0x1c, 0x93, 0x00, 0x1d, 0xf6, 0xf9, 0xfc, 0x9b, 0x02, 0x98, 0xf7, 0x33, 0xfa, 0x27, 0xf9, 0x31, 0xf5, 0x5e, 0xf0, 0x18, 0xe7, 0x50, 0xed, 0x20, 0xf3, 0xa7, 0xfe, 0x88, 0x07, 0x68, 0xfb, 0x1b, 0xf5, 0xaa, 0xfa, 0xda, 0x0b, 0xd3, 0x13, 0xb9, 0x27, 0x02, 0x29, 0xe5, 0x18, 0x85, 0x17, 0xb7, 0x0f, 0x39, 0x00, 0xe2, 0x07, 0x1f, 0xf8, 0x35, 0xee, 0x83, 0xf6, 0xd8, 0xf3, 0x94, 0xeb, 0xe3, 0xd2, 0xb5, 0xeb, 0xe1, 0xf0, 0xad, 0xe0, 0x9e, 0xe7, 0x87, 0xec, 0x59, 0xf8, 0x09, 0xfa, 0xa4, 0xfd, 0xf0, 0xfe, 0xc8, 0x07, 0xea, 0x13, 0xc6, 0x0d, 0x3f, 0x1b, 0x24, 0x17, 0x39, 0x07, 0x58, 0xfb, 0xb3, 0x05, 0x20, 0x10, 0x5f, 0x17, 0xc7, 0x25, 0xb6, 0x19, 0xd4, 0x2e, 0x14, 0x26, 0xd3, 0x0b, 0x44, 0x08, 0x10, 0xfc, 0x42, 0xfd, 0x24, 0xf5, 0xce, 0xe7, 0xfd, 0xf1, 0x81, 0xe1, 0x80, 0xda, 0x38, 0xe6, 0x48, 0xf9, 0x26, 0x0a, 0x78, 0x1f, 0xaf, 0x14, 0x88, 0x19, 0xe7, 0x2e, 0x99, 0x1a, 0x51, 0x0e, 0x5b, 0xfd, 0x9c, 0xf7, 0xc9, 0xec, 0x90, 0xf5, 0xaf, 0xf3, 0xb1, 0xec, 0x28, 0xf8, 0xbf, 0xeb, 0xb4, 0xf5, 0xcf, 0xf2, 0xca, 0xd5, 0xd9, 0xe5, 0xa8, 0xe4, 0x8b, 0xde, 0x9c, 0xea, 0x77, 0xf1, 0xa7, 0xe5, 0x46, 0xf1, 0x56, 0xfa, 0x10, 0x03, 0x35, 0x13, 0x30, 0x00, 0x6c, 0x01, 0x68, 0xf3, 0x61, 0xe5, 0xf2, 0xd7, 0x72, 0xe7, 0x82, 0xf6, 0xa6, 0x04, 0x36, 0x10, 0xa9, 0x1b, 0x21, 0x17, 0x93, 0x0a, 0x2a, 0x13, 0xca, 0x1a, 0xde, 0x0f, 0xf1, 0x0c, 0x8c, 0x01, 0x62, 0x17, 0x0d, 0x17, 0x44, 0x18, 0x45, 0x16, 0x08, 0x09, 0x13, 0x03, 0x4f, 0x07, 0x4d, 0x0b, 0x1c, 0x1b, 0x3a, 0x27, 0x38, 0x1b, 0x34, 0x1f, 0xc8, 0x1b, 0x0a, 0x0c, 0xad, 0xf0, 0x0b, 0xfd, 0x47, 0xf9, 0x05, 0xf5, 0x2d, 0xe1, 0x44, 0xdc, 0x7c, 0xe1, 0x31, 0xe1, 0x84, 0xda, 0x48, 0xd8, 0xe9, 0xef, 0x25, 0xfc, 0xb8, 0x02, 0x61, 0xff, 0x21, 0xff, 0x92, 0xf8, 0x51, 0xf8, 0xa5, 0xed, 0xbe, 0xec, 0x79, 0xe7, 0xd0, 0xec, 0xe1, 0xf4, 0xc4, 0xf2, 0x4b, 0x01, 0xda, 0x03, 0x2a, 0xfd, 0xb2, 0x0b, 0x30, 0x14, 0xba, 0x21, 0x9f, 0x33, 0x9d, 0x1d, 0x07, 0x21, 0xc4, 0x14, 0x01, 0x08, 0xb3, 0xf5, 0x66, 0x00, 0x03, 0x07, 0x77, 0x0f, 0x03, 0x15, 0xda, 0xfb, 0xf5, 0xee, 0xfb, 0xf9, 0x1c, 0xf7, 0xb0, 0xfa, 0xab, 0xec, 0xa6, 0xec, 0xd7, 0xf0, 0x0d, 0xf6, 0xe3, 0xf0, 0x8d, 0xf9, 0x89, 0xfb, 0xa6, 0xf9, 0x0c, 0x07, 0xd6, 0xf9, 0x30, 0xed, 0x1c, 0xe9, 0x57, 0xfc, 0xef, 0xfb, 0x67, 0xff, 0x32, 0x03, 0x48, 0xfc, 0x17, 0xfb, 0x1f, 0x05, 0x29, 0x10, 0x9e, 0x1f, 0xdc, 0x2c, 0x48, 0x26, 0x74, 0x1f, 0xb1, 0x2b, 0xa7, 0x20, 0x60, 0x0e, 0x1f, 0x04, 0x62, 0x00, 0x2b, 0xff, 0xe8, 0xfb, 0xb3, 0xf8, 0xe2, 0xf7, 0xd4, 0xfa, 0xb3, 0xfe, 0x24, 0xf8, 0xfe, 0xdc, 0x81, 0xd2, 0xbf, 0xdd, 0xe5, 0xe2, 0xe0, 0xe4, 0xf1, 0xe9, 0xb6, 0xeb, 0x75, 0xec, 0x08, 0xfb, 0xd8, 0xfa, 0x25, 0xf8, 0x72, 0xfa, 0xa4, 0xfa, 0x29, 0xfe, 0xb2, 0x05, 0x62, 0x05, 0x34, 0xff, 0x77, 0x02, 0xc6, 0x07, 0x7b, 0xfd, 0xcb, 0xf3, 0x3a, 0xfc, 0x03, 0x00, 0x2f, 0x06, 0x17, 0x09, 0xbe, 0x0d, 0xa9, 0x09, 0x23, 0x06, 0x0f, 0x0f, 0xe5, 0x1d, 0xf5, 0x21, 0x29, 0x24, 0xf2, 0x25, 0xa3, 0x13, 0xb0, 0x14, 0x1a, 0x17, 0x50, 0x12, 0x44, 0x18, 0x32, 0x14, 0x3f, 0x11, 0xa6, 0x01, 0xeb, 0xf9, 0x2b, 0xef, 0xbc, 0xf4, 0x5f, 0xfd, 0x81, 0xf3, 0x00, 0xe6, 0xac, 0xdf, 0x99, 0xe4, 0xb3, 0xe7, 0xa4, 0xdf, 0x3a, 0xd1, 0x33, 0xd5, 0xa7, 0xdc, 0xe1, 0xdf, 0x2c, 0xe7, 0xac, 0xef, 0x9e, 0xf1, 0x16, 0x02, 0xa4, 0xff, 0x29, 0xff, 0x67, 0x04, 0xbb, 0xf6, 0xdc, 0xf8, 0xea, 0x0a, 0x90, 0x0f, 0x12, 0x09, 0x26, 0x17, 0x66, 0x1b, 0x85, 0x18, 0xbb, 0x1d, 0x32, 0x10, 0x9b, 0xf9, 0xd1, 0xfe, 0xd2, 0xf9, 0xd5, 0xf9, 0x7a, 0x01, 0x00, 0x08, 0x99, 0x0b, 0xb6, 0xfd, 0x80, 0xff, 0x63, 0x03, 0x67, 0x0b, 0x09, 0x0b, 0x79, 0x08, 0x5f, 0x05, 0xbc, 0x0a, 0xea, 0x11, 0x18, 0x0f, 0xcf, 0x05, 0xc4, 0xf9, 0x42, 0xf1, 0x0c, 0xef, 0x00, 0xe9, 0x6b, 0xe1, 0x4a, 0xec, 0xdf, 0xf1, 0x8f, 0xfd, 0x42, 0xff, 0xf0, 0xf5, 0x8b, 0xe8, 0xb5, 0xee, 0x49, 0xf0, 0x64, 0xef, 0xdb, 0xfa, 0xed, 0xfa, 0xcb, 0x0b, 0x4c, 0x07, 0x93, 0x03, 0xf2, 0x01, 0x01, 0x06, 0xf8, 0x10, 0x3e, 0x1f, 0xb1, 0x1c, 0x3c, 0x1d, 0xf0, 0x1d, 0x9b, 0x20, 0x32, 0x20, 0x12, 0x19, 0x80, 0x14, 0x65, 0x0a, 0x1e, 0x02, 0xd3, 0xf6, 0x6d, 0xed, 0xd0, 0xf4, 0x59, 0xf9, 0x9d, 0x01, 0x24, 0x08, 0xf2, 0xfd, 0x06, 0xf6, 0xc4, 0xfa, 0x7a, 0xf8, 0x4a, 0xf2, 0xfb, 0xf0, 0xda, 0xec, 0x69, 0xf7, 0xa2, 0xf8, 0x94, 0x03, 0xa7, 0x0d, 0x60, 0x0a, 0xd9, 0x0a, 0x5b, 0x0c, 0xaf, 0x11, 0x60, 0x18, 0xaf, 0x14, 0x9e, 0x0c, 0xac, 0x0e, 0xa6, 0x08, 0xbc, 0x02, 0x03, 0xf9, 0x34, 0xff, 0x36, 0xf6, 0x87, 0xf8, 0xc0, 0xf5, 0x1b, 0xec, 0x92, 0xf0, 0x79, 0xe1, 0x5d, 0xdf, 0x91, 0xe3, 0x79, 0xda, 0x4a, 0xdf, 0xcd, 0xe8, 0xc4, 0xf6, 0x5a, 0x01, 0xf8, 0x01, 0xf6, 0xff, 0xcd, 0xfe, 0x23, 0x03, 0xb7, 0xf4, 0xdf, 0xfb, 0x76, 0x04, 0x56, 0x06, 0x4a, 0x09, 0xc1, 0xfe, 0xf0, 0x06, 0x14, 0xfe, 0xd4, 0xf6, 0x73, 0xfa, 0x47, 0x02, 0x34, 0x09, 0xae, 0x15, 0x36, 0x16, 0x33, 0x1f, 0xde, 0x1d, 0x8b, 0x24, 0x9b, 0x1d, 0x10, 0x14, 0x8d, 0x15, 0x8f, 0x0f, 0xa0, 0x0b, 0xc5, 0x0b, 0x2b, 0x02, 0x91, 0x03, 0x3e, 0x01, 0x90, 0xf6, 0x86, 0xf9, 0xcf, 0xfd, 0xdd, 0xf7, 0xd9, 0xee, 0xd6, 0xf0, 0xc5, 0xee, 0xc6, 0xe6, 0xf6, 0xf0, 0x8e, 0xf9, 0xc0, 0xf6, 0x02, 0xf3, 0xa9, 0xf1, 0xe5, 0xe8, 0x64, 0xe7, 0x28, 0xe9, 0x2c, 0xe2, 0xa0, 0xed, 0xcf, 0xed, 0x79, 0xe8, 0xef, 0xea, 0xae, 0xf4, 0x07, 0xf8, 0x63, 0xf9, 0xaa, 0xf3, 0xf9, 0xf7, 0x65, 0xfa, 0x70, 0xfc, 0xc5, 0x02, 0xd5, 0x09, 0xcb, 0x13, 0x05, 0x1a, 0xfc, 0x15, 0x30, 0x1f, 0x85, 0x2b, 0x1f, 0x25, 0xf5, 0x23, 0xee, 0x2d, 0x3d, 0x3d, 0x70, 0x35, 0x52, 0x31, 0xc9, 0x28, 0xe7, 0x18, 0x71, 0x0e, 0x95, 0x05, 0x16, 0x05, 0x72, 0xfb, 0x56, 0xf7, 0xda, 0xf6, 0xb9, 0xe9, 0x34, 0xe6, 0xe6, 0xed, 0x7f, 0xf4, 0x30, 0xf8, 0x50, 0xf4, 0xda, 0xeb, 0x73, 0xe7, 0xe9, 0xe0, 0x45, 0xe0, 0xba, 0xdf, 0xb2, 0xdf, 0x4d, 0xe7, 0x02, 0xec, 0x68, 0xe2, 0x98, 0xdc, 0x24, 0xe4, 0x8b, 0xe2, 0xb4, 0xe6, 0x2d, 0xed, 0x4c, 0xf6, 0x32, 0xfa, 0x3f, 0xfd, 0x3b, 0x02, 0x43, 0x12, 0xcd, 0x1b, 0xb1, 0x15, 0x9a, 0x13, 0x02, 0x0f, 0xb4, 0x11, 0x5b, 0x14, 0xb7, 0x17, 0xb8, 0x0f, 0x97, 0x07, 0xe5, 0x01, 0x1b, 0xff, 0x4a, 0x06, 0xfa, 0x03, 0x42, 0x01, 0x0e, 0xf8, 0x0f, 0xfd, 0x71, 0xff, 0x7b, 0xfc, 0x0f, 0x03, 0x8b, 0x03, 0xa8, 0xf8, 0xda, 0x05, 0xf8, 0x05, 0xe1, 0xfb, 0x80, 0xff, 0x1d, 0x08, 0x4b, 0x16, 0xc5, 0x12, 0xfa, 0x0f, 0x0d, 0xff, 0x80, 0xf1, 0x25, 0xf2, 0xad, 0xee, 0xe7, 0xf4, 0xe4, 0xf4, 0xa7, 0xfb, 0x4c, 0xf2, 0xf5, 0xf7, 0x9a, 0xfc, 0xff, 0x01, 0xa6, 0x03, 0x70, 0x0a, 0x40, 0x09, 0xec, 0x04, 0xa2, 0x03, 0x15, 0xf8, 0x9a, 0xfa, 0xa7, 0xfd, 0xb6, 0x07, 0x25, 0x0d, 0xc1, 0x05, 0x3e, 0xff, 0xb3, 0xfc, 0x48, 0xfa, 0x38, 0xf9, 0x17, 0xf8, 0xf7, 0xf2, 0x72, 0xf9, 0x93, 0x03, 0x5d, 0x08, 0x1c, 0x00, 0xe2, 0x06, 0xc5, 0x10, 0xf7, 0x0b, 0x6c, 0x07, 0x89, 0xfd, 0x44, 0xf4, 0x3a, 0xf6, 0x3b, 0xf9, 0x97, 0xf4, 0x70, 0xff, 0xa2, 0xf5, 0x36, 0xf3, 0xd1, 0xf9, 0xaa, 0xf6, 0x99, 0xf1, 0x21, 0xf8, 0xba, 0xfa, 0xdf, 0x09, 0xf6, 0x0c, 0x18, 0x0f, 0xef, 0x08, 0x93, 0x03, 0x23, 0x0b, 0x06, 0x09, 0x0a, 0x0c, 0x27, 0xfd, 0x6a, 0xf6, 0xbb, 0xf6, 0xc3, 0xf7, 0xc7, 0xf5, 0xdf, 0xfb, 0x2a, 0x08, 0x07, 0x11, 0x37, 0x11, 0x43, 0x1c, 0x6b, 0x1c, 0x4b, 0x15, 0xee, 0x13, 0x32, 0x10, 0x58, 0x14, 0xc2, 0x05, 0xea, 0x02, 0xf6, 0xf8, 0x99, 0xf3, 0xe7, 0xf6, 0x04, 0xf1, 0xb3, 0xf8, 0xa3, 0xf1, 0x22, 0xeb, 0x45, 0xf4, 0x04, 0xf7, 0x71, 0xf5, 0x60, 0xfd, 0xf7, 0x00, 0x86, 0x01, 0x71, 0x00, 0xa3, 0x05, 0x1d, 0x09, 0xa3, 0x01, 0x98, 0xf8, 0xcc, 0xfd, 0xe7, 0xfc, 0xf0, 0xf3, 0xdf, 0xf5, 0xa8, 0xfb, 0xdc, 0xf8, 0x4b, 0xf6, 0x42, 0xf6, 0x46, 0x02, 0xd4, 0x04, 0x21, 0x03, 0xdd, 0xfc, 0x65, 0xf4, 0x55, 0xec, 0x4a, 0xeb, 0xb3, 0xee, 0xb2, 0xf6, 0x3a, 0x02, 0xad, 0x01, 0x39, 0x02, 0xa1, 0x06, 0x26, 0x0b, 0xdb, 0x06, 0xef, 0x01, 0xec, 0xfa, 0x8e, 0xf7, 0xcf, 0xf6, 0xaa, 0xff, 0xf6, 0x03, 0x20, 0x10, 0x18, 0x0d, 0x03, 0x0b, 0x6a, 0x14, 0x0c, 0x10, 0x4f, 0x0d, 0x4a, 0x10, 0xbf, 0x09, 0xa3, 0x0f, 0xc1, 0x10, 0x4f, 0x10, 0x1f, 0x06, 0xb6, 0xfe, 0xcc, 0xff, 0x68, 0xec, 0x81, 0xe3, 0xa0, 0xe7, 0xed, 0xf4, 0xd6, 0xfa, 0xa8, 0xff, 0xa2, 0xf7, 0xf1, 0xf2, 0xb2, 0xfb, 0x1f, 0xf6, 0xbf, 0xec, 0xe9, 0xe8, 0x0b, 0xf2, 0x78, 0xf6, 0xd2, 0xf6, 0x8f, 0xf9, 0xe2, 0xf9, 0x4c, 0xfb, 0xaa, 0xff, 0x5c, 0x04, 0x4f, 0x0b, 0x0f, 0x13, 0x2b, 0x13, 0x7f, 0x17, 0x01, 0x23, 0x66, 0x1d, 0x03, 0x1c, 0x80, 0x22, 0x62, 0x1b, 0x3e, 0x16, 0xc0, 0x0e, 0xb0, 0x18, 0xab, 0x14, 0x00, 0x0e, 0x03, 0x05, 0xc5, 0x01, 0xfb, 0x02, 0x5f, 0xfc, 0x48, 0xfc, 0x5c, 0xf7, 0xeb, 0xfb, 0x04, 0xfb, 0xb9, 0xf6, 0x3c, 0xef, 0x3b, 0xec, 0x25, 0xed, 0xb1, 0xe2, 0x5d, 0xe3, 0x8f, 0xdc, 0x9d, 0xe3, 0x91, 0xe2, 0x72, 0xe3, 0x03, 0xe9, 0x1e, 0xf2, 0x76, 0xf7, 0xef, 0xfc, 0x50, 0x03, 0x24, 0x11, 0x7e, 0x14, 0x5e, 0x15, 0xb2, 0x1f, 0x31, 0x22, 0x89, 0x18, 0x95, 0x1e, 0xef, 0x1f, 0x75, 0x15, 0x41, 0x11, 0xa0, 0x09, 0x3b, 0x02, 0x12, 0xfa, 0x3c, 0xfa, 0x7f, 0xf3, 0x2c, 0xf2, 0xf4, 0xf1, 0xd7, 0xe8, 0x75, 0xe0, 0xff, 0xe0, 0x5e, 0xe6, 0x1e, 0xe5, 0xc6, 0xde, 0xe0, 0xe0, 0x6c, 0xe4, 0x81, 0xe7, 0xbf, 0xea, 0x92, 0xf5, 0x52, 0xf8, 0x47, 0xfc, 0x03, 0x00, 0x9a, 0xf7, 0x72, 0xf5, 0xae, 0xfe, 0xc1, 0x08, 0x29, 0x13, 0x77, 0x1b, 0x9d, 0x13, 0xc9, 0x06, 0x4f, 0x0d, 0x08, 0x11, 0x3d, 0x0d, 0x10, 0x0e, 0x5f, 0x00, 0xd4, 0xf7, 0x0c, 0xf8, 0xa5, 0xf9, 0x0f, 0xfa, 0xbd, 0xf6, 0xa3, 0xfa, 0x7d, 0x02, 0xd1, 0x01, 0xf5, 0xfa, 0x95, 0xf5, 0x0f, 0xff, 0x7f, 0x03, 0x41, 0x00, 0x35, 0xff, 0x43, 0xf8, 0x50, 0xf7, 0x6a, 0xf8, 0xa9, 0xfd, 0x93, 0x03, 0xef, 0x0e, 0xe8, 0x11, 0xea, 0x14, 0x68, 0x1d, 0x2c, 0x14, 0x25, 0x0d, 0x78, 0x0d, 0xc8, 0x0a, 0x33, 0x0e, 0x36, 0x0d, 0x73, 0x03, 0xb8, 0xfb, 0xb6, 0xfa, 0x1b, 0x01, 0x8a, 0x02, 0xd5, 0x01, 0xa5, 0xff, 0x69, 0xff, 0xf7, 0xf9, 0xbf, 0xf6, 0x49, 0xf6, 0x8c, 0xf6, 0x25, 0xfa, 0x43, 0xf6, 0x78, 0xef, 0x7d, 0xef, 0xbd, 0xf6, 0xc4, 0x00, 0x04, 0x03, 0xcc, 0xfd, 0xb3, 0xf3, 0x28, 0xec, 0x7a, 0xef, 0x48, 0xef, 0xaa, 0xee, 0xa8, 0xee, 0xe3, 0xef, 0xb8, 0xfa, 0x97, 0x00, 0x18, 0x05, 0x9d, 0x04, 0x53, 0xfb, 0x76, 0x00, 0x16, 0x02, 0x82, 0xff, 0x77, 0x03, 0xad, 0x07, 0xbe, 0x0f, 0x25, 0x12, 0x56, 0x12, 0xaa, 0x16, 0xc3, 0x15, 0x73, 0x12, 0xe0, 0x15, 0xd7, 0x1b, 0xe7, 0x1a, 0x8f, 0x15, 0x58, 0x16, 0x2d, 0x11, 0xeb, 0x0e, 0x0e, 0x0a, 0xdf, 0x06, 0xdb, 0x02, 0x65, 0xfc, 0x1f, 0xff, 0x4c, 0xfd, 0xfa, 0xf8, 0xc0, 0xf8, 0x80, 0xfc, 0x19, 0xf9, 0x58, 0xf2, 0x4b, 0xee, 0x73, 0xf5, 0x71, 0xf6, 0xe4, 0xf5, 0x9b, 0xf4, 0xbb, 0xe7, 0x7b, 0xe3, 0xad, 0xeb, 0x78, 0xf3, 0x8f, 0xf9, 0x5a, 0xfb, 0x05, 0xf0, 0xb8, 0xec, 0xd5, 0xf1, 0x41, 0xf6, 0xfa, 0xf7, 0x6c, 0xfb, 0x00, 0xfd, 0xb3, 0x04, 0x87, 0x04, 0xb4, 0xff, 0x68, 0xfe, 0x6d, 0x02, 0xf5, 0x01, 0xb5, 0x07, 0x77, 0x0a, 0x33, 0x0e, 0x57, 0x0c, 0x9e, 0x0b, 0x73, 0x13, 0xf8, 0x19, 0x05, 0x1a, 0xe9, 0x1a, 0xda, 0x1d, 0x3b, 0x1d, 0x65, 0x1c, 0x4a, 0x17, 0x99, 0x0e, 0x39, 0x06, 0x84, 0xfe, 0x08, 0xfa, 0x68, 0xfe, 0xd8, 0xfc, 0x02, 0xfc, 0x4e, 0xf5, 0x30, 0xed, 0x08, 0xed, 0xcf, 0xef, 0xf2, 0xed, 0x6b, 0xe9, 0xde, 0xe6, 0x4d, 0xeb, 0x7e, 0xe5, 0xb2, 0xe7, 0xa6, 0xe5, 0x6a, 0xec, 0xe8, 0xf3, 0xd3, 0xef, 0x43, 0xf2, 0x0a, 0xf6, 0x62, 0xfb, 0x2f, 0xfc, 0x78, 0xff, 0x39, 0x04, 0xd6, 0x05, 0xde, 0x08, 0x6b, 0x0e, 0x78, 0x11, 0xed, 0x14, 0x48, 0x15, 0xf2, 0x18, 0xc9, 0x21, 0x9c, 0x20, 0xf6, 0x1b, 0xcb, 0x18, 0xc3, 0x1e, 0x1f, 0x1f, 0xda, 0x19, 0x40, 0x15, 0x61, 0x0a, 0x4c, 0x08, 0xd1, 0x03, 0xa8, 0xfd, 0x1b, 0xf6, 0x68, 0xf2, 0x9d, 0xf6, 0xf3, 0xf5, 0x9e, 0xf4, 0x04, 0xf1, 0xde, 0xf4, 0xf1, 0xf3, 0x24, 0xf2, 0xed, 0xe9, 0x5f, 0xee, 0x46, 0xee, 0x9e, 0xea, 0xfb, 0xe9, 0xbe, 0xea, 0x12, 0xf2, 0x31, 0xf5, 0xca, 0xf8, 0x54, 0xfb, 0x67, 0xfd, 0x83, 0x01, 0xd4, 0x07, 0x65, 0x06, 0xa7, 0x09, 0xc0, 0x0d, 0x46, 0x0c, 0x13, 0x06, 0x0a, 0x08, 0x28, 0x06, 0x1a, 0x03, 0x9a, 0x07, 0x46, 0x00, 0x4c, 0xf7, 0x94, 0xf8, 0xdb, 0xf9, 0xd6, 0xfb, 0x30, 0xf9, 0xe1, 0xf1, 0x13, 0xf3, 0xaf, 0xf4, 0xdd, 0xf5, 0xcd, 0xf7, 0xbe, 0xfb, 0xb7, 0xfe, 0xc8, 0x07, 0x6f, 0x05, 0xdb, 0xff, 0xcc, 0xfa, 0x7a, 0xfd, 0x3c, 0xff, 0x45, 0xfd, 0x95, 0xfe, 0x98, 0xfb, 0x8c, 0xf9, 0xb2, 0xfd, 0xa9, 0x02, 0xa3, 0xfe, 0x99, 0xf9, 0x3b, 0xfd, 0x48, 0x08, 0x1e, 0x0b, 0xbb, 0x0a, 0x23, 0x06, 0xbb, 0xfe, 0x4f, 0xff, 0x5c, 0xfc, 0x23, 0x00, 0x4a, 0x01, 0xe3, 0x01, 0xb0, 0xfe, 0x10, 0xfc, 0x80, 0xf9, 0x3e, 0xf6, 0xcf, 0xfc, 0x0c, 0xfe, 0x41, 0x00, 0x61, 0x04, 0x36, 0x05, 0xcf, 0x09, 0x62, 0x08, 0xde, 0x08, 0x82, 0x06, 0x8c, 0x04, 0x91, 0x04, 0x60, 0x05, 0xb5, 0x07, 0x38, 0x07, 0x8d, 0x0a, 0x24, 0x07, 0xef, 0x07, 0x4c, 0x0d, 0xf6, 0x0b, 0x34, 0x0e, 0x52, 0x0c, 0x3d, 0x08, 0x48, 0x07, 0x54, 0x06, 0x0b, 0x07, 0x7d, 0x07, 0xf5, 0x08, 0x8f, 0x09, 0xb6, 0x0d, 0xc0, 0x08, 0xca, 0x07, 0xcc, 0x05, 0xe4, 0xff, 0x16, 0xfa, 0x75, 0xfe, 0x79, 0x02, 0x90, 0x03, 0x68, 0x00, 0x5b, 0xfc, 0x50, 0xf6, 0x30, 0xf5, 0x8f, 0xf2, 0x04, 0xf1, 0x13, 0xee, 0xc6, 0xe9, 0x1a, 0xe9, 0x3d, 0xe6, 0xe7, 0xe5, 0xf4, 0xe7, 0x51, 0xe9, 0x03, 0xf1, 0x7a, 0xf1, 0xad, 0xed, 0x88, 0xec, 0x7e, 0xee, 0xa9, 0xeb, 0x11, 0xed, 0xcc, 0xed, 0xd4, 0xee, 0x4a, 0xf4, 0x26, 0xf7, 0x78, 0xfc, 0xaa, 0x02, 0x1a, 0x09, 0x5e, 0x0d, 0x10, 0x0e, 0xbe, 0x0e, 0x97, 0x10, 0x77, 0x0e, 0x31, 0x0a, 0xc0, 0x0b, 0xa2, 0x10, 0x80, 0x12, 0xce, 0x10, 0xb5, 0x0f, 0x75, 0x09, 0x71, 0x04, 0x72, 0x07, 0x4b, 0x07, 0x5f, 0x09, 0x45, 0x0a, 0x17, 0x08, 0x06, 0x05, 0xf1, 0x03, 0x88, 0x05, 0xaf, 0x04, 0x0d, 0x02, 0x4c, 0x05, 0xa7, 0x00, 0x44, 0xfe, 0x33, 0xfd, 0xec, 0xfa, 0x41, 0xf7, 0x9d, 0xf8, 0xae, 0xf7, 0x05, 0xfd, 0x36, 0x00, 0x5b, 0x00, 0x09, 0x02, 0xe6, 0xf9, 0x84, 0xf6, 0x95, 0xf3, 0x6f, 0xf0, 0x1e, 0xf2, 0xd1, 0xf7, 0x39, 0xf9, 0x91, 0xfe, 0x2d, 0x04, 0xf6, 0xfe, 0x2a, 0xfe, 0x6e, 0xfd, 0x15, 0xf8, 0x7a, 0xf6, 0xa8, 0xf6, 0x29, 0xf6, 0xa8, 0xf8, 0xca, 0xf9, 0x41, 0x00, 0xb2, 0xfe, 0x63, 0xfd, 0xe9, 0xff, 0x32, 0x07, 0xac, 0x0b, 0xca, 0x0d, 0x10, 0x09, 0x3c, 0x0e, 0xfa, 0x13, 0xbb, 0x11, 0x74, 0x0f, 0x9d, 0x08, 0x65, 0x06, 0xfc, 0x00, 0x4c, 0x04, 0xfb, 0x05, 0x15, 0x08, 0x8f, 0x09, 0x34, 0xff, 0x00, 0xfe, 0xaa, 0x02, 0xe8, 0xff, 0x92, 0x00, 0x85, 0xff, 0xa4, 0x01, 0x27, 0x06, 0x7d, 0x03, 0xd8, 0x06, 0xd2, 0x0a, 0x2b, 0x09, 0xf0, 0x09, 0xb8, 0x0d, 0x3b, 0x0a, 0xfd, 0x09, 0xc6, 0x07, 0x1c, 0x02, 0x68, 0xfa, 0x9d, 0xf9, 0x25, 0xf8, 0xd1, 0xf6, 0x92, 0xf7, 0x94, 0xef, 0x51, 0xed, 0x77, 0xef, 0x24, 0xee, 0xc3, 0xf0, 0xfb, 0xed, 0x55, 0xf1, 0xd7, 0xf3, 0xec, 0xf1, 0x7f, 0xf1, 0x21, 0xf8, 0xe3, 0xfc, 0xd8, 0xfb, 0xc1, 0x00, 0x26, 0xfd, 0xec, 0xfa, 0x62, 0xf9, 0xdf, 0x00, 0x28, 0x02, 0x06, 0x06, 0xe0, 0x02, 0x21, 0xfc, 0xe0, 0xfe, 0x53, 0xfe, 0xea, 0xfd, 0xb0, 0x00, 0xac, 0x05, 0x06, 0x0c, 0xf1, 0x0a, 0xad, 0x0d, 0x3c, 0x11, 0x46, 0x07, 0xff, 0x05, 0xf5, 0x04, 0x96, 0x03, 0xc8, 0x02, 0x8e, 0xff, 0x43, 0x02, 0xa4, 0x00, 0x06, 0xfe, 0x04, 0xfd, 0xa6, 0xfd, 0x6c, 0xfc, 0xa9, 0xfd, 0x49, 0xfd, 0x36, 0x01, 0x24, 0x07, 0x43, 0x07, 0x65, 0x03, 0x14, 0x07, 0x2b, 0x05, 0xed, 0x01, 0x89, 0xff, 0xe9, 0xfa, 0xe9, 0xf6, 0xa3, 0xf8, 0x0d, 0xfc, 0x51, 0xf8, 0x19, 0xfc, 0x84, 0xf8, 0xb4, 0xf5, 0x61, 0xf7, 0x47, 0xf3, 0xbd, 0xf3, 0xc1, 0xf7, 0x0a, 0xf7, 0xc9, 0xfa, 0xee, 0xfb, 0x54, 0xfe, 0x27, 0x01, 0xd0, 0x00, 0x93, 0x02, 0xe7, 0x06, 0xdc, 0x08, 0xe8, 0x0c, 0x83, 0x0c, 0x0a, 0x0c, 0x9e, 0x0e, 0x94, 0x0b, 0x6f, 0x0a, 0x78, 0x01, 0x24, 0xfe, 0x73, 0x01, 0xb6, 0x01, 0xfb, 0x01, 0x4c, 0x01, 0x9c, 0x03, 0x1d, 0xfe, 0x40, 0xf9, 0xdd, 0xf9, 0x38, 0xf6, 0x6d, 0xf6, 0x70, 0xf7, 0x55, 0xf9, 0x9c, 0xf9, 0x70, 0xfe, 0x7f, 0x00, 0x6e, 0xfc, 0x04, 0xfb, 0x80, 0xfd, 0x9e, 0xfd, 0x4f, 0xfe, 0xee, 0xfd, 0x29, 0xfb, 0x42, 0xfc, 0x31, 0xfd, 0xa3, 0xfe, 0x2f, 0x00, 0x85, 0xfe, 0xd4, 0xfe, 0x4f, 0x03, 0x1a, 0x03, 0xd2, 0x04, 0x99, 0x07, 0x51, 0x0b, 0x69, 0x11, 0xb9, 0x0d, 0x9f, 0x0d, 0x9a, 0x0d, 0x0b, 0x0b, 0xe2, 0x06, 0xdc, 0x05, 0xc0, 0x05, 0x8b, 0x00, 0xa1, 0x01, 0x7e, 0xfe, 0xcb, 0xfc, 0x18, 0xfd, 0x7a, 0xfa, 0x42, 0xfc, 0xf9, 0xf9, 0xdb, 0xfa, 0xbc, 0xfa, 0xdc, 0xfa, 0x2a, 0xfa, 0xc0, 0xfa, 0x87, 0xfa, 0x2f, 0xff, 0x59, 0x00, 0x6a, 0x04, 0x73, 0x04, 0x3e, 0x03, 0x48, 0x06, 0x05, 0x0c, 0x1d, 0x0b, 0xd4, 0x0a, 0xd7, 0x0b, 0x4e, 0x0d, 0x6c, 0x09, 0x73, 0x04, 0x3b, 0x07, 0x07, 0x02, 0x1c, 0xfd, 0x6f, 0xfb, 0x8d, 0xfb, 0x85, 0xf7, 0xd1, 0xf5, 0x38, 0xf8, 0x0d, 0xfa, 0x20, 0xf9, 0xb4, 0xf8, 0x55, 0xf6, 0x01, 0xf3, 0x8f, 0xf0, 0x13, 0xed, 0xcf, 0xec, 0xdc, 0xeb, 0x43, 0xec, 0x63, 0xed, 0xd8, 0xf0, 0x45, 0xf6, 0xb3, 0xf6, 0x16, 0xf6, 0x6b, 0xf9, 0x0d, 0xfa, 0x23, 0xfb, 0x0d, 0xf8, 0xab, 0xfa, 0xfb, 0xfb, 0x8d, 0x00, 0x41, 0x02, 0xbf, 0x06, 0x11, 0x0a, 0x50, 0x07, 0xcb, 0x09, 0x84, 0x0c, 0x91, 0x0b, 0x62, 0x0e, 0x5a, 0x10, 0x62, 0x10, 0xb6, 0x12, 0xdc, 0x0f, 0x27, 0x0f, 0x6d, 0x0a, 0x04, 0x0a, 0xd9, 0x08, 0xe3, 0x07, 0x8a, 0x07, 0x48, 0x06, 0x20, 0x05, 0x2b, 0x07, 0x89, 0x02, 0x40, 0xfe, 0x3f, 0xfc, 0x1f, 0xf9, 0x31, 0xf7, 0x23, 0xf8, 0xe9, 0xfa, 0xca, 0xf9, 0x6f, 0xfc, 0x2a, 0xfb, 0x6d, 0xf8, 0x91, 0xf9, 0x21, 0xfa, 0x39, 0xfb, 0xc5, 0xfb, 0x32, 0xfd, 0xd8, 0x02, 0x96, 0x00, 0xce, 0x01, 0x18, 0x00, 0x34, 0xff, 0x92, 0x00, 0x8d, 0x01, 0xf2, 0x04, 0x5c, 0x07, 0x5d, 0x06, 0xdc, 0x07, 0x1a, 0x09, 0xc9, 0x09, 0x2b, 0x08, 0x6f, 0x08, 0x0a, 0x09, 0x01, 0x0a, 0xef, 0x08, 0x0b, 0x09, 0x74, 0x05, 0x67, 0x01, 0x35, 0x01, 0x1f, 0xfe, 0x3a, 0xfb, 0xdb, 0xf9, 0x74, 0xf8, 0xec, 0xf6, 0xa6, 0xf0, 0xc6, 0xf1, 0x9f, 0xf3, 0x2c, 0xf3, 0x3d, 0xf4, 0x64, 0xf7, 0xb6, 0xfa, 0x41, 0xfe, 0xdb, 0xfe, 0x10, 0xfc, 0x03, 0xfc, 0xef, 0xff, 0x3a, 0x00, 0x55, 0x02, 0x57, 0x00, 0x42, 0x02, 0x8d, 0xfe, 0xe2, 0xf8, 0x0c, 0xf8, 0x84, 0xfb, 0x1a, 0xfe, 0xbf, 0xfe, 0x08, 0xfb, 0x64, 0xfc, 0x1b, 0xfd, 0xde, 0xf9, 0xa6, 0xfb, 0x17, 0x00, 0x69, 0x03, 0x59, 0x05, 0xef, 0x02, 0xa2, 0xfe, 0x27, 0xff, 0xa1, 0xff, 0x84, 0xff, 0x9c, 0x00, 0xaf, 0xfe, 0xe0, 0xfc, 0x3e, 0xfd, 0x4c, 0xfe, 0xcb, 0xfc, 0x85, 0x00, 0x0e, 0x02, 0xb9, 0x00, 0xea, 0x00, 0x81, 0x03, 0x0b, 0x04, 0x4d, 0x03, 0x69, 0x04, 0xcf, 0x03, 0x2d, 0x02, 0xa6, 0xfe, 0xed, 0xfb, 0xe4, 0xfa, 0x4a, 0xfa, 0x1e, 0xfb, 0xd4, 0xfb, 0xc0, 0xfb, 0x1b, 0xfa, 0xba, 0xfa, 0x63, 0xfb, 0xfd, 0xfd, 0x70, 0x00, 0xde, 0x03, 0xb7, 0x00, 0x9b, 0xfd, 0xf3, 0xff, 0x4e, 0xfc, 0x2a, 0xfe, 0x77, 0xfa, 0x03, 0xfd, 0xe9, 0xfd, 0xd9, 0xf7, 0x7c, 0xf8, 0x41, 0xfa, 0x38, 0xfc, 0xe0, 0xfd, 0x24, 0x00, 0xde, 0x02, 0xd4, 0x07, 0x00, 0x08, 0xfc, 0x09, 0x8a, 0x0a, 0x97, 0x0b, 0xa0, 0x0a, 0x66, 0x08, 0xff, 0x06, 0x1d, 0x09, 0xce, 0x09, 0xed, 0x07, 0x78, 0x09, 0x09, 0x06, 0xa4, 0x00, 0xe2, 0xfd, 0x85, 0xfe, 0xec, 0x00, 0xea, 0xfe, 0x94, 0xfe, 0x9e, 0xfc, 0x2f, 0xfe, 0x6d, 0xfe, 0xc8, 0xff, 0x0e, 0x00, 0x93, 0xfd, 0x7c, 0xff, 0x59, 0xfd, 0x9f, 0xf8, 0xb1, 0xf9, 0x39, 0xfa, 0x19, 0xfd, 0xd5, 0xfd, 0xc0, 0xff, 0x01, 0xfe, 0xf6, 0xfe, 0x34, 0xff, 0x8e, 0xfd, 0x4f, 0xff, 0x49, 0xff, 0x94, 0xff, 0xd6, 0x00, 0x2d, 0x04, 0x28, 0x02, 0xa0, 0x01, 0x78, 0x02, 0xaa, 0x02, 0xc6, 0x04, 0x2e, 0x03, 0x7a, 0xff, 0x77, 0x00, 0x54, 0xfe, 0x4f, 0xfe, 0x6a, 0x00, 0xac, 0x01, 0xda, 0x03, 0x43, 0x00, 0x96, 0xfc, 0x1a, 0xfc, 0xb8, 0xfb, 0x41, 0xfb, 0x56, 0xfa, 0xba, 0xfb, 0x7c, 0xfb, 0xa8, 0xfb, 0x6a, 0xfa, 0xaa, 0xfb, 0xb7, 0xf7, 0xbb, 0xf6, 0xe2, 0xf8, 0x72, 0xfc, 0x60, 0xff, 0x2c, 0x04, 0x87, 0x07, 0x74, 0x04, 0x2d, 0x06, 0x4a, 0x07, 0x41, 0x04, 0x66, 0x02, 0x61, 0x01, 0xb9, 0x00, 0x31, 0xfe, 0x6c, 0xfc, 0xca, 0xfb, 0xb3, 0xff, 0x08, 0x02, 0xdc, 0x01, 0x69, 0x01, 0x40, 0x01, 0x15, 0x03, 0xd6, 0xff, 0x1e, 0xfe, 0x2d, 0xfd, 0x61, 0x00, 0x9f, 0x01, 0x06, 0x02, 0x0d, 0x01, 0xc9, 0xfc, 0x2d, 0xff, 0xc8, 0x01, 0x07, 0x03, 0xf2, 0x03, 0xde, 0x05, 0x6a, 0x02, 0x6c, 0x02, 0x5c, 0x03, 0x81, 0x03, 0x1c, 0x04, 0x8f, 0x04, 0xeb, 0x03, 0xac, 0x01, 0xc5, 0xff, 0x18, 0xfd, 0x80, 0xfc, 0xbe, 0xfc, 0x84, 0xfa, 0x5c, 0xf9, 0xb3, 0xfb, 0xc4, 0xfc, 0xa7, 0xfa, 0x13, 0xf9, 0x7d, 0xf7, 0xbd, 0xfa, 0x95, 0xfb, 0xf7, 0xf9, 0xc9, 0xf8, 0xaf, 0xf8, 0x2c, 0xfb, 0x6d, 0xfa, 0x4b, 0xfc, 0xe8, 0xfe, 0x23, 0x03, 0x0e, 0x05, 0xbd, 0x06, 0x68, 0x07, 0x07, 0x0a, 0x69, 0x0b, 0x02, 0x0c, 0x08, 0x0c, 0x00, 0x0a, 0x94, 0x08, 0x67, 0x0b, 0x39, 0x0a, 0x0f, 0x0a, 0x47, 0x09, 0xe1, 0x06, 0x19, 0x07, 0xb4, 0x04, 0x46, 0x01, 0xbc, 0xfd, 0x4e, 0xfd, 0x13, 0xfe, 0xfb, 0xfd, 0xa0, 0xfb, 0x2f, 0xfa, 0xd1, 0xfa, 0x04, 0xfc, 0x70, 0xfc, 0x07, 0xfc, 0xf9, 0xfc, 0x21, 0xff, 0x2a, 0x00, 0x0b, 0x00, 0x7c, 0x01, 0x17, 0x04, 0xfd, 0x04, 0x51, 0x05, 0x19, 0x07, 0xc2, 0x09, 0x57, 0x06, 0xa6, 0x03, 0xa1, 0x00, 0x25, 0xfb, 0xfe, 0xf9, 0xec, 0xf8, 0xa3, 0xf9, 0x28, 0xf9, 0x3f, 0xf6, 0x4b, 0xf4, 0x37, 0xf3, 0xb5, 0xf2, 0x25, 0xf6, 0x96, 0xf8, 0x3f, 0xf9, 0x3f, 0xf9, 0x32, 0xf6, 0x98, 0xf3, 0x71, 0xf4, 0xb4, 0xf8, 0x60, 0xf9, 0x03, 0xf9, 0xe6, 0xf8, 0x0b, 0xfb, 0x73, 0xfc, 0xe7, 0xfd, 0x0e, 0xff, 0xa1, 0xfc, 0x20, 0xfe, 0x3a, 0xff, 0x5b, 0x00, 0xd9, 0x02, 0x8f, 0x04, 0xe9, 0x05, 0x37, 0x07, 0xb6, 0x0a, 0x65, 0x0b, 0x03, 0x0b, 0x70, 0x0a, 0x91, 0x07, 0xd3, 0x08, 0xd6, 0x07, 0x91, 0x07, 0x28, 0x09, 0x30, 0x0a, 0x5b, 0x0c, 0x40, 0x0d, 0x86, 0x0d, 0x65, 0x0c, 0x9b, 0x0c, 0xb2, 0x0c, 0x12, 0x0b, 0x99, 0x0b, 0x3a, 0x0d, 0x47, 0x0a, 0x38, 0x09, 0x37, 0x08, 0x43, 0x05, 0x37, 0x01, 0x56, 0x00, 0x9d, 0xff, 0xba, 0xfd, 0xd1, 0xfa, 0x90, 0xf7, 0x40, 0xf5, 0x47, 0xf3, 0xd8, 0xf3, 0x5a, 0xf3, 0xf2, 0xf2, 0x73, 0xf1, 0xcc, 0xed, 0x63, 0xee, 0xba, 0xef, 0xb1, 0xf0, 0xee, 0xf2, 0x5f, 0xf3, 0xf7, 0xf5, 0x45, 0xf6, 0x91, 0xf6, 0x81, 0xfa, 0xa8, 0xfa, 0x0f, 0xfc, 0xad, 0xfd, 0xe2, 0xfb, 0x13, 0xfc, 0xff, 0xff, 0x42, 0x01, 0xcd, 0x01, 0x5c, 0x01, 0xde, 0x01, 0x1c, 0x04, 0x83, 0x03, 0x42, 0x01, 0x53, 0xfe, 0x29, 0x02, 0xf9, 0x03, 0x4e, 0x04, 0x1c, 0x04, 0x84, 0x01, 0xdf, 0xff, 0xd3, 0xff, 0x28, 0x01, 0xa4, 0x03, 0x67, 0x06, 0x32, 0x06, 0x20, 0x08, 0xf5, 0x08, 0x20, 0x09, 0x73, 0x08, 0x1f, 0x09, 0x7c, 0x09, 0x07, 0x08, 0x20, 0x07, 0xe6, 0x03, 0x41, 0x02, 0x8e, 0x01, 0xd3, 0xfe, 0x52, 0xfc, 0x25, 0xfc, 0x9a, 0xfd, 0xfa, 0xfd, 0xd8, 0xfc, 0xf4, 0xfb, 0x89, 0xfc, 0xdb, 0xfc, 0xd7, 0xfc, 0xe9, 0xfa, 0xaa, 0xfd, 0x22, 0xfd, 0xd1, 0xfc, 0xdb, 0xfb, 0x25, 0xf9, 0xaf, 0xf8, 0xb2, 0xfb, 0x64, 0xfb, 0x6c, 0xfc, 0x5c, 0xfd, 0x28, 0x00, 0x1d, 0x01, 0xf3, 0xff, 0x56, 0x01, 0xf0, 0x02, 0x56, 0x01, 0xd9, 0x00, 0x7d, 0x01, 0xe9, 0x02, 0x39, 0x03, 0x24, 0x03, 0xb8, 0x03, 0x42, 0x04, 0x8a, 0x05, 0xa8, 0x08, 0x4f, 0x0b, 0xd7, 0x0c, 0x15, 0x0c, 0x1e, 0x08, 0x05, 0x06, 0xd6, 0x05, 0xb2, 0x02, 0x15, 0x03, 0x5d, 0x01, 0x0f, 0x00, 0xd8, 0xff, 0xba, 0xfc, 0x36, 0xfa, 0xea, 0xf7, 0xd7, 0xf7, 0x77, 0xf8, 0x41, 0xf5, 0x36, 0xf6, 0x02, 0xf5, 0xe9, 0xf2, 0x21, 0xf3, 0x74, 0xf6, 0x85, 0xfa, 0x32, 0xfc, 0x8a, 0xfc, 0xab, 0xfd, 0xf1, 0x00, 0x50, 0x01, 0x3d, 0x01, 0x30, 0x03, 0xef, 0x03, 0x91, 0x04, 0x37, 0x04, 0x56, 0x06, 0x8b, 0x06, 0x5c, 0x04, 0x44, 0x06, 0x9b, 0x03, 0x53, 0x00, 0xfb, 0xfc, 0x62, 0x00, 0x10, 0x00, 0x27, 0xff, 0xb7, 0xfc, 0xda, 0xfb, 0xea, 0xfd, 0xba, 0xfe, 0x2d, 0xfd, 0xec, 0xfc, 0xd1, 0xfd, 0xad, 0xfd, 0x56, 0xfc, 0x6c, 0xfb, 0xad, 0xfb, 0xcd, 0xfc, 0xb3, 0xfe, 0x70, 0x00, 0x06, 0x02, 0x97, 0x01, 0xbd, 0x00, 0xe0, 0x02, 0xfb, 0x03, 0x33, 0x05, 0x1d, 0x05, 0x98, 0x05, 0x6f, 0x05, 0xc9, 0x05, 0xf3, 0x04, 0xc2, 0x03, 0xca, 0x02, 0x20, 0xff, 0xaa, 0xfd, 0x66, 0xff, 0x4a, 0x00, 0x44, 0x00, 0x2c, 0x00, 0x35, 0x00, 0xf2, 0xff, 0x8d, 0xfc, 0xca, 0xfb, 0x32, 0xfa, 0x1d, 0xf8, 0x12, 0xf7, 0xdf, 0xf8, 0x5a, 0xf9, 0x71, 0xfa, 0xfd, 0xfb, 0x1e, 0xfc, 0x42, 0xfc, 0x16, 0xfd, 0xd6, 0xfc, 0x22, 0xfb, 0x81, 0xfa, 0x34, 0xf8, 0x7c, 0xf7, 0x45, 0xf9, 0x55, 0xf8, 0xad, 0xfa, 0x1c, 0xfc, 0x35, 0xfe, 0xdc, 0x00, 0xf1, 0x00, 0x2e, 0x01, 0xb2, 0x04, 0x03, 0x06, 0xd2, 0x06, 0x15, 0x09, 0x48, 0x08, 0x20, 0x07, 0x5f, 0x06, 0x75, 0x06, 0x56, 0x06, 0x18, 0x05, 0x16, 0x03, 0x2b, 0xff, 0x54, 0xff, 0x7a, 0x01, 0x48, 0x00, 0x62, 0x00, 0xb9, 0xfe, 0xb4, 0xfc, 0x61, 0xfe, 0xef, 0xfd, 0x08, 0xfd, 0x92, 0xfb, 0x21, 0xfa, 0x86, 0xfb, 0x63, 0xfd, 0xec, 0xfe, 0xcb, 0xff, 0xb6, 0x02, 0xb9, 0x04, 0x61, 0x07, 0x44, 0x07, 0x71, 0x08, 0x4a, 0x09, 0x12, 0x09, 0xf7, 0x07, 0x78, 0x09, 0xd8, 0x09, 0xcb, 0x07, 0x35, 0x06, 0x39, 0x04, 0xad, 0x03, 0xc5, 0x02, 0xfd, 0x00, 0xd3, 0xfe, 0x0f, 0xfd, 0x5d, 0xfa, 0x25, 0xfc, 0x80, 0xfb, 0x3d, 0xfb, 0x12, 0xfa, 0x98, 0xf7, 0x7b, 0xf7, 0x49, 0xf9, 0xd9, 0xf8, 0xe9, 0xf8, 0x01, 0xfb, 0x4c, 0xfc, 0x35, 0xfd, 0x5d, 0xfb, 0xc1, 0xf9, 0xc8, 0xf8, 0xe0, 0xf9, 0x7f, 0xfa, 0xdb, 0xfb, 0x2c, 0xfe, 0x50, 0xff, 0x25, 0xff, 0xa6, 0xff, 0xa2, 0x01, 0x86, 0x02, 0x75, 0x02, 0x11, 0x03, 0xc3, 0x04, 0xcb, 0x05, 0x94, 0x07, 0xac, 0x09, 0xe5, 0x08, 0x14, 0x08, 0xb1, 0x05, 0x23, 0x05, 0x64, 0x04, 0xc7, 0x03, 0x1e, 0x03, 0xa8, 0xfe, 0x6d, 0xfd, 0xcd, 0xfc, 0xa6, 0xfc, 0x73, 0xfb, 0xea, 0xfa, 0x49, 0xfc, 0x91, 0xff, 0xe3, 0xff, 0xf6, 0x01, 0x11, 0x03, 0xab, 0x01, 0x32, 0x01, 0xf5, 0x01, 0x22, 0x03, 0x75, 0x04, 0xee, 0x03, 0x7d, 0x01, 0xf4, 0xfd, 0x4a, 0xfc, 0x0f, 0xfc, 0x61, 0xfc, 0xb4, 0xfb, 0x19, 0xfb, 0x2e, 0xfa, 0x0c, 0xfb, 0xe6, 0xf9, 0xff, 0xf7, 0xb3, 0xf9, 0x94, 0xfb, 0xaa, 0xfc, 0x49, 0xfe, 0xf0, 0xfd, 0x50, 0xfd, 0x4b, 0xfe, 0x25, 0x00, 0xb0, 0x01, 0xda, 0x02, 0x38, 0x05, 0x0f, 0x06, 0x10, 0x05, 0x0f, 0x05, 0x4c, 0x05, 0xfa, 0x04, 0x46, 0x04, 0x4d, 0x05, 0xee, 0x05, 0x97, 0x03, 0x9d, 0x02, 0xe6, 0x00, 0x37, 0xff, 0x7a, 0xfe, 0x55, 0xfd, 0xe7, 0xfc, 0xdc, 0xfc, 0x6b, 0xfb, 0x1a, 0xf9, 0x8d, 0xfa, 0x17, 0xfb, 0x80, 0xfc, 0xc3, 0xfd, 0x22, 0xfe, 0x5b, 0xfe, 0x3d, 0xfd, 0xfb, 0xfc, 0x13, 0xfd, 0xcd, 0xfd, 0x2e, 0xfe, 0xbf, 0xfd, 0x43, 0xfd, 0x67, 0xfc, 0xd6, 0xfb, 0x67, 0xfb, 0x1a, 0xfd, 0xdd, 0xfe, 0x0c, 0x01, 0x13, 0x02, 0x12, 0x03, 0xb5, 0x00, 0x10, 0x00, 0xaf, 0x00, 0x28, 0x00, 0xc6, 0xff, 0xdc, 0xfe, 0xb3, 0x01, 0x6b, 0x02, 0x60, 0x02, 0x29, 0x03, 0x8d, 0x05, 0x84, 0x05, 0x16, 0x05, 0x74, 0x04, 0x50, 0x04, 0xdb, 0x03, 0x2b, 0x04, 0xd3, 0x03, 0xbf, 0x02, 0xc5, 0x01, 0x0e, 0x01, 0x77, 0x01, 0x63, 0x00, 0xe0, 0xff, 0xe7, 0xfd, 0xb4, 0xfb, 0xcc, 0xfb, 0xdf, 0xfa, 0xe2, 0xfb, 0x33, 0xfc, 0xd9, 0xfb, 0x4e, 0xfc, 0x32, 0xfc, 0xd4, 0xfb, 0x3a, 0xfb, 0x52, 0xfc, 0xbf, 0xff, 0x89, 0xfe, 0x04, 0xfe, 0xfe, 0xfc, 0x38, 0xfb, 0x73, 0xfb, 0x34, 0xfb, 0x86, 0xfd, 0xce, 0xfe, 0xb1, 0xff, 0x6a, 0x00, 0x7a, 0x01, 0x59, 0x02, 0xf4, 0x01, 0x25, 0x03, 0x9f, 0x04, 0x52, 0x04, 0x37, 0x04, 0x22, 0x04, 0xbb, 0x03, 0x51, 0x04, 0xca, 0x04, 0x8a, 0x06, 0x8a, 0x07, 0x47, 0x06, 0xa4, 0x04, 0x8f, 0x02, 0x36, 0x00, 0xeb, 0xfe, 0x16, 0xff, 0x25, 0x00, 0x2a, 0x00, 0xc0, 0xff, 0x19, 0xfe, 0xba, 0xfc, 0xd7, 0xfa, 0x27, 0xfb, 0xff, 0xf9, 0x8c, 0xf9, 0x5d, 0xfa, 0x99, 0xfc, 0xf7, 0xfd, 0xc6, 0xfd, 0xeb, 0xfe, 0xf2, 0xff, 0xa3, 0x00, 0x85, 0x01, 0x9e, 0x02, 0x22, 0x05, 0xd8, 0x06, 0x5f, 0x07, 0xb2, 0x08, 0x66, 0x09, 0xba, 0x08, 0xfa, 0x07, 0x35, 0x09, 0xc7, 0x08, 0x49, 0x07, 0x2b, 0x06, 0x1f, 0x06, 0xba, 0x04, 0x73, 0x03, 0xd8, 0x01, 0xbe, 0x01, 0x68, 0x01, 0x0a, 0x00, 0x8e, 0xfd, 0xbb, 0xfa, 0x47, 0xf9, 0x3e, 0xf7, 0xba, 0xf5, 0x20, 0xf5, 0xba, 0xf5, 0xdc, 0xf5, 0x2d, 0xf6, 0x02, 0xf6, 0x5b, 0xf6, 0x13, 0xf7, 0xbd, 0xf7, 0x29, 0xf9, 0xa7, 0xf9, 0x8f, 0xf9, 0xc5, 0xfb, 0x95, 0xfb, 0xe9, 0xfb, 0xf9, 0xfc, 0x1f, 0xff, 0x75, 0x01, 0x2e, 0x01, 0x1c, 0x02, 0x9e, 0x01, 0xa1, 0x01, 0x7d, 0x02, 0x36, 0x02, 0xf8, 0x02, 0xac, 0x04, 0x20, 0x06, 0x9c, 0x07, 0x71, 0x07, 0xac, 0x06, 0x57, 0x06, 0xa6, 0x04, 0x49, 0x04, 0x69, 0x04, 0x55, 0x06, 0x9a, 0x05, 0x06, 0x05, 0x9c, 0x04, 0xc7, 0x00, 0x67, 0xff, 0x32, 0x00, 0xa4, 0xff, 0x0d, 0xff, 0x04, 0xfd, 0x92, 0xfc, 0x97, 0xfb, 0xdc, 0xf9, 0x33, 0xfa, 0x81, 0xfb, 0x85, 0xfc, 0x7d, 0xfc, 0x32, 0xfc, 0x1d, 0xfd, 0x46, 0xfe, 0x96, 0xfd, 0x72, 0xfe, 0xab, 0xff, 0x47, 0x01, 0x24, 0x02, 0x71, 0x02, 0x9a, 0x01, 0xb4, 0x00, 0x88, 0xff, 0x1d, 0xff, 0x56, 0xff, 0x0e, 0xfe, 0x49, 0xff, 0x64, 0x00, 0xdc, 0x01, 0x4a, 0x02, 0xfb, 0x02, 0x3f, 0x03, 0xa4, 0x03, 0xa4, 0x02, 0xd2, 0x01, 0x90, 0x02, 0x01, 0x01, 0x88, 0x00, 0x78, 0xfe, 0x43, 0xfe, 0x3d, 0xfe, 0xbb, 0xfd, 0x31, 0xfe, 0x09, 0xfe, 0x0a, 0xfe, 0xe6, 0xff, 0x48, 0x00, 0x0f, 0x00, 0x20, 0xff, 0xe3, 0xfc, 0xa5, 0xfb, 0xe8, 0xf9, 0x9b, 0xfa, 0x99, 0xfa, 0x9e, 0xfb, 0x6d, 0xfb, 0x67, 0xfb, 0xf4, 0xfa, 0xe7, 0xf9, 0xa3, 0xfa, 0x7e, 0xfb, 0x4c, 0xfd, 0x6f, 0xff, 0xe0, 0x00, 0x2e, 0x01, 0xca, 0x02, 0x98, 0x02, 0x8e, 0x02, 0xe3, 0x03, 0xe2, 0x03, 0xe1, 0x04, 0x21, 0x05, 0x56, 0x04, 0xce, 0x03, 0xdd, 0x04, 0x24, 0x06, 0x21, 0x06, 0xdf, 0x05, 0x36, 0x05, 0x28, 0x03, 0x8b, 0x01, 0xbb, 0xff, 0x3c, 0xfe, 0x85, 0xfc, 0x1a, 0xfd, 0xf9, 0xfc, 0x6d, 0xfc, 0x80, 0xfc, 0x17, 0xfc, 0xcd, 0xfb, 0xc5, 0xfc, 0x21, 0xfc, 0x7f, 0xfc, 0xe8, 0xfb, 0x92, 0xfc, 0xa7, 0xfb, 0xea, 0xfb, 0x9e, 0xfd, 0xfb, 0xff, 0x40, 0x01, 0x53, 0x02, 0x7f, 0x02, 0x79, 0x02, 0xc0, 0x03, 0xe6, 0x03, 0xb7, 0x04, 0xd8, 0x04, 0xf1, 0x04, 0x0d, 0x04, 0x95, 0x04, 0xe0, 0x04, 0x6b, 0x04, 0x56, 0x04, 0xf5, 0x03, 0x88, 0x03, 0x6f, 0x04, 0x09, 0x03, 0xdd, 0x02, 0x8d, 0x01, 0x24, 0x00, 0xd4, 0x00, 0x33, 0x00, 0x16, 0x00, 0xc4, 0xff, 0x99, 0x00, 0x36, 0x01, 0x57, 0x01, 0x61, 0xff, 0x04, 0xfe, 0x06, 0xfe, 0xf7, 0xfb, 0xec, 0xf9, 0x70, 0xfa, 0x43, 0xfb, 0x87, 0xfb, 0xf3, 0xfb, 0x3b, 0xfc, 0x03, 0xfb, 0x3c, 0xfa, 0x86, 0xfa, 0x7b, 0xfb, 0x56, 0xfb, 0xb4, 0xfa, 0xef, 0xf9, 0xf9, 0xf9, 0xe8, 0xfa, 0x21, 0xfb, 0x84, 0xfc, 0x89, 0xfb, 0xf2, 0xfb, 0xb6, 0xfb, 0xf6, 0xfa, 0xc5, 0xfb, 0x62, 0xfd, 0x54, 0xff, 0x27, 0x00, 0x41, 0x00, 0x06, 0xff, 0xb7, 0xfd, 0xff, 0xfe, 0x47, 0x00, 0x94, 0x00, 0x42, 0x01, 0x89, 0x00, 0xdb, 0xff, 0x85, 0xff, 0x0e, 0x01, 0xc7, 0x00, 0xb6, 0x00, 0x56, 0x01, 0x7e, 0x00, 0xf3, 0x01, 0x46, 0x02, 0x19, 0x02, 0x20, 0x03, 0xdd, 0x04, 0x6f, 0x06, 0x40, 0x07, 0x17, 0x07, 0xcc, 0x06, 0x0c, 0x07, 0x66, 0x06, 0x44, 0x05, 0xa7, 0x04, 0x6e, 0x04, 0x59, 0x03, 0x5f, 0x03, 0x0b, 0x04, 0x21, 0x03, 0x0f, 0x03, 0x3f, 0x02, 0x88, 0x01, 0xe4, 0xff, 0x32, 0xfe, 0x7b, 0xfc, 0x5e, 0xfb, 0x32, 0xfc, 0x49, 0xfd, 0xe6, 0xfd, 0xce, 0xfd, 0xf0, 0xfc, 0xd1, 0xfb, 0x11, 0xfb, 0x2d, 0xfa, 0xcb, 0xf9, 0xf8, 0xfa, 0x7d, 0xf9, 0x3d, 0xfa, 0xbb, 0xfa, 0x3a, 0xfc, 0xf2, 0xfc, 0x1a, 0xfe, 0xb9, 0xff, 0x55, 0x01, 0x79, 0x02, 0x2c, 0x04, 0xac, 0x05, 0xbf, 0x06, 0x14, 0x08, 0xee, 0x08, 0x0e, 0x09, 0x40, 0x0a, 0xab, 0x09, 0x44, 0x08, 0x85, 0x06, 0xcc, 0x05, 0x76, 0x04, 0x47, 0x02, 0xed, 0x00, 0x6d, 0x00, 0x5d, 0xff, 0x95, 0xfe, 0xfb, 0xfe, 0x3e, 0xff, 0xc7, 0xfe, 0x5c, 0xfd, 0x82, 0xfd, 0xd6, 0xfc, 0x9e, 0xfa, 0xa9, 0xf9, 0x58, 0xf8, 0xcb, 0xf8, 0x57, 0xf8, 0x08, 0xf8, 0x8b, 0xf7, 0x4e, 0xf6, 0x64, 0xf7, 0xa1, 0xf8, 0x2b, 0xfa, 0xe2, 0xfa, 0xe5, 0xfb, 0x28, 0xfc, 0x6f, 0xfe, 0x6b, 0xff, 0x16, 0x01, 0x91, 0x01, 0x9d, 0x02, 0x7a, 0x04, 0x1f, 0x06, 0x70, 0x06, 0x64, 0x06, 0x94, 0x06, 0xf2, 0x07, 0x87, 0x07, 0xeb, 0x06, 0x6c, 0x07, 0xf6, 0x05, 0x9d, 0x04, 0xad, 0x04, 0xab, 0x05, 0xc0, 0x04, 0x2c, 0x03, 0x0a, 0x01, 0x3d, 0xfe, 0x1c, 0xfe, 0x33, 0xfd, 0x68, 0xfb, 0xd3, 0xf9, 0xb3, 0xf8, 0xeb, 0xf8, 0x65, 0xf8, 0x42, 0xf8, 0x0f, 0xf9, 0x8a, 0xfb, 0x01, 0xfd, 0x0f, 0xfe, 0xf1, 0xfd, 0x6f, 0xfe, 0xda, 0xfe, 0x0c, 0xfe, 0x96, 0xfd, 0xf4, 0xfc, 0x5a, 0xfe, 0x0b, 0xff, 0x2f, 0x00, 0x09, 0x00, 0x43, 0xff, 0xad, 0xfe, 0x2a, 0xff, 0x4c, 0xff, 0x74, 0x00, 0x15, 0x01, 0xa8, 0x02, 0x4e, 0x04, 0xcf, 0x05, 0x1a, 0x07, 0x1d, 0x08, 0xe6, 0x08, 0x76, 0x09, 0xf2, 0x09, 0xab, 0x08, 0xdc, 0x07, 0xf8, 0x05, 0xe0, 0x03, 0x54, 0x02, 0x6b, 0x01, 0xd3, 0xff, 0xf7, 0xfe, 0x1c, 0xfe, 0xaa, 0xfc, 0xff, 0xfc, 0xb2, 0xfc, 0xd3, 0xfb, 0xcc, 0xfb, 0xf7, 0xfb, 0x9a, 0xfb, 0x1e, 0xfb, 0xa9, 0xfb, 0xb1, 0xfa, 0xc2, 0xfa, 0x61, 0xfb, 0x0e, 0xfd, 0x9f, 0xfe, 0xf0, 0xff, 0x80, 0x01, 0x93, 0x01, 0xf4, 0x01, 0x34, 0x03, 0x61, 0x03, 0xe1, 0x02, 0xe9, 0x03, 0x5a, 0x03, 0xa8, 0x02, 0x2c, 0x02, 0xc8, 0x01, 0x3f, 0x00, 0x6e, 0xfe, 0xc3, 0xfd, 0x7c, 0xfc, 0x35, 0xfb, 0x10, 0xfb, 0x66, 0xfb, 0x51, 0xfb, 0x28, 0xfa, 0x98, 0xf8, 0x84, 0xf7, 0x98, 0xf7, 0xba, 0xf7, 0xee, 0xf7, 0x3a, 0xf8, 0xa8, 0xf8, 0x47, 0xf9, 0x1a, 0xfa, 0x29, 0xfa, 0x13, 0xfc, 0xbf, 0xfd, 0x40, 0xfe, 0xd8, 0xff, 0x2f, 0x01, 0xd3, 0x02, 0x49, 0x04, 0x16, 0x06, 0x39, 0x07, 0x0a, 0x09, 0xc3, 0x09, 0x46, 0x09, 0xa0, 0x08, 0xde, 0x09, 0x79, 0x0a, 0xaf, 0x09, 0x5f, 0x08, 0x4d, 0x06, 0x84, 0x04, 0x30, 0x03, 0xcb, 0x02, 0x8e, 0x01, 0xea, 0x00, 0x24, 0x00, 0x5f, 0xff, 0xff, 0xfe, 0xdc, 0xfc, 0x1b, 0xfc, 0xb1, 0xfb, 0xef, 0xfa, 0x09, 0xfb, 0x78, 0xfb, 0xc8, 0xfc, 0x4a, 0xfe, 0xd8, 0xfe, 0x26, 0xff, 0xa0, 0x00, 0x76, 0x01, 0xbc, 0x00, 0xea, 0x00, 0x38, 0x00, 0xfc, 0xff, 0xe8, 0xff, 0x32, 0xff, 0x15, 0xfe, 0xc9, 0xfd, 0xac, 0xfd, 0x52, 0xfe, 0xa2, 0xfe, 0xb1, 0xff, 0x25, 0x01, 0x65, 0x02, 0x40, 0x02, 0x8e, 0x03, 0x79, 0x03, 0x65, 0x01, 0x6a, 0x00, 0xc4, 0x00, 0xee, 0xff, 0x15, 0xff, 0xa6, 0xfe, 0x9e, 0xfd, 0x7a, 0xfc, 0x57, 0xfc, 0x03, 0xfd, 0x3c, 0xfc, 0xdf, 0xfb, 0x35, 0xfc, 0x06, 0xfc, 0x36, 0xfc, 0xfc, 0xfb, 0xd1, 0xfb, 0x4c, 0xfb, 0x9f, 0xfa, 0xd8, 0xfa, 0xcf, 0xfb, 0x5f, 0xfc, 0xff, 0xfd, 0x13, 0xff, 0x37, 0x00, 0x21, 0x01, 0x44, 0x01, 0x80, 0x02, 0x18, 0x03, 0xc2, 0x02, 0xf5, 0x02, 0x88, 0x03, 0xe1, 0x03, 0x65, 0x03, 0x29, 0x04, 0xe8, 0x04, 0x24, 0x04, 0xde, 0x03, 0xbd, 0x03, 0x52, 0x03, 0x0f, 0x02, 0x94, 0x00, 0x16, 0x00, 0x42, 0xfe, 0x3f, 0xfe, 0x07, 0xfe, 0x76, 0xfe, 0x52, 0xfe, 0xd6, 0xfd, 0x94, 0xfe, 0x2c, 0xfe, 0x33, 0xfe, 0xd1, 0xfe, 0x50, 0xff, 0x84, 0x00, 0x7c, 0x00, 0x54, 0xff, 0x1f, 0xff, 0x8f, 0xfe, 0x0e, 0xfe, 0xaa, 0xfd, 0x94, 0xfe, 0x3d, 0xff, 0x4e, 0xff, 0x4d, 0xff, 0xeb, 0xff, 0xa3, 0xff, 0xb4, 0xff, 0x5c, 0x00, 0xb1, 0x00, 0x6a, 0x01, 0xbf, 0x01, 0x08, 0x02, 0x16, 0x02, 0x6e, 0x01, 0x26, 0x01, 0x4d, 0x01, 0xb1, 0x00, 0xe5, 0x00, 0xf5, 0xff, 0x1f, 0xff, 0xeb, 0xfe, 0xa0, 0xff, 0xfd, 0xff, 0x12, 0x00, 0xa0, 0xff, 0x76, 0xfe, 0xe5, 0xfe, 0x5d, 0xff, 0x90, 0xfe, 0xcf, 0xfe, 0xad, 0xfe, 0xb3, 0xfe, 0xc4, 0xfe, 0x7d, 0xfe, 0xa2, 0xfe, 0x0c, 0xff, 0x16, 0xff, 0xd7, 0xfe, 0x39, 0xff, 0x19, 0x00, 0x71, 0x00, 0xc0, 0x00, 0xaf, 0xff, 0x15, 0xff, 0xbf, 0xfe, 0x36, 0xfe, 0x46, 0xff, 0xad, 0xff, 0xfe, 0xff, 0x0e, 0x00, 0xe6, 0xff, 0x92, 0x00, 0xf1, 0x00, 0xdb, 0x01, 0x36, 0x02, 0x68, 0x01, 0xf8, 0x01, 0xbf, 0x02, 0x97, 0x02, 0x33, 0x02, 0x36, 0x02, 0xd7, 0x02, 0x97, 0x02, 0x05, 0x02, 0x91, 0x01, 0x3b, 0x02, 0xa8, 0x02, 0xb5, 0x02, 0x6f, 0x02, 0x42, 0x03, 0x06, 0x03, 0xd6, 0x01, 0xeb, 0x01, 0x1d, 0x02, 0xa4, 0x01, 0x21, 0x01, 0xa2, 0xff, 0x6c, 0xfe, 0xdf, 0xfd, 0x38, 0xfd, 0x90, 0xfc, 0x27, 0xfb, 0xd6, 0xfa, 0x71, 0xfb, 0x2b, 0xfb, 0x23, 0xfb, 0x27, 0xfc, 0x5f, 0xfc, 0x8f, 0xfc, 0x95, 0xfc, 0x97, 0xfc, 0x5e, 0xfd, 0x68, 0xfd, 0x8b, 0xfc, 0x7d, 0xfc, 0x87, 0xfc, 0x81, 0xfc, 0x9e, 0xfc, 0x13, 0xfe, 0x9b, 0xfe, 0xb7, 0xff, 0x4c, 0x00, 0x1d, 0x00, 0xa2, 0x00, 0x16, 0x01, 0x6e, 0x00, 0x75, 0x01, 0x3e, 0x01, 0x80, 0x01, 0x62, 0x02, 0x25, 0x03, 0x3d, 0x04, 0x0f, 0x04, 0x8c, 0x04, 0x37, 0x05, 0x6e, 0x04, 0x20, 0x04, 0x42, 0x05, 0x3b, 0x05, 0xfa, 0x04, 0xb8, 0x04, 0x5b, 0x04, 0xcc, 0x03, 0x03, 0x02, 0x82, 0x00, 0x44, 0xff, 0x8a, 0xfe, 0xb6, 0xfd, 0xda, 0xfd, 0x2d, 0xfd, 0x6d, 0xfc, 0x45, 0xfc, 0xe5, 0xfb, 0xef, 0xfb, 0xff, 0xfb, 0x2f, 0xfc, 0x19, 0xfc, 0x08, 0xfd, 0x9d, 0xfd, 0x9b, 0xfd, 0xa9, 0xfd, 0x9a, 0xfd, 0x1b, 0xfd, 0xca, 0xfd, 0x69, 0xfd, 0x1a, 0xfd, 0x78, 0xfd, 0x71, 0xfd, 0x0d, 0xfe, 0xac, 0xfe, 0x74, 0xff, 0x9b, 0xff, 0xf3, 0xfe, 0x75, 0xff, 0x84, 0x00, 0x2f, 0x01, 0x88, 0x01, 0x12, 0x02, 0xb9, 0x01, 0x88, 0x02, 0x63, 0x03, 0x39, 0x04, 0x91, 0x04, 0x87, 0x04, 0x65, 0x04, 0x97, 0x03, 0x18, 0x03, 0x12, 0x03, 0xcb, 0x03, 0xa4, 0x03, 0xea, 0x02, 0x58, 0x02, 0x9c, 0x01, 0x39, 0x00, 0xe3, 0xff, 0x2d, 0xff, 0xc5, 0xfe, 0xb6, 0xfe, 0x80, 0xfe, 0x50, 0xfe, 0x38, 0xfe, 0x50, 0xfd, 0x12, 0xfc, 0xde, 0xfc, 0xff, 0xfd, 0x3d, 0xfe, 0xc4, 0xfe, 0xb1, 0xfe, 0xd4, 0xfe, 0x86, 0xfe, 0xcf, 0xfe, 0x4f, 0xff, 0x0e, 0xff, 0x38, 0xff, 0xa1, 0xfe, 0xff, 0xfe, 0xa0, 0xfe, 0xd2, 0xfe, 0x0f, 0xff, 0x9d, 0xfe, 0x56, 0xfe, 0x3b, 0xfe, 0xab, 0xfe, 0xc6, 0xff, 0x87, 0xff, 0x5f, 0xff, 0x36, 0xff, 0x2f, 0x00, 0xe6, 0x00, 0x04, 0x01, 0xb9, 0x01, 0x86, 0x02, 0xde, 0x02, 0x34, 0x03, 0x00, 0x04, 0x74, 0x04, 0x86, 0x04, 0x53, 0x05, 0x38, 0x06, 0xc9, 0x06, 0x15, 0x07, 0x73, 0x07, 0x7b, 0x07, 0x21, 0x07, 0x1e, 0x06, 0x3e, 0x05, 0x7a, 0x04, 0xc4, 0x03, 0xf5, 0x02, 0x3f, 0x02, 0xdf, 0x00, 0xf9, 0xfe, 0x26, 0xfd, 0x95, 0xfb, 0x01, 0xfa, 0x0e, 0xf9, 0x4b, 0xf8, 0xa2, 0xf7, 0x13, 0xf7, 0x4f, 0xf6, 0xb3, 0xf6, 0x2a, 0xf7, 0x46, 0xf7, 0x18, 0xf8, 0xf7, 0xf8, 0xd8, 0xf9, 0xa6, 0xfa, 0x36, 0xfa, 0xfe, 0xf9, 0x2f, 0xfb, 0x7b, 0xfc, 0x05, 0xfd, 0x4f, 0xfd, 0xbc, 0xfd, 0x6d, 0xfe, 0xb4, 0xfe, 0x2e, 0xff, 0xcf, 0xff, 0x9b, 0x00, 0xab, 0x01, 0x62, 0x02, 0xd2, 0x02, 0x00, 0x03, 0x68, 0x02, 0x8b, 0x01, 0xad, 0x01, 0x66, 0x02, 0x9c, 0x02, 0xfd, 0x02, 0x18, 0x03, 0x42, 0x02, 0x44, 0x01, 0x08, 0x01, 0xee, 0x00, 0x08, 0x00, 0xdd, 0xff, 0xd4, 0xff, 0xfa, 0xff, 0xd3, 0xff, 0x2d, 0xff, 0x03, 0xff, 0x6a, 0xff, 0x52, 0xff, 0x8a, 0xff, 0x61, 0xff, 0xd2, 0xff, 0x05, 0x01, 0x45, 0x02, 0x13, 0x03, 0x8c, 0x03, 0x48, 0x04, 0x50, 0x04, 0x34, 0x04, 0xbe, 0x03, 0x23, 0x03, 0xe3, 0x02, 0xd1, 0x02, 0xda, 0x02, 0x73, 0x03, 0x88, 0x03, 0xd4, 0x03, 0x16, 0x04, 0x12, 0x04, 0x5f, 0x04, 0xb4, 0x04, 0xea, 0x04, 0x43, 0x05, 0xd8, 0x05, 0x08, 0x06, 0x2e, 0x06, 0x33, 0x06, 0x07, 0x05, 0x7f, 0x03, 0xde, 0x02, 0x52, 0x02, 0xd4, 0x00, 0xd2, 0xff, 0xda, 0xfe, 0x8a, 0xfe, 0xb6, 0xfd, 0xfc, 0xfc, 0x57, 0xfc, 0xb5, 0xfb, 0xc1, 0xfa, 0x47, 0xfa, 0xc2, 0xf9, 0x0b, 0xf9, 0x70, 0xf8, 0xbc, 0xf7, 0xda, 0xf6, 0x05, 0xf6, 0x0e, 0xf6, 0xec, 0xf5, 0xde, 0xf6, 0xc4, 0xf6, 0x39, 0xf7, 0x27, 0xf8, 0x71, 0xf8, 0x36, 0xf9, 0x3c, 0xfa, 0xc4, 0xfb, 0xd6, 0xfc, 0xc2, 0xfd, 0xa5, 0xfe, 0x6f, 0xff, 0x05, 0x00, 0xba, 0x00, 0x98, 0x01, 0xb8, 0x02, 0xbb, 0x03, 0x4a, 0x04, 0x22, 0x05, 0xfa, 0x04, 0xae, 0x04, 0x14, 0x05, 0xb3, 0x05, 0x03, 0x06, 0x6e, 0x06, 0x2c, 0x06, 0xc9, 0x04, 0xa2, 0x03, 0x70, 0x02, 0x03, 0x01, 0x81, 0xff, 0xc4, 0xfe, 0xf3, 0xfd, 0x6c, 0xfd, 0x33, 0xfd, 0x37, 0xfd, 0x6b, 0xfc, 0xda, 0xfb, 0x42, 0xfc, 0xeb, 0xfb, 0xb4, 0xfb, 0xa4, 0xfb, 0x72, 0xfb, 0xe9, 0xfa, 0x06, 0xfb, 0x2b, 0xfb, 0xa3, 0xfb, 0x77, 0xfc, 0x7b, 0xfd, 0xee, 0xfe, 0x7f, 0x00, 0xb2, 0x01, 0x2b, 0x02, 0x28, 0x02, 0x54, 0x03, 0xbd, 0x03, 0x59, 0x03, 0x94, 0x03, 0xcd, 0x03, 0xd3, 0x03, 0x7e, 0x03, 0x7e, 0x03, 0x27, 0x03, 0x34, 0x03, 0x44, 0x03, 0x2d, 0x03, 0x72, 0x03, 0xd7, 0x02, 0x88, 0x02, 0x1f, 0x03, 0x71, 0x03, 0x92, 0x03, 0x9e, 0x03, 0x37, 0x03, 0x34, 0x03, 0xf9, 0x02, 0xd0, 0x02, 0x4a, 0x02, 0x09, 0x01, 0x33, 0x00, 0x93, 0xff, 0xe4, 0xfe, 0x1a, 0xfe, 0xda, 0xfd, 0x54, 0xfd, 0x93, 0xfc, 0xe1, 0xfb, 0xbd, 0xfb, 0xc3, 0xfb, 0x45, 0xfb, 0x47, 0xfa, 0x23, 0xf9, 0x07, 0xf9, 0x33, 0xf9, 0x0c, 0xf9, 0x58, 0xf9, 0x1a, 0xfa, 0x9d, 0xfb, 0x1c, 0xfc, 0x81, 0xfc, 0xc3, 0xfc, 0x49, 0xfd, 0xff, 0xfd, 0xc8, 0xfe, 0x3a, 0xff, 0x41, 0x00, 0x63, 0x01, 0xef, 0x01, 0xbd, 0x02, 0x19, 0x04, 0xaf, 0x04, 0xae, 0x04, 0x3f, 0x04, 0xd0, 0x03, 0xee, 0x02, 0x51, 0x02, 0xf4, 0x01, 0xdf, 0x01, 0xfb, 0x01, 0x7c, 0x02, 0xe0, 0x02, 0xee, 0x02, 0x1f, 0x03, 0xec, 0x02, 0x7a, 0x02, 0xd8, 0x01, 0xe2, 0x00, 0x7e, 0xff, 0x2f, 0xfe, 0x7f, 0xfd, 0x60, 0xfd, 0xb3, 0xfd, 0x26, 0xfd, 0x66, 0xfc, 0xb4, 0xfb, 0xa1, 0xfb, 0xd9, 0xfb, 0xbc, 0xfb, 0xb8, 0xfb, 0x50, 0xfc, 0x6f, 0xfd, 0x83, 0xfe, 0xc6, 0xfe, 0xf8, 0xfe, 0x59, 0xfe, 0xfb, 0xfd, 0x79, 0xfe, 0x36, 0xfe, 0xdd, 0xfe, 0x75, 0xff, 0xea, 0xff, 0xba, 0x00, 0xc9, 0x00, 0x38, 0x01, 0x21, 0x02, 0xc0, 0x02, 0xb1, 0x03, 0x8a, 0x04, 0x88, 0x05, 0x54, 0x06, 0x71, 0x06, 0x5c, 0x06, 0x6d, 0x06, 0x80, 0x06, 0xf9, 0x05, 0x5d, 0x05, 0x31, 0x05, 0x6c, 0x05, 0xd6, 0x04, 0x3d, 0x04, 0x74, 0x03, 0x78, 0x02, 0x60, 0x01, 0xb6, 0x00, 0x4a, 0x00, 0x94, 0xff, 0x87, 0xfe, 0x4a, 0xfd, 0x03, 0xfc, 0x1f, 0xfb, 0xfd, 0xf9, 0x53, 0xf9, 0xdd, 0xf8, 0xc3, 0xf8, 0x73, 0xf9, 0x34, 0xfa, 0x44, 0xfb, 0xcb, 0xfb, 0x97, 0xfb, 0x8a, 0xfb, 0x2f, 0xfc, 0x74, 0xfc, 0xd4, 0xfc, 0x8b, 0xfd, 0xab, 0xfe, 0xc0, 0xff, 0x72, 0x00, 0x34, 0x01, 0x87, 0x01, 0x8e, 0x01, 0x3e, 0x02, 0xf0, 0x02, 0xc5, 0x02, 0x0c, 0x03, 0xed, 0x02, 0x5a, 0x02, 0x82, 0x02, 0xe3, 0x02, 0x8f, 0x03, 0x5a, 0x03, 0x24, 0x03, 0x33, 0x03, 0x6a, 0x03, 0xaa, 0x03, 0xec, 0x03, 0xf4, 0x03, 0xa8, 0x03, 0x8b, 0x02, 0x1d, 0x01, 0x90, 0xff, 0x54, 0xfe, 0x91, 0xfd, 0x2d, 0xfd, 0xf5, 0xfc, 0x8c, 0xfc, 0xc3, 0xfb, 0x6d, 0xfb, 0x49, 0xfc, 0x73, 0xfc, 0xc2, 0xfc, 0x55, 0xfd, 0x15, 0xfe, 0x03, 0xff, 0x18, 0xff, 0x78, 0xfe, 0xa5, 0xfd, 0xb2, 0xfd, 0xc2, 0xfd, 0x9b, 0xfd, 0xaa, 0xfd, 0xf1, 0xfd, 0xf3, 0xfe, 0x7f, 0xff, 0x29, 0x00, 0x6d, 0x01, 0xdf, 0x02, 0xf7, 0x03, 0xf8, 0x04, 0x01, 0x06, 0x19, 0x07, 0xcf, 0x07, 0x0f, 0x08, 0x89, 0x08, 0xec, 0x08, 0xfb, 0x08, 0x51, 0x09, 0x13, 0x09, 0x60, 0x08, 0xe2, 0x07, 0x32, 0x07, 0x78, 0x06, 0x95, 0x05, 0x20, 0x04, 0x14, 0x02, 0xc5, 0x00, 0x1d, 0xff, 0x47, 0xfd, 0x99, 0xfb, 0x48, 0xfa, 0x0d, 0xf9, 0xfe, 0xf7, 0x87, 0xf7, 0x6a, 0xf7, 0xea, 0xf7, 0xff, 0xf7, 0x60, 0xf8, 0xed, 0xf8, 0x69, 0xf9, 0xd3, 0xf9, 0x5b, 0xfa, 0xcf, 0xfa, 0x6a, 0xfb, 0x6e, 0xfb, 0x48, 0xfb, 0xb6, 0xfb, 0xa9, 0xfc, 0x5c, 0xfd, 0x69, 0xfe, 0xf4, 0xfe, 0x8d, 0xff, 0xe0, 0xff, 0x3e, 0x00, 0xd5, 0x00, 0x76, 0x01, 0x13, 0x02, 0x16, 0x03, 0xdb, 0x03, 0x34, 0x04, 0xcd, 0x03, 0xb0, 0x02, 0xaf, 0x01, 0xd6, 0x00, 0xb9, 0xff, 0xe3, 0xfe, 0xcf, 0xfd, 0xbc, 0xfc, 0xd3, 0xfb, 0x1e, 0xfb, 0xf5, 0xfa, 0xd8, 0xfa, 0x0d, 0xfb, 0xc0, 0xfb, 0x46, 0xfc, 0x97, 0xfc, 0x76, 0xfc, 0x15, 0xfc, 0x2c, 0xfc, 0x2c, 0xfc, 0x49, 0xfc, 0x47, 0xfc, 0x81, 0xfc, 0xed, 0xfc, 0x04, 0xfe, 0x12, 0xff, 0xf7, 0xff, 0x63, 0x00, 0xaa, 0x00, 0x63, 0x01, 0xf7, 0x01, 0xf2, 0x01, 0x07, 0x02, 0x97, 0x02, 0x93, 0x02, 0xbd, 0x02, 0x83, 0x02, 0x51, 0x01, 0xc1, 0x00, 0x64, 0x00, 0x11, 0x00, 0xd7, 0xff, 0x84, 0xff, 0x57, 0xff, 0x26, 0xff, 0x64, 0xff, 0x00, 0x00, 0x71, 0x00, 0x73, 0x00, 0x1a, 0x00, 0xbb, 0xff, 0xd7, 0xff, 0xc4, 0xff, 0x71, 0xff, 0x98, 0xff, 0x00, 0xff, 0x9d, 0xfe, 0x05, 0xff, 0xd7, 0xff, 0x39, 0x00, 0x0c, 0x00, 0xe5, 0xff, 0x23, 0xff, 0xc3, 0xfe, 0xba, 0xfe, 0x81, 0xfe, 0x8b, 0xfe, 0xa6, 0xfe, 0xfe, 0xfe, 0xdd, 0xff, 0xb8, 0x00, 0xa6, 0x01, 0x52, 0x02, 0x96, 0x02, 0x2d, 0x03, 0x83, 0x03, 0xbf, 0x03, 0x1c, 0x04, 0x9f, 0x04, 0x69, 0x05, 0xda, 0x05, 0xfb, 0x05, 0xfc, 0x05, 0x70, 0x06, 0xa6, 0x06, 0x7c, 0x06, 0x08, 0x06, 0x68, 0x05, 0xeb, 0x04, 0x09, 0x04, 0xfa, 0x02, 0xc1, 0x01, 0x74, 0x00, 0x7e, 0xff, 0xba, 0xfe, 0x21, 0xfe, 0x4a, 0xfd, 0xb4, 0xfc, 0xca, 0xfb, 0xd9, 0xfa, 0xa7, 0xfa, 0xb9, 0xfa, 0xb9, 0xfa, 0xe3, 0xfa, 0xe9, 0xfa, 0xf9, 0xfa, 0x45, 0xfb, 0xe5, 0xfa, 0xc8, 0xfa, 0x78, 0xfa, 0x79, 0xfa, 0xf6, 0xfa, 0xf6, 0xfb, 0x53, 0xfd, 0x8e, 0xfe, 0xc8, 0xff, 0xc9, 0x00, 0x07, 0x01, 0x91, 0x01, 0x7a, 0x02, 0xe5, 0x02, 0x5a, 0x03, 0xbf, 0x03, 0x1f, 0x04, 0x61, 0x04, 0xac, 0x04, 0xdd, 0x04, 0xaa, 0x04, 0x76, 0x04, 0xb2, 0x03, 0x54, 0x03, 0x8b, 0x03, 0xae, 0x03, 0xc1, 0x03, 0x2e, 0x03, 0xa4, 0x02, 0x36, 0x02, 0xac, 0x01, 0xe0, 0x00, 0x39, 0x00, 0x25, 0x00, 0xe8, 0xff, 0x66, 0xff, 0x92, 0xfe, 0x14, 0xfe, 0x4b, 0xfd, 0xa0, 0xfc, 0x6b, 0xfc, 0x10, 0xfc, 0xf2, 0xfb, 0x86, 0xfb, 0x56, 0xfb, 0x0b, 0xfb, 0x73, 0xfa, 0x7c, 0xfa, 0x2c, 0xfb, 0xff, 0xfb, 0x02, 0xfd, 0xdf, 0xfd, 0x8b, 0xfe, 0x78, 0xff, 0xeb, 0xff, 0xeb, 0xff, 0x35, 0x00, 0x97, 0x00, 0x01, 0x01, 0xef, 0x00, 0xea, 0x00, 0xc0, 0x00, 0x7d, 0x00, 0xa0, 0x00, 0x2f, 0x01, 0xcb, 0x01, 0x38, 0x02, 0xad, 0x02, 0x37, 0x03, 0xa4, 0x03, 0x04, 0x04, 0xd4, 0x03, 0x7c, 0x03, 0x68, 0x03, 0x7d, 0x02, 0x3c, 0x01, 0x2d, 0x00, 0xc2, 0xff, 0xf5, 0xfe, 0x6e, 0xfe, 0xf0, 0xfd, 0xa0, 0xfd, 0xab, 0xfd, 0xb8, 0xfd, 0xf1, 0xfd, 0xf6, 0xfe, 0xd2, 0xff, 0x66, 0x00, 0xa0, 0x00, 0xf6, 0x00, 0x1d, 0x01, 0x7a, 0x00, 0x25, 0x00, 0xcf, 0xff, 0x7a, 0xff, 0x25, 0xff, 0xf8, 0xfe, 0xbc, 0xfe, 0xa3, 0xfe, 0xa5, 0xfe, 0xac, 0xfe, 0xe7, 0xfe, 0x26, 0xff, 0xd4, 0xfe, 0xc7, 0xfe, 0xde, 0xfe, 0x62, 0xfe, 0x08, 0xfe, 0xb6, 0xfd, 0x84, 0xfd, 0x2c, 0xfd, 0x09, 0xfd, 0x3a, 0xfd, 0x98, 0xfd, 0xd2, 0xfd, 0x18, 0xfe, 0xc8, 0xfd, 0xa5, 0xfd, 0xab, 0xfd, 0x6a, 0xfd, 0x55, 0xfd, 0xd3, 0xfc, 0x02, 0xfd, 0xb5, 0xfd, 0x1d, 0xfe, 0xa7, 0xfe, 0x48, 0xff, 0x68, 0xff, 0x9c, 0xff, 0x2e, 0x00, 0x71, 0x00, 0x94, 0x00, 0xca, 0x00, 0xa7, 0x00, 0xa4, 0x00, 0x0d, 0x01, 0x0e, 0x01, 0x31, 0x01, 0xb0, 0x01, 0x20, 0x02, 0x82, 0x02, 0x7b, 0x02, 0xe0, 0x02, 0x22, 0x03, 0x5f, 0x03, 0x71, 0x03, 0xaf, 0x03, 0xb7, 0x03, 0xa0, 0x03, 0xdc, 0x03, 0x0a, 0x04, 0x24, 0x04, 0x73, 0x04, 0xaa, 0x04, 0x9d, 0x04, 0x89, 0x04, 0xd6, 0x03, 0xee, 0x02, 0x33, 0x02, 0xb1, 0x01, 0x00, 0x01, 0xc5, 0x00, 0x5b, 0x00, 0x24, 0x00, 0xcd, 0xff, 0x46, 0xff, 0xa1, 0xfe, 0x1d, 0xfe, 0x53, 0xfe, 0xac, 0xfe, 0xfb, 0xfe, 0x3f, 0xff, 0xc4, 0xff, 0x6a, 0x00, 0x0a, 0x01, 0xbd, 0x01, 0xc1, 0x02, 0x13, 0x04, 0x20, 0x05, 0xf4, 0x05, 0xac, 0x06, 0x56, 0x07, 0x8e, 0x07, 0x86, 0x07, 0xb8, 0x07, 0x9a, 0x07, 0xea, 0x06, 0x0b, 0x06, 0xd7, 0x04, 0x7e, 0x03, 0xcf, 0x01, 0x2e, 0x00, 0xb1, 0xfe, 0x16, 0xfd, 0x7c, 0xfb, 0xfe, 0xf9, 0x9d, 0xf8, 0x40, 0xf7, 0x4a, 0xf6, 0x98, 0xf5, 0x3e, 0xf5, 0xde, 0xf4, 0x9b, 0xf4, 0x84, 0xf4, 0x96, 0xf4, 0x9a, 0xf4, 0x04, 0xf5, 0x6d, 0xf5, 0xcd, 0xf5, 0x06, 0xf6, 0x81, 0xf6, 0xff, 0xf6, 0xf7, 0xf7, 0x04, 0xf9, 0xfa, 0xf9, 0x35, 0xfb, 0xa5, 0xfc, 0x2e, 0xfe, 0x80, 0xff, 0xce, 0x00, 0xb9, 0x01, 0x8b, 0x02, 0x6e, 0x03, 0x30, 0x04, 0x77, 0x04, 0x9f, 0x04, 0x58, 0x05, 0xf4, 0x05, 0x26, 0x06, 0x1c, 0x06, 0x3d, 0x06, 0x51, 0x06, 0xda, 0x05, 0x8e, 0x05, 0xba, 0x05, 0x6f, 0x05, 0xcf, 0x04, 0x1f, 0x04, 0x25, 0x03, 0x7c, 0x02, 0xdb, 0x01, 0x10, 0x01, 0x89, 0x00, 0x8d, 0xff, 0xbd, 0xfe, 0x65, 0xfe, 0xde, 0xfd, 0xb9, 0xfd, 0x9e, 0xfd, 0x79, 0xfd, 0x12, 0xfd, 0x31, 0xfc, 0x43, 0xfb, 0xb7, 0xfa, 0x8d, 0xfa, 0x63, 0xfa, 0x8a, 0xfa, 0xf2, 0xfa, 0xb5, 0xfb, 0x29, 0xfc, 0x61, 0xfc, 0xde, 0xfc, 0x45, 0xfd, 0x8d, 0xfd, 0x43, 0xfe, 0x7b, 0xfe, 0x6a, 0xfe, 0xb5, 0xfe, 0x52, 0xff, 0xca, 0xff, 0x4e, 0x00, 0x90, 0x00, 0x72, 0x00, 0x12, 0x00, 0xaf, 0xff, 0xab, 0xff, 0xd0, 0xff, 0xb3, 0xff, 0x90, 0xff, 0xb8, 0xff, 0x64, 0x00, 0xdc, 0x00, 0x61, 0x01, 0xee, 0x01, 0x7d, 0x02, 0x11, 0x03, 0x96, 0x03, 0x0a, 0x04, 0xa9, 0x04, 0x58, 0x05, 0xab, 0x05, 0x52, 0x06, 0xfc, 0x06, 0xb7, 0x07, 0x14, 0x08, 0x48, 0x08, 0x91, 0x08, 0xc7, 0x08, 0x22, 0x08, 0x45, 0x07, 0x80, 0x06, 0x4b, 0x05, 0x0b, 0x04, 0xe5, 0x02, 0x4f, 0x01, 0x74, 0xff, 0xb5, 0xfd, 0x25, 0xfc, 0xee, 0xfa, 0xec, 0xf9, 0x48, 0xf9, 0xc6, 0xf8, 0x67, 0xf8, 0xf5, 0xf7, 0xc8, 0xf7, 0x5f, 0xf7, 0x01, 0xf7, 0xad, 0xf6, 0xc8, 0xf6, 0x19, 0xf7, 0x92, 0xf7, 0x04, 0xf8, 0xad, 0xf8, 0xeb, 0xf9, 0x09, 0xfb, 0x4a, 0xfc, 0xb2, 0xfd, 0xe9, 0xfe, 0xd8, 0xff, 0xab, 0x00, 0x39, 0x01, 0xc8, 0x01, 0x8c, 0x02, 0x54, 0x03, 0xca, 0x03, 0x57, 0x04, 0xa2, 0x04, 0xdb, 0x04, 0x4a, 0x05, 0xa6, 0x05, 0x40, 0x06, 0xca, 0x06, 0x1e, 0x07, 0x35, 0x07, 0xd9, 0x06, 0x61, 0x06, 0x87, 0x05, 0xb0, 0x04, 0xad, 0x03, 0xeb, 0x02, 0x68, 0x02, 0xb9, 0x01, 0x0c, 0x01, 0x55, 0x00, 0x65, 0xff, 0x94, 0xfe, 0xfe, 0xfd, 0x85, 0xfd, 0xa3, 0xfc, 0xdb, 0xfb, 0x6b, 0xfb, 0x33, 0xfb, 0x23, 0xfb, 0x53, 0xfb, 0x85, 0xfb, 0x84, 0xfb, 0x70, 0xfb, 0x98, 0xfb, 0x14, 0xfc, 0x75, 0xfc, 0xde, 0xfc, 0x22, 0xfd, 0x81, 0xfd, 0xd4, 0xfd, 0x00, 0xfe, 0x4f, 0xfe, 0x4e, 0xfe, 0x71, 0xfe, 0x06, 0xff, 0x26, 0xff, 0x72, 0xff, 0xaf, 0xff, 0x03, 0x00, 0x5a, 0x00, 0xac, 0x00, 0x51, 0x01, 0x2e, 0x02, 0xec, 0x02, 0x7d, 0x03, 0x23, 0x04, 0x8e, 0x04, 0x86, 0x04, 0x62, 0x04, 0x06, 0x04, 0xd3, 0x03, 0xa1, 0x03, 0xc1, 0x02, 0x12, 0x02, 0x98, 0x01, 0x76, 0x01, 0x82, 0x01, 0x9b, 0x01, 0xb9, 0x01, 0xb4, 0x01, 0x27, 0x01, 0xd7, 0x00, 0xcb, 0x00, 0x8d, 0x00, 0xfe, 0xff, 0xad, 0xff, 0x58, 0xff, 0x2f, 0xff, 0xca, 0xfe, 0x53, 0xfe, 0x01, 0xfe, 0x09, 0xfe, 0x16, 0xfe, 0x18, 0xfe, 0x45, 0xfe, 0x91, 0xfe, 0x34, 0xff, 0xc6, 0xff, 0x42, 0x00, 0xd4, 0x00, 0x6c, 0x01, 0xd4, 0x01, 0x33, 0x02, 0x8c, 0x02, 0xd6, 0x02, 0xda, 0x02, 0x14, 0x03, 0xc1, 0x03, 0x39, 0x04, 0x4f, 0x04, 0x23, 0x04, 0xf0, 0x03, 0x54, 0x03, 0xb2, 0x02, 0x33, 0x02, 0x92, 0x01, 0xee, 0x00, 0x47, 0x00, 0xe6, 0xff, 0x82, 0xff, 0x0e, 0xff, 0x81, 0xfe, 0x27, 0xfe, 0xb9, 0xfd, 0xf6, 0xfc, 0xcd, 0xfb, 0xe1, 0xfa, 0xf4, 0xf9, 0x51, 0xf9, 0xdd, 0xf8, 0x90, 0xf8, 0xa8, 0xf8, 0xfe, 0xf8, 0x5e, 0xf9, 0xfc, 0xf9, 0xbd, 0xfa, 0x24, 0xfb, 0xb1, 0xfb, 0x66, 0xfc, 0xd8, 0xfc, 0x32, 0xfd, 0x8b, 0xfd, 0x86, 0xfd, 0xbc, 0xfd, 0xd4, 0xfd, 0x99, 0xfd, 0x80, 0xfd, 0x90, 0xfd, 0xbe, 0xfd, 0x12, 0xfe, 0x27, 0xfe, 0x6f, 0xfe, 0xbf, 0xfe, 0x29, 0xff, 0x98, 0xff, 0x26, 0x00, 0xb2, 0x00, 0x55, 0x01, 0x77, 0x02, 0x5b, 0x03, 0x07, 0x04, 0x9c, 0x04, 0x2a, 0x05, 0xb4, 0x05, 0x1a, 0x06, 0x55, 0x06, 0x54, 0x06, 0xee, 0x05, 0x6b, 0x05, 0x22, 0x05, 0xdc, 0x04, 0xed, 0x03, 0xe8, 0x02, 0x7d, 0x01, 0xff, 0xff, 0x02, 0xff, 0x49, 0xfe, 0xbd, 0xfd, 0x27, 0xfd, 0x81, 0xfc, 0x05, 0xfc, 0xd7, 0xfb, 0xe5, 0xfb, 0x22, 0xfc, 0x64, 0xfc, 0x73, 0xfc, 0x8f, 0xfc, 0x7b, 0xfc, 0x81, 0xfc, 0x78, 0xfc, 0x81, 0xfc, 0x61, 0xfc, 0x8c, 0xfc, 0x20, 0xfd, 0x82, 0xfd, 0xfa, 0xfd, 0xac, 0xfe, 0xbe, 0xff, 0x78, 0x00, 0x2f, 0x01, 0xec, 0x01, 0x8d, 0x02, 0x33, 0x03, 0xcf, 0x03, 0x38, 0x04, 0x93, 0x04, 0xa5, 0x04, 0x7a, 0x04, 0x2e, 0x04, 0x0c, 0x04, 0xa1, 0x03, 0xf3, 0x02, 0xc9, 0x01, 0x95, 0x00, 0xef, 0xff, 0xc7, 0xff, 0xa1, 0xff, 0x62, 0xff, 0x19, 0xff, 0x23, 0xff, 0xe7, 0xfe, 0xc6, 0xfe, 0xb3, 0xfe, 0xef, 0xfe, 0x25, 0xff, 0x1c, 0xff, 0x1d, 0xff, 0x84, 0xff, 0x00, 0x00, 0x6c, 0x00, 0x13, 0x01, 0xb7, 0x01, 0x63, 0x02, 0xd8, 0x02, 0x88, 0x03, 0x10, 0x04, 0x8e, 0x04, 0x0c, 0x05, 0xa0, 0x05, 0x28, 0x06, 0x3c, 0x06, 0xa0, 0x05, 0xc3, 0x04, 0x8c, 0x03, 0xa5, 0x02, 0xd5, 0x01, 0xde, 0x00, 0xc1, 0xff, 0xff, 0xfe, 0xf4, 0xfd, 0xee, 0xfc, 0x47, 0xfc, 0x71, 0xfb, 0x92, 0xfa, 0xd3, 0xf9, 0x36, 0xf9, 0xc0, 0xf8, 0x76, 0xf8, 0x1d, 0xf8, 0x92, 0xf7, 0x50, 0xf7, 0x32, 0xf7, 0xa2, 0xf7, 0x1f, 0xf8, 0xd5, 0xf8, 0xe0, 0xf9, 0xf2, 0xfa, 0xf2, 0xfb, 0xec, 0xfc, 0xe9, 0xfd, 0xe8, 0xfe, 0xcf, 0xff, 0x05, 0x01, 0x59, 0x02, 0xc1, 0x03, 0xaf, 0x04, 0x36, 0x05, 0x94, 0x05, 0xc7, 0x05, 0x1b, 0x06, 0x68, 0x06, 0x5f, 0x06, 0x53, 0x06, 0x43, 0x06, 0x56, 0x06, 0x58, 0x06, 0x10, 0x06, 0x96, 0x05, 0x45, 0x05, 0xde, 0x04, 0x12, 0x04, 0x76, 0x03, 0x03, 0x03, 0xe6, 0x02, 0x7d, 0x02, 0x23, 0x02, 0xcf, 0x01, 0xc7, 0x01, 0x89, 0x01, 0x6b, 0x01, 0x95, 0x01, 0xce, 0x01, 0xaf, 0x01, 0x5a, 0x01, 0x9d, 0x00, 0xee, 0xff, 0x34, 0xff, 0x4d, 0xfe, 0x7b, 0xfd, 0xbf, 0xfc, 0x07, 0xfc, 0x2b, 0xfb, 0x62, 0xfa, 0x7d, 0xf9, 0xe7, 0xf8, 0x3b, 0xf8, 0xc5, 0xf7, 0xa0, 0xf7, 0xa9, 0xf7, 0xd9, 0xf7, 0x11, 0xf8, 0x63, 0xf8, 0xb6, 0xf8, 0x35, 0xf9, 0xbf, 0xf9, 0x33, 0xfa, 0xb3, 0xfa, 0x44, 0xfb, 0xe4, 0xfb, 0x93, 0xfc, 0x3a, 0xfd, 0x36, 0xfe, 0x43, 0xff, 0x79, 0x00, 0x5e, 0x01, 0x36, 0x02, 0xb9, 0x02, 0x48, 0x03, 0xd8, 0x03, 0x78, 0x04, 0x6b, 0x05, 0x41, 0x06, 0xa6, 0x06, 0x8b, 0x06, 0x5f, 0x06, 0x80, 0x05, 0xb4, 0x04, 0x38, 0x04, 0x73, 0x03, 0x7a, 0x02, 0x79, 0x01, 0x6c, 0x00, 0xf7, 0xff, 0x94, 0xff, 0x06, 0xff, 0xa9, 0xfe, 0x5c, 0xfe, 0x19, 0xfe, 0x1b, 0xfe, 0x2e, 0xfe, 0x7c, 0xfe, 0xce, 0xfe, 0x3f, 0xff, 0x5a, 0xff, 0x4a, 0xff, 0x57, 0xff, 0x4f, 0xff, 0x22, 0xff, 0x2d, 0xff, 0x71, 0xff, 0xdb, 0xff, 0x0d, 0x00, 0x1b, 0x00, 0x5f, 0x00, 0x9b, 0x00, 0xfe, 0x00, 0x85, 0x01, 0xbc, 0x01, 0xf2, 0x01, 0x0e, 0x02, 0x3b, 0x02, 0x7e, 0x02, 0xa8, 0x02, 0x8f, 0x02, 0x68, 0x02, 0x35, 0x02, 0x95, 0x01, 0xe7, 0x00, 0x36, 0x00, 0x94, 0xff, 0x0f, 0xff, 0x8a, 0xfe, 0x68, 0xfe, 0x9d, 0xfe, 0xf1, 0xfe, 0x53, 0xff, 0xe9, 0xff, 0xa3, 0x00, 0x19, 0x01, 0x7a, 0x01, 0x77, 0x01, 0x79, 0x01, 0x14, 0x01, 0xa3, 0x00, 0xfb, 0xff, 0x93, 0xff, 0x0e, 0xff, 0x75, 0xfe, 0xe6, 0xfd, 0x41, 0xfd, 0xf0, 0xfc, 0xec, 0xfc, 0xed, 0xfc, 0x35, 0xfd, 0xb8, 0xfd, 0xf5, 0xfd, 0xec, 0xfd, 0xb3, 0xfd, 0x62, 0xfd, 0x02, 0xfd, 0xe2, 0xfc, 0xa1, 0xfc, 0xa2, 0xfc, 0xa8, 0xfc, 0xd2, 0xfc, 0xf2, 0xfc, 0xf4, 0xfc, 0x18, 0xfd, 0x56, 0xfd, 0x62, 0xfd, 0xa1, 0xfd, 0x22, 0xfe, 0xa7, 0xfe, 0x4d, 0xff, 0xf1, 0xff, 0x90, 0x00, 0x00, 0x01, 0xa3, 0x01, 0x77, 0x02, 0x65, 0x03, 0x55, 0x04, 0x04, 0x05, 0x6d, 0x05, 0xe4, 0x05, 0xf9, 0x05, 0xbd, 0x05, 0x3e, 0x05, 0xb2, 0x04, 0x33, 0x04, 0x49, 0x03, 0x21, 0x02, 0xe8, 0x00, 0xd4, 0xff, 0x09, 0xff, 0x6f, 0xfe, 0xf9, 0xfd, 0x7d, 0xfd, 0x1b, 0xfd, 0xcd, 0xfc, 0xf2, 0xfc, 0x68, 0xfd, 0xee, 0xfd, 0x60, 0xfe, 0x94, 0xfe, 0x70, 0xfe, 0x25, 0xfe, 0x0b, 0xfe, 0xe8, 0xfd, 0xa7, 0xfd, 0x56, 0xfd, 0xf3, 0xfc, 0xf3, 0xfc, 0x57, 0xfd, 0xb1, 0xfd, 0x0d, 0xfe, 0xa0, 0xfe, 0x24, 0xff, 0xaf, 0xff, 0x0b, 0x00, 0x58, 0x00, 0x97, 0x00, 0xd7, 0x00, 0x66, 0x01, 0xff, 0x01, 0x83, 0x02, 0xf4, 0x02, 0x43, 0x03, 0x53, 0x03, 0x6e, 0x03, 0x44, 0x03, 0x00, 0x03, 0xe3, 0x02, 0x96, 0x02, 0x16, 0x02, 0x8b, 0x01, 0xd1, 0x00, 0x31, 0x00, 0xd4, 0xff, 0x97, 0xff, 0x48, 0xff, 0xed, 0xfe, 0x64, 0xfe, 0xdf, 0xfd, 0xac, 0xfd, 0x95, 0xfd, 0x7a, 0xfd, 0xc9, 0xfd, 0x42, 0xfe, 0xd9, 0xfe, 0xf4, 0xfe, 0x92, 0xfe, 0x20, 0xfe, 0xad, 0xfd, 0x6a, 0xfd, 0x32, 0xfd, 0x19, 0xfd, 0xdd, 0xfc, 0xfb, 0xfc, 0x66, 0xfd, 0xd7, 0xfd, 0x6b, 0xfe, 0x03, 0xff, 0x79, 0xff, 0xce, 0xff, 0x1e, 0x00, 0x8f, 0x00, 0x0d, 0x01, 0x6e, 0x01, 0x41, 0x02, 0x46, 0x03, 0x0a, 0x04, 0x7e, 0x04, 0xa3, 0x04, 0x39, 0x04, 0xb5, 0x03, 0x44, 0x03, 0x8d, 0x02, 0xc4, 0x01, 0x58, 0x01, 0x11, 0x01, 0xc0, 0x00, 0x02, 0x00, 0x0a, 0xff, 0x14, 0xfe, 0x4f, 0xfd, 0xe0, 0xfc, 0x8c, 0xfc, 0x72, 0xfc, 0x86, 0xfc, 0xd1, 0xfc, 0x02, 0xfd, 0xff, 0xfc, 0x21, 0xfd, 0x71, 0xfd, 0xcf, 0xfd, 0x42, 0xfe, 0xf0, 0xfe, 0xd4, 0xff, 0xbe, 0x00, 0x7e, 0x01, 0xe4, 0x01, 0x51, 0x02, 0x89, 0x02, 0xc3, 0x02, 0xff, 0x02, 0x6b, 0x03, 0xb7, 0x03, 0xb5, 0x03, 0x60, 0x03, 0x03, 0x03, 0xaf, 0x02, 0x72, 0x02, 0x46, 0x02, 0x27, 0x02, 0x12, 0x02, 0xa6, 0x01, 0xcc, 0x00, 0xba, 0xff, 0xd8, 0xfe, 0xcd, 0xfd, 0xff, 0xfc, 0x60, 0xfc, 0x06, 0xfc, 0x15, 0xfc, 0x30, 0xfc, 0x7c, 0xfc, 0xad, 0xfc, 0xcd, 0xfc, 0xba, 0xfc, 0xcd, 0xfc, 0xad, 0xfc, 0x99, 0xfc, 0xa3, 0xfc, 0xe9, 0xfc, 0x0c, 0xfd, 0x48, 0xfd, 0xa5, 0xfd, 0x29, 0xfe, 0xdf, 0xfe, 0x83, 0xff, 0x19, 0x00, 0x99, 0x00, 0xc9, 0x00, 0xd9, 0x00, 0xa9, 0x00, 0x8c, 0x00, 0xdf, 0x00, 0x49, 0x01, 0x9b, 0x01, 0xe9, 0x01, 0x11, 0x02, 0x31, 0x02, 0x9d, 0x02, 0x36, 0x03, 0xa9, 0x03, 0x0e, 0x04, 0x63, 0x04, 0x8d, 0x04, 0x99, 0x04, 0x60, 0x04, 0x16, 0x04, 0x95, 0x03, 0xbb, 0x02, 0xfa, 0x01, 0x57, 0x01, 0xc4, 0x00, 0x4e, 0x00, 0xcc, 0xff, 0x1b, 0xff, 0x7a, 0xfe, 0xf4, 0xfd, 0x89, 0xfd, 0x6a, 0xfd, 0x72, 0xfd, 0x5c, 0xfd, 0x68, 0xfd, 0x64, 0xfd, 0x67, 0xfd, 0xab, 0xfd, 0xdd, 0xfd, 0x1e, 0xfe, 0x4e, 0xfe, 0xb9, 0xfe, 0x29, 0xff, 0xae, 0xff, 0x60, 0x00, 0x4d, 0x01, 0x71, 0x02, 0x58, 0x03, 0x2c, 0x04, 0xc9, 0x04, 0x12, 0x05, 0xf3, 0x04, 0xc6, 0x04, 0x2e, 0x04, 0x40, 0x03, 0x91, 0x02, 0x05, 0x02, 0x38, 0x01, 0x57, 0x00, 0x2d, 0xff, 0xc1, 0xfd, 0x8f, 0xfc, 0x9f, 0xfb, 0xbb, 0xfa, 0x0f, 0xfa, 0x7a, 0xf9, 0x1f, 0xf9, 0xfe, 0xf8, 0x13, 0xf9, 0x30, 0xf9, 0x78, 0xf9, 0xea, 0xf9, 0x97, 0xfa, 0x40, 0xfb, 0xbb, 0xfb, 0x5a, 0xfc, 0x0c, 0xfd, 0xa8, 0xfd, 0x39, 0xfe, 0xbe, 0xfe, 0x38, 0xff, 0xdd, 0xff, 0x8d, 0x00, 0x2d, 0x01, 0x01, 0x02, 0xf7, 0x02, 0xe3, 0x03, 0xaf, 0x04, 0x6e, 0x05, 0xfd, 0x05, 0x56, 0x06, 0x83, 0x06, 0x99, 0x06, 0xe4, 0x06, 0xf7, 0x06, 0xcd, 0x06, 0x65, 0x06, 0xc2, 0x05, 0xe8, 0x04, 0x1b, 0x04, 0x66, 0x03, 0x9b, 0x02, 0xc3, 0x01, 0xa5, 0x00, 0x8f, 0xff, 0x8b, 0xfe, 0x7f, 0xfd, 0xca, 0xfc, 0x78, 0xfc, 0x44, 0xfc, 0x54, 0xfc, 0x36, 0xfc, 0x00, 0xfc, 0xcb, 0xfb, 0x89, 0xfb, 0x9f, 0xfb, 0xe7, 0xfb, 0x0c, 0xfc, 0x2c, 0xfc, 0x5c, 0xfc, 0x9a, 0xfc, 0xe4, 0xfc, 0x39, 0xfd, 0x89, 0xfd, 0xb2, 0xfd, 0xfe, 0xfd, 0x3b, 0xfe, 0x77, 0xfe, 0x9c, 0xfe, 0x9e, 0xfe, 0x9e, 0xfe, 0xcb, 0xfe, 0xa6, 0xfe, 0x94, 0xfe, 0x84, 0xfe, 0x91, 0xfe, 0xaf, 0xfe, 0xb6, 0xfe, 0xe7, 0xfe, 0x12, 0xff, 0x55, 0xff, 0x9a, 0xff, 0xb2, 0xff, 0xec, 0xff, 0x5e, 0x00, 0xf4, 0x00, 0x99, 0x01, 0x43, 0x02, 0xe1, 0x02, 0x88, 0x03, 0xff, 0x03, 0x2e, 0x04, 0xea, 0x03, 0x5f, 0x03, 0xdd, 0x02, 0xa0, 0x02, 0x6e, 0x02, 0x30, 0x02, 0x01, 0x02, 0xa0, 0x01, 0x1b, 0x01, 0x83, 0x00, 0xe5, 0xff, 0x1a, 0xff, 0x85, 0xfe, 0x1d, 0xfe, 0xc9, 0xfd, 0x7e, 0xfd, 0x6a, 0xfd, 0xbf, 0xfd, 0x07, 0xfe, 0x67, 0xfe, 0xf4, 0xfe, 0x72, 0xff, 0xcf, 0xff, 0x1e, 0x00, 0x37, 0x00, 0x80, 0x00, 0xe0, 0x00, 0xeb, 0x00, 0xca, 0x00, 0x81, 0x00, 0x24, 0x00, 0x07, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x0b, 0x00, 0xfd, 0xff, 0xbc, 0xff, 0x58, 0xff, 0x0c, 0xff, 0xa3, 0xfe, 0x53, 0xfe, 0x27, 0xfe, 0x20, 0xfe, 0x37, 0xfe, 0x44, 0xfe, 0x70, 0xfe, 0x71, 0xfe, 0x8f, 0xfe, 0xd9, 0xfe, 0x3c, 0xff, 0x84, 0xff, 0xe7, 0xff, 0x7b, 0x00, 0x13, 0x01, 0xdc, 0x01, 0xa9, 0x02, 0x60, 0x03, 0x1e, 0x04, 0x87, 0x04, 0x92, 0x04, 0xac, 0x04, 0xa2, 0x04, 0x72, 0x04, 0x5a, 0x04, 0x63, 0x04, 0x75, 0x04, 0x67, 0x04, 0xfe, 0x03, 0x79, 0x03, 0xbe, 0x02, 0xe7, 0x01, 0x5f, 0x01, 0xe1, 0x00, 0x3b, 0x00, 0x98, 0xff, 0xf4, 0xfe, 0x43, 0xfe, 0x92, 0xfd, 0xc9, 0xfc, 0x01, 0xfc, 0x4f, 0xfb, 0xc3, 0xfa, 0x6c, 0xfa, 0x68, 0xfa, 0xc8, 0xfa, 0x4d, 0xfb, 0xac, 0xfb, 0xe6, 0xfb, 0xe1, 0xfb, 0xbd, 0xfb, 0xa2, 0xfb, 0xa9, 0xfb, 0xcf, 0xfb, 0xd3, 0xfb, 0xef, 0xfb, 0x09, 0xfc, 0x2a, 0xfc, 0x8d, 0xfc, 0xe6, 0xfc, 0x05, 0xfd, 0x09, 0xfd, 0x1a, 0xfd, 0x4d, 0xfd, 0xae, 0xfd, 0x2a, 0xfe, 0xf6, 0xfe, 0xc2, 0xff, 0x9b, 0x00, 0x4a, 0x01, 0x26, 0x02, 0xc3, 0x02, 0x5c, 0x03, 0xfd, 0x03, 0xc0, 0x04, 0x07, 0x05, 0x31, 0x05, 0x49, 0x05, 0x3d, 0x05, 0x2e, 0x05, 0xca, 0x04, 0xac, 0x04, 0x62, 0x04, 0xe3, 0x03, 0x6f, 0x03, 0x54, 0x03, 0x0e, 0x03, 0xa1, 0x02, 0x3c, 0x02, 0xc3, 0x01, 0x4a, 0x01, 0xcb, 0x00, 0x10, 0x00, 0x3a, 0xff, 0x61, 0xfe, 0xb3, 0xfd, 0x50, 0xfd, 0xf7, 0xfc, 0x8f, 0xfc, 0x41, 0xfc, 0x03, 0xfc, 0xee, 0xfb, 0x31, 0xfc, 0x7e, 0xfc, 0xec, 0xfc, 0x67, 0xfd, 0xcf, 0xfd, 0x15, 0xfe, 0x89, 0xfe, 0x02, 0xff, 0x01, 0xff, 0xf5, 0xfe, 0xe1, 0xfe, 0xf2, 0xfe, 0xfc, 0xfe, 0xf1, 0xfe, 0xe4, 0xfe, 0xbb, 0xfe, 0xde, 0xfe, 0x2b, 0xff, 0x92, 0xff, 0x8e, 0xff, 0x5d, 0xff, 0x28, 0xff, 0x55, 0xff, 0xb4, 0xff, 0x2a, 0x00, 0x7b, 0x00, 0xdc, 0x00, 0x7e, 0x01, 0x55, 0x02, 0x26, 0x03, 0x08, 0x04, 0xc2, 0x04, 0x45, 0x05, 0x8e, 0x05, 0x97, 0x05, 0x5d, 0x05, 0xd5, 0x04, 0x30, 0x04, 0x64, 0x03, 0xb4, 0x02, 0xee, 0x01, 0x05, 0x01, 0x3f, 0x00, 0x9d, 0xff, 0x1e, 0xff, 0xe4, 0xfe, 0x94, 0xfe, 0xf6, 0xfd, 0x70, 0xfd, 0xdc, 0xfc, 0x6c, 0xfc, 0x52, 0xfc, 0x46, 0xfc, 0x5a, 0xfc, 0xae, 0xfc, 0x0a, 0xfd, 0x76, 0xfd, 0xe2, 0xfd, 0x69, 0xfe, 0xda, 0xfe, 0x34, 0xff, 0x88, 0xff, 0xe1, 0xff, 0x07, 0x00, 0xcf, 0xff, 0xc5, 0xff, 0xa3, 0xff, 0x92, 0xff, 0x78, 0xff, 0x2b, 0xff, 0xb7, 0xfe, 0x5a, 0xfe, 0x18, 0xfe, 0xed, 0xfd, 0xf0, 0xfd, 0xf3, 0xfd, 0xfc, 0xfd, 0x01, 0xfe, 0x0a, 0xfe, 0x38, 0xfe, 0xa7, 0xfe, 0x13, 0xff, 0x57, 0xff, 0x7a, 0xff, 0x6e, 0xff, 0x60, 0xff, 0x7a, 0xff, 0x9b, 0xff, 0xdc, 0xff, 0xe6, 0xff, 0xba, 0xff, 0x77, 0xff, 0x6b, 0xff, 0x75, 0xff, 0x81, 0xff, 0xb7, 0xff, 0xe8, 0xff, 0x59, 0x00, 0xff, 0x00, 0xa7, 0x01, 0x75, 0x02, 0x0b, 0x03, 0x86, 0x03, 0x08, 0x04, 0x55, 0x04, 0x19, 0x04, 0xb6, 0x03, 0x2d, 0x03, 0x82, 0x02, 0xee, 0x01, 0x72, 0x01, 0x0e, 0x01, 0xc4, 0x00, 0x82, 0x00, 0x4a, 0x00, 0xda, 0xff, 0x5b, 0xff, 0xf1, 0xfe, 0xc9, 0xfe, 0xa3, 0xfe, 0xb9, 0xfe, 0x18, 0xff, 0xa4, 0xff, 0xf6, 0xff, 0x26, 0x00, 0x33, 0x00, 0x4b, 0x00, 0x62, 0x00, 0x4b, 0x00, 0x4b, 0x00, 0x8e, 0x00, 0xe1, 0x00, 0x37, 0x01, 0x81, 0x01, 0x89, 0x01, 0x85, 0x01, 0x61, 0x01, 0x64, 0x01, 0xcd, 0x01, 0x03, 0x02, 0x15, 0x02, 0xf4, 0x01, 0xba, 0x01, 0x6f, 0x01, 0x39, 0x01, 0x12, 0x01, 0xb6, 0x00, 0x3a, 0x00, 0x5d, 0xff, 0x6b, 0xfe, 0x8f, 0xfd, 0xa5, 0xfc, 0x10, 0xfc, 0x94, 0xfb, 0x22, 0xfb, 0xb9, 0xfa, 0x7d, 0xfa, 0x3a, 0xfa, 0x37, 0xfa, 0x66, 0xfa, 0xae, 0xfa, 0xf3, 0xfa, 0x1b, 0xfb, 0x27, 0xfb, 0x55, 0xfb, 0xc6, 0xfb, 0x75, 0xfc, 0x4a, 0xfd, 0x26, 0xfe, 0xa9, 0xfe, 0x5a, 0xff, 0x2b, 0x00, 0xd4, 0x00, 0x6a, 0x01, 0xd7, 0x01, 0x72, 0x02, 0x10, 0x03, 0x92, 0x03, 0xe7, 0x03, 0x2f, 0x04, 0x70, 0x04, 0xaf, 0x04, 0x0b, 0x05, 0x40, 0x05, 0x4d, 0x05, 0x6d, 0x05, 0x65, 0x05, 0x7f, 0x05, 0x92, 0x05, 0x93, 0x05, 0xc3, 0x05, 0xfe, 0x05, 0xe1, 0x05, 0xbb, 0x05, 0x27, 0x05, 0x52, 0x04, 0x70, 0x03, 0x53, 0x02, 0x34, 0x01, 0xcc, 0xff, 0x66, 0xfe, 0xfb, 0xfc, 0xe0, 0xfb, 0x16, 0xfb, 0x84, 0xfa, 0x0f, 0xfa, 0x58, 0xf9, 0x92, 0xf8, 0xfa, 0xf7, 0xab, 0xf7, 0x95, 0xf7, 0x96, 0xf7, 0xa6, 0xf7, 0xce, 0xf7, 0x48, 0xf8, 0xfc, 0xf8, 0xd3, 0xf9, 0xda, 0xfa, 0xf0, 0xfb, 0xf6, 0xfc, 0xff, 0xfd, 0xbf, 0xfe, 0x38, 0xff, 0xdf, 0xff, 0x8e, 0x00, 0x2c, 0x01, 0xec, 0x01, 0xa9, 0x02, 0x6e, 0x03, 0x39, 0x04, 0xe7, 0x04, 0x87, 0x05, 0x59, 0x06, 0xfe, 0x06, 0x9e, 0x07, 0x00, 0x08, 0x1d, 0x08, 0xf0, 0x07, 0xb2, 0x07, 0x2b, 0x07, 0x95, 0x06, 0xc3, 0x05, 0x06, 0x05, 0x38, 0x04, 0x37, 0x03, 0x02, 0x02, 0xe0, 0x00, 0xd0, 0xff, 0xe6, 0xfe, 0x54, 0xfe, 0xc7, 0xfd, 0x78, 0xfd, 0x26, 0xfd, 0xd7, 0xfc, 0xbf, 0xfc, 0xf6, 0xfc, 0x1f, 0xfd, 0x4d, 0xfd, 0xa4, 0xfd, 0xe8, 0xfd, 0xfe, 0xfd, 0x03, 0xfe, 0xc2, 0xfd, 0x80, 0xfd, 0x7a, 0xfd, 0xa8, 0xfd, 0xf2, 0xfd, 0x22, 0xfe, 0x1b, 0xfe, 0x33, 0xfe, 0x5f, 0xfe, 0xe5, 0xfe, 0x94, 0xff, 0x1c, 0x00, 0x49, 0x00, 0x6b, 0x00, 0x60, 0x00, 0x70, 0x00, 0x5c, 0x00, 0x78, 0x00, 0x6b, 0x00, 0x41, 0x00, 0xea, 0xff, 0x93, 0xff, 0x19, 0xff, 0xbd, 0xfe, 0x6e, 0xfe, 0x34, 0xfe, 0x11, 0xfe, 0x15, 0xfe, 0x50, 0xfe, 0x6e, 0xfe, 0xa1, 0xfe, 0xd7, 0xfe, 0x15, 0xff, 0x2f, 0xff, 0x26, 0xff, 0x1b, 0xff, 0x30, 0xff, 0x56, 0xff, 0x60, 0xff, 0x58, 0xff, 0x23, 0xff, 0x1b, 0xff, 0x38, 0xff, 0x65, 0xff, 0x6a, 0xff, 0x54, 0xff, 0x67, 0xff, 0xa1, 0xff, 0xe9, 0xff, 0x72, 0x00, 0xfa, 0x00, 0xb1, 0x01, 0x46, 0x02, 0xa5, 0x02, 0xc3, 0x02, 0xea, 0x02, 0xc0, 0x02, 0xb7, 0x02, 0x9e, 0x02, 0x5a, 0x02, 0x21, 0x02, 0x98, 0x01, 0x29, 0x01, 0xd7, 0x00, 0x7c, 0x00, 0x32, 0x00, 0x08, 0x00, 0xf6, 0xff, 0x9b, 0xff, 0x5e, 0xff, 0x16, 0xff, 0xbb, 0xfe, 0x4d, 0xfe, 0xd3, 0xfd, 0x90, 0xfd, 0x51, 0xfd, 0xf2, 0xfc, 0x98, 0xfc, 0x52, 0xfc, 0x19, 0xfc, 0x01, 0xfc, 0xeb, 0xfb, 0xcd, 0xfb, 0xc3, 0xfb, 0xf9, 0xfb, 0x52, 0xfc, 0xbf, 0xfc, 0x4a, 0xfd, 0xfa, 0xfd, 0xc2, 0xfe, 0x84, 0xff, 0x11, 0x00, 0x9b, 0x00, 0xeb, 0x00, 0xfe, 0x00, 0x16, 0x01, 0x3a, 0x01, 0x45, 0x01, 0x6a, 0x01, 0x69, 0x01, 0x5b, 0x01, 0x4a, 0x01, 0x1f, 0x01, 0xe4, 0x00, 0x97, 0x00, 0x66, 0x00, 0x5c, 0x00, 0x5d, 0x00, 0x59, 0x00, 0x77, 0x00, 0xa7, 0x00, 0xe3, 0x00, 0x51, 0x01, 0x00, 0x02, 0x93, 0x02, 0x30, 0x03, 0xb1, 0x03, 0x39, 0x04, 0xa0, 0x04, 0xa1, 0x04, 0x8c, 0x04, 0x4f, 0x04, 0xf9, 0x03, 0x82, 0x03, 0xfb, 0x02, 0x5c, 0x02, 0x65, 0x01, 0x22, 0x00, 0xdd, 0xfe, 0x96, 0xfd, 0xc8, 0xfc, 0x11, 0xfc, 0x86, 0xfb, 0x13, 0xfb, 0x9e, 0xfa, 0x79, 0xfa, 0x64, 0xfa, 0x78, 0xfa, 0xd6, 0xfa, 0x51, 0xfb, 0xc6, 0xfb, 0x2d, 0xfc, 0x68, 0xfc, 0x7d, 0xfc, 0xb6, 0xfc, 0x1a, 0xfd, 0x8d, 0xfd, 0x11, 0xfe, 0xaf, 0xfe, 0x5d, 0xff, 0xde, 0xff, 0x6b, 0x00, 0xed, 0x00, 0x58, 0x01, 0xa8, 0x01, 0x08, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0x9f, 0x02, 0x93, 0x02, 0x5b, 0x02, 0x4f, 0x02, 0x46, 0x02, 0x2c, 0x02, 0x04, 0x02, 0xb0, 0x01, 0x3f, 0x01, 0xdf, 0x00, 0x7a, 0x00, 0x4a, 0x00, 0x2c, 0x00, 0x1e, 0x00, 0x0a, 0x00, 0x18, 0x00, 0x3a, 0x00, 0x5a, 0x00, 0x7b, 0x00, 0xa3, 0x00, 0x9e, 0x00, 0xbe, 0x00, 0x9a, 0x00, 0x57, 0x00, 0x0c, 0x00, 0xdd, 0xff, 0xd1, 0xff, 0xa7, 0xff, 0x5d, 0xff, 0x17, 0xff, 0xf7, 0xfe, 0xf6, 0xfe, 0x04, 0xff, 0x27, 0xff, 0x44, 0xff, 0x62, 0xff, 0x5e, 0xff, 0x6c, 0xff, 0xa4, 0xff, 0xcc, 0xff, 0x04, 0x00, 0x1e, 0x00, 0x23, 0x00, 0x0a, 0x00, 0x17, 0x00, 0x2b, 0x00, 0x43, 0x00, 0x4d, 0x00, 0x4a, 0x00, 0x57, 0x00, 0x68, 0x00, 0x5d, 0x00, 0x55, 0x00, 0x3c, 0x00, 0x28, 0x00, 0x27, 0x00, 0x0d, 0x00, 0xf7, 0xff, 0xe3, 0xff, 0xbd, 0xff, 0x75, 0xff, 0x2e, 0xff, 0xfd, 0xfe, 0xe2, 0xfe, 0xcc, 0xfe, 0x8d, 0xfe, 0x49, 0xfe, 0x34, 0xfe, 0x4d, 0xfe, 0x6c, 0xfe, 0xa6, 0xfe, 0xb7, 0xfe, 0xed, 0xfe, 0x1d, 0xff, 0x2d, 0xff, 0x3a, 0xff, 0x32, 0xff, 0x25, 0xff, 0x2c, 0xff, 0x30, 0xff, 0x3e, 0xff, 0x71, 0xff, 0x8c, 0xff, 0xb5, 0xff, 0xe8, 0xff, 0x16, 0x00, 0x49, 0x00, 0xaf, 0x00, 0x12, 0x01, 0x8d, 0x01, 0xd6, 0x01, 0x1c, 0x02, 0x39, 0x02, 0x30, 0x02, 0x41, 0x02, 0x77, 0x02, 0x92, 0x02, 0x73, 0x02, 0x3b, 0x02, 0xbb, 0x01, 0x5e, 0x01, 0x46, 0x01, 0x39, 0x01, 0x22, 0x01, 0xf9, 0x00, 0xca, 0x00, 0x51, 0x00, 0x07, 0x00, 0xa8, 0xff, 0x4e, 0xff, 0xf0, 0xfe, 0xb8, 0xfe, 0x60, 0xfe, 0x34, 0xfe, 0xff, 0xfd, 0xc5, 0xfd, 0x9d, 0xfd, 0x6c, 0xfd, 0x5a, 0xfd, 0x58, 0xfd, 0x23, 0xfd, 0xe4, 0xfc, 0xb1, 0xfc, 0xa3, 0xfc, 0xae, 0xfc, 0xf4, 0xfc, 0x58, 0xfd, 0xd8, 0xfd, 0x59, 0xfe, 0xaa, 0xfe, 0xe8, 0xfe, 0x00, 0xff, 0x1e, 0xff, 0x41, 0xff, 0x37, 0xff, 0x74, 0xff, 0xec, 0xff, 0x86, 0x00, 0x00, 0x01, 0x5d, 0x01, 0x96, 0x01, 0xc2, 0x01, 0x20, 0x02, 0x6c, 0x02, 0xcc, 0x02, 0x3d, 0x03, 0xbe, 0x03, 0x27, 0x04, 0x3d, 0x04, 0xff, 0x03, 0x95, 0x03, 0x1c, 0x03, 0xb7, 0x02, 0x6e, 0x02, 0x09, 0x02, 0xa3, 0x01, 0x17, 0x01, 0xa5, 0x00, 0x80, 0x00, 0x7d, 0x00, 0x71, 0x00, 0x6b, 0x00, 0x62, 0x00, 0x4d, 0x00, 0x07, 0x00, 0x95, 0xff, 0x0b, 0xff, 0x84, 0xfe, 0xf1, 0xfd, 0x7d, 0xfd, 0x3b, 0xfd, 0x0e, 0xfd, 0x0b, 0xfd, 0x0c, 0xfd, 0xff, 0xfc, 0xeb, 0xfc, 0xc7, 0xfc, 0x97, 0xfc, 0x6d, 0xfc, 0x76, 0xfc, 0x84, 0xfc, 0xe7, 0xfc, 0x81, 0xfd, 0x29, 0xfe, 0xaf, 0xfe, 0xca, 0xfe, 0xc9, 0xfe, 0xbf, 0xfe, 0xd3, 0xfe, 0xcd, 0xfe, 0xe2, 0xfe, 0xf3, 0xfe, 0x2b, 0xff, 0xa3, 0xff, 0x49, 0x00, 0x15, 0x01, 0xf8, 0x01, 0xad, 0x02, 0x29, 0x03, 0x7d, 0x03, 0x8f, 0x03, 0x8d, 0x03, 0x7c, 0x03, 0x4b, 0x03, 0x43, 0x03, 0x86, 0x03, 0xd2, 0x03, 0x4d, 0x04, 0xa2, 0x04, 0xda, 0x04, 0xf7, 0x04, 0xbb, 0x04, 0x68, 0x04, 0x0b, 0x04, 0x78, 0x03, 0xcc, 0x02, 0x16, 0x02, 0x56, 0x01, 0x6a, 0x00, 0xa2, 0xff, 0xa3, 0xfe, 0xc5, 0xfd, 0x31, 0xfd, 0xbb, 0xfc, 0x7a, 0xfc, 0x2b, 0xfc, 0xd6, 0xfb, 0x60, 0xfb, 0x1d, 0xfb, 0x10, 0xfb, 0x13, 0xfb, 0x26, 0xfb, 0x2f, 0xfb, 0x4c, 0xfb, 0xac, 0xfb, 0x33, 0xfc, 0xc8, 0xfc, 0x59, 0xfd, 0xfb, 0xfd, 0x8e, 0xfe, 0xfa, 0xfe, 0x65, 0xff, 0xe7, 0xff, 0x56, 0x00, 0x9d, 0x00, 0xac, 0x00, 0xf4, 0x00, 0x25, 0x01, 0x49, 0x01, 0x41, 0x01, 0x0d, 0x01, 0xb4, 0x00, 0x63, 0x00, 0x0f, 0x00, 0xd5, 0xff, 0xc4, 0xff, 0xe0, 0xff, 0x06, 0x00, 0x40, 0x00, 0x69, 0x00, 0x3e, 0x00, 0x1b, 0x00, 0x08, 0x00, 0x24, 0x00, 0x23, 0x00, 0x0a, 0x00, 0xc7, 0xff, 0x97, 0xff, 0x76, 0xff, 0x65, 0xff, 0x6c, 0xff, 0x41, 0xff, 0x53, 0xff, 0x49, 0xff, 0x4b, 0xff, 0x25, 0xff, 0xf5, 0xfe, 0xdf, 0xfe, 0xdb, 0xfe, 0x11, 0xff, 0x73, 0xff, 0x05, 0x00, 0xa7, 0x00, 0xfb, 0x00, 0x30, 0x01, 0x44, 0x01, 0x25, 0x01, 0xef, 0x00, 0xa6, 0x00, 0x6c, 0x00, 0x38, 0x00, 0x09, 0x00, 0xe2, 0xff, 0xc4, 0xff, 0xd0, 0xff, 0xbe, 0xff, 0xcf, 0xff, 0xc7, 0xff, 0xc3, 0xff, 0xe9, 0xff, 0xff, 0xff, 0x27, 0x00, 0x57, 0x00, 0x89, 0x00, 0x92, 0x00, 0x6f, 0x00, 0x3c, 0x00, 0x03, 0x00, 0xd0, 0xff, 0x8e, 0xff, 0x65, 0xff, 0x1c, 0xff, 0xe8, 0xfe, 0xbf, 0xfe, 0xe2, 0xfe, 0xfd, 0xfe, 0x0b, 0xff, 0xe6, 0xfe, 0xcf, 0xfe, 0xac, 0xfe, 0xc6, 0xfe, 0xd2, 0xfe, 0xe2, 0xfe, 0xd2, 0xfe, 0xa8, 0xfe, 0xa7, 0xfe, 0xbd, 0xfe, 0xc8, 0xfe, 0xe4, 0xfe, 0xf6, 0xfe, 0x13, 0xff, 0x36, 0xff, 0x4b, 0xff, 0x91, 0xff, 0x37, 0x00, 0xc7, 0x00, 0x87, 0x01, 0x24, 0x02, 0xd0, 0x02, 0x50, 0x03, 0x90, 0x03, 0xe7, 0x03, 0x5c, 0x04, 0xad, 0x04, 0xf5, 0x04, 0x34, 0x05, 0x54, 0x05, 0x7f, 0x05, 0x80, 0x05, 0x7c, 0x05, 0x71, 0x05, 0x6a, 0x05, 0x04, 0x05, 0x9a, 0x04, 0xe1, 0x03, 0xfd, 0x02, 0xd2, 0x01, 0xcc, 0x00, 0xab, 0xff, 0x74, 0xfe, 0x6b, 0xfd, 0x8c, 0xfc, 0xdf, 0xfb, 0x42, 0xfb, 0xe8, 0xfa, 0xa4, 0xfa, 0x63, 0xfa, 0x2a, 0xfa, 0xff, 0xf9, 0xd8, 0xf9, 0xa1, 0xf9, 0x7d, 0xf9, 0x7d, 0xf9, 0x8e, 0xf9, 0xdb, 0xf9, 0x38, 0xfa, 0xcf, 0xfa, 0x92, 0xfb, 0x7b, 0xfc, 0x71, 0xfd, 0x81, 0xfe, 0x5e, 0xff, 0x58, 0x00, 0x48, 0x01, 0x19, 0x02, 0xde, 0x02, 0x90, 0x03, 0xf2, 0x03, 0x4c, 0x04, 0x8f, 0x04, 0xdd, 0x04, 0x0e, 0x05, 0x27, 0x05, 0xe0, 0x04, 0xa0, 0x04, 0x2e, 0x04, 0xa0, 0x03, 0xff, 0x02, 0x11, 0x02, 0x4f, 0x01, 0xd0, 0x00, 0x70, 0x00, 0x08, 0x00, 0xc2, 0xff, 0x48, 0xff, 0xbf, 0xfe, 0x35, 0xfe, 0xad, 0xfd, 0x03, 0xfd, 0x79, 0xfc, 0x0e, 0xfc, 0xcf, 0xfb, 0xbf, 0xfb, 0xd7, 0xfb, 0x33, 0xfc, 0xa4, 0xfc, 0x15, 0xfd, 0x63, 0xfd, 0x89, 0xfd, 0xb4, 0xfd, 0x17, 0xfe, 0x3f, 0xfe, 0x86, 0xfe, 0xa1, 0xfe, 0x17, 0xff, 0x71, 0xff, 0x12, 0x00, 0x98, 0x00, 0x34, 0x01, 0xef, 0x01, 0x9a, 0x02, 0x6d, 0x03, 0x2b, 0x04, 0xce, 0x04, 0x0f, 0x05, 0x8d, 0x05, 0xcb, 0x05, 0xc0, 0x05, 0x3d, 0x05, 0x8c, 0x04, 0xbb, 0x03, 0xec, 0x02, 0x25, 0x02, 0x78, 0x01, 0xcd, 0x00, 0xd4, 0xff, 0xf8, 0xfe, 0x01, 0xfe, 0x3d, 0xfd, 0x8e, 0xfc, 0x04, 0xfc, 0x9b, 0xfb, 0x76, 0xfb, 0x97, 0xfb, 0xe4, 0xfb, 0x87, 0xfc, 0x0e, 0xfd, 0xa3, 0xfd, 0x37, 0xfe, 0xc3, 0xfe, 0x46, 0xff, 0xd2, 0xff, 0x04, 0x00, 0x22, 0x00, 0xfa, 0xff, 0xb7, 0xff, 0x73, 0xff, 0x66, 0xff, 0x63, 0xff, 0x3b, 0xff, 0x23, 0xff, 0xc6, 0xfe, 0x9c, 0xfe, 0x71, 0xfe, 0x6e, 0xfe, 0x9a, 0xfe, 0xa6, 0xfe, 0xc7, 0xfe, 0x00, 0xff, 0x35, 0xff, 0x5e, 0xff, 0xa4, 0xff, 0xcb, 0xff, 0xbe, 0xff, 0xb2, 0xff, 0x6b, 0xff, 0x32, 0xff, 0x4a, 0xff, 0x68, 0xff, 0x6b, 0xff, 0x5c, 0xff, 0x13, 0xff, 0xea, 0xfe, 0xe8, 0xfe, 0xcf, 0xfe, 0xc2, 0xfe, 0xa3, 0xfe, 0x96, 0xfe, 0xe5, 0xfe, 0x23, 0xff, 0x74, 0xff, 0xdc, 0xff, 0x66, 0x00, 0xee, 0x00, 0x61, 0x01, 0xd1, 0x01, 0x52, 0x02, 0xd9, 0x02, 0x49, 0x03, 0x9f, 0x03, 0x1b, 0x04, 0x83, 0x04, 0xcf, 0x04, 0xc8, 0x04, 0x8a, 0x04, 0xf4, 0x03, 0x45, 0x03, 0xa2, 0x02, 0x13, 0x02, 0x6c, 0x01, 0xf2, 0x00, 0x87, 0x00, 0x3d, 0x00, 0xf0, 0xff, 0xb7, 0xff, 0x72, 0xff, 0x6e, 0xff, 0x74, 0xff, 0x81, 0xff, 0xa4, 0xff, 0xc8, 0xff, 0xb4, 0xff, 0xa6, 0xff, 0x73, 0xff, 0x52, 0xff, 0x21, 0xff, 0xd8, 0xfe, 0x8a, 0xfe, 0x7a, 0xfe, 0x92, 0xfe, 0xac, 0xfe, 0xe2, 0xfe, 0xef, 0xfe, 0x05, 0xff, 0xfb, 0xfe, 0x05, 0xff, 0x29, 0xff, 0x3f, 0xff, 0x28, 0xff, 0x09, 0xff, 0xd3, 0xfe, 0x8a, 0xfe, 0x78, 0xfe, 0x76, 0xfe, 0x3d, 0xfe, 0x2a, 0xfe, 0x29, 0xfe, 0x5e, 0xfe, 0x8f, 0xfe, 0xc8, 0xfe, 0x04, 0xff, 0x79, 0xff, 0xcb, 0xff, 0x24, 0x00, 0x6b, 0x00, 0xb8, 0x00, 0xea, 0x00, 0x04, 0x01, 0x22, 0x01, 0x33, 0x01, 0x4f, 0x01, 0x4a, 0x01, 0x55, 0x01, 0x41, 0x01, 0xfe, 0x00, 0xa0, 0x00, 0x3c, 0x00, 0xbe, 0xff, 0x63, 0xff, 0xfc, 0xfe, 0xaa, 0xfe, 0x90, 0xfe, 0x77, 0xfe, 0x91, 0xfe, 0xb0, 0xfe, 0xe0, 0xfe, 0xf4, 0xfe, 0xf2, 0xfe, 0xf6, 0xfe, 0xd1, 0xfe, 0x7b, 0xfe, 0x3a, 0xfe, 0xf7, 0xfd, 0xae, 0xfd, 0x8b, 0xfd, 0x75, 0xfd, 0x74, 0xfd, 0x5b, 0xfd, 0x68, 0xfd, 0x65, 0xfd, 0x58, 0xfd, 0x74, 0xfd, 0xc2, 0xfd, 0x14, 0xfe, 0x6d, 0xfe, 0x89, 0xfe, 0xa5, 0xfe, 0xdd, 0xfe, 0x2c, 0xff, 0x7e, 0xff, 0x14, 0x00, 0x79, 0x00, 0xe6, 0x00, 0x33, 0x01, 0x34, 0x01, 0x51, 0x01, 0x90, 0x01, 0x98, 0x01, 0x8f, 0x01, 0x6d, 0x01, 0x33, 0x01, 0x3c, 0x01, 0x6b, 0x01, 0x96, 0x01, 0xf1, 0x01, 0x3f, 0x02, 0x4e, 0x02, 0x67, 0x02, 0x65, 0x02, 0x1d, 0x02, 0xd3, 0x01, 0x8b, 0x01, 0x5a, 0x01, 0x2e, 0x01, 0x03, 0x01, 0x0e, 0x01, 0x46, 0x01, 0x88, 0x01, 0xeb, 0x01, 0x74, 0x02, 0xd5, 0x02, 0x28, 0x03, 0x78, 0x03, 0x83, 0x03, 0xb2, 0x03, 0xb8, 0x03, 0x8c, 0x03, 0x52, 0x03, 0xfc, 0x02, 0x97, 0x02, 0x01, 0x02, 0x4c, 0x01, 0x88, 0x00, 0xeb, 0xff, 0x36, 0xff, 0xba, 0xfe, 0x48, 0xfe, 0xe3, 0xfd, 0x68, 0xfd, 0x05, 0xfd, 0xae, 0xfc, 0x3d, 0xfc, 0x99, 0xfb, 0x0a, 0xfb, 0x75, 0xfa, 0x1d, 0xfa, 0xee, 0xf9, 0xdb, 0xf9, 0xe0, 0xf9, 0xfd, 0xf9, 0x12, 0xfa, 0x57, 0xfa, 0xb6, 0xfa, 0x34, 0xfb, 0xf3, 0xfb, 0xc8, 0xfc, 0xa7, 0xfd, 0x67, 0xfe, 0x0b, 0xff, 0xc3, 0xff, 0x68, 0x00, 0x02, 0x01, 0x9f, 0x01, 0x42, 0x02, 0xe7, 0x02, 0x82, 0x03, 0x39, 0x04, 0xcc, 0x04, 0x25, 0x05, 0x52, 0x05, 0x85, 0x05, 0xd6, 0x05, 0xdc, 0x05, 0xda, 0x05, 0x7e, 0x05, 0x40, 0x05, 0x02, 0x05, 0x6e, 0x04, 0xca, 0x03, 0x0e, 0x03, 0x39, 0x02, 0x82, 0x01, 0xdd, 0x00, 0x52, 0x00, 0xc7, 0xff, 0x39, 0xff, 0xca, 0xfe, 0x68, 0xfe, 0x01, 0xfe, 0xcb, 0xfd, 0xbe, 0xfd, 0xb7, 0xfd, 0x9d, 0xfd, 0x6b, 0xfd, 0x1f, 0xfd, 0xeb, 0xfc, 0xc6, 0xfc, 0xb2, 0xfc, 0xd8, 0xfc, 0xfa, 0xfc, 0x40, 0xfd, 0x9c, 0xfd, 0xf9, 0xfd, 0x4c, 0xfe, 0x90, 0xfe, 0xe7, 0xfe, 0x13, 0xff, 0x50, 0xff, 0xb1, 0xff, 0x1d, 0x00, 0x8c, 0x00, 0xcd, 0x00, 0x03, 0x01, 0x3a, 0x01, 0x6b, 0x01, 0xb2, 0x01, 0x15, 0x02, 0x6b, 0x02, 0xc4, 0x02, 0xfc, 0x02, 0xf6, 0x02, 0xeb, 0x02, 0xa8, 0x02, 0x35, 0x02, 0xb4, 0x01, 0x41, 0x01, 0x9e, 0x00, 0xfc, 0xff, 0x5a, 0xff, 0x94, 0xfe, 0x07, 0xfe, 0x99, 0xfd, 0x33, 0xfd, 0xb6, 0xfc, 0x4d, 0xfc, 0xe5, 0xfb, 0xab, 0xfb, 0x9f, 0xfb, 0xa7, 0xfb, 0xe4, 0xfb, 0x17, 0xfc, 0x54, 0xfc, 0x8e, 0xfc, 0xd2, 0xfc, 0x47, 0xfd, 0xec, 0xfd, 0x6b, 0xfe, 0x12, 0xff, 0x9c, 0xff, 0x08, 0x00, 0x56, 0x00, 0x7e, 0x00, 0x8a, 0x00, 0x54, 0x00, 0x19, 0x00, 0xca, 0xff, 0x73, 0xff, 0x46, 0xff, 0x3f, 0xff, 0x26, 0xff, 0xf3, 0xfe, 0x95, 0xfe, 0x3b, 0xfe, 0xf5, 0xfd, 0xd7, 0xfd, 0xc7, 0xfd, 0xc9, 0xfd, 0xba, 0xfd, 0xeb, 0xfd, 0x3a, 0xfe, 0xac, 0xfe, 0x19, 0xff, 0x93, 0xff, 0x03, 0x00, 0x72, 0x00, 0xe6, 0x00, 0x5c, 0x01, 0xd4, 0x01, 0x59, 0x02, 0xb8, 0x02, 0xe0, 0x02, 0xdd, 0x02, 0xa3, 0x02, 0x18, 0x02, 0xb6, 0x01, 0x61, 0x01, 0xfa, 0x00, 0x94, 0x00, 0x48, 0x00, 0x11, 0x00, 0xe7, 0xff, 0xcf, 0xff, 0xd2, 0xff, 0xd1, 0xff, 0xd8, 0xff, 0xea, 0xff, 0x02, 0x00, 0x07, 0x00, 0xec, 0xff, 0xc1, 0xff, 0x98, 0xff, 0x45, 0xff, 0x0a, 0xff, 0x06, 0xff, 0xdc, 0xfe, 0xd1, 0xfe, 0xf5, 0xfe, 0x2b, 0xff, 0x99, 0xff, 0xdc, 0xff, 0x0f, 0x00, 0x3a, 0x00, 0x5e, 0x00, 0xa6, 0x00, 0xfe, 0x00, 0x79, 0x01, 0xd2, 0x01, 0x46, 0x02, 0xa8, 0x02, 0xe9, 0x02, 0x2d, 0x03, 0x6c, 0x03, 0x9b, 0x03, 0xd2, 0x03, 0xff, 0x03, 0x2f, 0x04, 0x54, 0x04, 0x65, 0x04, 0x23, 0x04, 0xed, 0x03, 0x80, 0x03, 0xff, 0x02, 0x78, 0x02, 0xe7, 0x01, 0x4a, 0x01, 0x92, 0x00, 0xdc, 0xff, 0xec, 0xfe, 0x32, 0xfe, 0x6d, 0xfd, 0xee, 0xfc, 0x79, 0xfc, 0x30, 0xfc, 0x10, 0xfc, 0xee, 0xfb, 0xe5, 0xfb, 0x05, 0xfc, 0x14, 0xfc, 0x2b, 0xfc, 0x45, 0xfc, 0x88, 0xfc, 0xb0, 0xfc, 0xbb, 0xfc, 0xb1, 0xfc, 0x9f, 0xfc, 0x89, 0xfc, 0xaf, 0xfc, 0xf2, 0xfc, 0x54, 0xfd, 0xc7, 0xfd, 0x35, 0xfe, 0xa3, 0xfe, 0x13, 0xff, 0x6c, 0xff, 0xe6, 0xff, 0x1e, 0x00, 0x55, 0x00, 0x8d, 0x00, 0xdc, 0x00, 0x37, 0x01, 0x93, 0x01, 0x04, 0x02, 0x57, 0x02, 0x92, 0x02, 0xba, 0x02, 0xdd, 0x02, 0xd6, 0x02, 0xe2, 0x02, 0x1b, 0x03, 0x20, 0x03, 0xe8, 0x02, 0xaf, 0x02, 0x47, 0x02, 0x08, 0x02, 0xb3, 0x01, 0x65, 0x01, 0x44, 0x01, 0x1d, 0x01, 0x03, 0x01, 0x01, 0x01, 0xea, 0x00, 0xb5, 0x00, 0x66, 0x00, 0x06, 0x00, 0x90, 0xff, 0x44, 0xff, 0xcb, 0xfe, 0x58, 0xfe, 0xf6, 0xfd, 0xd0, 0xfd, 0xd9, 0xfd, 0xe3, 0xfd, 0xe9, 0xfd, 0xc2, 0xfd, 0xaf, 0xfd, 0xb4, 0xfd, 0xb1, 0xfd, 0xa9, 0xfd, 0x9d, 0xfd, 0x81, 0xfd, 0x64, 0xfd, 0x41, 0xfd, 0x40, 0xfd, 0x4b, 0xfd, 0x69, 0xfd, 0x73, 0xfd, 0x88, 0xfd, 0xb4, 0xfd, 0x14, 0xfe, 0x61, 0xfe, 0xc6, 0xfe, 0x26, 0xff, 0xd2, 0xff, 0x73, 0x00, 0x3c, 0x01, 0x0e, 0x02, 0xe7, 0x02, 0xaf, 0x03, 0x37, 0x04, 0x94, 0x04, 0xe1, 0x04, 0xfc, 0x04, 0xfb, 0x04, 0xfe, 0x04, 0x03, 0x05, 0xf2, 0x04, 0xb7, 0x04, 0x33, 0x04, 0xac, 0x03, 0x00, 0x03, 0x3a, 0x02, 0x8d, 0x01, 0xa1, 0x00, 0xe8, 0xff, 0x39, 0xff, 0x93, 0xfe, 0xe1, 0xfd, 0x64, 0xfd, 0xd6, 0xfc, 0x53, 0xfc, 0xec, 0xfb, 0x74, 0xfb, 0x1c, 0xfb, 0xea, 0xfa, 0xd9, 0xfa, 0xce, 0xfa, 0xd8, 0xfa, 0x05, 0xfb, 0x3e, 0xfb, 0x84, 0xfb, 0xd6, 0xfb, 0x2b, 0xfc, 0x65, 0xfc, 0xa0, 0xfc, 0x14, 0xfd, 0x6a, 0xfd, 0xd3, 0xfd, 0x63, 0xfe, 0x0e, 0xff, 0xb2, 0xff, 0x2c, 0x00, 0xa1, 0x00, 0xfa, 0x00, 0x67, 0x01, 0xbf, 0x01, 0x1e, 0x02, 0x9e, 0x02, 0xfa, 0x02, 0x61, 0x03, 0xc2, 0x03, 0x14, 0x04, 0x43, 0x04, 0x83, 0x04, 0x58, 0x04, 0x2d, 0x04, 0xd9, 0x03, 0x70, 0x03, 0xd5, 0x02, 0x53, 0x02, 0xac, 0x01, 0x0a, 0x01, 0xc7, 0x00, 0x93, 0x00, 0x85, 0x00, 0x42, 0x00, 0xeb, 0xff, 0x6e, 0xff, 0xf5, 0xfe, 0x9e, 0xfe, 0x54, 0xfe, 0x03, 0xfe, 0xb6, 0xfd, 0x62, 0xfd, 0x29, 0xfd, 0x19, 0xfd, 0x1b, 0xfd, 0x13, 0xfd, 0x19, 0xfd, 0x0e, 0xfd, 0x31, 0xfd, 0x6f, 0xfd, 0xc6, 0xfd, 0x3e, 0xfe, 0xe2, 0xfe, 0xa8, 0xff, 0x58, 0x00, 0xf9, 0x00, 0x7b, 0x01, 0xc3, 0x01, 0x17, 0x02, 0x57, 0x02, 0x70, 0x02, 0x68, 0x02, 0xa2, 0x02, 0x9d, 0x02, 0x97, 0x02, 0x6e, 0x02, 0x39, 0x02, 0xf4, 0x01, 0xa7, 0x01, 0x6e, 0x01, 0x1e, 0x01, 0xdc, 0x00, 0x5c, 0x00, 0x0b, 0x00, 0x82, 0xff, 0x18, 0xff, 0xb6, 0xfe, 0x97, 0xfe, 0x64, 0xfe, 0x24, 0xfe, 0xef, 0xfd, 0x94, 0xfd, 0x60, 0xfd, 0x57, 0xfd, 0x56, 0xfd, 0x40, 0xfd, 0x2e, 0xfd, 0xf9, 0xfc, 0xc8, 0xfc, 0xcd, 0xfc, 0xea, 0xfc, 0x3a, 0xfd, 0x9f, 0xfd, 0xe0, 0xfd, 0x21, 0xfe, 0x5e, 0xfe, 0xa2, 0xfe, 0xe8, 0xfe, 0x3e, 0xff, 0xaf, 0xff, 0x1b, 0x00, 0x87, 0x00, 0xbf, 0x00, 0x13, 0x01, 0x85, 0x01, 0x0a, 0x02, 0xa6, 0x02, 0x46, 0x03, 0xaf, 0x03, 0xf1, 0x03, 0xbb, 0x03, 0xa3, 0x03, 0x7a, 0x03, 0xfe, 0x02, 0xca, 0x02, 0x9e, 0x02, 0x80, 0x02, 0x4c, 0x02, 0x1a, 0x02, 0xab, 0x01, 0x04, 0x01, 0x97, 0x00, 0xf5, 0xff, 0x73, 0xff, 0x18, 0xff, 0x9d, 0xfe, 0x4a, 0xfe, 0xd8, 0xfd, 0x86, 0xfd, 0x61, 0xfd, 0x5c, 0xfd, 0x79, 0xfd, 0x86, 0xfd, 0x89, 0xfd, 0x5e, 0xfd, 0x58, 0xfd, 0x5e, 0xfd, 0x83, 0xfd, 0xcf, 0xfd, 0x47, 0xfe, 0x97, 0xfe, 0x08, 0xff, 0x58, 0xff, 0x86, 0xff, 0xaf, 0xff, 0xe7, 0xff, 0x0f, 0x00, 0x1d, 0x00, 0x18, 0x00, 0x20, 0x00, 0x4d, 0x00, 0x86, 0x00, 0xdc, 0x00, 0x0e, 0x01, 0x36, 0x01, 0x1b, 0x01, 0xf0, 0x00, 0xda, 0x00, 0x75, 0x00, 0x41, 0x00, 0x20, 0x00, 0x02, 0x00, 0x1b, 0x00, 0x2d, 0x00, 0x47, 0x00, 0x4d, 0x00, 0x5b, 0x00, 0x60, 0x00, 0x68, 0x00, 0x50, 0x00, 0x10, 0x00, 0xd2, 0xff, 0x69, 0xff, 0x24, 0xff, 0x05, 0xff, 0xce, 0xfe, 0xb9, 0xfe, 0x8f, 0xfe, 0x71, 0xfe, 0x85, 0xfe, 0x99, 0xfe, 0xbb, 0xfe, 0xf8, 0xfe, 0x48, 0xff, 0x96, 0xff, 0x38, 0x00, 0x9d, 0x00, 0x10, 0x01, 0x5e, 0x01, 0x65, 0x01, 0x5f, 0x01, 0x5c, 0x01, 0x52, 0x01, 0x08, 0x01, 0x07, 0x01, 0xe5, 0x00, 0xc3, 0x00, 0xd4, 0x00, 0xba, 0x00, 0xc0, 0x00, 0xb8, 0x00, 0xe5, 0x00, 0x44, 0x01, 0xa4, 0x01, 0xe3, 0x01, 0x34, 0x02, 0x7b, 0x02, 0xae, 0x02, 0xd3, 0x02, 0xbf, 0x02, 0x8b, 0x02, 0x59, 0x02, 0xcd, 0x01, 0x5e, 0x01, 0xca, 0x00, 0x59, 0x00, 0xe0, 0xff, 0x87, 0xff, 0x46, 0xff, 0xf2, 0xfe, 0xcf, 0xfe, 0x76, 0xfe, 0x5e, 0xfe, 0x55, 0xfe, 0x71, 0xfe, 0xbe, 0xfe, 0x28, 0xff, 0x8c, 0xff, 0xdc, 0xff, 0x36, 0x00, 0x8c, 0x00, 0xb1, 0x00, 0xd0, 0x00, 0xf1, 0x00, 0x1a, 0x01, 0x0f, 0x01, 0xdf, 0x00, 0x77, 0x00, 0x08, 0x00, 0x82, 0xff, 0xf0, 0xfe, 0x75, 0xfe, 0xe4, 0xfd, 0x9e, 0xfd, 0x32, 0xfd, 0x15, 0xfd, 0xe0, 0xfc, 0xda, 0xfc, 0xf0, 0xfc, 0x14, 0xfd, 0x54, 0xfd, 0x9f, 0xfd, 0xf0, 0xfd, 0x56, 0xfe, 0xa3, 0xfe, 0xd0, 0xfe, 0xfc, 0xfe, 0x15, 0xff, 0x11, 0xff, 0x3c, 0xff, 0x4e, 0xff, 0x70, 0xff, 0x85, 0xff, 0xa4, 0xff, 0xd4, 0xff, 0x02, 0x00, 0x3b, 0x00, 0x79, 0x00, 0x81, 0x00, 0x83, 0x00, 0x95, 0x00, 0x8e, 0x00, 0x8f, 0x00, 0x97, 0x00, 0xae, 0x00, 0xdb, 0x00, 0xf4, 0x00, 0x06, 0x01, 0x09, 0x01, 0xce, 0x00, 0x9e, 0x00, 0x8c, 0x00, 0x29, 0x00, 0xeb, 0xff, 0x98, 0xff, 0x4d, 0xff, 0x06, 0xff, 0xa2, 0xfe, 0x2e, 0xfe, 0xaa, 0xfd, 0x75, 0xfd, 0x34, 0xfd, 0x1c, 0xfd, 0x24, 0xfd, 0x3d, 0xfd, 0x9c, 0xfd, 0xc3, 0xfd, 0x13, 0xfe, 0x78, 0xfe, 0xc2, 0xfe, 0xe4, 0xfe, 0x46, 0xff, 0x47, 0xff, 0x4e, 0xff, 0x6c, 0xff, 0x79, 0xff, 0x97, 0xff, 0xa0, 0xff, 0xa5, 0xff, 0xb2, 0xff, 0xfa, 0xff, 0x61, 0x00, 0xf7, 0x00, 0x5c, 0x01, 0x73, 0x01, 0x5c, 0x01, 0x0b, 0x01, 0xe2, 0x00, 0xce, 0x00, 0x98, 0x00, 0x62, 0x00, 0x2d, 0x00, 0xe8, 0xff, 0xcd, 0xff, 0xe6, 0xff, 0xec, 0xff, 0xe8, 0xff, 0xac, 0xff, 0x6d, 0xff, 0x32, 0xff, 0x1d, 0xff, 0xfb, 0xfe, 0x1d, 0xff, 0x57, 0xff, 0x5c, 0xff, 0x92, 0xff, 0x9c, 0xff, 0xa5, 0xff, 0xa6, 0xff, 0xcf, 0xff, 0x1d, 0x00, 0x7e, 0x00, 0xef, 0x00, 0x68, 0x01, 0x02, 0x02, 0x5f, 0x02, 0xa8, 0x02, 0xe8, 0x02, 0x0e, 0x03, 0x13, 0x03, 0xdf, 0x02, 0x94, 0x02, 0x34, 0x02, 0x0d, 0x02, 0xb7, 0x01, 0x6f, 0x01, 0xe8, 0x00, 0x64, 0x00, 0xf8, 0xff, 0xae, 0xff, 0x72, 0xff, 0x3f, 0xff, 0x45, 0xff, 0x46, 0xff, 0x4f, 0xff, 0x32, 0xff, 0xff, 0xfe, 0x82, 0xfe, 0x44, 0xfe, 0x13, 0xfe, 0xf0, 0xfd, 0xad, 0xfd, 0x78, 0xfd, 0x42, 0xfd, 0x30, 0xfd, 0x37, 0xfd, 0x61, 0xfd, 0xaa, 0xfd, 0xde, 0xfd, 0x08, 0xfe, 0x2e, 0xfe, 0x56, 0xfe, 0x7a, 0xfe, 0xb4, 0xfe, 0x16, 0xff, 0x60, 0xff, 0xc5, 0xff, 0xfc, 0xff, 0x49, 0x00, 0x8c, 0x00, 0xb7, 0x00, 0x28, 0x01, 0xab, 0x01, 0x5b, 0x02, 0x1a, 0x03, 0xb0, 0x03, 0x22, 0x04, 0x4f, 0x04, 0x34, 0x04, 0x24, 0x04, 0x08, 0x04, 0xc9, 0x03, 0x38, 0x03, 0xc4, 0x02, 0x2c, 0x02, 0xb8, 0x01, 0x0b, 0x01, 0x9c, 0x00, 0x04, 0x00, 0x7f, 0xff, 0x15, 0xff, 0xaa, 0xfe, 0x51, 0xfe, 0xdc, 0xfd, 0x95, 0xfd, 0x5f, 0xfd, 0x18, 0xfd, 0xe7, 0xfc, 0xc1, 0xfc, 0xb7, 0xfc, 0xe3, 0xfc, 0x0f, 0xfd, 0x68, 0xfd, 0xd2, 0xfd, 0x25, 0xfe, 0x88, 0xfe, 0xd9, 0xfe, 0x29, 0xff, 0x8b, 0xff, 0xec, 0xff, 0x74, 0x00, 0x00, 0x01, 0x81, 0x01, 0xda, 0x01, 0x11, 0x02, 0x65, 0x02, 0xa3, 0x02, 0xca, 0x02, 0xcf, 0x02, 0xc2, 0x02, 0x8e, 0x02, 0x66, 0x02, 0x18, 0x02, 0xbc, 0x01, 0x4e, 0x01, 0xbe, 0x00, 0x21, 0x00, 0xb1, 0xff, 0x33, 0xff, 0xb7, 0xfe, 0x43, 0xfe, 0x05, 0xfe, 0xaa, 0xfd, 0x74, 0xfd, 0x58, 0xfd, 0x62, 0xfd, 0x86, 0xfd, 0x94, 0xfd, 0xd8, 0xfd, 0x14, 0xfe, 0x34, 0xfe, 0x6b, 0xfe, 0xa7, 0xfe, 0xe3, 0xfe, 0x1b, 0xff, 0x55, 0xff, 0xc1, 0xff, 0x1e, 0x00, 0xa3, 0x00, 0xf6, 0x00, 0x70, 0x01, 0x89, 0x01, 0x9d, 0x01, 0x9d, 0x01, 0x8d, 0x01, 0x65, 0x01, 0x65, 0x01, 0x33, 0x01, 0xf2, 0x00, 0x99, 0x00, 0x44, 0x00, 0xf0, 0xff, 0xaa, 0xff, 0x67, 0xff, 0x2c, 0xff, 0x0a, 0xff, 0xcf, 0xfe, 0xb9, 0xfe, 0x88, 0xfe, 0x85, 0xfe, 0xa5, 0xfe, 0xa0, 0xfe, 0xcc, 0xfe, 0x0c, 0xff, 0x39, 0xff, 0x71, 0xff, 0xa3, 0xff, 0xaf, 0xff, 0xb1, 0xff, 0xcf, 0xff, 0xe0, 0xff, 0xf5, 0xff, 0x20, 0x00, 0x2d, 0x00, 0x39, 0x00, 0x22, 0x00, 0x15, 0x00, 0xff, 0xff, 0xf7, 0xff, 0xf5, 0xff, 0xda, 0xff, 0xc8, 0xff, 0xdb, 0xff, 0xe6, 0xff, 0xf2, 0xff, 0x36, 0x00, 0x9a, 0x00, 0xdd, 0x00, 0x2b, 0x01, 0x6e, 0x01, 0xb8, 0x01, 0x0b, 0x02, 0x62, 0x02, 0xb9, 0x02, 0x34, 0x03, 0x6a, 0x03, 0xa8, 0x03, 0xa5, 0x03, 0xa3, 0x03, 0x6f, 0x03, 0x18, 0x03, 0xb9, 0x02, 0x69, 0x02, 0xfa, 0x01, 0x6d, 0x01, 0xc7, 0x00, 0x0a, 0x00, 0x26, 0xff, 0x56, 0xfe, 0xaa, 0xfd, 0xed, 0xfc, 0x5c, 0xfc, 0x8f, 0xfb, 0xfa, 0xfa, 0x8e, 0xfa, 0x67, 0xfa, 0x4b, 0xfa, 0x67, 0xfa, 0x9c, 0xfa, 0xcc, 0xfa, 0x34, 0xfb, 0x94, 0xfb, 0x02, 0xfc, 0x63, 0xfc, 0xcd, 0xfc, 0x41, 0xfd, 0x9c, 0xfd, 0xfe, 0xfd, 0x5d, 0xfe, 0xaa, 0xfe, 0x13, 0xff, 0xaa, 0xff, 0x2c, 0x00, 0xb9, 0x00, 0x02, 0x01, 0x43, 0x01, 0x66, 0x01, 0x7a, 0x01, 0x8c, 0x01, 0xb3, 0x01, 0xeb, 0x01, 0x2c, 0x02, 0x61, 0x02, 0x79, 0x02, 0x65, 0x02, 0x02, 0x02, 0x98, 0x01, 0x4f, 0x01, 0xe0, 0x00, 0x58, 0x00, 0xfa, 0xff, 0x7e, 0xff, 0x55, 0xff, 0x22, 0xff, 0x06, 0xff, 0x02, 0xff, 0x0c, 0xff, 0x04, 0xff, 0x23, 0xff, 0x56, 0xff, 0x9f, 0xff, 0xe9, 0xff, 0x1a, 0x00, 0x49, 0x00, 0x9e, 0x00, 0xde, 0x00, 0xe7, 0x00, 0x27, 0x01, 0x58, 0x01, 0x80, 0x01, 0xa1, 0x01, 0xcb, 0x01, 0x00, 0x02, 0x22, 0x02, 0x5b, 0x02, 0x95, 0x02, 0xe7, 0x02, 0xfb, 0x02, 0xf0, 0x02, 0xbb, 0x02, 0x82, 0x02, 0x0d, 0x02, 0x54, 0x01, 0x9d, 0x00, 0xed, 0xff, 0x31, 0xff, 0x99, 0xfe, 0x18, 0xfe, 0x9a, 0xfd, 0x32, 0xfd, 0xde, 0xfc, 0x9f, 0xfc, 0x55, 0xfc, 0x3f, 0xfc, 0x1a, 0xfc, 0xe5, 0xfb, 0xcf, 0xfb, 0xb7, 0xfb, 0xe5, 0xfb, 0x04, 0xfc, 0x3c, 0xfc, 0x77, 0xfc, 0xca, 0xfc, 0x1d, 0xfd, 0xa7, 0xfd, 0x27, 0xfe, 0xb1, 0xfe, 0x3f, 0xff, 0xa9, 0xff, 0x27, 0x00, 0xae, 0x00, 0x2f, 0x01, 0xa3, 0x01, 0x1b, 0x02, 0x6c, 0x02, 0xb4, 0x02, 0xcc, 0x02, 0xee, 0x02, 0xf8, 0x02, 0x04, 0x03, 0xbd, 0x02, 0x61, 0x02, 0xf4, 0x01, 0xa1, 0x01, 0x2a, 0x01, 0xc9, 0x00, 0x7c, 0x00, 0x39, 0x00, 0x45, 0x00, 0x40, 0x00, 0x3e, 0x00, 0x47, 0x00, 0x3c, 0x00, 0x20, 0x00, 0xec, 0xff, 0xc0, 0xff, 0x93, 0xff, 0xb0, 0xff, 0xd1, 0xff, 0x17, 0x00, 0x5b, 0x00, 0xc5, 0x00, 0xf4, 0x00, 0x4d, 0x01, 0x9e, 0x01, 0x07, 0x02, 0x4d, 0x02, 0x6d, 0x02, 0x8e, 0x02, 0x75, 0x02, 0x1a, 0x02, 0xa9, 0x01, 0x01, 0x01, 0x30, 0x00, 0x75, 0xff, 0xcd, 0xfe, 0x3c, 0xfe, 0xa9, 0xfd, 0x64, 0xfd, 0x18, 0xfd, 0xd9, 0xfc, 0xba, 0xfc, 0xc2, 0xfc, 0xd2, 0xfc, 0xc5, 0xfc, 0xc9, 0xfc, 0xbc, 0xfc, 0xcc, 0xfc, 0xe3, 0xfc, 0xea, 0xfc, 0xfd, 0xfc, 0x24, 0xfd, 0x6f, 0xfd, 0x9a, 0xfd, 0x0d, 0xfe, 0x87, 0xfe, 0x26, 0xff, 0x9f, 0xff, 0x11, 0x00, 0x7c, 0x00, 0xf9, 0x00, 0x6a, 0x01, 0xce, 0x01, 0x14, 0x02, 0x3d, 0x02, 0x50, 0x02, 0x41, 0x02, 0x50, 0x02, 0x35, 0x02, 0x2f, 0x02, 0x0a, 0x02, 0xc7, 0x01, 0x9c, 0x01, 0x4f, 0x01, 0x0c, 0x01, 0xc1, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0xa1, 0x00, 0xb4, 0x00, 0xe0, 0x00, 0x06, 0x01, 0x3d, 0x01, 0x4f, 0x01, 0x6a, 0x01, 0x40, 0x01, 0xf9, 0x00, 0x97, 0x00, 0x3c, 0x00, 0x0c, 0x00, 0xba, 0xff, 0x99, 0xff, 0x74, 0xff, 0x45, 0xff, 0x0b, 0xff, 0xac, 0xfe, 0x6f, 0xfe, 0x3e, 0xfe, 0x43, 0xfe, 0x55, 0xfe, 0x6b, 0xfe, 0x7d, 0xfe, 0x79, 0xfe, 0x95, 0xfe, 0xdc, 0xfe, 0x10, 0xff, 0x4f, 0xff, 0x97, 0xff, 0xa9, 0xff, 0xc1, 0xff, 0xd2, 0xff, 0xd5, 0xff, 0xcc, 0xff, 0xc4, 0xff, 0xb5, 0xff, 0x6a, 0xff, 0x2d, 0xff, 0xf4, 0xfe, 0xdf, 0xfe, 0xe2, 0xfe, 0xcc, 0xfe, 0xc1, 0xfe, 0xde, 0xfe, 0xe7, 0xfe, 0x2f, 0xff, 0x9b, 0xff, 0x40, 0x00, 0xdf, 0x00, 0x7c, 0x01, 0xdc, 0x01, 0x3a, 0x02, 0x62, 0x02, 0x4c, 0x02, 0x57, 0x02, 0x23, 0x02, 0xd8, 0x01, 0x91, 0x01, 0xfc, 0x00, 0x9f, 0x00, 0x4c, 0x00, 0x1a, 0x00, 0xc5, 0xff, 0x67, 0xff, 0xf3, 0xfe, 0x79, 0xfe, 0x57, 0xfe, 0x03, 0xfe, 0xdf, 0xfd, 0xc0, 0xfd, 0xac, 0xfd, 0xa2, 0xfd, 0xb0, 0xfd, 0xc8, 0xfd, 0x08, 0xfe, 0x44, 0xfe, 0x65, 0xfe, 0x84, 0xfe, 0x5c, 0xfe, 0x5e, 0xfe, 0x6c, 0xfe, 0x5f, 0xfe, 0x54, 0xfe, 0x71, 0xfe, 0x74, 0xfe, 0xa4, 0xfe, 0xd8, 0xfe, 0x0f, 0xff, 0x40, 0xff, 0x61, 0xff, 0x9c, 0xff, 0xcc, 0xff, 0xdd, 0xff, 0xf0, 0xff, 0x0f, 0x00, 0x25, 0x00, 0x5b, 0x00, 0xa9, 0x00, 0xc9, 0x00, 0xe6, 0x00, 0xda, 0x00, 0xb8, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xdc, 0x00, 0xf8, 0x00, 0x02, 0x01, 0x07, 0x01, 0x1b, 0x01, 0x09, 0x01, 0xfd, 0x00, 0x14, 0x01, 0x24, 0x01, 0x41, 0x01, 0x67, 0x01, 0xa0, 0x01, 0xb3, 0x01, 0xad, 0x01, 0xae, 0x01, 0x9b, 0x01, 0x67, 0x01, 0x3d, 0x01, 0x08, 0x01, 0xd4, 0x00, 0x7b, 0x00, 0x19, 0x00, 0xb1, 0xff, 0x51, 0xff, 0x39, 0xff, 0x31, 0xff, 0x3c, 0xff, 0x47, 0xff, 0x34, 0xff, 0x12, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x0f, 0xff, 0x25, 0xff, 0x50, 0xff, 0x77, 0xff, 0xaf, 0xff, 0xcf, 0xff, 0xf5, 0xff, 0xea, 0xff, 0x0d, 0x00, 0xff, 0xff, 0x1d, 0x00, 0x35, 0x00, 0x75, 0x00, 0xcf, 0x00, 0x1a, 0x01, 0x50, 0x01, 0x74, 0x01, 0x98, 0x01, 0x81, 0x01, 0x65, 0x01, 0x3c, 0x01, 0x15, 0x01, 0x05, 0x01, 0xd8, 0x00, 0x9d, 0x00, 0x52, 0x00, 0x1d, 0x00, 0xd6, 0xff, 0x83, 0xff, 0x4e, 0xff, 0x1a, 0xff, 0xee, 0xfe, 0xd2, 0xfe, 0xec, 0xfe, 0xf2, 0xfe, 0x32, 0xff, 0x6a, 0xff, 0xac, 0xff, 0xd4, 0xff, 0xd4, 0xff, 0xc7, 0xff, 0xb6, 0xff, 0xad, 0xff, 0x8c, 0xff, 0xac, 0xff, 0x8d, 0xff, 0x6a, 0xff, 0x52, 0xff, 0x25, 0xff, 0x11, 0xff, 0x20, 0xff, 0x21, 0xff, 0x2f, 0xff, 0x3d, 0xff, 0x41, 0xff, 0x6f, 0xff, 0x8b, 0xff, 0x9e, 0xff, 0xc1, 0xff, 0xf0, 0xff, 0xe9, 0xff, 0xb4, 0xff, 0x71, 0xff, 0x2c, 0xff, 0xd9, 0xfe, 0xa7, 0xfe, 0x6e, 0xfe, 0x6a, 0xfe, 0x6a, 0xfe, 0x6a, 0xfe, 0x7a, 0xfe, 0x5e, 0xfe, 0x49, 0xfe, 0x4c, 0xfe, 0x31, 0xfe, 0x7b, 0xfe, 0x96, 0xfe, 0xe2, 0xfe, 0x1d, 0xff, 0x5f, 0xff, 0xc7, 0xff, 0x44, 0x00, 0xd5, 0x00, 0x4d, 0x01, 0xc4, 0x01, 0x1e, 0x02, 0x4d, 0x02, 0x48, 0x02, 0x62, 0x02, 0x74, 0x02, 0x88, 0x02, 0x6c, 0x02, 0x4b, 0x02, 0x1a, 0x02, 0xbd, 0x01, 0x84, 0x01, 0x57, 0x01, 0x00, 0x01, 0x79, 0x00, 0x27, 0x00, 0xa7, 0xff, 0x3d, 0xff, 0x14, 0xff, 0xe5, 0xfe, 0xe0, 0xfe, 0x99, 0xfe, 0x79, 0xfe, 0x47, 0xfe, 0x49, 0xfe, 0x5b, 0xfe, 0x79, 0xfe, 0xce, 0xfe, 0xfa, 0xfe, 0x51, 0xff, 0x76, 0xff, 0x8d, 0xff, 0xbb, 0xff, 0xba, 0xff, 0xf5, 0xff, 0x3f, 0x00, 0x9d, 0x00, 0xe7, 0x00, 0x35, 0x01, 0x53, 0x01, 0x44, 0x01, 0x1e, 0x01, 0xf8, 0x00, 0xde, 0x00, 0xb4, 0x00, 0x42, 0x00, 0xdf, 0xff, 0x77, 0xff, 0x24, 0xff, 0xd0, 0xfe, 0x83, 0xfe, 0x53, 0xfe, 0x07, 0xfe, 0xf7, 0xfd, 0xfa, 0xfd, 0x3d, 0xfe, 0x89, 0xfe, 0xf2, 0xfe, 0x51, 0xff, 0xa4, 0xff, 0xe8, 0xff, 0x28, 0x00, 0x5a, 0x00, 0x83, 0x00, 0xbc, 0x00, 0xd0, 0x00, 0xfa, 0x00, 0x1f, 0x01, 0x4b, 0x01, 0x6f, 0x01, 0x90, 0x01, 0x9a, 0x01, 0x8e, 0x01, 0x79, 0x01, 0x37, 0x01, 0xe6, 0x00, 0xb7, 0x00, 0x55, 0x00, 0x2b, 0x00, 0x08, 0x00, 0xf2, 0xff, 0x03, 0x00, 0xe8, 0xff, 0xdf, 0xff, 0xd4, 0xff, 0xaa, 0xff, 0x65, 0xff, 0x1b, 0xff, 0xb0, 0xfe, 0x48, 0xfe, 0x24, 0xfe, 0x05, 0xfe, 0x0c, 0xfe, 0x17, 0xfe, 0x25, 0xfe, 0xf8, 0xfd, 0xf9, 0xfd, 0xf6, 0xfd, 0xf5, 0xfd, 0x01, 0xfe, 0xff, 0xfd, 0x29, 0xfe, 0x58, 0xfe, 0x86, 0xfe, 0xe2, 0xfe, 0x2b, 0xff, 0x7b, 0xff, 0xb6, 0xff, 0xf3, 0xff, 0x33, 0x00, 0x8f, 0x00, 0xce, 0x00, 0x19, 0x01, 0x56, 0x01, 0x72, 0x01, 0x9c, 0x01, 0x9a, 0x01, 0x8c, 0x01, 0x7d, 0x01, 0x78, 0x01, 0x30, 0x01, 0x2e, 0x01, 0x07, 0x01, 0xfc, 0x00, 0xd9, 0x00, 0xcb, 0x00, 0xa9, 0x00, 0x6b, 0x00, 0x3a, 0x00, 0x15, 0x00, 0xf1, 0xff, 0xd5, 0xff, 0xd8, 0xff, 0xb9, 0xff, 0x9c, 0xff, 0x66, 0xff, 0xf4, 0xfe, 0xa4, 0xfe, 0x44, 0xfe, 0x23, 0xfe, 0x05, 0xfe, 0xf0, 0xfd, 0xef, 0xfd, 0x16, 0xfe, 0x17, 0xfe, 0x3d, 0xfe, 0x86, 0xfe, 0xcd, 0xfe, 0xf5, 0xfe, 0x2e, 0xff, 0x51, 0xff, 0x86, 0xff, 0xc5, 0xff, 0xda, 0xff, 0x15, 0x00, 0x2e, 0x00, 0x66, 0x00, 0xa1, 0x00, 0xdd, 0x00, 0x03, 0x01, 0x5b, 0x01, 0x91, 0x01, 0xa4, 0x01, 0xd5, 0x01, 0xf0, 0x01, 0xe7, 0x01, 0x28, 0x02, 0x3f, 0x02, 0x68, 0x02, 0x85, 0x02, 0x6d, 0x02, 0x7c, 0x02, 0x93, 0x02, 0x75, 0x02, 0x68, 0x02, 0x26, 0x02, 0xaa, 0x01, 0x23, 0x01, 0x68, 0x00, 0xb2, 0xff, 0x12, 0xff, 0x99, 0xfe, 0x12, 0xfe, 0xcf, 0xfd, 0xb7, 0xfd, 0xa3, 0xfd, 0xa5, 0xfd, 0xb0, 0xfd, 0xb9, 0xfd, 0x9c, 0xfd, 0x8b, 0xfd, 0x92, 0xfd, 0x80, 0xfd, 0x73, 0xfd, 0x85, 0xfd, 0x9d, 0xfd, 0xc7, 0xfd, 0xc7, 0xfd, 0xef, 0xfd, 0xe8, 0xfd, 0x19, 0xfe, 0x5e, 0xfe, 0xbe, 0xfe, 0x29, 0xff, 0x8a, 0xff, 0xdf, 0xff, 0x31, 0x00, 0x8f, 0x00, 0xe1, 0x00, 0x40, 0x01, 0xb3, 0x01, 0x63, 0x02, 0x05, 0x03, 0x85, 0x03, 0xf3, 0x03, 0x21, 0x04, 0x10, 0x04, 0x0a, 0x04, 0xde, 0x03, 0xab, 0x03, 0x49, 0x03, 0xff, 0x02, 0x5f, 0x02, 0xd8, 0x01, 0x4e, 0x01, 0x9e, 0x00, 0x2c, 0x00, 0x9b, 0xff, 0x65, 0xff, 0x2c, 0xff, 0x3f, 0xff, 0x3a, 0xff, 0x68, 0xff, 0x6b, 0xff, 0x5d, 0xff, 0x44, 0xff, 0x21, 0xff, 0x05, 0xff, 0xdb, 0xfe, 0xac, 0xfe, 0x92, 0xfe, 0x4b, 0xfe, 0x35, 0xfe, 0x32, 0xfe, 0x5a, 0xfe, 0x78, 0xfe, 0x9d, 0xfe, 0xd9, 0xfe, 0x01, 0xff, 0x32, 0xff, 0x5c, 0xff, 0x67, 0xff, 0x64, 0xff, 0x40, 0xff, 0x01, 0xff, 0xec, 0xfe, 0xe5, 0xfe, 0x91, 0xfe, 0x5a, 0xfe, 0xf5, 0xfd, 0x93, 0xfd, 0x67, 0xfd, 0x77, 0xfd, 0x87, 0xfd, 0xa9, 0xfd, 0xa4, 0xfd, 0x86, 0xfd, 0x66, 0xfd, 0x41, 0xfd, 0x1f, 0xfd, 0x1e, 0xfd, 0x30, 0xfd, 0x34, 0xfd, 0x6e, 0xfd, 0xb5, 0xfd, 0x29, 0xfe, 0xb2, 0xfe, 0x40, 0xff, 0xbe, 0xff, 0x30, 0x00, 0x75, 0x00, 0x8c, 0x00, 0x91, 0x00, 0xa6, 0x00, 0xc1, 0x00, 0xd7, 0x00, 0x10, 0x01, 0x62, 0x01, 0xed, 0x01, 0x70, 0x02, 0xec, 0x02, 0x3f, 0x03, 0x6e, 0x03, 0x58, 0x03, 0x20, 0x03, 0xad, 0x02, 0x33, 0x02, 0xb2, 0x01, 0x4e, 0x01, 0x05, 0x01, 0xfb, 0x00, 0xf6, 0x00, 0xfd, 0x00, 0xdf, 0x00, 0x9c, 0x00, 0x6a, 0x00, 0xfb, 0xff, 0x9a, 0xff, 0x3c, 0xff, 0xd0, 0xfe, 0x83, 0xfe, 0x65, 0xfe, 0x40, 0xfe, 0x3b, 0xfe, 0x0b, 0xfe, 0xf0, 0xfd, 0xd8, 0xfd, 0xe4, 0xfd, 0x0d, 0xfe, 0x3e, 0xfe, 0x6d, 0xfe, 0xb2, 0xfe, 0x0e, 0xff, 0x68, 0xff, 0xe8, 0xff, 0x5e, 0x00, 0xfe, 0x00, 0xa9, 0x01, 0x57, 0x02, 0x0b, 0x03, 0x9e, 0x03, 0x13, 0x04, 0x84, 0x04, 0xe6, 0x04, 0x63, 0x05, 0x8e, 0x05, 0x97, 0x05, 0x5b, 0x05, 0xfa, 0x04, 0x4b, 0x04, 0xbc, 0x03, 0x3d, 0x03, 0x7c, 0x02, 0xc2, 0x01, 0xd4, 0x00, 0xf6, 0xff, 0x0b, 0xff, 0x2d, 0xfe, 0x87, 0xfd, 0xf2, 0xfc, 0x75, 0xfc, 0x04, 0xfc, 0x8e, 0xfb, 0x56, 0xfb, 0x34, 0xfb, 0x1b, 0xfb, 0x26, 0xfb, 0x2f, 0xfb, 0x3e, 0xfb, 0x40, 0xfb, 0x43, 0xfb, 0x3c, 0xfb, 0x60, 0xfb, 0xbd, 0xfb, 0x17, 0xfc, 0x92, 0xfc, 0x03, 0xfd, 0xa1, 0xfd, 0x31, 0xfe, 0xe1, 0xfe, 0xaa, 0xff, 0x77, 0x00, 0x52, 0x01, 0xec, 0x01, 0x6b, 0x02, 0x0a, 0x03, 0x5d, 0x03, 0xa0, 0x03, 0x06, 0x04, 0x59, 0x04, 0x7d, 0x04, 0x73, 0x04, 0x41, 0x04, 0xc7, 0x03, 0x4d, 0x03, 0xde, 0x02, 0x6e, 0x02, 0xf0, 0x01, 0x71, 0x01, 0xe3, 0x00, 0x82, 0x00, 0x18, 0x00, 0x9a, 0xff, 0x2a, 0xff, 0xba, 0xfe, 0x48, 0xfe, 0x09, 0xfe, 0xdb, 0xfd, 0xd8, 0xfd, 0xdb, 0xfd, 0xda, 0xfd, 0xd2, 0xfd, 0xa8, 0xfd, 0x8c, 0xfd, 0x79, 0xfd, 0x6c, 0xfd, 0x92, 0xfd, 0xae, 0xfd, 0xec, 0xfd, 0x14, 0xfe, 0x26, 0xfe, 0x44, 0xfe, 0x7f, 0xfe, 0xd6, 0xfe, 0x35, 0xff, 0xc5, 0xff, 0x33, 0x00, 0xb8, 0x00, 0x39, 0x01, 0x9c, 0x01, 0xec, 0x01, 0x19, 0x02, 0x23, 0x02, 0xff, 0x01, 0xc2, 0x01, 0x79, 0x01, 0x3f, 0x01, 0xd2, 0x00, 0x68, 0x00, 0x18, 0x00, 0xe0, 0xff, 0xd6, 0xff, 0xbc, 0xff, 0x8d, 0xff, 0x3f, 0xff, 0xf9, 0xfe, 0x97, 0xfe, 0x63, 0xfe, 0x38, 0xfe, 0x1e, 0xfe, 0x41, 0xfe, 0x42, 0xfe, 0x69, 0xfe, 0x90, 0xfe, 0xa7, 0xfe, 0xaf, 0xfe, 0xf0, 0xfe, 0x28, 0xff, 0x74, 0xff, 0x9f, 0xff, 0xdb, 0xff, 0x16, 0x00, 0x4a, 0x00, 0x84, 0x00, 0xd2, 0x00, 0xfc, 0x00, 0xe7, 0x00, 0xad, 0x00, 0x85, 0x00, 0x45, 0x00, 0xff, 0xff, 0xdd, 0xff, 0xc3, 0xff, 0xb7, 0xff, 0xba, 0xff, 0xb7, 0xff, 0xa8, 0xff, 0x8f, 0xff, 0xa5, 0xff, 0xb5, 0xff, 0xaf, 0xff, 0xc1, 0xff, 0xce, 0xff, 0xd3, 0xff, 0xed, 0xff, 0xf7, 0xff, 0x15, 0x00, 0x14, 0x00, 0x1a, 0x00, 0x29, 0x00, 0x17, 0x00, 0xfb, 0xff, 0x11, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2b, 0x00, 0x19, 0x00, 0x48, 0x00, 0x61, 0x00, 0x87, 0x00, 0xb6, 0x00, 0xe8, 0x00, 0xed, 0x00, 0xd4, 0x00, 0x7c, 0x00, 0x1f, 0x00, 0xd9, 0xff, 0x9e, 0xff, 0x83, 0xff, 0x81, 0xff, 0x89, 0xff, 0x8b, 0xff, 0x8f, 0xff, 0x79, 0xff, 0x5a, 0xff, 0x33, 0xff, 0xfa, 0xfe, 0xbd, 0xfe, 0xc4, 0xfe, 0xcb, 0xfe, 0xf7, 0xfe, 0x41, 0xff, 0x81, 0xff, 0xca, 0xff, 0xeb, 0xff, 0xe3, 0xff, 0xf9, 0xff, 0xdb, 0xff, 0xe0, 0xff, 0xd5, 0xff, 0xbb, 0xff, 0xed, 0xff, 0x1f, 0x00, 0x51, 0x00, 0x5c, 0x00, 0x79, 0x00, 0x5f, 0x00, 0x59, 0x00, 0x4b, 0x00, 0x39, 0x00, 0x5f, 0x00, 0x8f, 0x00, 0xe2, 0x00, 0x16, 0x01, 0x59, 0x01, 0x47, 0x01, 0x5a, 0x01, 0x3f, 0x01, 0x23, 0x01, 0x09, 0x01, 0xf2, 0x00, 0xd6, 0x00, 0xdc, 0x00, 0xb4, 0x00, 0x8c, 0x00, 0x78, 0x00, 0x5e, 0x00, 0x44, 0x00, 0x47, 0x00, 0x33, 0x00, 0x4e, 0x00, 0x8a, 0x00, 0xb0, 0x00, 0xdf, 0x00, 0xf5, 0x00, 0xdf, 0x00, 0xa8, 0x00, 0x86, 0x00, 0x23, 0x00, 0xbe, 0xff, 0x53, 0xff, 0xfd, 0xfe, 0xaa, 0xfe, 0x62, 0xfe, 0x5a, 0xfe, 0x54, 0xfe, 0x67, 0xfe, 0x7d, 0xfe, 0xb7, 0xfe, 0xcd, 0xfe, 0xc8, 0xfe, 0xc5, 0xfe, 0x9f, 0xfe, 0xa2, 0xfe, 0xb6, 0xfe, 0xc6, 0xfe, 0x09, 0xff, 0x30, 0xff, 0x83, 0xff, 0xc2, 0xff, 0xfd, 0xff, 0x3f, 0x00, 0x6f, 0x00, 0x9c, 0x00, 0xc0, 0x00, 0x9c, 0x00, 0x76, 0x00, 0x31, 0x00, 0xe9, 0xff, 0xcc, 0xff, 0xab, 0xff, 0x84, 0xff, 0x8b, 0xff, 0x59, 0xff, 0x44, 0xff, 0x27, 0xff, 0xf1, 0xfe, 0xc0, 0xfe, 0x95, 0xfe, 0x74, 0xfe, 0x3f, 0xfe, 0x32, 0xfe, 0x1d, 0xfe, 0x23, 0xfe, 0x73, 0xfe, 0xa5, 0xfe, 0x0c, 0xff, 0x55, 0xff, 0xa9, 0xff, 0xe8, 0xff, 0x29, 0x00, 0x5e, 0x00, 0x84, 0x00, 0x9e, 0x00, 0xa0, 0x00, 0x99, 0x00, 0xa1, 0x00, 0x76, 0x00, 0x78, 0x00, 0x71, 0x00, 0x7d, 0x00, 0xa0, 0x00, 0xb0, 0x00, 0xb7, 0x00, 0xca, 0x00, 0xdb, 0x00, 0xb7, 0x00, 0xb5, 0x00, 0xa9, 0x00, 0xce, 0x00, 0xbd, 0x00, 0xce, 0x00, 0xd4, 0x00, 0xfe, 0x00, 0x08, 0x01, 0x13, 0x01, 0x21, 0x01, 0x00, 0x01, 0xef, 0x00, 0xcd, 0x00, 0x88, 0x00, 0x4d, 0x00, 0x02, 0x00, 0xbd, 0xff, 0x6d, 0xff, 0x30, 0xff, 0xed, 0xfe, 0xbb, 0xfe, 0x74, 0xfe, 0x57, 0xfe, 0x25, 0xfe, 0xeb, 0xfd, 0xde, 0xfd, 0xc0, 0xfd, 0xbb, 0xfd, 0xc7, 0xfd, 0xdd, 0xfd, 0x09, 0xfe, 0x29, 0xfe, 0x28, 0xfe, 0x43, 0xfe, 0x64, 0xfe, 0x95, 0xfe, 0xa9, 0xfe, 0xd6, 0xfe, 0xe8, 0xfe, 0x06, 0xff, 0x27, 0xff, 0x57, 0xff, 0xb6, 0xff, 0xee, 0xff, 0x3e, 0x00, 0x87, 0x00, 0xe5, 0x00, 0x3f, 0x01, 0x63, 0x01, 0x7d, 0x01, 0xa2, 0x01, 0xc9, 0x01, 0xde, 0x01, 0xdc, 0x01, 0xef, 0x01, 0xc4, 0x01, 0x9d, 0x01, 0x8f, 0x01, 0x78, 0x01, 0x4c, 0x01, 0xf0, 0x00, 0xa7, 0x00, 0x30, 0x00, 0xe4, 0xff, 0xb5, 0xff, 0x61, 0xff, 0x18, 0xff, 0xd7, 0xfe, 0x8a, 0xfe, 0x81, 0xfe, 0x7c, 0xfe, 0x82, 0xfe, 0xa2, 0xfe, 0xb8, 0xfe, 0xb1, 0xfe, 0xc7, 0xfe, 0xc1, 0xfe, 0xcb, 0xfe, 0xd6, 0xfe, 0xc8, 0xfe, 0xd9, 0xfe, 0xe8, 0xfe, 0x19, 0xff, 0x46, 0xff, 0xa4, 0xff, 0xdd, 0xff, 0x16, 0x00, 0x55, 0x00, 0x84, 0x00, 0xcb, 0x00, 0x29, 0x01, 0x9a, 0x01, 0xfd, 0x01, 0x3c, 0x02, 0x4d, 0x02, 0x47, 0x02, 0x41, 0x02, 0xfc, 0x01, 0x9e, 0x01, 0x34, 0x01, 0x92, 0x00, 0x49, 0x00, 0x18, 0x00, 0xf4, 0xff, 0xee, 0xff, 0xd6, 0xff, 0xb8, 0xff, 0x7f, 0xff, 0x65, 0xff, 0x3b, 0xff, 0x2f, 0xff, 0x30, 0xff, 0x2f, 0xff, 0x3b, 0xff, 0x7f, 0xff, 0xc5, 0xff, 0x20, 0x00, 0x65, 0x00, 0xce, 0x00, 0x27, 0x01, 0x84, 0x01, 0xd5, 0x01, 0x36, 0x02, 0x66, 0x02, 0x92, 0x02, 0xbb, 0x02, 0xb1, 0x02, 0xb7, 0x02, 0xb2, 0x02, 0x8f, 0x02, 0x26, 0x02, 0xd1, 0x01, 0x47, 0x01, 0xe1, 0x00, 0x5a, 0x00, 0x0d, 0x00, 0xc6, 0xff, 0x99, 0xff, 0x61, 0xff, 0x29, 0xff, 0xce, 0xfe, 0x56, 0xfe, 0xd1, 0xfd, 0x3e, 0xfd, 0xc7, 0xfc, 0x64, 0xfc, 0x0d, 0xfc, 0xf8, 0xfb, 0xf3, 0xfb, 0x24, 0xfc, 0x4c, 0xfc, 0x9e, 0xfc, 0xdc, 0xfc, 0x12, 0xfd, 0x4f, 0xfd, 0x8f, 0xfd, 0xbb, 0xfd, 0xf0, 0xfd, 0x13, 0xfe, 0x3d, 0xfe, 0x9f, 0xfe, 0x25, 0xff, 0x98, 0xff, 0x1c, 0x00, 0x51, 0x00, 0x77, 0x00, 0x80, 0x00, 0x86, 0x00, 0x96, 0x00, 0xa3, 0x00, 0xb1, 0x00, 0xe1, 0x00, 0xf2, 0x00, 0xee, 0x00, 0xe5, 0x00, 0xa2, 0x00, 0x66, 0x00, 0x47, 0x00, 0x30, 0x00, 0x32, 0x00, 0x39, 0x00, 0x5a, 0x00, 0x83, 0x00, 0x96, 0x00, 0xc4, 0x00, 0xe6, 0x00, 0x04, 0x01, 0x1b, 0x01, 0x1a, 0x01, 0xeb, 0x00, 0xc4, 0x00, 0x86, 0x00, 0x48, 0x00, 0x02, 0x00, 0xd7, 0xff, 0xa5, 0xff, 0xb0, 0xff, 0x91, 0xff, 0x7c, 0xff, 0x35, 0xff, 0xe3, 0xfe, 0x9f, 0xfe, 0x57, 0xfe, 0x30, 0xfe, 0x2c, 0xfe, 0x2d, 0xfe, 0x3f, 0xfe, 0x42, 0xfe, 0x3d, 0xfe, 0x4b, 0xfe, 0x51, 0xfe, 0x85, 0xfe, 0xa3, 0xfe, 0xc9, 0xfe, 0xd8, 0xfe, 0xdb, 0xfe, 0xca, 0xfe, 0xda, 0xfe, 0x0c, 0xff, 0x49, 0xff, 0xa2, 0xff, 0xc7, 0xff, 0xf7, 0xff, 0x27, 0x00, 0x54, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x78, 0x00, 0x6e, 0x00, 0x7f, 0x00, 0xa9, 0x00, 0xd0, 0x00, 0xe5, 0x00, 0xca, 0x00, 0xe3, 0x00, 0xbd, 0x00, 0xbd, 0x00, 0xce, 0x00, 0xfa, 0x00, 0x1e, 0x01, 0x5d, 0x01, 0x8c, 0x01, 0xd2, 0x01, 0x09, 0x02, 0x20, 0x02, 0x62, 0x02, 0x8a, 0x02, 0x91, 0x02, 0x67, 0x02, 0x19, 0x02, 0xca, 0x01, 0x5e, 0x01, 0xdd, 0x00, 0x7b, 0x00, 0xed, 0xff, 0x87, 0xff, 0x18, 0xff, 0x00, 0xff, 0xce, 0xfe, 0xd0, 0xfe, 0xaf, 0xfe, 0x9b, 0xfe, 0x93, 0xfe, 0x92, 0xfe, 0x78, 0xfe, 0x9e, 0xfe, 0xa5, 0xfe, 0xca, 0xfe, 0xdb, 0xfe, 0x09, 0xff, 0x32, 0xff, 0x61, 0xff, 0xa3, 0xff, 0xd5, 0xff, 0x0d, 0x00, 0x46, 0x00, 0x58, 0x00, 0x47, 0x00, 0x35, 0x00, 0x01, 0x00, 0xe0, 0xff, 0xc2, 0xff, 0xb3, 0xff, 0xc2, 0xff, 0xe2, 0xff, 0xce, 0xff, 0xa2, 0xff, 0x62, 0xff, 0x1f, 0xff, 0xe8, 0xfe, 0xa9, 0xfe, 0x8b, 0xfe, 0x81, 0xfe, 0xa5, 0xfe, 0xbf, 0xfe, 0xe5, 0xfe, 0xfe, 0xfe, 0x1b, 0xff, 0x3a, 0xff, 0x2f, 0xff, 0x5a, 0xff, 0x69, 0xff, 0xa1, 0xff, 0xc9, 0xff, 0x10, 0x00, 0x4a, 0x00, 0x95, 0x00, 0xbf, 0x00, 0x0c, 0x01, 0x4a, 0x01, 0x96, 0x01, 0xdb, 0x01, 0x32, 0x02, 0x80, 0x02, 0xe2, 0x02, 0x40, 0x03, 0x81, 0x03, 0xb8, 0x03, 0xa1, 0x03, 0x4a, 0x03, 0x09, 0x03, 0xb5, 0x02, 0x40, 0x02, 0xe6, 0x01, 0x7b, 0x01, 0x2d, 0x01, 0xe2, 0x00, 0x74, 0x00, 0x27, 0x00, 0xbf, 0xff, 0x49, 0xff, 0xed, 0xfe, 0x87, 0xfe, 0x1a, 0xfe, 0xae, 0xfd, 0x2c, 0xfd, 0xa9, 0xfc, 0x3d, 0xfc, 0xff, 0xfb, 0xeb, 0xfb, 0xde, 0xfb, 0xd6, 0xfb, 0xcc, 0xfb, 0xc7, 0xfb, 0xcf, 0xfb, 0x01, 0xfc, 0x33, 0xfc, 0x9c, 0xfc, 0xf5, 0xfc, 0x61, 0xfd, 0xc4, 0xfd, 0x49, 0xfe, 0xb6, 0xfe, 0x3c, 0xff, 0xbb, 0xff, 0x1b, 0x00, 0xac, 0x00, 0x27, 0x01, 0xaf, 0x01, 0x23, 0x02, 0x86, 0x02, 0xc7, 0x02, 0xdc, 0x02, 0xbe, 0x02, 0xb8, 0x02, 0x63, 0x02, 0x21, 0x02, 0xd1, 0x01, 0x9c, 0x01, 0x6a, 0x01, 0x31, 0x01, 0xec, 0x00, 0x8d, 0x00, 0x2c, 0x00, 0xe2, 0xff, 0xc0, 0xff, 0xbc, 0xff, 0x86, 0xff, 0x84, 0xff, 0x63, 0xff, 0x77, 0xff, 0xa1, 0xff, 0xd2, 0xff, 0x09, 0x00, 0x3e, 0x00, 0x63, 0x00, 0x80, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x3d, 0x00, 0x26, 0x00, 0x19, 0x00, 0xf9, 0xff, 0x0e, 0x00, 0xed, 0xff, 0xe4, 0xff, 0xc3, 0xff, 0xb7, 0xff, 0x7d, 0xff, 0x5a, 0xff, 0x47, 0xff, 0x33, 0xff, 0x2f, 0xff, 0x3e, 0xff, 0x36, 0xff, 0x42, 0xff, 0x49, 0xff, 0x31, 0xff, 0x3d, 0xff, 0x44, 0xff, 0x60, 0xff, 0x6c, 0xff, 0x84, 0xff, 0x92, 0xff, 0xd6, 0xff, 0x23, 0x00, 0x81, 0x00, 0xd5, 0x00, 0x23, 0x01, 0x5f, 0x01, 0x81, 0x01, 0x9d, 0x01, 0x8d, 0x01, 0x85, 0x01, 0x36, 0x01, 0xd7, 0x00, 0x7c, 0x00, 0x10, 0x00, 0xb7, 0xff, 0x7c, 0xff, 0x67, 0xff, 0x3b, 0xff, 0x19, 0xff, 0xf6, 0xfe, 0xbb, 0xfe, 0x80, 0xfe, 0x45, 0xfe, 0x25, 0xfe, 0x02, 0xfe, 0x1d, 0xfe, 0x64, 0xfe, 0xa5, 0xfe, 0xd5, 0xfe, 0xf4, 0xfe, 0xde, 0xfe, 0xba, 0xfe, 0xdc, 0xfe, 0xc8, 0xfe, 0xb8, 0xfe, 0xcc, 0xfe, 0xbc, 0xfe, 0xf8, 0xfe, 0xe7, 0xfe, 0x19, 0xff, 0x4f, 0xff, 0x84, 0xff, 0xcc, 0xff, 0x25, 0x00, 0x7d, 0x00, 0xcc, 0x00, 0xf1, 0x00, 0xd9, 0x00, 0xd1, 0x00, 0xaf, 0x00, 0x79, 0x00, 0x4b, 0x00, 0x34, 0x00, 0xff, 0xff, 0xf9, 0xff, 0xef, 0xff, 0xe1, 0xff, 0xf7, 0xff, 0xd2, 0xff, 0xd3, 0xff, 0xe0, 0xff, 0xe2, 0xff, 0xea, 0xff, 0x1a, 0x00, 0x2f, 0x00, 0x29, 0x00, 0x1f, 0x00, 0x04, 0x00, 0xac, 0xff, 0x83, 0xff, 0x56, 0xff, 0x2e, 0xff, 0x0f, 0xff, 0xfa, 0xfe, 0xe8, 0xfe, 0x03, 0xff, 0x23, 0xff, 0x4e, 0xff, 0x80, 0xff, 0xc5, 0xff, 0xe2, 0xff, 0x12, 0x00, 0x42, 0x00, 0xae, 0x00, 0xda, 0x00, 0x3c, 0x01, 0x89, 0x01, 0xd7, 0x01, 0x30, 0x02, 0x60, 0x02, 0xc3, 0x02, 0x13, 0x03, 0x5b, 0x03, 0xa6, 0x03, 0xdf, 0x03, 0x04, 0x04, 0x3d, 0x04, 0x37, 0x04, 0x33, 0x04, 0x0e, 0x04, 0xa1, 0x03, 0x2b, 0x03, 0xbe, 0x02, 0x07, 0x02, 0x5b, 0x01, 0xb8, 0x00, 0x05, 0x00, 0x6b, 0xff, 0xed, 0xfe, 0x73, 0xfe, 0xfc, 0xfd, 0x9a, 0xfd, 0x19, 0xfd, 0xb2, 0xfc, 0x37, 0xfc, 0xe5, 0xfb, 0xad, 0xfb, 0x69, 0xfb, 0x4d, 0xfb, 0x49, 0xfb, 0x53, 0xfb, 0x65, 0xfb, 0xb0, 0xfb, 0xd9, 0xfb, 0x33, 0xfc, 0x66, 0xfc, 0x97, 0xfc, 0xee, 0xfc, 0x2c, 0xfd, 0x6c, 0xfd, 0xc6, 0xfd, 0x07, 0xfe, 0x39, 0xfe, 0x71, 0xfe, 0xad, 0xfe, 0xd0, 0xfe, 0x28, 0xff, 0x7e, 0xff, 0xb1, 0xff, 0x00, 0x00, 0x1e, 0x00, 0x53, 0x00, 0x9e, 0x00, 0xd2, 0x00, 0x31, 0x01, 0xa0, 0x01, 0xf2, 0x01, 0x32, 0x02, 0x43, 0x02, 0x1a, 0x02, 0xd0, 0x01, 0xa1, 0x01, 0x6e, 0x01, 0x3a, 0x01, 0x34, 0x01, 0x1a, 0x01, 0x0c, 0x01, 0x02, 0x01, 0xd3, 0x00, 0xa5, 0x00, 0x53, 0x00, 0x44, 0x00, 0x2a, 0x00, 0x10, 0x00, 0x07, 0x00, 0x06, 0x00, 0x08, 0x00, 0xfd, 0xff, 0x1a, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x27, 0x00, 0x2b, 0x00, 0x27, 0x00, 0x11, 0x00, 0xfd, 0xff, 0xde, 0xff, 0xa6, 0xff, 0xa5, 0xff, 0x8a, 0xff, 0x99, 0xff, 0xb9, 0xff, 0xd4, 0xff, 0x13, 0x00, 0x4f, 0x00, 0x75, 0x00, 0x8e, 0x00, 0xad, 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc6, 0x00, 0xca, 0x00, 0xe3, 0x00, 0xee, 0x00, 0xf6, 0x00, 0xf0, 0x00, 0xd3, 0x00, 0x91, 0x00, 0x5d, 0x00, 0x38, 0x00, 0x24, 0x00, 0x17, 0x00, 0xf7, 0xff, 0xda, 0xff, 0xc6, 0xff, 0x91, 0xff, 0x8b, 0xff, 0xa9, 0xff, 0xa6, 0xff, 0xa8, 0xff, 0x7f, 0xff, 0x34, 0xff, 0xf5, 0xfe, 0xd1, 0xfe, 0x96, 0xfe, 0x53, 0xfe, 0x2e, 0xfe, 0x02, 0xfe, 0xfa, 0xfd, 0x0b, 0xfe, 0x34, 0xfe, 0x67, 0xfe, 0xaa, 0xfe, 0xd0, 0xfe, 0xf4, 0xfe, 0x27, 0xff, 0x4c, 0xff, 0x86, 0xff, 0xe6, 0xff, 0x3f, 0x00, 0xb8, 0x00, 0x2b, 0x01, 0x9a, 0x01, 0x2a, 0x02, 0x9f, 0x02, 0x26, 0x03, 0xab, 0x03, 0x25, 0x04, 0x6e, 0x04, 0xa3, 0x04, 0x65, 0x04, 0x42, 0x04, 0xb5, 0x03, 0x1d, 0x03, 0x6d, 0x02, 0xe5, 0x01, 0x4b, 0x01, 0x96, 0x00, 0xf7, 0xff, 0x3a, 0xff, 0x88, 0xfe, 0xf6, 0xfd, 0xa2, 0xfd, 0x54, 0xfd, 0x15, 0xfd, 0xf4, 0xfc, 0xcf, 0xfc, 0xaf, 0xfc, 0x96, 0xfc, 0x76, 0xfc, 0x65, 0xfc, 0x6b, 0xfc, 0x7d, 0xfc, 0x81, 0xfc, 0xb1, 0xfc, 0xc3, 0xfc, 0x0d, 0xfd, 0x42, 0xfd, 0x92, 0xfd, 0xe4, 0xfd, 0x2f, 0xfe, 0x96, 0xfe, 0xd6, 0xfe, 0x39, 0xff, 0x95, 0xff, 0xf4, 0xff, 0x2d, 0x00, 0x8a, 0x00, 0xca, 0x00, 0xf7, 0x00, 0x1a, 0x01, 0x44, 0x01, 0x80, 0x01, 0x7a, 0x01, 0x88, 0x01, 0x88, 0x01, 0x97, 0x01, 0xaa, 0x01, 0x89, 0x01, 0x88, 0x01, 0x64, 0x01, 0x31, 0x01, 0x2f, 0x01, 0x32, 0x01, 0x1a, 0x01, 0x03, 0x01, 0xdf, 0x00, 0xba, 0x00, 0xaf, 0x00, 0x91, 0x00, 0x6c, 0x00, 0x47, 0x00, 0x1c, 0x00, 0xfd, 0xff, 0xcd, 0xff, 0x96, 0xff, 0x54, 0xff, 0xfc, 0xfe, 0xa5, 0xfe, 0x6d, 0xfe, 0x41, 0xfe, 0x15, 0xfe, 0x0e, 0xfe, 0x0d, 0xfe, 0x26, 0xfe, 0x22, 0xfe, 0x41, 0xfe, 0x53, 0xfe, 0x45, 0xfe, 0x55, 0xfe, 0x88, 0xfe, 0xac, 0xfe, 0xf2, 0xfe, 0x29, 0xff, 0x55, 0xff, 0x7a, 0xff, 0x9d, 0xff, 0xc8, 0xff, 0xf7, 0xff, 0x16, 0x00, 0x3f, 0x00, 0x71, 0x00, 0x99, 0x00, 0xbd, 0x00, 0xbe, 0x00, 0xdd, 0x00, 0xdd, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x21, 0x01, 0x1a, 0x01, 0x00, 0x01, 0xd1, 0x00, 0x94, 0x00, 0x2c, 0x00, 0x00, 0x00, 0xc6, 0xff, 0xaa, 0xff, 0x79, 0xff, 0x4e, 0xff, 0x3c, 0xff, 0x0c, 0xff, 0x01, 0xff, 0xfc, 0xfe, 0x25, 0xff, 0x53, 0xff, 0x8e, 0xff, 0xd6, 0xff, 0xfd, 0xff, 0x37, 0x00, 0x7e, 0x00, 0xa9, 0x00, 0xe4, 0x00, 0x05, 0x01, 0x00, 0x01, 0xe3, 0x00, 0xb2, 0x00, 0xb7, 0x00, 0x89, 0x00, 0x6e, 0x00, 0x44, 0x00, 0x16, 0x00, 0xfd, 0xff, 0xcf, 0xff, 0xc2, 0xff, 0x8d, 0xff, 0x69, 0xff, 0x36, 0xff, 0xfe, 0xfe, 0xd6, 0xfe, 0xc4, 0xfe, 0xba, 0xfe, 0xc3, 0xfe, 0xbe, 0xfe, 0xa3, 0xfe, 0x7e, 0xfe, 0x34, 0xfe, 0x13, 0xfe, 0xf1, 0xfd, 0x11, 0xfe, 0x22, 0xfe, 0x4c, 0xfe, 0x7a, 0xfe, 0xc2, 0xfe, 0x07, 0xff, 0x33, 0xff, 0x93, 0xff, 0x07, 0x00, 0x74, 0x00, 0xcc, 0x00, 0x33, 0x01, 0x86, 0x01, 0xff, 0x01, 0x35, 0x02, 0x53, 0x02, 0x77, 0x02, 0x67, 0x02, 0x36, 0x02, 0x01, 0x02, 0xd1, 0x01, 0x60, 0x01, 0x21, 0x01, 0xe6, 0x00, 0xa7, 0x00, 0x9d, 0x00, 0x51, 0x00, 0x3d, 0x00, 0x31, 0x00, 0x3f, 0x00, 0x47, 0x00, 0x57, 0x00, 0x70, 0x00, 0x86, 0x00, 0x80, 0x00, 0x72, 0x00, 0x6a, 0x00, 0x62, 0x00, 0x3a, 0x00, 0xfe, 0xff, 0xca, 0xff, 0x94, 0xff, 0x4f, 0xff, 0x45, 0xff, 0x26, 0xff, 0x2a, 0xff, 0x26, 0xff, 0x1a, 0xff, 0x1a, 0xff, 0x13, 0xff, 0x12, 0xff, 0x1d, 0xff, 0x4b, 0xff, 0x51, 0xff, 0x7d, 0xff, 0x60, 0xff, 0x5d, 0xff, 0x58, 0xff, 0x5c, 0xff, 0x57, 0xff, 0x60, 0xff, 0x8b, 0xff, 0x7c, 0xff, 0x6f, 0xff, 0x59, 0xff, 0x50, 0xff, 0x30, 0xff, 0x36, 0xff, 0x65, 0xff, 0x91, 0xff, 0xc4, 0xff, 0xca, 0xff, 0xd0, 0xff, 0xca, 0xff, 0xb7, 0xff, 0xaa, 0xff, 0xa8, 0xff, 0x9f, 0xff, 0x91, 0xff, 0x64, 0xff, 0x42, 0xff, 0x07, 0xff, 0xea, 0xfe, 0xca, 0xfe, 0xc2, 0xfe, 0xcc, 0xfe, 0xe2, 0xfe, 0x40, 0xff, 0x7d, 0xff, 0xef, 0xff, 0x44, 0x00, 0xa0, 0x00, 0xd1, 0x00, 0x0e, 0x01, 0x2e, 0x01, 0x45, 0x01, 0x31, 0x01, 0x22, 0x01, 0xe6, 0x00, 0x90, 0x00, 0x79, 0x00, 0x4c, 0x00, 0x2e, 0x00, 0xf6, 0xff, 0xd6, 0xff, 0x6e, 0xff, 0x1c, 0xff, 0xf4, 0xfe, 0xaf, 0xfe, 0x89, 0xfe, 0x84, 0xfe, 0x71, 0xfe, 0x7f, 0xfe, 0x95, 0xfe, 0xae, 0xfe, 0xd7, 0xfe, 0x0c, 0xff, 0x28, 0xff, 0x4b, 0xff, 0x48, 0xff, 0x30, 0xff, 0x3b, 0xff, 0x34, 0xff, 0x50, 0xff, 0x90, 0xff, 0xdf, 0xff, 0x34, 0x00, 0x82, 0x00, 0xb4, 0x00, 0xce, 0x00, 0xd6, 0x00, 0xf9, 0x00, 0x00, 0x01, 0xdd, 0x00, 0xbf, 0x00, 0x96, 0x00, 0x78, 0x00, 0x66, 0x00, 0x4c, 0x00, 0x64, 0x00, 0x33, 0x00, 0x18, 0x00, 0x10, 0x00, 0xf6, 0xff, 0xfa, 0xff, 0xfe, 0xff, 0xea, 0xff, 0xdf, 0xff, 0xc7, 0xff, 0xa4, 0xff, 0x92, 0xff, 0xbc, 0xff, 0xeb, 0xff, 0x13, 0x00, 0x4f, 0x00, 0x82, 0x00, 0xb6, 0x00, 0xde, 0x00, 0xf6, 0x00, 0x2e, 0x01, 0x44, 0x01, 0x64, 0x01, 0x84, 0x01, 0x99, 0x01, 0x9d, 0x01, 0x70, 0x01, 0x40, 0x01, 0x13, 0x01, 0x10, 0x01, 0xe1, 0x00, 0xa8, 0x00, 0x82, 0x00, 0x55, 0x00, 0x2b, 0x00, 0xef, 0xff, 0xd9, 0xff, 0xa7, 0xff, 0x89, 0xff, 0x67, 0xff, 0x32, 0xff, 0xff, 0xfe, 0xd1, 0xfe, 0x9c, 0xfe, 0x6b, 0xfe, 0x2e, 0xfe, 0x18, 0xfe, 0x2c, 0xfe, 0x1e, 0xfe, 0x4b, 0xfe, 0x8b, 0xfe, 0xb7, 0xfe, 0xee, 0xfe, 0x1d, 0xff, 0x4a, 0xff, 0x76, 0xff, 0xb2, 0xff, 0xaf, 0xff, 0xbc, 0xff, 0xa9, 0xff, 0x97, 0xff, 0x72, 0xff, 0x65, 0xff, 0x65, 0xff, 0x81, 0xff, 0xad, 0xff, 0xcc, 0xff, 0xfc, 0xff, 0x08, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x16, 0x00, 0x40, 0x00, 0x6a, 0x00, 0x8a, 0x00, 0xb0, 0x00, 0xa9, 0x00, 0xc0, 0x00, 0xdf, 0x00, 0x22, 0x01, 0x38, 0x01, 0x5d, 0x01, 0x5a, 0x01, 0x53, 0x01, 0x24, 0x01, 0xdf, 0x00, 0xc8, 0x00, 0x88, 0x00, 0x6c, 0x00, 0x30, 0x00, 0x1e, 0x00, 0xe6, 0xff, 0xb4, 0xff, 0x80, 0xff, 0x58, 0xff, 0x37, 0xff, 0x11, 0xff, 0xeb, 0xfe, 0xd2, 0xfe, 0xd8, 0xfe, 0xc8, 0xfe, 0xb0, 0xfe, 0xa5, 0xfe, 0x8b, 0xfe, 0x91, 0xfe, 0x69, 0xfe, 0x49, 0xfe, 0x3b, 0xfe, 0x41, 0xfe, 0x3f, 0xfe, 0x64, 0xfe, 0x7b, 0xfe, 0xa3, 0xfe, 0xda, 0xfe, 0xf8, 0xfe, 0x26, 0xff, 0x4d, 0xff, 0x81, 0xff, 0xb5, 0xff, 0xd8, 0xff, 0x1b, 0x00, 0x45, 0x00, 0x8f, 0x00, 0xcd, 0x00, 0x02, 0x01, 0x32, 0x01, 0x34, 0x01, 0x12, 0x01, 0xe9, 0x00, 0xca, 0x00, 0xdd, 0x00, 0xbc, 0x00, 0xbe, 0x00, 0xb2, 0x00, 0x8e, 0x00, 0x90, 0x00, 0x7e, 0x00, 0x93, 0x00, 0x89, 0x00, 0xbf, 0x00, 0xcb, 0x00, 0xe9, 0x00, 0xe4, 0x00, 0x06, 0x01, 0xf3, 0x00, 0x05, 0x01, 0xe7, 0x00, 0xd5, 0x00, 0xc7, 0x00, 0x94, 0x00, 0x6b, 0x00, 0x1f, 0x00, 0x9c, 0xff, 0x58, 0xff, 0xef, 0xfe, 0xaf, 0xfe, 0x6c, 0xfe, 0x33, 0xfe, 0x13, 0xfe, 0xcf, 0xfd, 0xd6, 0xfd, 0x0a, 0xfe, 0x53, 0xfe, 0x81, 0xfe, 0xca, 0xfe, 0xe2, 0xfe, 0x00, 0xff, 0x01, 0xff, 0xe8, 0xfe, 0xe6, 0xfe, 0xca, 0xfe, 0xf6, 0xfe, 0x0e, 0xff, 0x5a, 0xff, 0x88, 0xff, 0xd9, 0xff, 0x12, 0x00, 0x48, 0x00, 0x90, 0x00, 0xcd, 0x00, 0x09, 0x01, 0x4e, 0x01, 0x7c, 0x01, 0x9f, 0x01, 0x9d, 0x01, 0x8e, 0x01, 0x7a, 0x01, 0x59, 0x01, 0x51, 0x01, 0x2e, 0x01, 0x39, 0x01, 0x15, 0x01, 0x20, 0x01, 0x13, 0x01, 0x16, 0x01, 0xfa, 0x00, 0xff, 0x00, 0xd4, 0x00, 0x95, 0x00, 0x4b, 0x00, 0xfa, 0xff, 0xae, 0xff, 0x43, 0xff, 0x0d, 0xff, 0xba, 0xfe, 0x86, 0xfe, 0x75, 0xfe, 0x6b, 0xfe, 0x7b, 0xfe, 0x64, 0xfe, 0x66, 0xfe, 0x48, 0xfe, 0x37, 0xfe, 0x4f, 0xfe, 0x44, 0xfe, 0x54, 0xfe, 0x83, 0xfe, 0xa4, 0xfe, 0xc5, 0xfe, 0x04, 0xff, 0x2c, 0xff, 0x53, 0xff, 0x68, 0xff, 0x92, 0xff, 0x99, 0xff, 0x93, 0xff, 0x8c, 0xff, 0x97, 0xff, 0x9a, 0xff, 0xb7, 0xff, 0xbb, 0xff, 0xdf, 0xff, 0xfe, 0xff, 0xee, 0xff, 0x01, 0x00, 0x03, 0x00, 0xe9, 0xff, 0xf3, 0xff, 0xb8, 0xff, 0xa1, 0xff, 0x89, 0xff, 0x8f, 0xff, 0xae, 0xff, 0xcf, 0xff, 0xff, 0xff, 0x2f, 0x00, 0x77, 0x00, 0xd9, 0x00, 0x21, 0x01, 0x60, 0x01, 0x8e, 0x01, 0x90, 0x01, 0x7f, 0x01, 0x55, 0x01, 0x28, 0x01, 0xf0, 0x00, 0xed, 0x00, 0xb6, 0x00, 0xa0, 0x00, 0x7b, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x55, 0x00, 0x6f, 0x00, 0x8c, 0x00, 0xc3, 0x00, 0xe5, 0x00, 0x0c, 0x01, 0x3c, 0x01, 0x36, 0x01, 0x27, 0x01, 0x25, 0x01, 0xf5, 0x00, 0xc2, 0x00, 0x8d, 0x00, 0x5c, 0x00, 0x35, 0x00, 0xea, 0xff, 0x97, 0xff, 0x6c, 0xff, 0x3d, 0xff, 0xf8, 0xfe, 0xdd, 0xfe, 0xdd, 0xfe, 0xa1, 0xfe, 0x7e, 0xfe, 0x60, 0xfe, 0x33, 0xfe, 0x15, 0xfe, 0xfb, 0xfd, 0xca, 0xfd, 0xc3, 0xfd, 0xbc, 0xfd, 0xd9, 0xfd, 0xeb, 0xfd, 0x0c, 0xfe, 0x2e, 0xfe, 0x57, 0xfe, 0x94, 0xfe, 0xcc, 0xfe, 0x2b, 0xff, 0x8f, 0xff, 0x2c, 0x00, 0xa5, 0x00, 0x2a, 0x01, 0x92, 0x01, 0xe1, 0x01, 0x10, 0x02, 0x3e, 0x02, 0x4c, 0x02, 0x78, 0x02, 0x53, 0x02, 0x35, 0x02, 0xdf, 0x01, 0x84, 0x01, 0x3f, 0x01, 0xe0, 0x00, 0xb2, 0x00, 0x4d, 0x00, 0x16, 0x00, 0xb5, 0xff, 0x78, 0xff, 0x3d, 0xff, 0x01, 0xff, 0xf0, 0xfe, 0xee, 0xfe, 0x0a, 0xff, 0x37, 0xff, 0x74, 0xff, 0xc1, 0xff, 0xea, 0xff, 0x12, 0x00, 0x38, 0x00, 0x47, 0x00, 0x39, 0x00, 0x15, 0x00, 0xdc, 0xff, 0x97, 0xff, 0x55, 0xff, 0x27, 0xff, 0xe1, 0xfe, 0xbf, 0xfe, 0xa0, 0xfe, 0x8e, 0xfe, 0x75, 0xfe, 0x69, 0xfe, 0x86, 0xfe, 0xa7, 0xfe, 0xbd, 0xfe, 0xe9, 0xfe, 0x11, 0xff, 0x25, 0xff, 0x33, 0xff, 0x4e, 0xff, 0x51, 0xff, 0x33, 0xff, 0x28, 0xff, 0x15, 0xff, 0xee, 0xfe, 0xed, 0xfe, 0x1e, 0xff, 0x56, 0xff, 0x83, 0xff, 0xae, 0xff, 0xcb, 0xff, 0xe4, 0xff, 0xfb, 0xff, 0x0a, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x41, 0x00, 0x6a, 0x00, 0x99, 0x00, 0x9c, 0x00, 0xbd, 0x00, 0xad, 0x00, 0xca, 0x00, 0xc6, 0x00, 0xcb, 0x00, 0xe6, 0x00, 0x05, 0x01, 0xdf, 0x00, 0xc2, 0x00, 0x6b, 0x00, 0xee, 0xff, 0x99, 0xff, 0x61, 0xff, 0x21, 0xff, 0xfc, 0xfe, 0xe1, 0xfe, 0xac, 0xfe, 0x8c, 0xfe, 0x77, 0xfe, 0x94, 0xfe, 0x8d, 0xfe, 0xa1, 0xfe, 0xaf, 0xfe, 0xba, 0xfe, 0xe0, 0xfe, 0xd8, 0xfe, 0xfa, 0xfe, 0x12, 0xff, 0x1c, 0xff, 0x55, 0xff, 0x7c, 0xff, 0xcf, 0xff, 0x32, 0x00, 0x9d, 0x00, 0x06, 0x01, 0x62, 0x01, 0xa6, 0x01, 0xbe, 0x01, 0xc1, 0x01, 0xc1, 0x01, 0x8c, 0x01, 0x4c, 0x01, 0x0e, 0x01, 0xd6, 0x00, 0xb3, 0x00, 0x83, 0x00, 0x50, 0x00, 0xfe, 0xff, 0xcb, 0xff, 0x9c, 0xff, 0x73, 0xff, 0x5d, 0xff, 0x69, 0xff, 0x68, 0xff, 0x7e, 0xff, 0x93, 0xff, 0xc0, 0xff, 0xf5, 0xff, 0x21, 0x00, 0x5a, 0x00, 0xa9, 0x00, 0xd9, 0x00, 0x1c, 0x01, 0x2d, 0x01, 0x47, 0x01, 0x53, 0x01, 0x6e, 0x01, 0x5f, 0x01, 0x4d, 0x01, 0x45, 0x01, 0x25, 0x01, 0xf2, 0x00, 0xc2, 0x00, 0x81, 0x00, 0x49, 0x00, 0x17, 0x00, 0xcf, 0xff, 0xa6, 0xff, 0x8f, 0xff, 0x68, 0xff, 0x2d, 0xff, 0xf9, 0xfe, 0x9e, 0xfe, 0x52, 0xfe, 0x36, 0xfe, 0x21, 0xfe, 0x0a, 0xfe, 0x10, 0xfe, 0xee, 0xfd, 0xdb, 0xfd, 0xc6, 0xfd, 0xe3, 0xfd, 0xdb, 0xfd, 0xfd, 0xfd, 0x0d, 0xfe, 0x38, 0xfe, 0x7c, 0xfe, 0xb9, 0xfe, 0x1f, 0xff, 0x92, 0xff, 0x0e, 0x00, 0x85, 0x00, 0xe1, 0x00, 0x34, 0x01, 0x5c, 0x01, 0x48, 0x01, 0x4f, 0x01, 0x2a, 0x01, 0x28, 0x01, 0x28, 0x01, 0x27, 0x01, 0x08, 0x01, 0xc2, 0x00, 0x60, 0x00, 0xf9, 0xff, 0xa5, 0xff, 0x62, 0xff, 0x1d, 0xff, 0x0e, 0xff, 0xf8, 0xfe, 0x02, 0xff, 0x17, 0xff, 0x12, 0xff, 0x2b, 0xff, 0x37, 0xff, 0x5f, 0xff, 0x66, 0xff, 0x96, 0xff, 0xb2, 0xff, 0xde, 0xff, 0xf9, 0xff, 0xf6, 0xff, 0x16, 0x00, 0x31, 0x00, 0x82, 0x00, 0xa1, 0x00, 0x07, 0x01, 0x36, 0x01, 0x95, 0x01, 0x9d, 0x01, 0xc7, 0x01, 0xd7, 0x01, 0xdf, 0x01, 0xd6, 0x01, 0xe0, 0x01, 0xcb, 0x01, 0x83, 0x01, 0x3b, 0x01, 0xc9, 0x00, 0x64, 0x00, 0xf9, 0xff, 0x8f, 0xff, 0x21, 0xff, 0xd9, 0xfe, 0xa5, 0xfe, 0x93, 0xfe, 0x65, 0xfe, 0x5b, 0xfe, 0x56, 0xfe, 0x40, 0xfe, 0x5e, 0xfe, 0x76, 0xfe, 0x8f, 0xfe, 0xbd, 0xfe, 0xf1, 0xfe, 0x37, 0xff, 0x74, 0xff, 0xd5, 0xff, 0x1c, 0x00, 0x71, 0x00, 0xb0, 0x00, 0xd1, 0x00, 0xe4, 0x00, 0xf6, 0x00, 0xd5, 0x00, 0x8e, 0x00, 0x5e, 0x00, 0x0e, 0x00, 0xd2, 0xff, 0x9d, 0xff, 0x94, 0xff, 0x64, 0xff, 0x63, 0xff, 0x44, 0xff, 0x40, 0xff, 0x30, 0xff, 0x64, 0xff, 0x99, 0xff, 0xdb, 0xff, 0x12, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x45, 0x00, 0x49, 0x00, 0x2f, 0x00, 0x1d, 0x00, 0xf4, 0xff, 0xbf, 0xff, 0x93, 0xff, 0x68, 0xff, 0x58, 0xff, 0x37, 0xff, 0x29, 0xff, 0x03, 0xff, 0x0c, 0xff, 0x12, 0xff, 0x12, 0xff, 0x1b, 0xff, 0x35, 0xff, 0x5b, 0xff, 0x76, 0xff, 0x6f, 0xff, 0x71, 0xff, 0x73, 0xff, 0x96, 0xff, 0x89, 0xff, 0xac, 0xff, 0xcb, 0xff, 0xf0, 0xff, 0x1b, 0x00, 0x65, 0x00, 0xb0, 0x00, 0xfc, 0x00, 0x14, 0x01, 0x2c, 0x01, 0x2e, 0x01, 0x31, 0x01, 0x11, 0x01, 0xdf, 0x00, 0x94, 0x00, 0x1c, 0x00, 0xac, 0xff, 0x80, 0xff, 0x55, 0xff, 0x29, 0xff, 0xe7, 0xfe, 0x83, 0xfe, 0x1c, 0xfe, 0x00, 0xfe, 0xe1, 0xfd, 0xc3, 0xfd, 0xcb, 0xfd, 0xa3, 0xfd, 0xc2, 0xfd, 0xea, 0xfd, 0x1f, 0xfe, 0x8a, 0xfe, 0xfd, 0xfe, 0x69, 0xff, 0xc3, 0xff, 0x0d, 0x00, 0x54, 0x00, 0x9e, 0x00, 0xdd, 0x00, 0x2e, 0x01, 0x8a, 0x01, 0xf4, 0x01, 0x3d, 0x02, 0x8b, 0x02, 0xb8, 0x02, 0xcc, 0x02, 0xd3, 0x02, 0xcf, 0x02, 0xc5, 0x02, 0xa3, 0x02, 0x6b, 0x02, 0x26, 0x02, 0xd4, 0x01, 0x6d, 0x01, 0x01, 0x01, 0x6f, 0x00, 0xf7, 0xff, 0x70, 0xff, 0x26, 0xff, 0xc0, 0xfe, 0x73, 0xfe, 0x3f, 0xfe, 0x02, 0xfe, 0x05, 0xfe, 0xfa, 0xfd, 0x15, 0xfe, 0x46, 0xfe, 0x62, 0xfe, 0x9b, 0xfe, 0xd7, 0xfe, 0x0c, 0xff, 0x50, 0xff, 0x9e, 0xff, 0xbd, 0xff, 0xd2, 0xff, 0xe9, 0xff, 0xe2, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xd5, 0xff, 0xf6, 0xff, 0xec, 0xff, 0xf6, 0xff, 0xf9, 0xff, 0x36, 0x00, 0x2f, 0x00, 0x44, 0x00, 0x66, 0x00, 0x8e, 0x00, 0xa4, 0x00, 0x8c, 0x00, 0x6f, 0x00, 0x3f, 0x00, 0x2c, 0x00, 0x16, 0x00, 0xef, 0xff, 0xdd, 0xff, 0xa4, 0xff, 0xa6, 0xff, 0x94, 0xff, 0x98, 0xff, 0xa3, 0xff, 0xab, 0xff, 0x9b, 0xff, 0xa8, 0xff, 0x93, 0xff, 0x7b, 0xff, 0x7a, 0xff, 0x7c, 0xff, 0x80, 0xff, 0x76, 0xff, 0x72, 0xff, 0x52, 0xff, 0x3f, 0xff, 0x41, 0xff, 0x38, 0xff, 0x40, 0xff, 0x5a, 0xff, 0x54, 0xff, 0x50, 0xff, 0x54, 0xff, 0x42, 0xff, 0x4d, 0xff, 0x75, 0xff, 0xbd, 0xff, 0xff, 0xff, 0x27, 0x00, 0x3c, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x1c, 0x00, 0xf9, 0xff, 0xec, 0xff, 0xbe, 0xff, 0x9d, 0xff, 0x99, 0xff, 0x9c, 0xff, 0xbf, 0xff, 0xd0, 0xff, 0xe7, 0xff, 0xca, 0xff, 0xc5, 0xff, 0x98, 0xff, 0x77, 0xff, 0x72, 0xff, 0x92, 0xff, 0xa3, 0xff, 0xd6, 0xff, 0xd5, 0xff, 0x01, 0x00, 0x22, 0x00, 0x31, 0x00, 0x5d, 0x00, 0x7e, 0x00, 0xb2, 0x00, 0xe1, 0x00, 0xf2, 0x00, 0x37, 0x01, 0x3c, 0x01, 0x54, 0x01, 0x56, 0x01, 0x6f, 0x01, 0x52, 0x01, 0x31, 0x01, 0x08, 0x01, 0xd5, 0x00, 0x7f, 0x00, 0x51, 0x00, 0x05, 0x00, 0xc6, 0xff, 0x85, 0xff, 0x65, 0xff, 0x5c, 0xff, 0x44, 0xff, 0x17, 0xff, 0xf3, 0xfe, 0xc4, 0xfe, 0x9f, 0xfe, 0x81, 0xfe, 0x6b, 0xfe, 0x5c, 0xfe, 0x4b, 0xfe, 0x43, 0xfe, 0x68, 0xfe, 0x84, 0xfe, 0xc9, 0xfe, 0xfb, 0xfe, 0x41, 0xff, 0x92, 0xff, 0xbf, 0xff, 0xfc, 0xff, 0x1e, 0x00, 0x1c, 0x00, 0x37, 0x00, 0x45, 0x00, 0x3b, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x1e, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xd6, 0xff, 0xe9, 0xff, 0xff, 0xff, 0x02, 0x00, 0x45, 0x00, 0x76, 0x00, 0xb7, 0x00, 0xde, 0x00, 0xed, 0x00, 0x10, 0x01, 0xfd, 0x00, 0xeb, 0x00, 0xee, 0x00, 0x08, 0x01, 0x2c, 0x01, 0x3b, 0x01, 0x4a, 0x01, 0x42, 0x01, 0x32, 0x01, 0x25, 0x01, 0x26, 0x01, 0x1e, 0x01, 0xff, 0x00, 0xd3, 0x00, 0xa3, 0x00, 0x7e, 0x00, 0x52, 0x00, 0xff, 0xff, 0xb1, 0xff, 0x3e, 0xff, 0xe0, 0xfe, 0x9f, 0xfe, 0x43, 0xfe, 0x14, 0xfe, 0xd6, 0xfd, 0xa0, 0xfd, 0x7d, 0xfd, 0x65, 0xfd, 0x55, 0xfd, 0x4d, 0xfd, 0x5e, 0xfd, 0x80, 0xfd, 0xaf, 0xfd, 0xda, 0xfd, 0x12, 0xfe, 0x4e, 0xfe, 0x82, 0xfe, 0xda, 0xfe, 0x17, 0xff, 0x6f, 0xff, 0xc7, 0xff, 0x48, 0x00, 0x8e, 0x00, 0xed, 0x00, 0x31, 0x01, 0x79, 0x01, 0x8c, 0x01, 0xe2, 0x01, 0xfc, 0x01, 0x35, 0x02, 0x58, 0x02, 0x69, 0x02, 0x87, 0x02, 0x9c, 0x02, 0x74, 0x02, 0x47, 0x02, 0xfd, 0x01, 0x9f, 0x01, 0x29, 0x01, 0xc2, 0x00, 0x85, 0x00, 0x3b, 0x00, 0xe1, 0xff, 0xb2, 0xff, 0x6c, 0xff, 0x40, 0xff, 0x0e, 0xff, 0xdf, 0xfe, 0xc4, 0xfe, 0x88, 0xfe, 0x6c, 0xfe, 0x46, 0xfe, 0x0e, 0xfe, 0xec, 0xfd, 0xda, 0xfd, 0xca, 0xfd, 0xc5, 0xfd, 0xcf, 0xfd, 0xe7, 0xfd, 0x08, 0xfe, 0x17, 0xfe, 0x62, 0xfe, 0xbc, 0xfe, 0x07, 0xff, 0x59, 0xff, 0x9b, 0xff, 0xc7, 0xff, 0xe8, 0xff, 0xea, 0xff, 0xeb, 0xff, 0xd0, 0xff, 0xd0, 0xff, 0xba, 0xff, 0xcb, 0xff, 0xfe, 0xff, 0x28, 0x00, 0x67, 0x00, 0x79, 0x00, 0xb1, 0x00, 0xb1, 0x00, 0x9e, 0x00, 0xa9, 0x00, 0xb2, 0x00, 0x93, 0x00, 0xbc, 0x00, 0xc8, 0x00, 0xeb, 0x00, 0xee, 0x00, 0xed, 0x00, 0xec, 0x00, 0xc8, 0x00, 0xa6, 0x00, 0x91, 0x00, 0x94, 0x00, 0x63, 0x00, 0x48, 0x00, 0x2b, 0x00, 0x08, 0x00, 0xeb, 0xff, 0xe7, 0xff, 0xbb, 0xff, 0xac, 0xff, 0x83, 0xff, 0x67, 0xff, 0x49, 0xff, 0x31, 0xff, 0x44, 0xff, 0x37, 0xff, 0x30, 0xff, 0x1f, 0xff, 0x13, 0xff, 0xfd, 0xfe, 0xe9, 0xfe, 0xfc, 0xfe, 0xf3, 0xfe, 0x15, 0xff, 0x1e, 0xff, 0x69, 0xff, 0xa5, 0xff, 0xe5, 0xff, 0x28, 0x00, 0x54, 0x00, 0x88, 0x00, 0xb3, 0x00, 0xa6, 0x00, 0xb2, 0x00, 0xbc, 0x00, 0x91, 0x00, 0x74, 0x00, 0x4a, 0x00, 0x1d, 0x00, 0x09, 0x00, 0xec, 0xff, 0xc6, 0xff, 0xa2, 0xff, 0x80, 0xff, 0x68, 0xff, 0x50, 0xff, 0x40, 0xff, 0x32, 0xff, 0x35, 0xff, 0x35, 0xff, 0x41, 0xff, 0x5c, 0xff, 0x5f, 0xff, 0x71, 0xff, 0x88, 0xff, 0xb6, 0xff, 0xda, 0xff, 0x12, 0x00, 0x3f, 0x00, 0x86, 0x00, 0xc1, 0x00, 0xd4, 0x00, 0xe5, 0x00, 0xf4, 0x00, 0xdd, 0x00, 0xb1, 0x00, 0x7d, 0x00, 0x50, 0x00, 0x1a, 0x00, 0x0e, 0x00, 0xed, 0xff, 0xe3, 0xff, 0xd0, 0xff, 0xb3, 0xff, 0xc5, 0xff, 0xc0, 0xff, 0xc5, 0xff, 0xe5, 0xff, 0x07, 0x00, 0x05, 0x00, 0x03, 0x00, 0xcc, 0xff, 0x97, 0xff, 0x5d, 0xff, 0x4d, 0xff, 0x2a, 0xff, 0x1d, 0xff, 0x16, 0xff, 0x04, 0xff, 0x09, 0xff, 0x2c, 0xff, 0x51, 0xff, 0x89, 0xff, 0xda, 0xff, 0x1e, 0x00, 0x55, 0x00, 0x52, 0x00, 0x56, 0x00, 0x30, 0x00, 0x09, 0x00, 0xec, 0xff, 0xd4, 0xff, 0xc6, 0xff, 0xb6, 0xff, 0xbf, 0xff, 0xb0, 0xff, 0xd1, 0xff, 0xf4, 0xff, 0x12, 0x00, 0x33, 0x00, 0x3f, 0x00, 0x55, 0x00, 0x5c, 0x00, 0x5b, 0x00, 0x73, 0x00, 0x8c, 0x00, 0xba, 0x00, 0xe1, 0x00, 0xfb, 0x00, 0x08, 0x01, 0x09, 0x01, 0xdf, 0x00, 0xb2, 0x00, 0x8e, 0x00, 0x5a, 0x00, 0x26, 0x00, 0x14, 0x00, 0xd4, 0xff, 0xb1, 0xff, 0x60, 0xff, 0x36, 0xff, 0x08, 0xff, 0xe0, 0xfe, 0xe9, 0xfe, 0xf3, 0xfe, 0xf2, 0xfe, 0xf2, 0xfe, 0xcc, 0xfe, 0x9b, 0xfe, 0x86, 0xfe, 0x80, 0xfe, 0x70, 0xfe, 0x78, 0xfe, 0x81, 0xfe, 0x86, 0xfe, 0x8b, 0xfe, 0x9d, 0xfe, 0xaf, 0xfe, 0xd1, 0xfe, 0xe6, 0xfe, 0xf3, 0xfe, 0x10, 0xff, 0x49, 0xff, 0x72, 0xff, 0xad, 0xff, 0xe6, 0xff, 0x10, 0x00, 0x46, 0x00, 0x76, 0x00, 0xa0, 0x00, 0xb6, 0x00, 0xc4, 0x00, 0xda, 0x00, 0xcf, 0x00, 0xcd, 0x00, 0xdc, 0x00, 0xf6, 0x00, 0x08, 0x01, 0x20, 0x01, 0x2b, 0x01, 0x37, 0x01, 0x1f, 0x01, 0xff, 0x00, 0xba, 0x00, 0x85, 0x00, 0x64, 0x00, 0x35, 0x00, 0x22, 0x00, 0x02, 0x00, 0x11, 0x00, 0xdf, 0xff, 0xc6, 0xff, 0xaf, 0xff, 0x7d, 0xff, 0x62, 0xff, 0x62, 0xff, 0x69, 0xff, 0x75, 0xff, 0x87, 0xff, 0x86, 0xff, 0xa3, 0xff, 0xbe, 0xff, 0xe5, 0xff, 0xf4, 0xff, 0x03, 0x00, 0xf3, 0xff, 0x03, 0x00, 0xe2, 0xff, 0xdd, 0xff, 0xdc, 0xff, 0x06, 0x00, 0xfb, 0xff, 0xf4, 0xff, 0xcc, 0xff, 0x8d, 0xff, 0x69, 0xff, 0x63, 0xff, 0x60, 0xff, 0x80, 0xff, 0x9a, 0xff, 0xb9, 0xff, 0xb5, 0xff, 0xca, 0xff, 0xcc, 0xff, 0xb2, 0xff, 0xbe, 0xff, 0xc1, 0xff, 0xc4, 0xff, 0xec, 0xff, 0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0x5f, 0x00, 0x86, 0x00, 0xad, 0x00, 0xd0, 0x00, 0xf3, 0x00, 0x1f, 0x01, 0x47, 0x01, 0x60, 0x01, 0x66, 0x01, 0x64, 0x01, 0x68, 0x01, 0x4b, 0x01, 0x1f, 0x01, 0xfc, 0x00, 0xbc, 0x00, 0x9e, 0x00, 0x8f, 0x00, 0x8e, 0x00, 0x81, 0x00, 0x7a, 0x00, 0x4f, 0x00, 0x1c, 0x00, 0xfb, 0xff, 0xc2, 0xff, 0x8b, 0xff, 0x65, 0xff, 0x1d, 0xff, 0xf0, 0xfe, 0xbb, 0xfe, 0xa1, 0xfe, 0x83, 0xfe, 0x7b, 0xfe, 0x66, 0xfe, 0x56, 0xfe, 0x46, 0xfe, 0x60, 0xfe, 0x55, 0xfe, 0x66, 0xfe, 0x8d, 0xfe, 0xaa, 0xfe, 0xc1, 0xfe, 0xfc, 0xfe, 0x21, 0xff, 0x5c, 0xff, 0x7c, 0xff, 0xb3, 0xff, 0xf1, 0xff, 0xfe, 0xff, 0x2b, 0x00, 0x59, 0x00, 0x58, 0x00, 0x66, 0x00, 0x59, 0x00, 0x55, 0x00, 0x3d, 0x00, 0x0f, 0x00, 0xf3, 0xff, 0xcc, 0xff, 0x9f, 0xff, 0x94, 0xff, 0x91, 0xff, 0x5f, 0xff, 0x45, 0xff, 0x11, 0xff, 0xe0, 0xfe, 0xbf, 0xfe, 0x95, 0xfe, 0x75, 0xfe, 0x63, 0xfe, 0x69, 0xfe, 0x73, 0xfe, 0x96, 0xfe, 0xb7, 0xfe, 0xe9, 0xfe, 0x17, 0xff, 0x3f, 0xff, 0x76, 0xff, 0x9c, 0xff, 0xd8, 0xff, 0x21, 0x00, 0x70, 0x00, 0xae, 0x00, 0xf6, 0x00, 0x13, 0x01, 0x5b, 0x01, 0x6f, 0x01, 0x84, 0x01, 0x85, 0x01, 0x77, 0x01, 0x57, 0x01, 0x42, 0x01, 0x21, 0x01, 0x1d, 0x01, 0x1f, 0x01, 0x1b, 0x01, 0x0e, 0x01, 0xe2, 0x00, 0xb5, 0x00, 0xa1, 0x00, 0x6d, 0x00, 0x48, 0x00, 0x27, 0x00, 0xf2, 0xff, 0xc7, 0xff, 0x6f, 0xff, 0x46, 0xff, 0x20, 0xff, 0x0d, 0xff, 0xfc, 0xfe, 0x0d, 0xff, 0x0c, 0xff, 0x0b, 0xff, 0x04, 0xff, 0xe3, 0xfe, 0xe0, 0xfe, 0xf2, 0xfe, 0x03, 0xff, 0x1a, 0xff, 0x30, 0xff, 0x31, 0xff, 0x33, 0xff, 0x4c, 0xff, 0x65, 0xff, 0x73, 0xff, 0x7e, 0xff, 0x7c, 0xff, 0x73, 0xff, 0x80, 0xff, 0x71, 0xff, 0x6e, 0xff, 0x65, 0xff, 0x6f, 0xff, 0x70, 0xff, 0x86, 0xff, 0x91, 0xff, 0x9e, 0xff, 0x9e, 0xff, 0xba, 0xff, 0xc3, 0xff, 0xe6, 0xff, 0xfa, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xcb, 0xff, 0xd2, 0xff, 0xc6, 0xff, 0xcd, 0xff, 0xcf, 0xff, 0xcb, 0xff, 0xd4, 0xff, 0xb1, 0xff, 0xd4, 0xff, 0xe1, 0xff, 0xfb, 0xff, 0x33, 0x00, 0x67, 0x00, 0xa0, 0x00, 0xc5, 0x00, 0xd2, 0x00, 0xb9, 0x00, 0xc2, 0x00, 0xc5, 0x00, 0x8b, 0x00, 0x81, 0x00, 0x47, 0x00, 0x07, 0x00, 0xef, 0xff, 0xe3, 0xff, 0xe7, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0xf5, 0xff, 0xfc, 0xff, 0xe7, 0xff, 0xd3, 0xff, 0xf5, 0xff, 0xe1, 0xff, 0xdb, 0xff, 0xde, 0xff, 0xc3, 0xff, 0xba, 0xff, 0xbc, 0xff, 0xbf, 0xff, 0xc8, 0xff, 0xb9, 0xff, 0xad, 0xff, 0xa7, 0xff, 0xab, 0xff, 0xaf, 0xff, 0xbd, 0xff, 0xeb, 0xff, 0xf7, 0xff, 0x13, 0x00, 0x12, 0x00, 0xf8, 0xff, 0xed, 0xff, 0xdb, 0xff, 0xf0, 0xff, 0x01, 0x00, 0x12, 0x00, 0x37, 0x00, 0x3b, 0x00, 0x6d, 0x00, 0x8f, 0x00, 0x9f, 0x00, 0xc2, 0x00, 0xf0, 0x00, 0x06, 0x01, 0x1b, 0x01, 0x0b, 0x01, 0x0a, 0x01, 0xf0, 0x00, 0xee, 0x00, 0xc3, 0x00, 0xa9, 0x00, 0x7d, 0x00, 0x54, 0x00, 0x35, 0x00, 0xf5, 0xff, 0xc7, 0xff, 0x8a, 0xff, 0x74, 0xff, 0x60, 0xff, 0x64, 0xff, 0x53, 0xff, 0x57, 0xff, 0x41, 0xff, 0x32, 0xff, 0x1c, 0xff, 0xff, 0xfe, 0xc9, 0xfe, 0x99, 0xfe, 0x72, 0xfe, 0x46, 0xfe, 0x5b, 0xfe, 0x62, 0xfe, 0x77, 0xfe, 0x77, 0xfe, 0x61, 0xfe, 0x5a, 0xfe, 0x55, 0xfe, 0x5c, 0xfe, 0x87, 0xfe, 0x9a, 0xfe, 0xd4, 0xfe, 0xf2, 0xfe, 0x2a, 0xff, 0x59, 0xff, 0xa1, 0xff, 0xba, 0xff, 0xe3, 0xff, 0x14, 0x00, 0x3b, 0x00, 0x79, 0x00, 0xc0, 0x00, 0x01, 0x01, 0x58, 0x01, 0xa5, 0x01, 0x0d, 0x02, 0x41, 0x02, 0x7d, 0x02, 0xa5, 0x02, 0xa7, 0x02, 0xc8, 0x02, 0xd4, 0x02, 0xcc, 0x02, 0xdd, 0x02, 0xc0, 0x02, 0xb0, 0x02, 0x84, 0x02, 0x35, 0x02, 0xe8, 0x01, 0x9c, 0x01, 0x41, 0x01, 0x04, 0x01, 0xc0, 0x00, 0x8a, 0x00, 0x4a, 0x00, 0xeb, 0xff, 0x95, 0xff, 0x34, 0xff, 0xdd, 0xfe, 0x88, 0xfe, 0x51, 0xfe, 0x13, 0xfe, 0xf8, 0xfd, 0xde, 0xfd, 0xa6, 0xfd, 0x97, 0xfd, 0x7d, 0xfd, 0x6c, 0xfd, 0x71, 0xfd, 0xb2, 0xfd, 0xee, 0xfd, 0x2b, 0xfe, 0x61, 0xfe, 0x80, 0xfe, 0x8a, 0xfe, 0xb1, 0xfe, 0xc6, 0xfe, 0xdf, 0xfe, 0xff, 0xfe, 0x01, 0xff, 0x18, 0xff, 0x18, 0xff, 0x3c, 0xff, 0x50, 0xff, 0x73, 0xff, 0x8e, 0xff, 0x97, 0xff, 0xc9, 0xff, 0x00, 0x00, 0x2a, 0x00, 0x60, 0x00, 0xac, 0x00, 0xc8, 0x00, 0xdf, 0x00, 0xe5, 0x00, 0xc8, 0x00, 0xa7, 0x00, 0x99, 0x00, 0x61, 0x00, 0x2e, 0x00, 0x05, 0x00, 0xfe, 0xff, 0xee, 0xff, 0xef, 0xff, 0xf8, 0xff, 0xfc, 0xff, 0x0b, 0x00, 0x05, 0x00, 0x02, 0x00, 0xf8, 0xff, 0xe0, 0xff, 0xd5, 0xff, 0xce, 0xff, 0xa6, 0xff, 0xc0, 0xff, 0xaf, 0xff, 0x9b, 0xff, 0x8c, 0xff, 0x82, 0xff, 0x82, 0xff, 0x78, 0xff, 0xaa, 0xff, 0xb8, 0xff, 0xdc, 0xff, 0xfe, 0xff, 0x20, 0x00, 0x3e, 0x00, 0x6b, 0x00, 0x6a, 0x00, 0x5e, 0x00, 0x4a, 0x00, 0x44, 0x00, 0x1f, 0x00, 0x0c, 0x00, 0xdd, 0xff, 0xc6, 0xff, 0xc7, 0xff, 0xc4, 0xff, 0xcc, 0xff, 0xd7, 0xff, 0xd0, 0xff, 0xbc, 0xff, 0xae, 0xff, 0xaa, 0xff, 0xa2, 0xff, 0xb1, 0xff, 0x9e, 0xff, 0x99, 0xff, 0x90, 0xff, 0x88, 0xff, 0x8c, 0xff, 0x96, 0xff, 0xb2, 0xff, 0xc4, 0xff, 0xd4, 0xff, 0xa1, 0xff, 0x99, 0xff, 0x5e, 0xff, 0x24, 0xff, 0x11, 0xff, 0x14, 0xff, 0x18, 0xff, 0x2f, 0xff, 0x21, 0xff, 0x20, 0xff, 0x14, 0xff, 0x1f, 0xff, 0x28, 0xff, 0x2b, 0xff, 0x25, 0xff, 0x25, 0xff, 0x32, 0xff, 0x3b, 0xff, 0x59, 0xff, 0xb2, 0xff, 0xee, 0xff, 0x37, 0x00, 0x55, 0x00, 0x68, 0x00, 0x7a, 0x00, 0x87, 0x00, 0x8f, 0x00, 0xbe, 0x00, 0xc6, 0x00, 0xe8, 0x00, 0xe8, 0x00, 0x03, 0x01, 0x00, 0x01, 0xe0, 0x00, 0xd2, 0x00, 0xc0, 0x00, 0xa4, 0x00, 0x9e, 0x00, 0x72, 0x00, 0x63, 0x00, 0x2a, 0x00, 0x18, 0x00, 0x20, 0x00, 0x24, 0x00, 0x38, 0x00, 0x46, 0x00, 0x5e, 0x00, 0x75, 0x00, 0x75, 0x00, 0x73, 0x00, 0x7e, 0x00, 0x52, 0x00, 0x3a, 0x00, 0x38, 0x00, 0x31, 0x00, 0x07, 0x00, 0xe9, 0xff, 0xa2, 0xff, 0x52, 0xff, 0x41, 0xff, 0xfb, 0xfe, 0xf2, 0xfe, 0xd2, 0xfe, 0xd1, 0xfe, 0xe7, 0xfe, 0x02, 0xff, 0x47, 0xff, 0xae, 0xff, 0x0e, 0x00, 0x6e, 0x00, 0xb5, 0x00, 0xf6, 0x00, 0x0d, 0x01, 0xf3, 0x00, 0xc7, 0x00, 0x88, 0x00, 0x3a, 0x00, 0xe8, 0xff, 0xe2, 0xff, 0xda, 0xff, 0xc3, 0xff, 0xb0, 0xff, 0x79, 0xff, 0x43, 0xff, 0xfa, 0xfe, 0xd6, 0xfe, 0xb4, 0xfe, 0xac, 0xfe, 0x9f, 0xfe, 0xc7, 0xfe, 0xce, 0xfe, 0xfb, 0xfe, 0x27, 0xff, 0x42, 0xff, 0x7b, 0xff, 0x9e, 0xff, 0xc9, 0xff, 0xe5, 0xff, 0x03, 0x00, 0x17, 0x00, 0x1f, 0x00, 0x2e, 0x00, 0x1c, 0x00, 0x13, 0x00, 0x09, 0x00, 0xd1, 0xff, 0xdd, 0xff, 0xba, 0xff, 0xbb, 0xff, 0xc8, 0xff, 0xc1, 0xff, 0xe0, 0xff, 0xf6, 0xff, 0xfe, 0xff, 0x1e, 0x00, 0x30, 0x00, 0x4a, 0x00, 0x5d, 0x00, 0x66, 0x00, 0x80, 0x00, 0x89, 0x00, 0x89, 0x00, 0x8a, 0x00, 0x6e, 0x00, 0x38, 0x00, 0xfc, 0xff, 0xb6, 0xff, 0x82, 0xff, 0x64, 0xff, 0x53, 0xff, 0x54, 0xff, 0x5f, 0xff, 0x4a, 0xff, 0x36, 0xff, 0x23, 0xff, 0x01, 0xff, 0xe7, 0xfe, 0xf4, 0xfe, 0xe4, 0xfe, 0xf9, 0xfe, 0x03, 0xff, 0x11, 0xff, 0x21, 0xff, 0x3d, 0xff, 0x42, 0xff, 0x57, 0xff, 0x7d, 0xff, 0x81, 0xff, 0xac, 0xff, 0xb6, 0xff, 0xdd, 0xff, 0xec, 0xff, 0x0c, 0x00, 0x17, 0x00, 0x4b, 0x00, 0x84, 0x00, 0xbd, 0x00, 0xed, 0x00, 0x0c, 0x01, 0x24, 0x01, 0x21, 0x01, 0x2c, 0x01, 0x32, 0x01, 0x44, 0x01, 0x5d, 0x01, 0x70, 0x01, 0x7c, 0x01, 0x79, 0x01, 0x6a, 0x01, 0x5d, 0x01, 0x43, 0x01, 0x1b, 0x01, 0xde, 0x00, 0xbd, 0x00, 0x97, 0x00, 0x7e, 0x00, 0x2c, 0x00, 0x0a, 0x00, 0xc5, 0xff, 0x8d, 0xff, 0x60, 0xff, 0x56, 0xff, 0x4d, 0xff, 0x4f, 0xff, 0x28, 0xff, 0x09, 0xff, 0xe7, 0xfe, 0xca, 0xfe, 0xad, 0xfe, 0x98, 0xfe, 0xa9, 0xfe, 0xa2, 0xfe, 0xb2, 0xfe, 0xd7, 0xfe, 0xee, 0xfe, 0x0f, 0xff, 0x32, 0xff, 0x55, 0xff, 0x62, 0xff, 0x8e, 0xff, 0xb5, 0xff, 0xd8, 0xff, 0x08, 0x00, 0x28, 0x00, 0x45, 0x00, 0x62, 0x00, 0x95, 0x00, 0xc6, 0x00, 0xdf, 0x00, 0x11, 0x01, 0x22, 0x01, 0x31, 0x01, 0x2a, 0x01, 0x27, 0x01, 0xf7, 0x00, 0xe7, 0x00, 0xb3, 0x00, 0xa2, 0x00, 0x6e, 0x00, 0x49, 0x00, 0x08, 0x00, 0xa5, 0xff, 0x5d, 0xff, 0x18, 0xff, 0xdf, 0xfe, 0xad, 0xfe, 0x8d, 0xfe, 0x89, 0xfe, 0x80, 0xfe, 0x80, 0xfe, 0x9f, 0xfe, 0x9a, 0xfe, 0x9b, 0xfe, 0xab, 0xfe, 0xb2, 0xfe, 0xc5, 0xfe, 0xcc, 0xfe, 0xcc, 0xfe, 0xe6, 0xfe, 0xe0, 0xfe, 0xfa, 0xfe, 0x10, 0xff, 0x3a, 0xff, 0x4c, 0xff, 0x92, 0xff, 0xae, 0xff, 0xe2, 0xff, 0x00, 0x00, 0x2e, 0x00, 0x47, 0x00, 0x42, 0x00, 0x4d, 0x00, 0x4e, 0x00, 0x5a, 0x00, 0x5f, 0x00, 0x53, 0x00, 0x31, 0x00, 0x1a, 0x00, 0xfd, 0xff, 0xed, 0xff, 0xdd, 0xff, 0xf1, 0xff, 0x08, 0x00, 0x2e, 0x00, 0x47, 0x00, 0x74, 0x00, 0x87, 0x00, 0xa3, 0x00, 0xbd, 0x00, 0xcc, 0x00, 0xe8, 0x00, 0xfd, 0x00, 0x00, 0x01, 0xf8, 0x00, 0xcd, 0x00, 0x90, 0x00, 0x4c, 0x00, 0x08, 0x00, 0xb6, 0xff, 0x7c, 0xff, 0x68, 0xff, 0x4e, 0xff, 0x47, 0xff, 0x40, 0xff, 0x51, 0xff, 0x5a, 0xff, 0x5b, 0xff, 0x75, 0xff, 0x9e, 0xff, 0xa0, 0xff, 0xab, 0xff, 0xbe, 0xff, 0xb2, 0xff, 0xb8, 0xff, 0xcc, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xf0, 0xff, 0xf8, 0xff, 0xf8, 0xff, 0x04, 0x00, 0x06, 0x00, 0x0f, 0x00, 0x04, 0x00, 0xe6, 0xff, 0xbf, 0xff, 0x9b, 0xff, 0x7f, 0xff, 0x47, 0xff, 0x1a, 0xff, 0xeb, 0xfe, 0xb3, 0xfe, 0xa0, 0xfe, 0x9a, 0xfe, 0x9b, 0xfe, 0x90, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x69, 0xfe, 0x87, 0xfe, 0xaa, 0xfe, 0xd1, 0xfe, 0x08, 0xff, 0x25, 0xff, 0x56, 0xff, 0x9e, 0xff, 0xf3, 0xff, 0x4a, 0x00, 0xb1, 0x00, 0x07, 0x01, 0x39, 0x01, 0x4b, 0x01, 0x69, 0x01, 0x49, 0x01, 0x46, 0x01, 0x11, 0x01, 0x04, 0x01, 0x05, 0x01, 0xed, 0x00, 0xf8, 0x00, 0xe7, 0x00, 0xdc, 0x00, 0xc2, 0x00, 0xab, 0x00, 0x95, 0x00, 0x87, 0x00, 0x6c, 0x00, 0x72, 0x00, 0x51, 0x00, 0x4a, 0x00, 0x2f, 0x00, 0x17, 0x00, 0x25, 0x00, 0x21, 0x00, 0x14, 0x00, 0x00, 0x00, 0xe3, 0xff, 0xc8, 0xff, 0xab, 0xff, 0x8c, 0xff, 0x79, 0xff, 0x55, 0xff, 0x28, 0xff, 0x1b, 0xff, 0x1c, 0xff, 0x1d, 0xff, 0x20, 0xff, 0x2e, 0xff, 0x25, 0xff, 0x1c, 0xff, 0x13, 0xff, 0x22, 0xff, 0x27, 0xff, 0x2b, 0xff, 0x4d, 0xff, 0x52, 0xff, 0x70, 0xff, 0x90, 0xff, 0xbe, 0xff, 0xd1, 0xff, 0xfd, 0xff, 0x07, 0x00, 0x18, 0x00, 0x35, 0x00, 0x67, 0x00, 0x96, 0x00, 0xb5, 0x00, 0xdb, 0x00, 0xe1, 0x00, 0xf0, 0x00, 0xf8, 0x00, 0xf4, 0x00, 0xf5, 0x00, 0xf3, 0x00, 0xdf, 0x00, 0xbe, 0x00, 0xc3, 0x00, 0xca, 0x00, 0xb3, 0x00, 0xbd, 0x00, 0xb3, 0x00, 0xa9, 0x00, 0x79, 0x00, 0x59, 0x00, 0x29, 0x00, 0xfa, 0xff, 0xe6, 0xff, 0xcf, 0xff, 0xca, 0xff, 0xa9, 0xff, 0x94, 0xff, 0x51, 0xff, 0x31, 0xff, 0x14, 0xff, 0xf8, 0xfe, 0xe6, 0xfe, 0xda, 0xfe, 0xcf, 0xfe, 0xc9, 0xfe, 0xd7, 0xfe, 0xf6, 0xfe, 0x02, 0xff, 0x17, 0xff, 0x1d, 0xff, 0x25, 0xff, 0x10, 0xff, 0x13, 0xff, 0xfd, 0xfe, 0xeb, 0xfe, 0xfa, 0xfe, 0xe6, 0xfe, 0xed, 0xfe, 0x02, 0xff, 0x20, 0xff, 0x2a, 0xff, 0x59, 0xff, 0x8e, 0xff, 0xd2, 0xff, 0x01, 0x00, 0x21, 0x00, 0x49, 0x00, 0x6f, 0x00, 0x8d, 0x00, 0x9c, 0x00, 0xbd, 0x00, 0xcf, 0x00, 0xef, 0x00, 0xe6, 0x00, 0xf3, 0x00, 0xd7, 0x00, 0xc8, 0x00, 0xa9, 0x00, 0x98, 0x00, 0x91, 0x00, 0x85, 0x00, 0x78, 0x00, 0x90, 0x00, 0x72, 0x00, 0x61, 0x00, 0x39, 0x00, 0xf4, 0xff, 0xb6, 0xff, 0x76, 0xff, 0x46, 0xff, 0x29, 0xff, 0x20, 0xff, 0x27, 0xff, 0x20, 0xff, 0x27, 0xff, 0x25, 0xff, 0x15, 0xff, 0x2a, 0xff, 0x3b, 0xff, 0x57, 0xff, 0x61, 0xff, 0x7a, 0xff, 0x96, 0xff, 0xa7, 0xff, 0xd1, 0xff, 0xee, 0xff, 0x11, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x24, 0x00, 0x19, 0x00, 0x09, 0x00, 0xfa, 0xff, 0xec, 0xff, 0xee, 0xff, 0xf9, 0xff, 0x03, 0x00, 0x19, 0x00, 0x1c, 0x00, 0x16, 0x00, 0xe6, 0xff, 0xc9, 0xff, 0xa9, 0xff, 0x95, 0xff, 0x7c, 0xff, 0x81, 0xff, 0x6e, 0xff, 0x65, 0xff, 0x49, 0xff, 0x23, 0xff, 0x15, 0xff, 0xfb, 0xfe, 0xf5, 0xfe, 0x20, 0xff, 0x3a, 0xff, 0x6d, 0xff, 0x9e, 0xff, 0xaa, 0xff, 0xbf, 0xff, 0xc7, 0xff, 0xcb, 0xff, 0xd2, 0xff, 0xef, 0xff, 0x1f, 0x00, 0x4e, 0x00, 0x87, 0x00, 0xb1, 0x00, 0xd4, 0x00, 0x08, 0x01, 0x11, 0x01, 0x34, 0x01, 0x4c, 0x01, 0x75, 0x01, 0x8e, 0x01, 0x93, 0x01, 0x7c, 0x01, 0x59, 0x01, 0x18, 0x01, 0xce, 0x00, 0xa6, 0x00, 0x77, 0x00, 0x24, 0x00, 0xf5, 0xff, 0xc0, 0xff, 0x87, 0xff, 0x5c, 0xff, 0x3f, 0xff, 0x19, 0xff, 0x09, 0xff, 0xfa, 0xfe, 0xed, 0xfe, 0xe7, 0xfe, 0xc2, 0xfe, 0xa7, 0xfe, 0x87, 0xfe, 0x67, 0xfe, 0x69, 0xfe, 0x8b, 0xfe, 0x96, 0xfe, 0xc2, 0xfe, 0xd8, 0xfe, 0x06, 0xff, 0x38, 0xff, 0x6a, 0xff, 0xbc, 0xff, 0x0f, 0x00, 0x4a, 0x00, 0x8c, 0x00, 0xbc, 0x00, 0xd9, 0x00, 0x01, 0x01, 0xee, 0x00, 0xd4, 0x00, 0xbe, 0x00, 0xac, 0x00, 0x9c, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x24, 0x00, 0x12, 0x00, 0xf0, 0xff, 0xdc, 0xff, 0xea, 0xff, 0xe8, 0xff, 0xfa, 0xff, 0x14, 0x00, 0x0b, 0x00, 0x11, 0x00, 0x07, 0x00, 0xf7, 0xff, 0xd6, 0xff, 0xdb, 0xff, 0xb3, 0xff, 0x99, 0xff, 0x89, 0xff, 0x89, 0xff, 0x91, 0xff, 0x96, 0xff, 0xa8, 0xff, 0xba, 0xff, 0xc1, 0xff, 0xb3, 0xff, 0xb1, 0xff, 0x98, 0xff, 0x83, 0xff, 0x95, 0xff, 0x8e, 0xff, 0x8a, 0xff, 0x79, 0xff, 0x5b, 0xff, 0x31, 0xff, 0x38, 0xff, 0x32, 0xff, 0x41, 0xff, 0x56, 0xff, 0x5a, 0xff, 0x63, 0xff, 0x63, 0xff, 0x64, 0xff, 0x7c, 0xff, 0x89, 0xff, 0x9e, 0xff, 0xd6, 0xff, 0xf6, 0xff, 0x12, 0x00, 0x2d, 0x00, 0x27, 0x00, 0x24, 0x00, 0x1b, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x19, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x2d, 0x00, 0x47, 0x00, 0x65, 0x00, 0x7e, 0x00, 0x95, 0x00, 0x98, 0x00, 0x9c, 0x00, 0x92, 0x00, 0x8e, 0x00, 0x91, 0x00, 0x97, 0x00, 0x95, 0x00, 0xaf, 0x00, 0xa2, 0x00, 0xaa, 0x00, 0x9e, 0x00, 0x8e, 0x00, 0x6c, 0x00, 0x37, 0x00, 0x14, 0x00, 0xdf, 0xff, 0xd5, 0xff, 0xb7, 0xff, 0x93, 0xff, 0x7e, 0xff, 0x5d, 0xff, 0x53, 0xff, 0x1d, 0xff, 0x07, 0xff, 0xed, 0xfe, 0xd0, 0xfe, 0xc9, 0xfe, 0xca, 0xfe, 0xec, 0xfe, 0x15, 0xff, 0x4f, 0xff, 0x8b, 0xff, 0xcd, 0xff, 0xf5, 0xff, 0x0b, 0x00, 0x15, 0x00, 0x13, 0x00, 0xf3, 0xff, 0xe9, 0xff, 0xda, 0xff, 0xd4, 0xff, 0xeb, 0xff, 0xf3, 0xff, 0x08, 0x00, 0xfb, 0xff, 0xf3, 0xff, 0xc4, 0xff, 0xc5, 0xff, 0xb4, 0xff, 0xbe, 0xff, 0xdd, 0xff, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x49, 0x00, 0x31, 0x00, 0x08, 0x00, 0xf7, 0xff, 0xcb, 0xff, 0xaa, 0xff, 0xc1, 0xff, 0xb9, 0xff, 0xcf, 0xff, 0xe1, 0xff, 0xed, 0xff, 0x00, 0x00, 0x06, 0x00, 0x2c, 0x00, 0x48, 0x00, 0x61, 0x00, 0x96, 0x00, 0xce, 0x00, 0xe7, 0x00, 0x06, 0x01, 0x09, 0x01, 0xf8, 0x00, 0xd9, 0x00, 0xb3, 0x00, 0x7a, 0x00, 0x57, 0x00, 0x0f, 0x00, 0xbd, 0xff, 0x94, 0xff, 0x59, 0xff, 0x48, 0xff, 0x30, 0xff, 0x42, 0xff, 0x2b, 0xff, 0x28, 0xff, 0xfb, 0xfe, 0xd6, 0xfe, 0xd4, 0xfe, 0xdb, 0xfe, 0xc9, 0xfe, 0xf8, 0xfe, 0x01, 0xff, 0x34, 0xff, 0x65, 0xff, 0x97, 0xff, 0xde, 0xff, 0x17, 0x00, 0x50, 0x00, 0x68, 0x00, 0x61, 0x00, 0x5d, 0x00, 0x42, 0x00, 0x26, 0x00, 0x15, 0x00, 0xf2, 0xff, 0xeb, 0xff, 0xc5, 0xff, 0xbe, 0xff, 0xc9, 0xff, 0xbb, 0xff, 0xb1, 0xff, 0xa0, 0xff, 0x84, 0xff, 0x6e, 0xff, 0x5b, 0xff, 0x40, 0xff, 0x4e, 0xff, 0x4c, 0xff, 0x61, 0xff, 0x7f, 0xff, 0x88, 0xff, 0xa6, 0xff, 0xbc, 0xff, 0xc6, 0xff, 0xc9, 0xff, 0xbd, 0xff, 0xb6, 0xff, 0xc4, 0xff, 0xcc, 0xff, 0xd0, 0xff, 0xda, 0xff, 0xd2, 0xff, 0xb4, 0xff, 0x9c, 0xff, 0x7f, 0xff, 0x5c, 0xff, 0x56, 0xff, 0x5a, 0xff, 0x58, 0xff, 0x72, 0xff, 0x83, 0xff, 0xa5, 0xff, 0xbd, 0xff, 0xd5, 0xff, 0xf7, 0xff, 0x22, 0x00, 0x43, 0x00, 0x62, 0x00, 0x9a, 0x00, 0xa8, 0x00, 0xcb, 0x00, 0xca, 0x00, 0xbb, 0x00, 0x9e, 0x00, 0x7a, 0x00, 0x73, 0x00, 0x59, 0x00, 0x50, 0x00, 0x48, 0x00, 0x3f, 0x00, 0x2e, 0x00, 0x27, 0x00, 0x06, 0x00, 0xf2, 0xff, 0xcb, 0xff, 0xb9, 0xff, 0xa0, 0xff, 0x8a, 0xff, 0x9d, 0xff, 0xb7, 0xff, 0xc8, 0xff, 0xe6, 0xff, 0x04, 0x00, 0x20, 0x00, 0x50, 0x00, 0x5f, 0x00, 0x73, 0x00, 0x93, 0x00, 0x95, 0x00, 0x81, 0x00, 0x81, 0x00, 0x42, 0x00, 0x11, 0x00, 0xe0, 0xff, 0xca, 0xff, 0xa3, 0xff, 0x87, 0xff, 0x6d, 0xff, 0x37, 0xff, 0x3b, 0xff, 0x2d, 0xff, 0x3d, 0xff, 0x5f, 0xff, 0x8a, 0xff, 0xb3, 0xff, 0xed, 0xff, 0x06, 0x00, 0x3a, 0x00, 0x34, 0x00, 0x52, 0x00, 0x56, 0x00, 0x5b, 0x00, 0x64, 0x00, 0x60, 0x00, 0x54, 0x00, 0x23, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xf6, 0xff, 0xfc, 0xff, 0x11, 0x00, 0x1b, 0x00, 0x23, 0x00, 0x05, 0x00, 0xe7, 0xff, 0xde, 0xff, 0xb3, 0xff, 0x8d, 0xff, 0x83, 0xff, 0x7b, 0xff, 0x7b, 0xff, 0x60, 0xff, 0x8d, 0xff, 0x98, 0xff, 0xc1, 0xff, 0xd2, 0xff, 0xf0, 0xff, 0xeb, 0xff, 0xe5, 0xff, 0xb2, 0xff, 0x7e, 0xff, 0x4f, 0xff, 0x16, 0xff, 0xf2, 0xfe, 0xf9, 0xfe, 0xf1, 0xfe, 0xff, 0xfe, 0x0e, 0xff, 0x04, 0xff, 0x0b, 0xff, 0x1d, 0xff, 0x18, 0xff, 0x24, 0xff, 0x1c, 0xff, 0x33, 0xff, 0x5c, 0xff, 0x66, 0xff, 0xae, 0xff, 0xf8, 0xff, 0x42, 0x00, 0x84, 0x00, 0xb2, 0x00, 0xe8, 0x00, 0xf0, 0x00, 0xcc, 0x00, 0xd4, 0x00, 0xb5, 0x00, 0x82, 0x00, 0x79, 0x00, 0x76, 0x00, 0x6b, 0x00, 0x49, 0x00, 0x19, 0x00, 0xd9, 0xff, 0x81, 0xff, 0x6c, 0xff, 0x31, 0xff, 0x25, 0xff, 0x1d, 0xff, 0x0e, 0xff, 0x21, 0xff, 0x1a, 0xff, 0x2f, 0xff, 0x3d, 0xff, 0x5d, 0xff, 0x8b, 0xff, 0xa2, 0xff, 0xb9, 0xff, 0xcb, 0xff, 0xcd, 0xff, 0xaf, 0xff, 0xd7, 0xff, 0xdb, 0xff, 0x00, 0x00, 0x11, 0x00, 0x17, 0x00, 0x25, 0x00, 0x35, 0x00, 0x4e, 0x00, 0x64, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8f, 0x00, 0x89, 0x00, 0x8a, 0x00, 0x62, 0x00, 0x63, 0x00, 0x48, 0x00, 0x30, 0x00, 0x33, 0x00, 0x21, 0x00, 0x2c, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x1e, 0x00, 0xf7, 0xff, 0x0e, 0x00, 0x18, 0x00, 0x24, 0x00, 0x49, 0x00, 0x5d, 0x00, 0x85, 0x00, 0x86, 0x00, 0x9d, 0x00, 0xa4, 0x00, 0xc5, 0x00, 0xd4, 0x00, 0xe9, 0x00, 0xe7, 0x00, 0xec, 0x00, 0xe4, 0x00, 0xa9, 0x00, 0x91, 0x00, 0x62, 0x00, 0x4b, 0x00, 0xfb, 0xff, 0xc6, 0xff, 0x6d, 0xff, 0x18, 0xff, 0xda, 0xfe, 0xa7, 0xfe, 0x80, 0xfe, 0x5a, 0xfe, 0x2c, 0xfe, 0xf9, 0xfd, 0xf0, 0xfd, 0xe0, 0xfd, 0xe7, 0xfd, 0xf9, 0xfd, 0xff, 0xfd, 0x0b, 0xfe, 0x17, 0xfe, 0x28, 0xfe, 0x3d, 0xfe, 0x76, 0xfe, 0xa0, 0xfe, 0xdc, 0xfe, 0x06, 0xff, 0x41, 0xff, 0x6e, 0xff, 0xa0, 0xff, 0xea, 0xff, 0x13, 0x00, 0x55, 0x00, 0x95, 0x00, 0xaa, 0x00, 0xd9, 0x00, 0x00, 0x01, 0x1a, 0x01, 0x42, 0x01, 0x78, 0x01, 0xa3, 0x01, 0xc0, 0x01, 0xc4, 0x01, 0xbb, 0x01, 0x94, 0x01, 0x90, 0x01, 0x88, 0x01, 0x5c, 0x01, 0x53, 0x01, 0x1b, 0x01, 0xfb, 0x00, 0xe7, 0x00, 0xb7, 0x00, 0xaa, 0x00, 0x91, 0x00, 0x60, 0x00, 0x43, 0x00, 0x20, 0x00, 0xef, 0xff, 0xc5, 0xff, 0x93, 0xff, 0x50, 0xff, 0x07, 0xff, 0xd4, 0xfe, 0xa0, 0xfe, 0x7c, 0xfe, 0x65, 0xfe, 0x43, 0xfe, 0x42, 0xfe, 0x37, 0xfe, 0x38, 0xfe, 0x57, 0xfe, 0x6d, 0xfe, 0xb4, 0xfe, 0xee, 0xfe, 0x41, 0xff, 0x8b, 0xff, 0xcf, 0xff, 0xfb, 0xff, 0x37, 0x00, 0x65, 0x00, 0x68, 0x00, 0x70, 0x00, 0x5a, 0x00, 0x38, 0x00, 0x20, 0x00, 0x31, 0x00, 0x2a, 0x00, 0x46, 0x00, 0x3f, 0x00, 0x3a, 0x00, 0x45, 0x00, 0x5e, 0x00, 0x67, 0x00, 0x83, 0x00, 0x98, 0x00, 0x96, 0x00, 0x90, 0x00, 0x7f, 0x00, 0x50, 0x00, 0x13, 0x00, 0xe8, 0xff, 0xba, 0xff, 0x85, 0xff, 0x78, 0xff, 0x7f, 0xff, 0x8b, 0xff, 0x7d, 0xff, 0x8b, 0xff, 0x8a, 0xff, 0x82, 0xff, 0x91, 0xff, 0x96, 0xff, 0xb0, 0xff, 0xde, 0xff, 0xdf, 0xff, 0x16, 0x00, 0x0d, 0x00, 0x1f, 0x00, 0x39, 0x00, 0x64, 0x00, 0x89, 0x00, 0xb8, 0x00, 0xe1, 0x00, 0xfd, 0x00, 0x24, 0x01, 0x47, 0x01, 0x5b, 0x01, 0x76, 0x01, 0x74, 0x01, 0x5e, 0x01, 0x39, 0x01, 0xff, 0x00, 0xaa, 0x00, 0x6d, 0x00, 0x32, 0x00, 0xf6, 0xff, 0xc3, 0xff, 0xa0, 0xff, 0x6e, 0xff, 0x2d, 0xff, 0x09, 0xff, 0xcf, 0xfe, 0x97, 0xfe, 0x66, 0xfe, 0x37, 0xfe, 0x02, 0xfe, 0xc5, 0xfd, 0xb4, 0xfd, 0xaf, 0xfd, 0x9d, 0xfd, 0xaf, 0xfd, 0xbf, 0xfd, 0xdc, 0xfd, 0xef, 0xfd, 0x1c, 0xfe, 0x40, 0xfe, 0x81, 0xfe, 0xb3, 0xfe, 0xe0, 0xfe, 0x14, 0xff, 0x35, 0xff, 0x57, 0xff, 0x7b, 0xff, 0x9b, 0xff, 0xbe, 0xff, 0x01, 0x00, 0x2e, 0x00, 0x7c, 0x00, 0xa9, 0x00, 0xd2, 0x00, 0xeb, 0x00, 0x28, 0x01, 0x27, 0x01, 0x54, 0x01, 0x7c, 0x01, 0xaf, 0x01, 0xb3, 0x01, 0xaa, 0x01, 0x99, 0x01, 0x67, 0x01, 0x55, 0x01, 0x2a, 0x01, 0x13, 0x01, 0xf7, 0x00, 0xe6, 0x00, 0xbb, 0x00, 0xa7, 0x00, 0x80, 0x00, 0x64, 0x00, 0x3b, 0x00, 0x0c, 0x00, 0xf5, 0xff, 0xe9, 0xff, 0xbb, 0xff, 0x98, 0xff, 0x71, 0xff, 0x32, 0xff, 0xee, 0xfe, 0xc6, 0xfe, 0x84, 0xfe, 0x49, 0xfe, 0x37, 0xfe, 0x20, 0xfe, 0x28, 0xfe, 0x1f, 0xfe, 0x2d, 0xfe, 0x3d, 0xfe, 0x2f, 0xfe, 0x59, 0xfe, 0x80, 0xfe, 0xba, 0xfe, 0xed, 0xfe, 0x3e, 0xff, 0x73, 0xff, 0xc0, 0xff, 0xe7, 0xff, 0x12, 0x00, 0x29, 0x00, 0x30, 0x00, 0x4e, 0x00, 0x7c, 0x00, 0x97, 0x00, 0xa6, 0x00, 0xb7, 0x00, 0xa9, 0x00, 0xae, 0x00, 0xa2, 0x00, 0xa8, 0x00, 0x8b, 0x00, 0x92, 0x00, 0x78, 0x00, 0x6d, 0x00, 0x5f, 0x00, 0x49, 0x00, 0x45, 0x00, 0x2f, 0x00, 0x3c, 0x00, 0x51, 0x00, 0x73, 0x00, 0x97, 0x00, 0xb3, 0x00, 0xb8, 0x00, 0xc5, 0x00, 0xc3, 0x00, 0xb3, 0x00, 0xb3, 0x00, 0xa6, 0x00, 0x7c, 0x00, 0x6c, 0x00, 0x2d, 0x00, 0xe9, 0xff, 0xaf, 0xff, 0x7f, 0xff, 0x43, 0xff, 0x1c, 0xff, 0x04, 0xff, 0xe1, 0xfe, 0xed, 0xfe, 0xe2, 0xfe, 0xff, 0xfe, 0x0a, 0xff, 0x20, 0xff, 0x23, 0xff, 0x30, 0xff, 0x2a, 0xff, 0x39, 0xff, 0x33, 0xff, 0x3b, 0xff, 0x52, 0xff, 0x68, 0xff, 0x93, 0xff, 0xb9, 0xff, 0xdc, 0xff, 0xf1, 0xff, 0xf1, 0xff, 0x0c, 0x00, 0x2a, 0x00, 0x3c, 0x00, 0x58, 0x00, 0x54, 0x00, 0x4b, 0x00, 0x4c, 0x00, 0x38, 0x00, 0x25, 0x00, 0x2d, 0x00, 0x2a, 0x00, 0x13, 0x00, 0x19, 0x00, 0x13, 0x00, 0x33, 0x00, 0x2f, 0x00, 0x46, 0x00, 0x5a, 0x00, 0x56, 0x00, 0x52, 0x00, 0x1d, 0x00, 0xfa, 0xff, 0xb4, 0xff, 0xa5, 0xff, 0x8e, 0xff, 0x8a, 0xff, 0x7c, 0xff, 0x7a, 0xff, 0x6b, 0xff, 0x48, 0xff, 0x5a, 0xff, 0x65, 0xff, 0x6e, 0xff, 0x88, 0xff, 0x84, 0xff, 0xa7, 0xff, 0xc6, 0xff, 0xdd, 0xff, 0xff, 0xff, 0x29, 0x00, 0x2f, 0x00, 0x43, 0x00, 0x53, 0x00, 0x3c, 0x00, 0x35, 0x00, 0x2c, 0x00, 0x05, 0x00, 0xfb, 0xff, 0xdf, 0xff, 0xb1, 0xff, 0xaa, 0xff, 0x9b, 0xff, 0xa1, 0xff, 0x8f, 0xff, 0x8e, 0xff, 0x82, 0xff, 0x6a, 0xff, 0x6c, 0xff, 0x63, 0xff, 0x71, 0xff, 0x83, 0xff, 0xa9, 0xff, 0xbb, 0xff, 0xcc, 0xff, 0xde, 0xff, 0xf3, 0xff, 0xfd, 0xff, 0x1d, 0x00, 0x40, 0x00, 0x78, 0x00, 0xb1, 0x00, 0xda, 0x00, 0x0d, 0x01, 0x35, 0x01, 0x4f, 0x01, 0x40, 0x01, 0x49, 0x01, 0x42, 0x01, 0x18, 0x01, 0xf8, 0x00, 0xe5, 0x00, 0xba, 0x00, 0x96, 0x00, 0x7f, 0x00, 0x64, 0x00, 0x3a, 0x00, 0x17, 0x00, 0xdd, 0xff, 0xa7, 0xff, 0x79, 0xff, 0x57, 0xff, 0x2d, 0xff, 0x0f, 0xff, 0xde, 0xfe, 0xc8, 0xfe, 0xaa, 0xfe, 0x9d, 0xfe, 0x90, 0xfe, 0x9a, 0xfe, 0x8b, 0xfe, 0x87, 0xfe, 0x9b, 0xfe, 0xad, 0xfe, 0xd9, 0xfe, 0x02, 0xff, 0x40, 0xff, 0x76, 0xff, 0x91, 0xff, 0xbe, 0xff, 0xea, 0xff, 0x12, 0x00, 0x19, 0x00, 0x36, 0x00, 0x36, 0x00, 0x4f, 0x00, 0x5f, 0x00, 0x70, 0x00, 0x70, 0x00, 0x73, 0x00, 0x65, 0x00, 0x3b, 0x00, 0x26, 0x00, 0x0e, 0x00, 0xd3, 0xff, 0xbc, 0xff, 0xa1, 0xff, 0x7a, 0xff, 0x5e, 0xff, 0x4c, 0xff, 0x40, 0xff, 0x31, 0xff, 0x35, 0xff, 0x4c, 0xff, 0x65, 0xff, 0x6c, 0xff, 0x8d, 0xff, 0x95, 0xff, 0x85, 0xff, 0x7b, 0xff, 0x70, 0xff, 0x5e, 0xff, 0x4a, 0xff, 0x4a, 0xff, 0x57, 0xff, 0x6e, 0xff, 0x85, 0xff, 0xbf, 0xff, 0xeb, 0xff, 0x02, 0x00, 0x0e, 0x00, 0x24, 0x00, 0x17, 0x00, 0x25, 0x00, 0x36, 0x00, 0x2d, 0x00, 0x46, 0x00, 0x3a, 0x00, 0x5b, 0x00, 0x53, 0x00, 0x5b, 0x00, 0x7c, 0x00, 0x9d, 0x00, 0xbb, 0x00, 0xd5, 0x00, 0xf1, 0x00, 0xf0, 0x00, 0xe2, 0x00, 0xdd, 0x00, 0xc4, 0x00, 0xad, 0x00, 0x95, 0x00, 0x70, 0x00, 0x59, 0x00, 0x41, 0x00, 0x13, 0x00, 0x03, 0x00, 0x01, 0x00, 0xf4, 0xff, 0xd7, 0xff, 0xb8, 0xff, 0x9b, 0xff, 0x5c, 0xff, 0x20, 0xff, 0x1e, 0xff, 0xfc, 0xfe, 0x03, 0xff, 0xf9, 0xfe, 0xe8, 0xfe, 0xd7, 0xfe, 0xca, 0xfe, 0xc2, 0xfe, 0xc5, 0xfe, 0xd0, 0xfe, 0xe3, 0xfe, 0xee, 0xfe, 0xff, 0xfe, 0x0d, 0xff, 0x24, 0xff, 0x3b, 0xff, 0x5b, 0xff, 0x87, 0xff, 0xc8, 0xff, 0xf1, 0xff, 0x22, 0x00, 0x42, 0x00, 0x53, 0x00, 0x79, 0x00, 0xa1, 0x00, 0xbf, 0x00, 0xdd, 0x00, 0x01, 0x01, 0x15, 0x01, 0x25, 0x01, 0x17, 0x01, 0x31, 0x01, 0x26, 0x01, 0x0b, 0x01, 0xf4, 0x00, 0xe0, 0x00, 0xb6, 0x00, 0x77, 0x00, 0x47, 0x00, 0xfe, 0xff, 0xb8, 0xff, 0x97, 0xff, 0x63, 0xff, 0x4f, 0xff, 0x1f, 0xff, 0x17, 0xff, 0xfe, 0xfe, 0xf0, 0xfe, 0xf5, 0xfe, 0x00, 0xff, 0xec, 0xfe, 0xe3, 0xfe, 0xd7, 0xfe, 0xde, 0xfe, 0xcd, 0xfe, 0xdd, 0xfe, 0xe4, 0xfe, 0xde, 0xfe, 0xfd, 0xfe, 0x04, 0xff, 0x30, 0xff, 0x5d, 0xff, 0x99, 0xff, 0xe1, 0xff, 0x0c, 0x00, 0x34, 0x00, 0x59, 0x00, 0x4e, 0x00, 0x50, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x78, 0x00, 0x68, 0x00, 0x70, 0x00, 0x57, 0x00, 0x5d, 0x00, 0x5d, 0x00, 0x4c, 0x00, 0x4b, 0x00, 0x40, 0x00, 0x2c, 0x00, 0x1b, 0x00, 0xf7, 0xff, 0xe1, 0xff, 0xf1, 0xff, 0xec, 0xff, 0xf9, 0xff, 0x1f, 0x00, 0x36, 0x00, 0x5b, 0x00, 0x64, 0x00, 0x70, 0x00, 0x90, 0x00, 0x99, 0x00, 0x93, 0x00, 0x9d, 0x00, 0xa0, 0x00, 0x94, 0x00, 0x83, 0x00, 0x6f, 0x00, 0x46, 0x00, 0x1b, 0x00, 0xe2, 0xff, 0xb4, 0xff, 0xa3, 0xff, 0x82, 0xff, 0x64, 0xff, 0x4d, 0xff, 0x3b, 0xff, 0x2c, 0xff, 0x20, 0xff, 0x1e, 0xff, 0x17, 0xff, 0x28, 0xff, 0x2b, 0xff, 0x4c, 0xff, 0x5e, 0xff, 0x90, 0xff, 0xae, 0xff, 0xd9, 0xff, 0xea, 0xff, 0x05, 0x00, 0x0f, 0x00, 0x38, 0x00, 0x59, 0x00, 0x6c, 0x00, 0x84, 0x00, 0x82, 0x00, 0x66, 0x00, 0x53, 0x00, 0x50, 0x00, 0x35, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xc2, 0xff, 0xaa, 0xff, 0x7c, 0xff, 0x62, 0xff, 0x5f, 0xff, 0x57, 0xff, 0x50, 0xff, 0x40, 0xff, 0x4a, 0xff, 0x2f, 0xff, 0x3d, 0xff, 0x30, 0xff, 0x29, 0xff, 0x25, 0xff, 0x23, 0xff, 0x10, 0xff, 0x28, 0xff, 0x26, 0xff, 0x59, 0xff, 0x5b, 0xff, 0x7b, 0xff, 0x92, 0xff, 0xa2, 0xff, 0xbd, 0xff, 0xfd, 0xff, 0x2a, 0x00, 0x5c, 0x00, 0x6a, 0x00, 0x62, 0x00, 0x6a, 0x00, 0x61, 0x00, 0x60, 0x00, 0x5d, 0x00, 0x70, 0x00, 0x66, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x59, 0x00, 0x5f, 0x00, 0x55, 0x00, 0x48, 0x00, 0x5e, 0x00, 0x58, 0x00, 0x59, 0x00, 0x62, 0x00, 0x5e, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x41, 0x00, 0x1a, 0x00, 0xff, 0xff, 0xf0, 0xff, 0xae, 0xff, 0xae, 0xff, 0x8e, 0xff, 0x64, 0xff, 0x6c, 0xff, 0x55, 0xff, 0x5e, 0xff, 0x57, 0xff, 0x53, 0xff, 0x61, 0xff, 0x87, 0xff, 0x8c, 0xff, 0xb7, 0xff, 0xd8, 0xff, 0xf8, 0xff, 0x0a, 0x00, 0x19, 0x00, 0x14, 0x00, 0x0c, 0x00, 0x03, 0x00, 0xed, 0xff, 0xea, 0xff, 0xcc, 0xff, 0xc8, 0xff, 0xa1, 0xff, 0x9f, 0xff, 0x84, 0xff, 0x78, 0xff, 0x7f, 0xff, 0x73, 0xff, 0x77, 0xff, 0x7e, 0xff, 0x8d, 0xff, 0xbc, 0xff, 0xd3, 0xff, 0xf5, 0xff, 0x09, 0x00, 0x22, 0x00, 0x28, 0x00, 0x41, 0x00, 0x54, 0x00, 0x57, 0x00, 0x5a, 0x00, 0x60, 0x00, 0x56, 0x00, 0x3f, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x1c, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x20, 0x00, 0x29, 0x00, 0x2a, 0x00, 0x3f, 0x00, 0x37, 0x00, 0x2c, 0x00, 0x15, 0x00, 0x10, 0x00, 0x09, 0x00, 0xf2, 0xff, 0xe0, 0xff, 0xed, 0xff, 0xc3, 0xff, 0xc7, 0xff, 0xbd, 0xff, 0xd6, 0xff, 0xd1, 0xff, 0xf1, 0xff, 0xf6, 0xff, 0x1a, 0x00, 0x22, 0x00, 0x29, 0x00, 0x29, 0x00, 0x13, 0x00, 0x13, 0x00, 0x08, 0x00, 0xe8, 0xff, 0xd6, 0xff, 0xb4, 0xff, 0x96, 0xff, 0x81, 0xff, 0x68, 0xff, 0x85, 0xff, 0x82, 0xff, 0x9c, 0xff, 0xa1, 0xff, 0xa2, 0xff, 0xa1, 0xff, 0x86, 0xff, 0x78, 0xff, 0x51, 0xff, 0x50, 0xff, 0x36, 0xff, 0x2f, 0xff, 0x36, 0xff, 0x30, 0xff, 0x48, 0xff, 0x57, 0xff, 0x78, 0xff, 0x8f, 0xff, 0xb6, 0xff, 0xd6, 0xff, 0xf2, 0xff, 0xde, 0xff, 0xed, 0xff, 0xbe, 0xff, 0x88, 0xff, 0x7a, 0xff, 0x6b, 0xff, 0x54, 0xff, 0x4d, 0xff, 0x4a, 0xff, 0x24, 0xff, 0x13, 0xff, 0x0c, 0xff, 0x14, 0xff, 0x05, 0xff, 0x27, 0xff, 0x28, 0xff, 0x49, 0xff, 0x52, 0xff, 0x6a, 0xff, 0x8c, 0xff, 0x8c, 0xff, 0xac, 0xff, 0xc6, 0xff, 0xd1, 0xff, 0xf5, 0xff, 0x0c, 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x24, 0x00, 0x34, 0x00, 0x53, 0x00, 0x61, 0x00, 0x7f, 0x00, 0x62, 0x00, 0x4d, 0x00, 0x54, 0x00, 0x3d, 0x00, 0x35, 0x00, 0x48, 0x00, 0x29, 0x00, 0x33, 0x00, 0x08, 0x00, 0x0d, 0x00, 0x0f, 0x00, 0xf6, 0xff, 0x07, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x09, 0x00, 0xf4, 0xff, 0xed, 0xff, 0xcf, 0xff, 0xd0, 0xff, 0xc0, 0xff, 0xd7, 0xff, 0xea, 0xff, 0x0e, 0x00, 0x29, 0x00, 0x44, 0x00, 0x5a, 0x00, 0x75, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0xbd, 0x00, 0xda, 0x00, 0xe6, 0x00, 0xd3, 0x00, 0xd4, 0x00, 0xcb, 0x00, 0xc6, 0x00, 0xaa, 0x00, 0x95, 0x00, 0x6d, 0x00, 0x51, 0x00, 0x36, 0x00, 0x11, 0x00, 0xfb, 0xff, 0xd2, 0xff, 0xac, 0xff, 0x76, 0xff, 0x5d, 0xff, 0x35, 0xff, 0x1c, 0xff, 0x13, 0xff, 0xf9, 0xfe, 0xf0, 0xfe, 0xe0, 0xfe, 0xdc, 0xfe, 0xcc, 0xfe, 0xbf, 0xfe, 0xbf, 0xfe, 0xb2, 0xfe, 0xc1, 0xfe, 0xc6, 0xfe, 0xf9, 0xfe, 0x14, 0xff, 0x5f, 0xff, 0x9a, 0xff, 0xe8, 0xff, 0x1b, 0x00, 0x51, 0x00, 0x68, 0x00, 0x89, 0x00, 0x9a, 0x00, 0x9e, 0x00, 0xa1, 0x00, 0xbb, 0x00, 0xbd, 0x00, 0xc4, 0x00, 0xb4, 0x00, 0xab, 0x00, 0x94, 0x00, 0x74, 0x00, 0x5c, 0x00, 0x4e, 0x00, 0x48, 0x00, 0x35, 0x00, 0x27, 0x00, 0xf3, 0xff, 0xe9, 0xff, 0xc9, 0xff, 0xa2, 0xff, 0x9c, 0xff, 0x80, 0xff, 0x74, 0xff, 0x68, 0xff, 0x73, 0xff, 0x64, 0xff, 0x55, 0xff, 0x4a, 0xff, 0x23, 0xff, 0x1a, 0xff, 0x13, 0xff, 0x0f, 0xff, 0x1a, 0xff, 0x2c, 0xff, 0x3b, 0xff, 0x4b, 0xff, 0x78, 0xff, 0xa7, 0xff, 0xda, 0xff, 0x12, 0x00, 0x49, 0x00, 0x79, 0x00, 0x92, 0x00, 0xb0, 0x00, 0xc1, 0x00, 0xdb, 0x00, 0xdd, 0x00, 0xf3, 0x00, 0xf0, 0x00, 0xe2, 0x00, 0xc8, 0x00, 0x95, 0x00, 0x67, 0x00, 0x47, 0x00, 0x2f, 0x00, 0x06, 0x00, 0xff, 0xff, 0xdf, 0xff, 0xc7, 0xff, 0x9d, 0xff, 0x84, 0xff, 0x72, 0xff, 0x6f, 0xff, 0x59, 0xff, 0x50, 0xff, 0x50, 0xff, 0x3e, 0xff, 0x3e, 0xff, 0x53, 0xff, 0x61, 0xff, 0x6a, 0xff, 0x4c, 0xff, 0x31, 0xff, 0x08, 0xff, 0xe6, 0xfe, 0xcd, 0xfe, 0xd9, 0xfe, 0xe3, 0xfe, 0xef, 0xfe, 0x05, 0xff, 0x09, 0xff, 0xfe, 0xfe, 0x02, 0xff, 0xfb, 0xfe, 0x00, 0xff, 0x0c, 0xff, 0x1f, 0xff, 0x54, 0xff, 0x97, 0xff, 0xcf, 0xff, 0x1f, 0x00, 0x61, 0x00, 0x9e, 0x00, 0xb9, 0x00, 0xc9, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xbd, 0x00, 0xbd, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xc6, 0x00, 0xd6, 0x00, 0xe9, 0x00, 0xf7, 0x00, 0xfe, 0x00, 0xed, 0x00, 0xc5, 0x00, 0x9b, 0x00, 0x6c, 0x00, 0x39, 0x00, 0x06, 0x00, 0x0c, 0x00, 0xf1, 0xff, 0xe2, 0xff, 0xcf, 0xff, 0xac, 0xff, 0x77, 0xff, 0x52, 0xff, 0x29, 0xff, 0x18, 0xff, 0xf1, 0xfe, 0xeb, 0xfe, 0xf7, 0xfe, 0xf4, 0xfe, 0x02, 0xff, 0x16, 0xff, 0x3a, 0xff, 0x36, 0xff, 0x56, 0xff, 0x6e, 0xff, 0x8e, 0xff, 0xa8, 0xff, 0xcd, 0xff, 0xd1, 0xff, 0xed, 0xff, 0xf9, 0xff, 0x09, 0x00, 0x1f, 0x00, 0x2e, 0x00, 0x55, 0x00, 0x57, 0x00, 0x69, 0x00, 0x99, 0x00, 0xca, 0x00, 0xe5, 0x00, 0x15, 0x01, 0x30, 0x01, 0x50, 0x01, 0x44, 0x01, 0x39, 0x01, 0x2f, 0x01, 0x0d, 0x01, 0xdb, 0x00, 0xbb, 0x00, 0x70, 0x00, 0x43, 0x00, 0x02, 0x00, 0xc6, 0xff, 0x98, 0xff, 0x71, 0xff, 0x57, 0xff, 0x45, 0xff, 0x2d, 0xff, 0x23, 0xff, 0x0d, 0xff, 0x0d, 0xff, 0x27, 0xff, 0x1f, 0xff, 0x44, 0xff, 0x4d, 0xff, 0x55, 0xff, 0x66, 0xff, 0x72, 0xff, 0x68, 0xff, 0x75, 0xff, 0x6f, 0xff, 0x6a, 0xff, 0x80, 0xff, 0x91, 0xff, 0xc5, 0xff, 0xe1, 0xff, 0x11, 0x00, 0x25, 0x00, 0x3d, 0x00, 0x46, 0x00, 0x3d, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x3d, 0x00, 0x4c, 0x00, 0x3e, 0x00, 0x34, 0x00, 0x28, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0xf8, 0xff, 0x0a, 0x00, 0x06, 0x00, 0x16, 0x00, 0x05, 0x00, 0x03, 0x00, 0xf0, 0xff, 0xee, 0xff, 0xdd, 0xff, 0xd9, 0xff, 0xdb, 0xff, 0xe9, 0xff, 0xff, 0xff, 0xfa, 0xff, 0x10, 0x00, 0x1b, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x18, 0x00, 0x09, 0x00, 0x08, 0x00, 0xf3, 0xff, 0xef, 0xff, 0xcc, 0xff, 0xac, 0xff, 0x8c, 0xff, 0x73, 0xff, 0x58, 0xff, 0x3e, 0xff, 0x22, 0xff, 0x11, 0xff, 0x13, 0xff, 0x0d, 0xff, 0x0c, 0xff, 0x19, 0xff, 0x29, 0xff, 0x29, 0xff, 0x26, 0xff, 0x24, 0xff, 0x21, 0xff, 0xfc, 0xfe, 0x17, 0xff, 0x02, 0xff, 0x00, 0xff, 0x0a, 0xff, 0x14, 0xff, 0x1c, 0xff, 0x2e, 0xff, 0x32, 0xff, 0x45, 0xff, 0x55, 0xff, 0x6c, 0xff, 0x80, 0xff, 0x9f, 0xff, 0xc5, 0xff, 0xdf, 0xff, 0x0f, 0x00, 0x33, 0x00, 0x4a, 0x00, 0x68, 0x00, 0x81, 0x00, 0x76, 0x00, 0x7c, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x7b, 0x00, 0x72, 0x00, 0x77, 0x00, 0x65, 0x00, 0x60, 0x00, 0x47, 0x00, 0x45, 0x00, 0x40, 0x00, 0x46, 0x00, 0x48, 0x00, 0x52, 0x00, 0x5c, 0x00, 0x60, 0x00, 0x65, 0x00, 0x5c, 0x00, 0x37, 0x00, 0x17, 0x00, 0xfb, 0xff, 0xd7, 0xff, 0xde, 0xff, 0xcc, 0xff, 0xca, 0xff, 0xba, 0xff, 0xa8, 0xff, 0xac, 0xff, 0x70, 0xff, 0x72, 0xff, 0x5d, 0xff, 0x54, 0xff, 0x59, 0xff, 0x58, 0xff, 0x65, 0xff, 0x86, 0xff, 0x89, 0xff, 0xbe, 0xff, 0xd4, 0xff, 0xfe, 0xff, 0x19, 0x00, 0x33, 0x00, 0x3b, 0x00, 0x6a, 0x00, 0x71, 0x00, 0x8a, 0x00, 0xb7, 0x00, 0xc0, 0x00, 0xc4, 0x00, 0xab, 0x00, 0xa8, 0x00, 0x7d, 0x00, 0x56, 0x00, 0x44, 0x00, 0x2a, 0x00, 0x28, 0x00, 0xf2, 0xff, 0xf4, 0xff, 0xda, 0xff, 0xd0, 0xff, 0xb9, 0xff, 0xc6, 0xff, 0xb4, 0xff, 0xab, 0xff, 0x85, 0xff, 0x5e, 0xff, 0x46, 0xff, 0x20, 0xff, 0x0e, 0xff, 0x01, 0xff, 0xf8, 0xfe, 0xe6, 0xfe, 0xe2, 0xfe, 0xd9, 0xfe, 0xd8, 0xfe, 0xee, 0xfe, 0x09, 0xff, 0x23, 0xff, 0x3e, 0xff, 0x49, 0xff, 0x4e, 0xff, 0x50, 0xff, 0x4b, 0xff, 0x63, 0xff, 0x78, 0xff, 0xa4, 0xff, 0xcf, 0xff, 0x09, 0x00, 0x44, 0x00, 0x65, 0x00, 0x8b, 0x00, 0xa6, 0x00, 0xc5, 0x00, 0xca, 0x00, 0xd1, 0x00, 0xde, 0x00, 0xdd, 0x00, 0xd3, 0x00, 0xbf, 0x00, 0xbe, 0x00, 0xa5, 0x00, 0xa9, 0x00, 0x9d, 0x00, 0xa2, 0x00, 0x8a, 0x00, 0x66, 0x00, 0x45, 0x00, 0xfa, 0xff, 0xd1, 0xff, 0xb2, 0xff, 0xaa, 0xff, 0xac, 0xff, 0xa9, 0xff, 0x9a, 0xff, 0x8c, 0xff, 0x75, 0xff, 0x64, 0xff, 0x54, 0xff, 0x49, 0xff, 0x30, 0xff, 0x28, 0xff, 0x21, 0xff, 0x1e, 0xff, 0x2b, 0xff, 0x3b, 0xff, 0x38, 0xff, 0x5d, 0xff, 0x60, 0xff, 0x72, 0xff, 0x93, 0xff, 0xb7, 0xff, 0xee, 0xff, 0x11, 0x00, 0x2a, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x35, 0x00, 0x22, 0x00, 0x31, 0x00, 0x31, 0x00, 0x3a, 0x00, 0x46, 0x00, 0x41, 0x00, 0x49, 0x00, 0x44, 0x00, 0x3e, 0x00, 0x3b, 0x00, 0x23, 0x00, 0x23, 0x00, 0x00, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0xe8, 0xff, 0xfe, 0xff, 0xf2, 0xff, 0xe8, 0xff, 0xec, 0xff, 0xd7, 0xff, 0xc5, 0xff, 0xc6, 0xff, 0xb1, 0xff, 0xa5, 0xff, 0xb0, 0xff, 0xb3, 0xff, 0xcb, 0xff, 0xe0, 0xff, 0xf9, 0xff, 0xfd, 0xff, 0x06, 0x00, 0x17, 0x00, 0x04, 0x00, 0x05, 0x00, 0x15, 0x00, 0xee, 0xff, 0x00, 0x00, 0xf1, 0xff, 0x09, 0x00, 0xff, 0xff, 0xfd, 0xff, 0x08, 0x00, 0xf1, 0xff, 0xf7, 0xff, 0x07, 0x00, 0x08, 0x00, 0x20, 0x00, 0x27, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x2f, 0x00, 0x11, 0x00, 0xfc, 0xff, 0xd8, 0xff, 0xbd, 0xff, 0x9e, 0xff, 0x8f, 0xff, 0x93, 0xff, 0xa4, 0xff, 0xad, 0xff, 0xbd, 0xff, 0xd5, 0xff, 0xe5, 0xff, 0xfa, 0xff, 0x0f, 0x00, 0x45, 0x00, 0x5c, 0x00, 0x74, 0x00, 0x8f, 0x00, 0x87, 0x00, 0x87, 0x00, 0x6f, 0x00, 0x54, 0x00, 0x42, 0x00, 0x14, 0x00, 0xee, 0xff, 0xbc, 0xff, 0xa4, 0xff, 0x7d, 0xff, 0x6b, 0xff, 0x55, 0xff, 0x4d, 0xff, 0x4b, 0xff, 0x2d, 0xff, 0x29, 0xff, 0x23, 0xff, 0x0b, 0xff, 0x07, 0xff, 0xf2, 0xfe, 0xf1, 0xfe, 0xdc, 0xfe, 0xe6, 0xfe, 0xf0, 0xfe, 0xf1, 0xfe, 0x16, 0xff, 0x2c, 0xff, 0x56, 0xff, 0x79, 0xff, 0xa0, 0xff, 0xce, 0xff, 0xee, 0xff, 0x0b, 0x00, 0x15, 0x00, 0x1f, 0x00, 0x20, 0x00, 0x2b, 0x00, 0x2b, 0x00, 0x42, 0x00, 0x46, 0x00, 0x6c, 0x00, 0x76, 0x00, 0x86, 0x00, 0x91, 0x00, 0x95, 0x00, 0xaf, 0x00, 0xaf, 0x00, 0xc4, 0x00, 0xc6, 0x00, 0xe5, 0x00, 0xdc, 0x00, 0xd5, 0x00, 0xb6, 0x00, 0xae, 0x00, 0x81, 0x00, 0x5a, 0x00, 0x32, 0x00, 0x03, 0x00, 0xd6, 0xff, 0xc1, 0xff, 0xa0, 0xff, 0x87, 0xff, 0x63, 0xff, 0x3a, 0xff, 0xff, 0xfe, 0xe7, 0xfe, 0xca, 0xfe, 0xbc, 0xfe, 0xb7, 0xfe, 0xb5, 0xfe, 0xb4, 0xfe, 0xae, 0xfe, 0xbb, 0xfe, 0xd8, 0xfe, 0xdc, 0xfe, 0xfa, 0xfe, 0x0e, 0xff, 0x06, 0xff, 0x11, 0xff, 0x34, 0xff, 0x35, 0xff, 0x56, 0xff, 0x72, 0xff, 0x6f, 0xff, 0xa1, 0xff, 0xb3, 0xff, 0xdb, 0xff, 0x03, 0x00, 0x27, 0x00, 0x53, 0x00, 0x78, 0x00, 0x8e, 0x00, 0xa9, 0x00, 0xce, 0x00, 0xe5, 0x00, 0x07, 0x01, 0x17, 0x01, 0x41, 0x01, 0x6d, 0x01, 0x99, 0x01, 0x9e, 0x01, 0xbf, 0x01, 0xb0, 0x01, 0x89, 0x01, 0x4d, 0x01, 0x1f, 0x01, 0xdc, 0x00, 0x9a, 0x00, 0x4f, 0x00, 0x27, 0x00, 0xe1, 0xff, 0xc0, 0xff, 0xa3, 0xff, 0x85, 0xff, 0x5b, 0xff, 0x4a, 0xff, 0x30, 0xff, 0x0e, 0xff, 0xe8, 0xfe, 0xcd, 0xfe, 0xb8, 0xfe, 0xb7, 0xfe, 0x9c, 0xfe, 0xa8, 0xfe, 0xad, 0xfe, 0xba, 0xfe, 0xc4, 0xfe, 0xee, 0xfe, 0x04, 0xff, 0x32, 0xff, 0x55, 0xff, 0x59, 0xff, 0x8e, 0xff, 0x96, 0xff, 0xa4, 0xff, 0xd1, 0xff, 0x03, 0x00, 0x29, 0x00, 0x42, 0x00, 0x5c, 0x00, 0x54, 0x00, 0x64, 0x00, 0x60, 0x00, 0x5e, 0x00, 0x6c, 0x00, 0x7d, 0x00, 0x70, 0x00, 0x70, 0x00, 0x64, 0x00, 0x4e, 0x00, 0x2f, 0x00, 0x0e, 0x00, 0x02, 0x00, 0xda, 0xff, 0xe5, 0xff, 0xce, 0xff, 0xdb, 0xff, 0xb7, 0xff, 0xb5, 0xff, 0x9e, 0xff, 0x9d, 0xff, 0x9a, 0xff, 0xa2, 0xff, 0xc3, 0xff, 0xc3, 0xff, 0xd7, 0xff, 0xcd, 0xff, 0xe5, 0xff, 0xd7, 0xff, 0xd1, 0xff, 0xe5, 0xff, 0x0d, 0x00, 0x10, 0x00, 0x24, 0x00, 0x31, 0x00, 0x20, 0x00, 0x1c, 0x00, 0x01, 0x00, 0xfd, 0xff, 0xf4, 0xff, 0xd0, 0xff, 0xc0, 0xff, 0xa6, 0xff, 0x72, 0xff, 0x56, 0xff, 0x53, 0xff, 0x42, 0xff, 0x25, 0xff, 0x2d, 0xff, 0x21, 0xff, 0x23, 0xff, 0x25, 0xff, 0x31, 0xff, 0x46, 0xff, 0x68, 0xff, 0x78, 0xff, 0x89, 0xff, 0xad, 0xff, 0xb5, 0xff, 0xbd, 0xff, 0xc6, 0xff, 0xdf, 0xff, 0xcb, 0xff, 0xe5, 0xff, 0xdf, 0xff, 0xd1, 0xff, 0xd0, 0xff, 0xb3, 0xff, 0xd1, 0xff, 0xb6, 0xff, 0xc6, 0xff, 0xe6, 0xff, 0xf3, 0xff, 0x0f, 0x00, 0x27, 0x00, 0x44, 0x00, 0x5c, 0x00, 0x68, 0x00, 0x66, 0x00, 0x7f, 0x00, 0x57, 0x00, 0x50, 0x00, 0x49, 0x00, 0x24, 0x00, 0x20, 0x00, 0x10, 0x00, 0xfb, 0xff, 0xdc, 0xff, 0xcf, 0xff, 0xd4, 0xff, 0xb4, 0xff, 0xb5, 0xff, 0x9d, 0xff, 0x8d, 0xff, 0x77, 0xff, 0x75, 0xff, 0x7d, 0xff, 0x92, 0xff, 0xa5, 0xff, 0xc2, 0xff, 0xb3, 0xff, 0x9d, 0xff, 0x90, 0xff, 0x71, 0xff, 0x5f, 0xff, 0x66, 0xff, 0x6b, 0xff, 0x8c, 0xff, 0xa6, 0xff, 0xbe, 0xff, 0xd9, 0xff, 0xd3, 0xff, 0xe7, 0xff, 0xed, 0xff, 0xf1, 0xff, 0x05, 0x00, 0x1b, 0x00, 0x3f, 0x00, 0x66, 0x00, 0x89, 0x00, 0xb6, 0x00, 0xca, 0x00, 0xea, 0x00, 0xfd, 0x00, 0x0b, 0x01, 0x31, 0x01, 0x41, 0x01, 0x59, 0x01, 0x5e, 0x01, 0x51, 0x01, 0x2f, 0x01, 0x00, 0x01, 0xc9, 0x00, 0x90, 0x00, 0x51, 0x00, 0x10, 0x00, 0xce, 0xff, 0xb3, 0xff, 0x79, 0xff, 0x60, 0xff, 0x40, 0xff, 0x1b, 0xff, 0xf5, 0xfe, 0xe5, 0xfe, 0xde, 0xfe, 0xc1, 0xfe, 0xcc, 0xfe, 0xc1, 0xfe, 0xbf, 0xfe, 0xc5, 0xfe, 0xd1, 0xfe, 0xcc, 0xfe, 0x08, 0xff, 0x03, 0xff, 0x1a, 0xff, 0x2d, 0xff, 0x36, 0xff, 0x43, 0xff, 0x57, 0xff, 0x6b, 0xff, 0x88, 0xff, 0x9d, 0xff, 0xae, 0xff, 0xb6, 0xff, 0xbd, 0xff, 0xb6, 0xff, 0xd5, 0xff, 0xf7, 0xff, 0x21, 0x00, 0x57, 0x00, 0x71, 0x00, 0xaf, 0x00, 0xa5, 0x00, 0xb0, 0x00, 0xc4, 0x00, 0xd7, 0x00, 0xb8, 0x00, 0xcf, 0x00, 0xbc, 0x00, 0xa5, 0x00, 0x91, 0x00, 0x61, 0x00, 0x5b, 0x00, 0x24, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x13, 0x00, 0x02, 0x00, 0x15, 0x00, 0x06, 0x00, 0xfd, 0xff, 0xe8, 0xff, 0xa4, 0xff, 0x92, 0xff, 0x62, 0xff, 0x5c, 0xff, 0x36, 0xff, 0x40, 0xff, 0x40, 0xff, 0x55, 0xff, 0x65, 0xff, 0x80, 0xff, 0xa9, 0xff, 0xd9, 0xff, 0x05, 0x00, 0x36, 0x00, 0x50, 0x00, 0x85, 0x00, 0x97, 0x00, 0x8e, 0x00, 0xa8, 0x00, 0xb5, 0x00, 0xad, 0x00, 0xaa, 0x00, 0xac, 0x00, 0x80, 0x00, 0x70, 0x00, 0x51, 0x00, 0x26, 0x00, 0x18, 0x00, 0xe6, 0xff, 0xbe, 0xff, 0x97, 0xff, 0x87, 0xff, 0x5c, 0xff, 0x48, 0xff, 0x2c, 0xff, 0x1b, 0xff, 0x00, 0xff, 0xf0, 0xfe, 0xe5, 0xfe, 0x08, 0xff, 0x0a, 0xff, 0x27, 0xff, 0x35, 0xff, 0x4a, 0xff, 0x48, 0xff, 0x4a, 0xff, 0x5b, 0xff, 0x68, 0xff, 0x67, 0xff, 0x6a, 0xff, 0x58, 0xff, 0x4f, 0xff, 0x34, 0xff, 0x3e, 0xff, 0x3c, 0xff, 0x47, 0xff, 0x50, 0xff, 0x5f, 0xff, 0x87, 0xff, 0x9f, 0xff, 0xb7, 0xff, 0xde, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf4, 0xff, 0xf1, 0xff, 0xee, 0xff, 0xe2, 0xff, 0xe8, 0xff, 0xdf, 0xff, 0xe9, 0xff, 0x09, 0x00, 0x26, 0x00, 0x4d, 0x00, 0x62, 0x00, 0x76, 0x00, 0x67, 0x00, 0x5e, 0x00, 0x69, 0x00, 0x52, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x78, 0x00, 0x8c, 0x00, 0x98, 0x00, 0xa6, 0x00, 0xba, 0x00, 0xbd, 0x00, 0xd7, 0x00, 0xe4, 0x00, 0xe4, 0x00, 0xe6, 0x00, 0xdd, 0x00, 0xc6, 0x00, 0xaf, 0x00, 0x92, 0x00, 0x6e, 0x00, 0x40, 0x00, 0xef, 0xff, 0xd8, 0xff, 0x96, 0xff, 0x66, 0xff, 0x3f, 0xff, 0x2a, 0xff, 0xed, 0xfe, 0xd3, 0xfe, 0xa8, 0xfe, 0x87, 0xfe, 0x69, 0xfe, 0x57, 0xfe, 0x46, 0xfe, 0x55, 0xfe, 0x6a, 0xfe, 0x8f, 0xfe, 0xb5, 0xfe, 0xcd, 0xfe, 0xf2, 0xfe, 0xf5, 0xfe, 0xff, 0xfe, 0x30, 0xff, 0x3c, 0xff, 0x65, 0xff, 0x8d, 0xff, 0xa2, 0xff, 0xc4, 0xff, 0xdf, 0xff, 0x13, 0x00, 0x22, 0x00, 0x4a, 0x00, 0x81, 0x00, 0xa9, 0x00, 0xd9, 0x00, 0x0a, 0x01, 0x2e, 0x01, 0x5b, 0x01, 0x62, 0x01, 0x6c, 0x01, 0x7c, 0x01, 0x78, 0x01, 0x6a, 0x01, 0x5f, 0x01, 0x39, 0x01, 0x12, 0x01, 0xe6, 0x00, 0xb8, 0x00, 0x8e, 0x00, 0x6d, 0x00, 0x35, 0x00, 0x07, 0x00, 0xed, 0xff, 0xac, 0xff, 0x8a, 0xff, 0x66, 0xff, 0x40, 0xff, 0x37, 0xff, 0x24, 0xff, 0x1a, 0xff, 0x22, 0xff, 0x37, 0xff, 0x42, 0xff, 0x5e, 0xff, 0x70, 0xff, 0x94, 0xff, 0x99, 0xff, 0xab, 0xff, 0xbc, 0xff, 0xbc, 0xff, 0xb8, 0xff, 0xbc, 0xff, 0xae, 0xff, 0x97, 0xff, 0xa3, 0xff, 0x97, 0xff, 0x8c, 0xff, 0x84, 0xff, 0x7f, 0xff, 0x71, 0xff, 0x60, 0xff, 0x83, 0xff, 0x8e, 0xff, 0xa3, 0xff, 0xa6, 0xff, 0xa5, 0xff, 0x9e, 0xff, 0xb1, 0xff, 0x8f, 0xff, 0xa6, 0xff, 0x98, 0xff, 0x90, 0xff, 0xa7, 0xff, 0x94, 0xff, 0xb9, 0xff, 0xc5, 0xff, 0xf1, 0xff, 0xea, 0xff, 0x00, 0x00, 0x1d, 0x00, 0x2c, 0x00, 0x35, 0x00, 0x50, 0x00, 0x4c, 0x00, 0x5c, 0x00, 0x5d, 0x00, 0x57, 0x00, 0x42, 0x00, 0x47, 0x00, 0x34, 0x00, 0x1a, 0x00, 0x07, 0x00, 0xe9, 0xff, 0xd2, 0xff, 0xb7, 0xff, 0xc3, 0xff, 0xce, 0xff, 0xe2, 0xff, 0xe9, 0xff, 0xfa, 0xff, 0xe8, 0xff, 0xf0, 0xff, 0xe0, 0xff, 0xce, 0xff, 0xc4, 0xff, 0xba, 0xff, 0xae, 0xff, 0xaa, 0xff, 0xad, 0xff, 0xc9, 0xff, 0xd2, 0xff, 0xee, 0xff, 0xff, 0xff, 0x16, 0x00, 0x25, 0x00, 0x32, 0x00, 0x3a, 0x00, 0x47, 0x00, 0x3e, 0x00, 0x32, 0x00, 0x39, 0x00, 0x24, 0x00, 0x0f, 0x00, 0x04, 0x00, 0xe2, 0xff, 0xaf, 0xff, 0x99, 0xff, 0x89, 0xff, 0x74, 0xff, 0x6c, 0xff, 0x6f, 0xff, 0x4f, 0xff, 0x4d, 0xff, 0x3a, 0xff, 0x29, 0xff, 0x1f, 0xff, 0x22, 0xff, 0x19, 0xff, 0x2a, 0xff, 0x3a, 0xff, 0x56, 0xff, 0x68, 0xff, 0x84, 0xff, 0x9f, 0xff, 0x93, 0xff, 0xb3, 0xff, 0xb8, 0xff, 0xc9, 0xff, 0xd0, 0xff, 0xd0, 0xff, 0xe4, 0xff, 0xff, 0xff, 0x08, 0x00, 0x26, 0x00, 0x52, 0x00, 0x5b, 0x00, 0x7b, 0x00, 0x7b, 0x00, 0x81, 0x00, 0x8d, 0x00, 0x9f, 0x00, 0x93, 0x00, 0x91, 0x00, 0x6a, 0x00, 0x31, 0x00, 0x00, 0x00, 0xe5, 0xff, 0xa4, 0xff, 0x90, 0xff, 0x87, 0xff, 0x6b, 0xff, 0x5e, 0xff, 0x56, 0xff, 0x45, 0xff, 0x48, 0xff, 0x33, 0xff, 0x49, 0xff, 0x40, 0xff, 0x5e, 0xff, 0x83, 0xff, 0xaf, 0xff, 0xea, 0xff, 0x0e, 0x00, 0x4c, 0x00, 0x6a, 0x00, 0x98, 0x00, 0xb4, 0x00, 0xc8, 0x00, 0xd7, 0x00, 0xe2, 0x00, 0xde, 0x00, 0xd1, 0x00, 0xc4, 0x00, 0xa1, 0x00, 0x62, 0x00, 0x4c, 0x00, 0x04, 0x00, 0xd2, 0xff, 0xb8, 0xff, 0xb0, 0xff, 0x94, 0xff, 0x83, 0xff, 0x74, 0xff, 0x5a, 0xff, 0x4f, 0xff, 0x39, 0xff, 0x37, 0xff, 0x47, 0xff, 0x4f, 0xff, 0x52, 0xff, 0x61, 0xff, 0x62, 0xff, 0x82, 0xff, 0x88, 0xff, 0xc4, 0xff, 0xe0, 0xff, 0x17, 0x00, 0x37, 0x00, 0x47, 0x00, 0x6d, 0x00, 0x64, 0x00, 0x6e, 0x00, 0x7b, 0x00, 0x79, 0x00, 0x73, 0x00, 0x68, 0x00, 0x52, 0x00, 0x3c, 0x00, 0x29, 0x00, 0x14, 0x00, 0x08, 0x00, 0xe8, 0xff, 0xc9, 0xff, 0x9f, 0xff, 0x82, 0xff, 0x67, 0xff, 0x40, 0xff, 0x34, 0xff, 0x14, 0xff, 0x06, 0xff, 0xf0, 0xfe, 0xf3, 0xfe, 0xf8, 0xfe, 0x0e, 0xff, 0x26, 0xff, 0x2e, 0xff, 0x3e, 0xff, 0x37, 0xff, 0x3f, 0xff, 0x35, 0xff, 0x51, 0xff, 0x57, 0xff, 0x74, 0xff, 0x83, 0xff, 0x94, 0xff, 0xa7, 0xff, 0xa7, 0xff, 0xd0, 0xff, 0xe9, 0xff, 0x14, 0x00, 0x1a, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x2c, 0x00, 0x1a, 0x00, 0x39, 0x00, 0x25, 0x00, 0x22, 0x00, 0x22, 0x00, 0x1e, 0x00, 0x25, 0x00, 0x1d, 0x00, 0x1a, 0x00, 0xfe, 0xff, 0xe6, 0xff, 0xea, 0xff, 0xc0, 0xff, 0xce, 0xff, 0xd8, 0xff, 0xd1, 0xff, 0xee, 0xff, 0xe4, 0xff, 0x06, 0x00, 0x20, 0x00, 0x48, 0x00, 0x5e, 0x00, 0x89, 0x00, 0x98, 0x00, 0xbe, 0x00, 0xc7, 0x00, 0xca, 0x00, 0xdd, 0x00, 0xd7, 0x00, 0xcc, 0x00, 0xae, 0x00, 0x8f, 0x00, 0x7d, 0x00, 0x48, 0x00, 0x3a, 0x00, 0x10, 0x00, 0x03, 0x00, 0xe8, 0xff, 0xd8, 0xff, 0xbb, 0xff, 0xab, 0xff, 0x96, 0xff, 0x86, 0xff, 0x77, 0xff, 0x63, 0xff, 0x63, 0xff, 0x5a, 0xff, 0x53, 0xff, 0x4a, 0xff, 0x3f, 0xff, 0x4e, 0xff, 0x48, 0xff, 0x42, 0xff, 0x56, 0xff, 0x3c, 0xff, 0x3b, 0xff, 0x47, 0xff, 0x5e, 0xff, 0x56, 0xff, 0x69, 0xff, 0x65, 0xff, 0x5b, 0xff, 0x66, 0xff, 0x5a, 0xff, 0x65, 0xff, 0x86, 0xff, 0xa3, 0xff, 0xb4, 0xff, 0xd1, 0xff, 0xed, 0xff, 0x11, 0x00, 0x29, 0x00, 0x36, 0x00, 0x54, 0x00, 0x4d, 0x00, 0x63, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x67, 0x00, 0x79, 0x00, 0x5b, 0x00, 0x58, 0x00, 0x5a, 0x00, 0x63, 0x00, 0x5e, 0x00, 0x5b, 0x00, 0x56, 0x00, 0x4a, 0x00, 0x46, 0x00, 0x48, 0x00, 0x4a, 0x00, 0x4a, 0x00, 0x4b, 0x00, 0x1d, 0x00, 0x10, 0x00, 0xf0, 0xff, 0xbe, 0xff, 0xa9, 0xff, 0xa1, 0xff, 0x78, 0xff, 0x79, 0xff, 0x56, 0xff, 0x53, 0xff, 0x5b, 0xff, 0x51, 0xff, 0x69, 0xff, 0x85, 0xff, 0x96, 0xff, 0xa4, 0xff, 0xa0, 0xff, 0xa4, 0xff, 0x92, 0xff, 0x7e, 0xff, 0x94, 0xff, 0x95, 0xff, 0x97, 0xff, 0xc0, 0xff, 0xc5, 0xff, 0xe3, 0xff, 0xe9, 0xff, 0xfc, 0xff, 0x14, 0x00, 0x1f, 0x00, 0x4a, 0x00, 0x66, 0x00, 0x8a, 0x00, 0xb0, 0x00, 0xc1, 0x00, 0xdd, 0x00, 0xe8, 0x00, 0xf7, 0x00, 0xf8, 0x00, 0x09, 0x01, 0x09, 0x01, 0x14, 0x01, 0xef, 0x00, 0xf0, 0x00, 0xd4, 0x00, 0xa6, 0x00, 0x8e, 0x00, 0x7c, 0x00, 0x4e, 0x00, 0x2a, 0x00, 0xf0, 0xff, 0xaf, 0xff, 0x66, 0xff, 0x3a, 0xff, 0xfa, 0xfe, 0xcc, 0xfe, 0xa5, 0xfe, 0x79, 0xfe, 0x70, 0xfe, 0x3c, 0xfe, 0x4a, 0xfe, 0x50, 0xfe, 0x49, 0xfe, 0x58, 0xfe, 0x68, 0xfe, 0x75, 0xfe, 0x86, 0xfe, 0x97, 0xfe, 0xae, 0xfe, 0xbf, 0xfe, 0xf3, 0xfe, 0x0e, 0xff, 0x3b, 0xff, 0x51, 0xff, 0x77, 0xff, 0x91, 0xff, 0xad, 0xff, 0xce, 0xff, 0xf5, 0xff, 0x25, 0x00, 0x49, 0x00, 0x6b, 0x00, 0x81, 0x00, 0xaa, 0x00, 0xa8, 0x00, 0xce, 0x00, 0xd7, 0x00, 0xed, 0x00, 0x0b, 0x01, 0x21, 0x01, 0x42, 0x01, 0x49, 0x01, 0x4e, 0x01, 0x4c, 0x01, 0x37, 0x01, 0x16, 0x01, 0xf4, 0x00, 0xd1, 0x00, 0xae, 0x00, 0x70, 0x00, 0x49, 0x00, 0x0d, 0x00, 0xdc, 0xff, 0xa6, 0xff, 0x8c, 0xff, 0x7a, 0xff, 0x5e, 0xff, 0x5b, 0xff, 0x50, 0xff, 0x52, 0xff, 0x4a, 0xff, 0x4d, 0xff, 0x4f, 0xff, 0x60, 0xff, 0x67, 0xff, 0x65, 0xff, 0x7b, 0xff, 0x83, 0xff, 0x97, 0xff, 0x88, 0xff, 0xac, 0xff, 0xae, 0xff, 0xc4, 0xff, 0xcc, 0xff, 0xe0, 0xff, 0xe3, 0xff, 0xea, 0xff, 0xe4, 0xff, 0xd6, 0xff, 0xc8, 0xff, 0xbd, 0xff, 0xb3, 0xff, 0xa0, 0xff, 0x9b, 0xff, 0x95, 0xff, 0x86, 0xff, 0x7d, 0xff, 0x77, 0xff, 0x81, 0xff, 0x71, 0xff, 0x7f, 0xff, 0x8c, 0xff, 0x80, 0xff, 0x96, 0xff, 0x97, 0xff, 0xa8, 0xff, 0xb1, 0xff, 0xbf, 0xff, 0xcb, 0xff, 0xc7, 0xff, 0xd3, 0xff, 0xb9, 0xff, 0x9f, 0xff, 0x98, 0xff, 0xaa, 0xff, 0x8b, 0xff, 0x9c, 0xff, 0xa5, 0xff, 0x95, 0xff, 0xa5, 0xff, 0x97, 0xff, 0xaf, 0xff, 0xc8, 0xff, 0xc7, 0xff, 0xf7, 0xff, 0x00, 0x00, 0x25, 0x00, 0x41, 0x00, 0x4f, 0x00, 0x58, 0x00, 0x64, 0x00, 0x62, 0x00, 0x5f, 0x00, 0x5c, 0x00, 0x53, 0x00, 0x40, 0x00, 0x2a, 0x00, 0x2d, 0x00, 0x0b, 0x00, 0xf6, 0xff, 0xf0, 0xff, 0xe0, 0xff, 0xbf, 0xff, 0xab, 0xff, 0x97, 0xff, 0x7b, 0xff, 0x70, 0xff, 0x56, 0xff, 0x52, 0xff, 0x49, 0xff, 0x43, 0xff, 0x43, 0xff, 0x53, 0xff, 0x64, 0xff, 0x6f, 0xff, 0x8f, 0xff, 0x7b, 0xff, 0x98, 0xff, 0x81, 0xff, 0x93, 0xff, 0x92, 0xff, 0xaf, 0xff, 0xb7, 0xff, 0xc3, 0xff, 0xc9, 0xff, 0xe0, 0xff, 0xd8, 0xff, 0xf3, 0xff, 0x06, 0x00, 0x12, 0x00, 0x37, 0x00, 0x47, 0x00, 0x61, 0x00, 0x80, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0xca, 0x00, 0xd7, 0x00, 0xf6, 0x00, 0xfd, 0x00, 0xf9, 0x00, 0xf7, 0x00, 0xf2, 0x00, 0xe7, 0x00, 0xb3, 0x00, 0xb8, 0x00, 0x8f, 0x00, 0x58, 0x00, 0x35, 0x00, 0x11, 0x00, 0xe9, 0xff, 0xc8, 0xff, 0xbb, 0xff, 0x91, 0xff, 0x76, 0xff, 0x6a, 0xff, 0x47, 0xff, 0x2c, 0xff, 0x2c, 0xff, 0x1f, 0xff, 0x0e, 0xff, 0x17, 0xff, 0x0f, 0xff, 0x06, 0xff, 0x09, 0xff, 0x13, 0xff, 0x21, 0xff, 0x2d, 0xff, 0x38, 0xff, 0x42, 0xff, 0x35, 0xff, 0x49, 0xff, 0x3b, 0xff, 0x4f, 0xff, 0x60, 0xff, 0x60, 0xff, 0x9a, 0xff, 0xbb, 0xff, 0xee, 0xff, 0x28, 0x00, 0x5b, 0x00, 0x79, 0x00, 0x89, 0x00, 0x8e, 0x00, 0x9c, 0x00, 0x72, 0x00, 0x7b, 0x00, 0x78, 0x00, 0x64, 0x00, 0x5c, 0x00, 0x59, 0x00, 0x4c, 0x00, 0x21, 0x00, 0x14, 0x00, 0xed, 0xff, 0xcf, 0xff, 0xbd, 0xff, 0xb1, 0xff, 0x9e, 0xff, 0xb8, 0xff, 0xaf, 0xff, 0xc8, 0xff, 0xcc, 0xff, 0xe2, 0xff, 0xe8, 0xff, 0xe6, 0xff, 0xfe, 0xff, 0x0d, 0x00, 0x0c, 0x00, 0x17, 0x00, 0x13, 0x00, 0x11, 0x00, 0x14, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x23, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x05, 0x00, 0x01, 0x00, 0xf4, 0xff, 0xe6, 0xff, 0xd9, 0xff, 0xbb, 0xff, 0xac, 0xff, 0x97, 0xff, 0x7a, 0xff, 0x65, 0xff, 0x5f, 0xff, 0x48, 0xff, 0x49, 0xff, 0x48, 0xff, 0x46, 0xff, 0x50, 0xff, 0x56, 0xff, 0x62, 0xff, 0x5d, 0xff, 0x7e, 0xff, 0x8d, 0xff, 0xa2, 0xff, 0xab, 0xff, 0xcd, 0xff, 0xbd, 0xff, 0xe3, 0xff, 0xeb, 0xff, 0xee, 0xff, 0x09, 0x00, 0x02, 0x00, 0x26, 0x00, 0x2e, 0x00, 0x43, 0x00, 0x6e, 0x00, 0x98, 0x00, 0xc5, 0x00, 0xd9, 0x00, 0xef, 0x00, 0x07, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x20, 0x01, 0x27, 0x01, 0x1c, 0x01, 0x10, 0x01, 0xf1, 0x00, 0xd7, 0x00, 0xb6, 0x00, 0x85, 0x00, 0x69, 0x00, 0x60, 0x00, 0x4a, 0x00, 0x41, 0x00, 0x2c, 0x00, 0x16, 0x00, 0xfb, 0xff, 0xd3, 0xff, 0xaa, 0xff, 0x81, 0xff, 0x65, 0xff, 0x3e, 0xff, 0x0f, 0xff, 0x0c, 0xff, 0xfa, 0xfe, 0xe7, 0xfe, 0xd7, 0xfe, 0xda, 0xfe, 0xc9, 0xfe, 0xb6, 0xfe, 0xbd, 0xfe, 0xa2, 0xfe, 0x9d, 0xfe, 0x91, 0xfe, 0x8b, 0xfe, 0x86, 0xfe, 0x84, 0xfe, 0x96, 0xfe, 0x9b, 0xfe, 0xcb, 0xfe, 0xcb, 0xfe, 0xfb, 0xfe, 0x15, 0xff, 0x2c, 0xff, 0x4b, 0xff, 0x65, 0xff, 0x84, 0xff, 0xac, 0xff, 0xd8, 0xff, 0x08, 0x00, 0x39, 0x00, 0x66, 0x00, 0x8f, 0x00, 0xba, 0x00, 0xcb, 0x00, 0xd7, 0x00, 0xe0, 0x00, 0xd8, 0x00, 0xbe, 0x00, 0xb6, 0x00, 0x97, 0x00, 0x78, 0x00, 0x7a, 0x00, 0x74, 0x00, 0x60, 0x00, 0x46, 0x00, 0x2e, 0x00, 0xe5, 0xff, 0xbe, 0xff, 0xa8, 0xff, 0x6d, 0xff, 0x6b, 0xff, 0x56, 0xff, 0x54, 0xff, 0x51, 0xff, 0x48, 0xff, 0x5e, 0xff, 0x80, 0xff, 0x93, 0xff, 0xad, 0xff, 0xc9, 0xff, 0xe0, 0xff, 0xf7, 0xff, 0xf4, 0xff, 0x11, 0x00, 0x19, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x19, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x02, 0x00, 0xf3, 0xff, 0xe0, 0xff, 0xdb, 0xff, 0xd6, 0xff, 0xc1, 0xff, 0xd5, 0xff, 0xbf, 0xff, 0xcf, 0xff, 0xcd, 0xff, 0xde, 0xff, 0x02, 0x00, 0x06, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x2b, 0x00, 0x32, 0x00, 0x2b, 0x00, 0x17, 0x00, 0x04, 0x00, 0xed, 0xff, 0xf4, 0xff, 0xdb, 0xff, 0xdf, 0xff, 0xe9, 0xff, 0xe7, 0xff, 0xe6, 0xff, 0xe4, 0xff, 0xe5, 0xff, 0xed, 0xff, 0xd1, 0xff, 0xca, 0xff, 0xc0, 0xff, 0xb4, 0xff, 0x9b, 0xff, 0xb7, 0xff, 0xa5, 0xff, 0xb4, 0xff, 0x9a, 0xff, 0xa4, 0xff, 0x9e, 0xff, 0xa2, 0xff, 0xb8, 0xff, 0xb9, 0xff, 0xc0, 0xff, 0xca, 0xff, 0xb3, 0xff, 0xc2, 0xff, 0xcb, 0xff, 0xc4, 0xff, 0xc6, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xed, 0xff, 0xe2, 0xff, 0xe2, 0xff, 0xd3, 0xff, 0xc8, 0xff, 0xc7, 0xff, 0xb4, 0xff, 0xd1, 0xff, 0xca, 0xff, 0xe1, 0xff, 0xe7, 0xff, 0x02, 0x00, 0x15, 0x00, 0x38, 0x00, 0x4c, 0x00, 0x5e, 0x00, 0x6a, 0x00, 0x64, 0x00, 0x6b, 0x00, 0x75, 0x00, 0x76, 0x00, 0x71, 0x00, 0x75, 0x00, 0x66, 0x00, 0x3e, 0x00, 0x26, 0x00, 0x19, 0x00, 0xee, 0xff, 0xdf, 0xff, 0xc3, 0xff, 0xb9, 0xff, 0xb1, 0xff, 0x98, 0xff, 0x91, 0xff, 0x8b, 0xff, 0x6f, 0xff, 0x5b, 0xff, 0x57, 0xff, 0x43, 0xff, 0x5c, 0xff, 0x69, 0xff, 0x74, 0xff, 0x96, 0xff, 0x9e, 0xff, 0xbd, 0xff, 0xaf, 0xff, 0xbd, 0xff, 0xbf, 0xff, 0xb6, 0xff, 0xc5, 0xff, 0xeb, 0xff, 0xfa, 0xff, 0x03, 0x00, 0x1f, 0x00, 0x05, 0x00, 0x06, 0x00, 0x09, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x26, 0x00, 0x15, 0x00, 0x0d, 0x00, 0xf8, 0xff, 0xfa, 0xff, 0xd4, 0xff, 0xe9, 0xff, 0xd8, 0xff, 0xc8, 0xff, 0xdf, 0xff, 0xda, 0xff, 0xea, 0xff, 0xf2, 0xff, 0x01, 0x00, 0x0c, 0x00, 0xfb, 0xff, 0x17, 0x00, 0x10, 0x00, 0x2b, 0x00, 0x32, 0x00, 0x46, 0x00, 0x66, 0x00, 0x8c, 0x00, 0xa5, 0x00, 0xd4, 0x00, 0xf5, 0x00, 0x1a, 0x01, 0x16, 0x01, 0x10, 0x01, 0x02, 0x01, 0xee, 0x00, 0xb9, 0x00, 0x81, 0x00, 0x60, 0x00, 0x0c, 0x00, 0xe1, 0xff, 0xbb, 0xff, 0x90, 0xff, 0x64, 0xff, 0x3f, 0xff, 0x11, 0xff, 0xd7, 0xfe, 0xb5, 0xfe, 0x85, 0xfe, 0x6a, 0xfe, 0x61, 0xfe, 0x5a, 0xfe, 0x6b, 0xfe, 0x7e, 0xfe, 0x88, 0xfe, 0xa5, 0xfe, 0xad, 0xfe, 0xba, 0xfe, 0xc5, 0xfe, 0xc8, 0xfe, 0xdd, 0xfe, 0xf7, 0xfe, 0x08, 0xff, 0x1e, 0xff, 0x4a, 0xff, 0x5c, 0xff, 0x7c, 0xff, 0x93, 0xff, 0xb6, 0xff, 0xd9, 0xff, 0xf3, 0xff, 0x11, 0x00, 0x34, 0x00, 0x52, 0x00, 0x7d, 0x00, 0x89, 0x00, 0xb8, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xea, 0x00, 0x01, 0x01, 0x1f, 0x01, 0x27, 0x01, 0x41, 0x01, 0x2e, 0x01, 0x44, 0x01, 0x29, 0x01, 0x2e, 0x01, 0x32, 0x01, 0x41, 0x01, 0x36, 0x01, 0x28, 0x01, 0x13, 0x01, 0xff, 0x00, 0xd3, 0x00, 0xb0, 0x00, 0x95, 0x00, 0x87, 0x00, 0x63, 0x00, 0x42, 0x00, 0x17, 0x00, 0xd9, 0xff, 0x9e, 0xff, 0x5d, 0xff, 0x33, 0xff, 0xfe, 0xfe, 0xe3, 0xfe, 0xd3, 0xfe, 0xad, 0xfe, 0xab, 0xfe, 0x85, 0xfe, 0x86, 0xfe, 0x70, 0xfe, 0x6b, 0xfe, 0x6c, 0xfe, 0x74, 0xfe, 0x84, 0xfe, 0xa6, 0xfe, 0xc0, 0xfe, 0xde, 0xfe, 0x1d, 0xff, 0x3b, 0xff, 0x5d, 0xff, 0x88, 0xff, 0xa1, 0xff, 0xc8, 0xff, 0xe3, 0xff, 0xf6, 0xff, 0x03, 0x00, 0x16, 0x00, 0x30, 0x00, 0x32, 0x00, 0x3a, 0x00, 0x42, 0x00, 0x3c, 0x00, 0x36, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x38, 0x00, 0x33, 0x00, 0x18, 0x00, 0x17, 0x00, 0xd9, 0xff, 0xd6, 0xff, 0xba, 0xff, 0xab, 0xff, 0xa1, 0xff, 0x91, 0xff, 0x88, 0xff, 0x6e, 0xff, 0x5e, 0xff, 0x6d, 0xff, 0x62, 0xff, 0x72, 0xff, 0x72, 0xff, 0x5d, 0xff, 0x50, 0xff, 0x4a, 0xff, 0x39, 0xff, 0x39, 0xff, 0x4f, 0xff, 0x61, 0xff, 0x72, 0xff, 0x7e, 0xff, 0x7b, 0xff, 0x87, 0xff, 0x7e, 0xff, 0x7e, 0xff, 0x8d, 0xff, 0x96, 0xff, 0xb8, 0xff, 0xd8, 0xff, 0xfa, 0xff, 0x1c, 0x00, 0x41, 0x00, 0x53, 0x00, 0x58, 0x00, 0x5f, 0x00, 0x68, 0x00, 0x67, 0x00, 0x81, 0x00, 0x7c, 0x00, 0x6d, 0x00, 0x77, 0x00, 0x64, 0x00, 0x4b, 0x00, 0x63, 0x00, 0x67, 0x00, 0x6a, 0x00, 0x63, 0x00, 0x49, 0x00, 0x32, 0x00, 0x0b, 0x00, 0xfb, 0xff, 0xe6, 0xff, 0xe5, 0xff, 0xe5, 0xff, 0xd3, 0xff, 0xdd, 0xff, 0xd4, 0xff, 0xc9, 0xff, 0xd6, 0xff, 0xd1, 0xff, 0xcd, 0xff, 0xc7, 0xff, 0xb6, 0xff, 0x9b, 0xff, 0xa0, 0xff, 0x91, 0xff, 0x78, 0xff, 0x73, 0xff, 0x79, 0xff, 0x6a, 0xff, 0x67, 0xff, 0x7e, 0xff, 0x85, 0xff, 0x9a, 0xff, 0xb5, 0xff, 0xb9, 0xff, 0xd1, 0xff, 0xd5, 0xff, 0xd2, 0xff, 0xe6, 0xff, 0xf6, 0xff, 0x0d, 0x00, 0x25, 0x00, 0x40, 0x00, 0x50, 0x00, 0x51, 0x00, 0x5e, 0x00, 0x70, 0x00, 0x72, 0x00, 0x76, 0x00, 0x74, 0x00, 0x6a, 0x00, 0x5f, 0x00, 0x4a, 0x00, 0x3d, 0x00, 0x30, 0x00, 0x29, 0x00, 0x1f, 0x00, 0x15, 0x00, 0x16, 0x00, 0x1f, 0x00, 0x1e, 0x00, 0x20, 0x00, 0x1d, 0x00, 0x2a, 0x00, 0x16, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0xdb, 0xff, 0xd2, 0xff, 0xd5, 0xff, 0xbe, 0xff, 0xb5, 0xff, 0xb7, 0xff, 0xa2, 0xff, 0x87, 0xff, 0x72, 0xff, 0x5e, 0xff, 0x3d, 0xff, 0x35, 0xff, 0x36, 0xff, 0x31, 0xff, 0x3a, 0xff, 0x36, 0xff, 0x4c, 0xff, 0x57, 0xff, 0x66, 0xff, 0x81, 0xff, 0xa3, 0xff, 0xb9, 0xff, 0xd5, 0xff, 0xde, 0xff, 0xcc, 0xff, 0xdc, 0xff, 0xd2, 0xff, 0xe0, 0xff, 0xcf, 0xff, 0xf4, 0xff, 0x02, 0x00, 0x21, 0x00, 0x2e, 0x00, 0x4b, 0x00, 0x5e, 0x00, 0x62, 0x00, 0x72, 0x00, 0x85, 0x00, 0x7f, 0x00, 0x82, 0x00, 0x7c, 0x00, 0x55, 0x00, 0x42, 0x00, 0x21, 0x00, 0x16, 0x00, 0xfa, 0xff, 0xf3, 0xff, 0xe7, 0xff, 0xdf, 0xff, 0xc3, 0xff, 0xbb, 0xff, 0xb4, 0xff, 0xa7, 0xff, 0x98, 0xff, 0x8b, 0xff, 0x9a, 0xff, 0x81, 0xff, 0x8e, 0xff, 0x87, 0xff, 0x97, 0xff, 0x96, 0xff, 0x9b, 0xff, 0x9e, 0xff, 0xb2, 0xff, 0xa7, 0xff, 0xb1, 0xff, 0xb9, 0xff, 0xaa, 0xff, 0xad, 0xff, 0xba, 0xff, 0xc2, 0xff, 0xc0, 0xff, 0xce, 0xff, 0xb6, 0xff, 0xae, 0xff, 0xac, 0xff, 0x87, 0xff, 0x9b, 0xff, 0x9c, 0xff, 0xa0, 0xff, 0xbd, 0xff, 0xc9, 0xff, 0xed, 0xff, 0xff, 0xff, 0x0a, 0x00, 0x1a, 0x00, 0x37, 0x00, 0x3d, 0x00, 0x44, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x53, 0x00, 0x42, 0x00, 0x49, 0x00, 0x45, 0x00, 0x35, 0x00, 0x54, 0x00, 0x51, 0x00, 0x6a, 0x00, 0x55, 0x00, 0x5e, 0x00, 0x3e, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xeb, 0xff, 0xdb, 0xff, 0xcc, 0xff, 0xb3, 0xff, 0x98, 0xff, 0x85, 0xff, 0x72, 0xff, 0x5e, 0xff, 0x4f, 0xff, 0x35, 0xff, 0x22, 0xff, 0x14, 0xff, 0x14, 0xff, 0x1f, 0xff, 0x40, 0xff, 0x4f, 0xff, 0x72, 0xff, 0x81, 0xff, 0x85, 0xff, 0x89, 0xff, 0x85, 0xff, 0x8e, 0xff, 0x86, 0xff, 0x92, 0xff, 0xb4, 0xff, 0xd7, 0xff, 0xf7, 0xff, 0x23, 0x00, 0x49, 0x00, 0x69, 0x00, 0x71, 0x00, 0x8b, 0x00, 0x81, 0x00, 0x81, 0x00, 0x96, 0x00, 0x7b, 0x00, 0x82, 0x00, 0x6a, 0x00, 0x69, 0x00, 0x3d, 0x00, 0x2d, 0x00, 0x13, 0x00, 0xf7, 0xff, 0xe7, 0xff, 0xdb, 0xff, 0xe2, 0xff, 0xd4, 0xff, 0xe0, 0xff, 0xe1, 0xff, 0xee, 0xff, 0xeb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0x05, 0x00, 0xf6, 0xff, 0xf6, 0xff, 0xd7, 0xff, 0xc4, 0xff, 0xbe, 0xff, 0xb7, 0xff, 0xb5, 0xff, 0xac, 0xff, 0xa7, 0xff, 0x95, 0xff, 0x87, 0xff, 0x75, 0xff, 0x6e, 0xff, 0x6e, 0xff, 0x6c, 0xff, 0x6c, 0xff, 0x76, 0xff, 0x86, 0xff, 0x90, 0xff, 0x9f, 0xff, 0xc2, 0xff, 0xd8, 0xff, 0xec, 0xff, 0xfe, 0xff, 0x1b, 0x00, 0x2f, 0x00, 0x29, 0x00, 0x30, 0x00, 0x25, 0x00, 0x35, 0x00, 0x37, 0x00, 0x30, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x07, 0x00, 0x0f, 0x00, 0xfb, 0xff, 0xe2, 0xff, 0xda, 0xff, 0xd0, 0xff, 0xdd, 0xff, 0xd1, 0xff, 0xca, 0xff, 0xca, 0xff, 0xb2, 0xff, 0xa5, 0xff, 0x7f, 0xff, 0x7a, 0xff, 0x73, 0xff, 0x78, 0xff, 0x5d, 0xff, 0x6d, 0xff, 0x6e, 0xff, 0x70, 0xff, 0x66, 0xff, 0x87, 0xff, 0x86, 0xff, 0xa0, 0xff, 0x9a, 0xff, 0xbc, 0xff, 0xbc, 0xff, 0xcf, 0xff, 0xcc, 0xff, 0xd3, 0xff, 0xe1, 0xff, 0xe7, 0xff, 0xe7, 0xff, 0xf1, 0xff, 0xea, 0xff, 0xe5, 0xff, 0xd4, 0xff, 0xcc, 0xff, 0xb7, 0xff, 0xad, 0xff, 0xbb, 0xff, 0xb7, 0xff, 0xb3, 0xff, 0xd0, 0xff, 0xcd, 0xff, 0xde, 0xff, 0xc6, 0xff, 0xe5, 0xff, 0xea, 0xff, 0xf9, 0xff, 0x00, 0x00, 0x2c, 0x00, 0x25, 0x00, 0x53, 0x00, 0x5b, 0x00, 0x81, 0x00, 0x8a, 0x00, 0x9e, 0x00, 0x9f, 0x00, 0x92, 0x00, 0x77, 0x00, 0x69, 0x00, 0x4e, 0x00, 0x3c, 0x00, 0x19, 0x00, 0x08, 0x00, 0xe0, 0xff, 0xc0, 0xff, 0x9c, 0xff, 0x8d, 0xff, 0x6b, 0xff, 0x62, 0xff, 0x52, 0xff, 0x57, 0xff, 0x4d, 0xff, 0x3e, 0xff, 0x4a, 0xff, 0x47, 0xff, 0x66, 0xff, 0x50, 0xff, 0x7a, 0xff, 0x76, 0xff, 0x94, 0xff, 0x96, 0xff, 0x9a, 0xff, 0xba, 0xff, 0xc3, 0xff, 0xd4, 0xff, 0xe5, 0xff, 0xf7, 0xff, 0xfe, 0xff, 0x10, 0x00, 0x10, 0x00, 0x1a, 0x00, 0x1f, 0x00, 0x1a, 0x00, 0x29, 0x00, 0x1b, 0x00, 0x11, 0x00, 0x09, 0x00, 0xf0, 0xff, 0xdc, 0xff, 0xd6, 0xff, 0xc3, 0xff, 0xad, 0xff, 0xbf, 0xff, 0xbb, 0xff, 0xd2, 0xff, 0xc7, 0xff, 0xd0, 0xff, 0xd0, 0xff, 0xcc, 0xff, 0xd3, 0xff, 0xe6, 0xff, 0xdd, 0xff, 0xf1, 0xff, 0xed, 0xff, 0xe0, 0xff, 0xe6, 0xff, 0xde, 0xff, 0xdc, 0xff, 0xcc, 0xff, 0xc5, 0xff, 0xad, 0xff, 0x9e, 0xff, 0xa7, 0xff, 0x94, 0xff, 0xac, 0xff, 0xac, 0xff, 0xc0, 0xff, 0xd8, 0xff, 0xdf, 0xff, 0xec, 0xff, 0xfe, 0xff, 0x0f, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x1a, 0x00, 0x0d, 0x00, 0x07, 0x00, 0x1a, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x0a, 0x00, 0x08, 0x00, 0xf1, 0xff, 0xd5, 0xff, 0xcc, 0xff, 0xc7, 0xff, 0xbc, 0xff, 0xc8, 0xff, 0xd4, 0xff, 0xe9, 0xff, 0xf3, 0xff, 0xf6, 0xff, 0x02, 0x00, 0x0c, 0x00, 0xfe, 0xff, 0x0e, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x22, 0x00, 0x1d, 0x00, 0x2c, 0x00, 0x21, 0x00, 0x27, 0x00, 0x16, 0x00, 0x18, 0x00, 0x18, 0x00, 0x17, 0x00, 0x13, 0x00, 0x0b, 0x00, 0xf8, 0xff, 0xed, 0xff, 0xd9, 0xff, 0xc6, 0xff, 0xca, 0xff, 0xac, 0xff, 0xb5, 0xff, 0x97, 0xff, 0x85, 0xff, 0x81, 0xff, 0x69, 0xff, 0x52, 0xff, 0x46, 0xff, 0x35, 0xff, 0x3c, 0xff, 0x3e, 0xff, 0x4e, 0xff, 0x53, 0xff, 0x4d, 0xff, 0x5c, 0xff, 0x5a, 0xff, 0x66, 0xff, 0x6c, 0xff, 0x7b, 0xff, 0x89, 0xff, 0x9e, 0xff, 0xaa, 0xff, 0xbf, 0xff, 0xea, 0xff, 0xfe, 0xff, 0x2a, 0x00, 0x46, 0x00, 0x6f, 0x00, 0xa2, 0x00, 0xc8, 0x00, 0xfb, 0x00, 0x25, 0x01, 0x49, 0x01, 0x68, 0x01, 0x6b, 0x01, 0x63, 0x01, 0x52, 0x01, 0x2a, 0x01, 0xfc, 0x00, 0xd1, 0x00, 0x97, 0x00, 0x66, 0x00, 0x29, 0x00, 0xf0, 0xff, 0xbd, 0xff, 0x87, 0xff, 0x58, 0xff, 0x39, 0xff, 0x17, 0xff, 0x08, 0xff, 0xf4, 0xfe, 0xe4, 0xfe, 0xd7, 0xfe, 0xd2, 0xfe, 0xcf, 0xfe, 0xe1, 0xfe, 0xe0, 0xfe, 0xf2, 0xfe, 0xf7, 0xfe, 0x03, 0xff, 0x12, 0xff, 0x1c, 0xff, 0x41, 0xff, 0x5c, 0xff, 0x77, 0xff, 0x93, 0xff, 0xa5, 0xff, 0xb4, 0xff, 0xc9, 0xff, 0xd4, 0xff, 0xdc, 0xff, 0xde, 0xff, 0xfe, 0xff, 0x02, 0x00, 0x23, 0x00, 0x2b, 0x00, 0x30, 0x00, 0x39, 0x00, 0x3e, 0x00, 0x37, 0x00, 0x35, 0x00, 0x43, 0x00, 0x36, 0x00, 0x4c, 0x00, 0x44, 0x00, 0x57, 0x00, 0x61, 0x00, 0x6a, 0x00, 0x7c, 0x00, 0x87, 0x00, 0x89, 0x00, 0x8e, 0x00, 0x80, 0x00, 0x68, 0x00, 0x5d, 0x00, 0x37, 0x00, 0x10, 0x00, 0xea, 0xff, 0xc5, 0xff, 0xa5, 0xff, 0x83, 0xff, 0x6c, 0xff, 0x70, 0xff, 0x5c, 0xff, 0x5e, 0xff, 0x53, 0xff, 0x58, 0xff, 0x4a, 0xff, 0x4a, 0xff, 0x4e, 0xff, 0x3a, 0xff, 0x3a, 0xff, 0x34, 0xff, 0x29, 0xff, 0x3b, 0xff, 0x3e, 0xff, 0x5c, 0xff, 0x79, 0xff, 0x86, 0xff, 0xa9, 0xff, 0xc9, 0xff, 0xcf, 0xff, 0xe6, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x10, 0x00, 0x19, 0x00, 0x1d, 0x00, 0x28, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x40, 0x00, 0x58, 0x00, 0x53, 0x00, 0x72, 0x00, 0x62, 0x00, 0x6e, 0x00, 0x7b, 0x00, 0x86, 0x00, 0x7d, 0x00, 0x7c, 0x00, 0x71, 0x00, 0x5b, 0x00, 0x58, 0x00, 0x1b, 0x00, 0x22, 0x00, 0xfe, 0xff, 0x0a, 0x00, 0xed, 0xff, 0x0a, 0x00, 0xe5, 0xff, 0xea, 0xff, 0xd8, 0xff, 0xcd, 0xff, 0xb7, 0xff, 0xa9, 0xff, 0xa8, 0xff, 0x90, 0xff, 0x8b, 0xff, 0x67, 0xff, 0x67, 0xff, 0x4d, 0xff, 0x34, 0xff, 0x38, 0xff, 0x49, 0xff, 0x4a, 0xff, 0x63, 0xff, 0x7b, 0xff, 0x8a, 0xff, 0xa1, 0xff, 0x90, 0xff, 0xa6, 0xff, 0xb0, 0xff, 0xab, 0xff, 0xb8, 0xff, 0xb4, 0xff, 0xb0, 0xff, 0xb9, 0xff, 0xd3, 0xff, 0xb9, 0xff, 0xce, 0xff, 0xc7, 0xff, 0xd1, 0xff, 0xd0, 0xff, 0xca, 0xff, 0xea, 0xff, 0x13, 0x00, 0x32, 0x00, 0x49, 0x00, 0x62, 0x00, 0x63, 0x00, 0x6d, 0x00, 0x52, 0x00, 0x3b, 0x00, 0x3f, 0x00, 0x17, 0x00, 0x21, 0x00, 0x04, 0x00, 0xf2, 0xff, 0xe1, 0xff, 0xc9, 0xff, 0xcc, 0xff, 0xb1, 0xff, 0xb5, 0xff, 0xd1, 0xff, 0xc8, 0xff, 0xda, 0xff, 0xea, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xfa, 0xff, 0xf5, 0xff, 0x10, 0x00, 0xff, 0xff, 0x19, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x4b, 0x00, 0x54, 0x00, 0x62, 0x00, 0x53, 0x00, 0x5c, 0x00, 0x4c, 0x00, 0x39, 0x00, 0x30, 0x00, 0x20, 0x00, 0xff, 0xff, 0xf5, 0xff, 0xe3, 0xff, 0xbf, 0xff, 0x9c, 0xff, 0x85, 0xff, 0x66, 0xff, 0x31, 0xff, 0x23, 0xff, 0x0b, 0xff, 0xf8, 0xfe, 0xf4, 0xfe, 0xdd, 0xfe, 0xe8, 0xfe, 0xd9, 0xfe, 0xdb, 0xfe, 0xe6, 0xfe, 0xf5, 0xfe, 0x05, 0xff, 0x2f, 0xff, 0x47, 0xff, 0x59, 0xff, 0x7f, 0xff, 0x7e, 0xff, 0x8e, 0xff, 0xa0, 0xff, 0xbe, 0xff, 0xc2, 0xff, 0xdc, 0xff, 0xfa, 0xff, 0x1f, 0x00, 0x3f, 0x00, 0x59, 0x00, 0x8c, 0x00, 0xbe, 0x00, 0xdd, 0x00, 0xed, 0x00, 0x13, 0x01, 0x10, 0x01, 0x04, 0x01, 0xf3, 0x00, 0xd8, 0x00, 0xa2, 0x00, 0x8d, 0x00, 0x60, 0x00, 0x3e, 0x00, 0x0b, 0x00, 0xf9, 0xff, 0xd3, 0xff, 0xb7, 0xff, 0x9a, 0xff, 0x96, 0xff, 0x84, 0xff, 0x7d, 0xff, 0x80, 0xff, 0x8b, 0xff, 0xa4, 0xff, 0xb3, 0xff, 0xcd, 0xff, 0xd7, 0xff, 0xe6, 0xff, 0xe5, 0xff, 0xee, 0xff, 0xef, 0xff, 0xee, 0xff, 0xec, 0xff, 0xe2, 0xff, 0xd3, 0xff, 0xd1, 0xff, 0xb7, 0xff, 0xc1, 0xff, 0xb1, 0xff, 0xb6, 0xff, 0xad, 0xff, 0xa4, 0xff, 0xa8, 0xff, 0x9c, 0xff, 0x98, 0xff, 0xa5, 0xff, 0x8e, 0xff, 0x93, 0xff, 0xa1, 0xff, 0x9c, 0xff, 0xa1, 0xff, 0xae, 0xff, 0xac, 0xff, 0xa4, 0xff, 0xa9, 0xff, 0xbb, 0xff, 0xbc, 0xff, 0xd0, 0xff, 0xea, 0xff, 0xdc, 0xff, 0xef, 0xff, 0xf0, 0xff, 0xf2, 0xff, 0x0d, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x0e, 0x00, 0xde, 0xff, 0xf2, 0xff, 0xec, 0xff, 0xe0, 0xff, 0xec, 0xff, 0xed, 0xff, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0xfe, 0xff, 0xe9, 0xff, 0xe7, 0xff, 0xdd, 0xff, 0xd5, 0xff, 0xd0, 0xff, 0xd0, 0xff, 0xb6, 0xff, 0xae, 0xff, 0xa7, 0xff, 0x92, 0xff, 0x98, 0xff, 0x99, 0xff, 0x93, 0xff, 0x9a, 0xff, 0xa1, 0xff, 0x92, 0xff, 0xa1, 0xff, 0xae, 0xff, 0xb6, 0xff, 0xd0, 0xff, 0xe9, 0xff, 0x03, 0x00, 0x21, 0x00, 0x28, 0x00, 0x40, 0x00, 0x53, 0x00, 0x59, 0x00, 0x4a, 0x00, 0x49, 0x00, 0x47, 0x00, 0x20, 0x00, 0x22, 0x00, 0x07, 0x00, 0xfa, 0xff, 0xe1, 0xff, 0xe2, 0xff, 0xcc, 0xff, 0xc4, 0xff, 0xc2, 0xff, 0xc3, 0xff, 0xbf, 0xff, 0xc7, 0xff, 0xd3, 0xff, 0xd0, 0xff, 0xcf, 0xff, 0xdb, 0xff, 0xcb, 0xff, 0xbb, 0xff, 0xbc, 0xff, 0xac, 0xff, 0xb1, 0xff, 0x9a, 0xff, 0x91, 0xff, 0x92, 0xff, 0x96, 0xff, 0x91, 0xff, 0x99, 0xff, 0xbe, 0xff, 0xbb, 0xff, 0xc6, 0xff, 0xd4, 0xff, 0xe3, 0xff, 0xed, 0xff, 0xfe, 0xff, 0x00, 0x00, 0x09, 0x00, 0x08, 0x00, 0x16, 0x00, 0x1e, 0x00, 0x08, 0x00, 0x17, 0x00, 0x15, 0x00, 0x0c, 0x00, 0x0f, 0x00, 0x05, 0x00, 0x11, 0x00, 0x01, 0x00, 0x08, 0x00, 0x1b, 0x00, 0x29, 0x00, 0x49, 0x00, 0x60, 0x00, 0x68, 0x00, 0x68, 0x00, 0x6c, 0x00, 0x4c, 0x00, 0x43, 0x00, 0x39, 0x00, 0x28, 0x00, 0x14, 0x00, 0x0d, 0x00, 0xee, 0xff, 0xf4, 0xff, 0xde, 0xff, 0xdb, 0xff, 0xd3, 0xff, 0xd2, 0xff, 0xbf, 0xff, 0x95, 0xff, 0x73, 0xff, 0x5a, 0xff, 0x32, 0xff, 0x16, 0xff, 0x0f, 0xff, 0x07, 0xff, 0x0b, 0xff, 0x06, 0xff, 0x0b, 0xff, 0x16, 0xff, 0x25, 0xff, 0x30, 0xff, 0x3b, 0xff, 0x47, 0xff, 0x5c, 0xff, 0x5f, 0xff, 0x6a, 0xff, 0x8d, 0xff, 0x97, 0xff, 0xaf, 0xff, 0xc1, 0xff, 0xde, 0xff, 0xee, 0xff, 0xfe, 0xff, 0x0f, 0x00, 0x13, 0x00, 0x16, 0x00, 0x25, 0x00, 0x2a, 0x00, 0x36, 0x00, 0x44, 0x00, 0x49, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x5c, 0x00, 0x63, 0x00, 0x71, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x65, 0x00, 0x56, 0x00, 0x53, 0x00, 0x4d, 0x00, 0x25, 0x00, 0x28, 0x00, 0x08, 0x00, 0xe9, 0xff, 0xd1, 0xff, 0xd4, 0xff, 0xc1, 0xff, 0xb2, 0xff, 0xa5, 0xff, 0x93, 0xff, 0x70, 0xff, 0x75, 0xff, 0x54, 0xff, 0x61, 0xff, 0x6d, 0xff, 0x6a, 0xff, 0x7a, 0xff, 0x69, 0xff, 0x7a, 0xff, 0x83, 0xff, 0x90, 0xff, 0xa0, 0xff, 0xa3, 0xff, 0xbe, 0xff, 0xc5, 0xff, 0xda, 0xff, 0xe6, 0xff, 0xff, 0xff, 0x07, 0x00, 0x29, 0x00, 0x19, 0x00, 0x1f, 0x00, 0x2d, 0x00, 0x0d, 0x00, 0x1f, 0x00, 0x28, 0x00, 0x24, 0x00, 0x36, 0x00, 0x2c, 0x00, 0x33, 0x00, 0x31, 0x00, 0x27, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x01, 0x00, 0xe3, 0xff, 0xbf, 0xff, 0xa5, 0xff, 0xac, 0xff, 0xa5, 0xff, 0xa3, 0xff, 0x93, 0xff, 0x7f, 0xff, 0x64, 0xff, 0x4f, 0xff, 0x39, 0xff, 0x2e, 0xff, 0x41, 0xff, 0x45, 0xff, 0x58, 0xff, 0x63, 0xff, 0x84, 0xff, 0x94, 0xff, 0xbf, 0xff, 0xc2, 0xff, 0xe7, 0xff, 0xfc, 0xff, 0x11, 0x00, 0x2d, 0x00, 0x4d, 0x00, 0x4f, 0x00, 0x58, 0x00, 0x5e, 0x00, 0x5e, 0x00, 0x56, 0x00, 0x64, 0x00, 0x72, 0x00, 0x71, 0x00, 0x78, 0x00, 0x78, 0x00, 0x87, 0x00, 0x7a, 0x00, 0x75, 0x00, 0x7f, 0x00, 0x83, 0x00, 0x82, 0x00, 0x6c, 0x00, 0x68, 0x00, 0x3f, 0x00, 0x20, 0x00, 0x03, 0x00, 0xdc, 0xff, 0xc3, 0xff, 0xb3, 0xff, 0x8c, 0xff, 0x92, 0xff, 0x81, 0xff, 0x82, 0xff, 0x85, 0xff, 0x82, 0xff, 0x8c, 0xff, 0x90, 0xff, 0x87, 0xff, 0xa0, 0xff, 0x8f, 0xff, 0xa0, 0xff, 0xad, 0xff, 0xa0, 0xff, 0xa3, 0xff, 0xb4, 0xff, 0xa5, 0xff, 0x9d, 0xff, 0x99, 0xff, 0x84, 0xff, 0x6e, 0xff, 0x6a, 0xff, 0x63, 0xff, 0x69, 0xff, 0x72, 0xff, 0x6b, 0xff, 0x74, 0xff, 0x73, 0xff, 0x78, 0xff, 0x84, 0xff, 0x9b, 0xff, 0x99, 0xff, 0xb2, 0xff, 0xa6, 0xff, 0xa7, 0xff, 0xae, 0xff, 0xa4, 0xff, 0xbf, 0xff, 0xae, 0xff, 0xca, 0xff, 0xdb, 0xff, 0xfe, 0xff, 0x0e, 0x00, 0x2e, 0x00, 0x3e, 0x00, 0x45, 0x00, 0x42, 0x00, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x3f, 0x00, 0x36, 0x00, 0x59, 0x00, 0x4f, 0x00, 0x6a, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x7d, 0x00, 0x76, 0x00, 0x7c, 0x00, 0x92, 0x00, 0x77, 0x00, 0x81, 0x00, 0x77, 0x00, 0x5e, 0x00, 0x46, 0x00, 0x23, 0x00, 0x12, 0x00, 0xf0, 0xff, 0xde, 0xff, 0xc8, 0xff, 0xa7, 0xff, 0x8a, 0xff, 0x7b, 0xff, 0x65, 0xff, 0x5f, 0xff, 0x5a, 0xff, 0x52, 0xff, 0x4d, 0xff, 0x4f, 0xff, 0x46, 0xff, 0x4c, 0xff, 0x5b, 0xff, 0x56, 0xff, 0x55, 0xff, 0x60, 0xff, 0x5c, 0xff, 0x6e, 0xff, 0x85, 0xff, 0x96, 0xff, 0xb2, 0xff, 0xcc, 0xff, 0xd8, 0xff, 0xeb, 0xff, 0xdb, 0xff, 0xf9, 0xff, 0xed, 0xff, 0xef, 0xff, 0x00, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x1f, 0x00, 0x25, 0x00, 0x1c, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x1e, 0x00, 0x28, 0x00, 0x33, 0x00, 0x43, 0x00, 0x4a, 0x00, 0x52, 0x00, 0x59, 0x00, 0x4e, 0x00, 0x3d, 0x00, 0x10, 0x00, 0xfd, 0xff, 0xd1, 0xff, 0xb0, 0xff, 0x96, 0xff, 0x9b, 0xff, 0x8e, 0xff, 0x96, 0xff, 0x83, 0xff, 0x60, 0xff, 0x5e, 0xff, 0x58, 0xff, 0x46, 0xff, 0x4c, 0xff, 0x4d, 0xff, 0x4d, 0xff, 0x5e, 0xff, 0x55, 0xff, 0x69, 0xff, 0x86, 0xff, 0x9c, 0xff, 0xa4, 0xff, 0xb4, 0xff, 0xc5, 0xff, 0xd4, 0xff, 0xea, 0xff, 0xdd, 0xff, 0x02, 0x00, 0x02, 0x00, 0x22, 0x00, 0x24, 0x00, 0x53, 0x00, 0x5e, 0x00, 0x75, 0x00, 0x88, 0x00, 0x91, 0x00, 0x90, 0x00, 0xa2, 0x00, 0x94, 0x00, 0x7f, 0x00, 0x8c, 0x00, 0x62, 0x00, 0x51, 0x00, 0x37, 0x00, 0x27, 0x00, 0xfe, 0xff, 0xee, 0xff, 0xd8, 0xff, 0xbe, 0xff, 0xaf, 0xff, 0xa2, 0xff, 0x88, 0xff, 0x87, 0xff, 0x71, 0xff, 0x75, 0xff, 0x76, 0xff, 0x81, 0xff, 0x83, 0xff, 0x96, 0xff, 0xab, 0xff, 0xae, 0xff, 0xab, 0xff, 0xbf, 0xff, 0xcc, 0xff, 0xbe, 0xff, 0xc2, 0xff, 0xca, 0xff, 0xc1, 0xff, 0xb8, 0xff, 0xbd, 0xff, 0xb9, 0xff, 0xb7, 0xff, 0x9f, 0xff, 0xa5, 0xff, 0x7f, 0xff, 0x79, 0xff, 0x74, 0xff, 0x64, 0xff, 0x6c, 0xff, 0x6a, 0xff, 0x67, 0xff, 0x7e, 0xff, 0x7c, 0xff, 0x83, 0xff, 0x95, 0xff, 0xa9, 0xff, 0xb1, 0xff, 0xbb, 0xff, 0xc7, 0xff, 0xd6, 0xff, 0xe3, 0xff, 0xf2, 0xff, 0xfe, 0xff, 0x26, 0x00, 0x40, 0x00, 0x6b, 0x00, 0x96, 0x00, 0xb5, 0x00, 0xd6, 0x00, 0xd8, 0x00, 0xe3, 0x00, 0xd2, 0x00, 0xc1, 0x00, 0xb1, 0x00, 0x8f, 0x00, 0x8a, 0x00, 0x67, 0x00, 0x59, 0x00, 0x3c, 0x00, 0x31, 0x00, 0x21, 0x00, 0xf2, 0xff, 0xe4, 0xff, 0xbd, 0xff, 0xa8, 0xff, 0x93, 0xff, 0x84, 0xff, 0x85, 0xff, 0x8a, 0xff, 0x81, 0xff, 0x8a, 0xff, 0x8d, 0xff, 0x8c, 0xff, 0x90, 0xff, 0x9e, 0xff, 0x96, 0xff, 0xab, 0xff, 0x96, 0xff, 0xa2, 0xff, 0xa0, 0xff, 0x8e, 0xff, 0x8c, 0xff, 0x85, 0xff, 0x7d, 0xff, 0x67, 0xff, 0x82, 0xff, 0x53, 0xff, 0x61, 0xff, 0x55, 0xff, 0x5a, 0xff, 0x58, 0xff, 0x66, 0xff, 0x7a, 0xff, 0x84, 0xff, 0x9e, 0xff, 0xa0, 0xff, 0xbb, 0xff, 0xa8, 0xff, 0xb0, 0xff, 0xbd, 0xff, 0xad, 0xff, 0xba, 0xff, 0xc2, 0xff, 0xbc, 0xff, 0xb6, 0xff, 0xc1, 0xff, 0xd1, 0xff, 0xcb, 0xff, 0xd9, 0xff, 0xdf, 0xff, 0xe1, 0xff, 0xdb, 0xff, 0xdb, 0xff, 0xe6, 0xff, 0xf3, 0xff, 0xf9, 0xff, 0x1b, 0x00, 0x2a, 0x00, 0x48, 0x00, 0x4f, 0x00, 0x62, 0x00, 0x58, 0x00, 0x53, 0x00, 0x4c, 0x00, 0x43, 0x00, 0x2d, 0x00, 0x1b, 0x00, 0xf7, 0xff, 0xee, 0xff, 0xe2, 0xff, 0xc8, 0xff, 0xc5, 0xff, 0xab, 0xff, 0xa9, 0xff, 0x98, 0xff, 0x8e, 0xff, 0x95, 0xff, 0xac, 0xff, 0x9d, 0xff, 0xbe, 0xff, 0xc3, 0xff, 0xda, 0xff, 0xf2, 0xff, 0x09, 0x00, 0x0d, 0x00, 0x13, 0x00, 0x05, 0x00, 0x08, 0x00, 0xfc, 0xff, 0x04, 0x00, 0xe2, 0xff, 0xf9, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0x17, 0x00, 0x18, 0x00, 0x39, 0x00, 0x33, 0x00, 0x47, 0x00, 0x4c, 0x00, 0x5a, 0x00, 0x4a, 0x00, 0x4a, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x15, 0x00, 0x0b, 0x00, 0x03, 0x00, 0xdf, 0xff, 0xe8, 0xff, 0xbd, 0xff, 0xbe, 0xff, 0xc0, 0xff, 0xc3, 0xff, 0xbb, 0xff, 0xb9, 0xff, 0xae, 0xff, 0xa7, 0xff, 0x91, 0xff, 0x94, 0xff, 0x90, 0xff, 0x95, 0xff, 0x98, 0xff, 0x89, 0xff, 0x8a, 0xff, 0x72, 0xff, 0x74, 0xff, 0x68, 0xff, 0x5b, 0xff, 0x79, 0xff, 0x7b, 0xff, 0x9b, 0xff, 0xae, 0xff, 0xc5, 0xff, 0xd7, 0xff, 0xf9, 0xff, 0x0a, 0x00, 0x0e, 0x00, 0x37, 0x00, 0x4d, 0x00, 0x5b, 0x00, 0x71, 0x00, 0x7b, 0x00, 0x77, 0x00, 0x77, 0x00, 0x83, 0x00, 0x81, 0x00, 0x84, 0x00, 0x96, 0x00, 0x8f, 0x00, 0x91, 0x00, 0x92, 0x00, 0x90, 0x00, 0x96, 0x00, 0x99, 0x00, 0xa0, 0x00, 0xa5, 0x00, 0xb2, 0x00, 0xa9, 0x00, 0xb8, 0x00, 0x9f, 0x00, 0x9d, 0x00, 0x83, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x45, 0x00, 0x0f, 0x00, 0xf0, 0xff, 0xbe, 0xff, 0x86, 0xff, 0x56, 0xff, 0x47, 0xff, 0x19, 0xff, 0xfe, 0xfe, 0xe4, 0xfe, 0xc9, 0xfe, 0x9f, 0xfe, 0x8a, 0xfe, 0x7b, 0xfe, 0x7a, 0xfe, 0x6e, 0xfe, 0x6c, 0xfe, 0x6c, 0xfe, 0x59, 0xfe, 0x5e, 0xfe, 0x70, 0xfe, 0x81, 0xfe, 0x95, 0xfe, 0xa9, 0xfe, 0xb6, 0xfe, 0xc6, 0xfe, 0xdd, 0xfe, 0x01, 0xff, 0x17, 0xff, 0x40, 0xff, 0x5b, 0xff, 0x7b, 0xff, 0x97, 0xff, 0xaf, 0xff, 0xdf, 0xff, 0xfe, 0xff, 0x22, 0x00, 0x44, 0x00, 0x5e, 0x00, 0x92, 0x00, 0xa7, 0x00, 0xc6, 0x00, 0xe6, 0x00, 0xf9, 0x00, 0x1f, 0x01, 0x2f, 0x01, 0x46, 0x01, 0x45, 0x01, 0x4a, 0x01, 0x2e, 0x01, 0x0f, 0x01, 0xff, 0x00, 0xd9, 0x00, 0xab, 0x00, 0x98, 0x00, 0x61, 0x00, 0x37, 0x00, 0x19, 0x00, 0x04, 0x00, 0xd5, 0xff, 0xc8, 0xff, 0xaf, 0xff, 0xa0, 0xff, 0x97, 0xff, 0x88, 0xff, 0x98, 0xff, 0xa1, 0xff, 0xa8, 0xff, 0xc4, 0xff, 0xc5, 0xff, 0xd9, 0xff, 0xf1, 0xff, 0xf1, 0xff, 0x07, 0x00, 0x23, 0x00, 0x31, 0x00, 0x45, 0x00, 0x3d, 0x00, 0x44, 0x00, 0x33, 0x00, 0x30, 0x00, 0x18, 0x00, 0x13, 0x00, 0x0e, 0x00, 0xee, 0xff, 0xe1, 0xff, 0xc9, 0xff, 0xd2, 0xff, 0xb8, 0xff, 0xb3, 0xff, 0xa8, 0xff, 0x8e, 0xff, 0x7e, 0xff, 0x4e, 0xff, 0x50, 0xff, 0x2a, 0xff, 0x2b, 0xff, 0x1f, 0xff, 0x17, 0xff, 0x30, 0xff, 0x2d, 0xff, 0x53, 0xff, 0x5e, 0xff, 0x80, 0xff, 0x9d, 0xff, 0xc8, 0xff, 0xd3, 0xff, 0xed, 0xff, 0x03, 0x00, 0x08, 0x00, 0xfe, 0xff, 0x19, 0x00, 0x07, 0x00, 0x19, 0x00, 0xf5, 0xff, 0x05, 0x00, 0xe2, 0xff, 0xda, 0xff, 0xde, 0xff, 0xcf, 0xff, 0xe4, 0xff, 0xe7, 0xff, 0xf8, 0xff, 0xf5, 0xff, 0xed, 0xff, 0xfa, 0xff, 0xe7, 0xff, 0xf8, 0xff, 0xfb, 0xff, 0xf7, 0xff, 0xfd, 0xff, 0x10, 0x00, 0x14, 0x00, 0x17, 0x00, 0x26, 0x00, 0x23, 0x00, 0x2a, 0x00, 0x1d, 0x00, 0x1a, 0x00, 0x14, 0x00, 0x16, 0x00, 0xf7, 0xff, 0x01, 0x00, 0xec, 0xff, 0xd9, 0xff, 0xd1, 0xff, 0xbf, 0xff, 0xba, 0xff, 0xa7, 0xff, 0x95, 0xff, 0x91, 0xff, 0x80, 0xff, 0x7f, 0xff, 0x6c, 0xff, 0x68, 0xff, 0x63, 0xff, 0x68, 0xff, 0x4e, 0xff, 0x46, 0xff, 0x48, 0xff, 0x46, 0xff, 0x39, 0xff, 0x53, 0xff, 0x57, 0xff, 0x6d, 0xff, 0x7b, 0xff, 0x80, 0xff, 0x90, 0xff, 0x8d, 0xff, 0x98, 0xff, 0xa1, 0xff, 0xa8, 0xff, 0xc3, 0xff, 0xe0, 0xff, 0x00, 0x00, 0x16, 0x00, 0x28, 0x00, 0x40, 0x00, 0x40, 0x00, 0x3d, 0x00, 0x32, 0x00, 0x24, 0x00, 0x11, 0x00, 0x09, 0x00, 0x0e, 0x00, 0xf5, 0xff, 0x0c, 0x00, 0xfb, 0xff, 0xec, 0xff, 0xec, 0xff, 0xde, 0xff, 0xcb, 0xff, 0xdd, 0xff, 0xdc, 0xff, 0xe4, 0xff, 0xcf, 0xff, 0xd2, 0xff, 0xd6, 0xff, 0xcb, 0xff, 0xc7, 0xff, 0xc9, 0xff, 0xd2, 0xff, 0xe2, 0xff, 0xf7, 0xff, 0xf8, 0xff, 0x08, 0x00, 0x17, 0x00, 0x01, 0x00, 0x06, 0x00, 0xf6, 0xff, 0xef, 0xff, 0xdf, 0xff, 0xf0, 0xff, 0xe7, 0xff, 0x03, 0x00, 0xff, 0xff, 0x23, 0x00, 0x22, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x48, 0x00, 0x4f, 0x00, 0x5c, 0x00, 0x53, 0x00, 0x61, 0x00, 0x58, 0x00, 0x51, 0x00, 0x4c, 0x00, 0x22, 0x00, 0x1e, 0x00, 0xf2, 0xff, 0xec, 0xff, 0xc5, 0xff, 0xc1, 0xff, 0x9b, 0xff, 0x9a, 0xff, 0x7e, 0xff, 0x82, 0xff, 0x7c, 0xff, 0x8a, 0xff, 0x96, 0xff, 0x98, 0xff, 0x96, 0xff, 0x92, 0xff, 0x82, 0xff, 0x79, 0xff, 0x6a, 0xff, 0x55, 0xff, 0x5f, 0xff, 0x58, 0xff, 0x60, 0xff, 0x6f, 0xff, 0x77, 0xff, 0x91, 0xff, 0x92, 0xff, 0xb4, 0xff, 0xc6, 0xff, 0xd3, 0xff, 0xf4, 0xff, 0x1f, 0x00, 0x37, 0x00, 0x4b, 0x00, 0x61, 0x00, 0x6a, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6a, 0x00, 0x73, 0x00, 0x5e, 0x00, 0x5c, 0x00, 0x60, 0x00, 0x40, 0x00, 0x55, 0x00, 0x3a, 0x00, 0x50, 0x00, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00, 0x46, 0x00, 0x31, 0x00, 0x1e, 0x00, 0x08, 0x00, 0xe0, 0xff, 0xcc, 0xff, 0xb8, 0xff, 0x9f, 0xff, 0x93, 0xff, 0x97, 0xff, 0x95, 0xff, 0x95, 0xff, 0x96, 0xff, 0xa3, 0xff, 0x9d, 0xff, 0x92, 0xff, 0xa0, 0xff, 0x88, 0xff, 0x89, 0xff, 0x6f, 0xff, 0x75, 0xff, 0x55, 0xff, 0x64, 0xff, 0x53, 0xff, 0x5e, 0xff, 0x56, 0xff, 0x5a, 0xff, 0x62, 0xff, 0x46, 0xff, 0x52, 0xff, 0x69, 0xff, 0x5c, 0xff, 0x79, 0xff, 0x8b, 0xff, 0x90, 0xff, 0x9f, 0xff, 0xa8, 0xff, 0xb1, 0xff, 0xca, 0xff, 0xdb, 0xff, 0xe7, 0xff, 0xf9, 0xff, 0xe4, 0xff, 0xfe, 0xff, 0xeb, 0xff, 0xf0, 0xff, 0xf0, 0xff, 0xf3, 0xff, 0x09, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x1c, 0x00, 0x2d, 0x00, 0x22, 0x00, 0x32, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x46, 0x00, 0x47, 0x00, 0x53, 0x00, 0x48, 0x00, 0x57, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x3f, 0x00, 0x45, 0x00, 0x4d, 0x00, 0x59, 0x00, 0x5c, 0x00, 0x60, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x55, 0x00, 0x44, 0x00, 0x3b, 0x00, 0x0b, 0x00, 0xf4, 0xff, 0xc7, 0xff, 0x9b, 0xff, 0x7c, 0xff, 0x5d, 0xff, 0x45, 0xff, 0x2e, 0xff, 0x20, 0xff, 0x06, 0xff, 0xfb, 0xfe, 0xf3, 0xfe, 0xd9, 0xfe, 0xdf, 0xfe, 0xde, 0xfe, 0xe3, 0xfe, 0xdf, 0xfe, 0xe2, 0xfe, 0xfe, 0xfe, 0x18, 0xff, 0x2e, 0xff, 0x47, 0xff, 0x5f, 0xff, 0x76, 0xff, 0x96, 0xff, 0x9e, 0xff, 0xbb, 0xff, 0xe4, 0xff, 0x02, 0x00, 0x18, 0x00, 0x26, 0x00, 0x47, 0x00, 0x52, 0x00, 0x64, 0x00, 0x73, 0x00, 0x94, 0x00, 0x96, 0x00, 0xa1, 0x00, 0x96, 0x00, 0x96, 0x00, 0x8b, 0x00, 0x8a, 0x00, 0x6c, 0x00, 0x77, 0x00, 0x5b, 0x00, 0x54, 0x00, 0x3a, 0x00, 0x19, 0x00, 0x18, 0x00, 0xff, 0xff, 0x01, 0x00, 0xf8, 0xff, 0xf6, 0xff, 0xf8, 0xff, 0xeb, 0xff, 0xe6, 0xff, 0xe5, 0xff, 0xd7, 0xff, 0xe9, 0xff, 0xf6, 0xff, 0xf4, 0xff, 0xec, 0xff, 0xf3, 0xff, 0xd0, 0xff, 0xc0, 0xff, 0xb0, 0xff, 0x95, 0xff, 0x89, 0xff, 0x88, 0xff, 0x6c, 0xff, 0x70, 0xff, 0x68, 0xff, 0x6b, 0xff, 0x75, 0xff, 0x91, 0xff, 0x9d, 0xff, 0xb1, 0xff, 0xad, 0xff, 0xaf, 0xff, 0xb9, 0xff, 0x9d, 0xff, 0x9f, 0xff, 0xa0, 0xff, 0x9e, 0xff, 0xa2, 0xff, 0xa4, 0xff, 0xad, 0xff, 0x9c, 0xff, 0xa3, 0xff, 0xaa, 0xff, 0xb5, 0xff, 0xa4, 0xff, 0xc6, 0xff, 0xbd, 0xff, 0xd8, 0xff, 0xd3, 0xff, 0xda, 0xff, 0xeb, 0xff, 0xdd, 0xff, 0xf6, 0xff, 0xec, 0xff, 0xfc, 0xff, 0x0a, 0x00, 0x2f, 0x00, 0x29, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x6f, 0x00, 0x78, 0x00, 0x6a, 0x00, 0x8a, 0x00, 0x7b, 0x00, 0x76, 0x00, 0x70, 0x00, 0x64, 0x00, 0x38, 0x00, 0x2b, 0x00, 0xfd, 0xff, 0xdc, 0xff, 0xc8, 0xff, 0xc1, 0xff, 0xac, 0xff, 0x9e, 0xff, 0x96, 0xff, 0x8d, 0xff, 0x87, 0xff, 0x75, 0xff, 0x85, 0xff, 0xa1, 0xff, 0xaf, 0xff, 0xbc, 0xff, 0xcd, 0xff, 0xe4, 0xff, 0xe5, 0xff, 0xea, 0xff, 0xed, 0xff, 0xe2, 0xff, 0xf6, 0xff, 0xfa, 0xff, 0xe7, 0xff, 0xfd, 0xff, 0xdf, 0xff, 0xf3, 0xff, 0xda, 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xf0, 0xff, 0xf1, 0xff, 0xf6, 0xff, 0xfa, 0xff, 0x07, 0x00, 0x11, 0x00, 0xff, 0xff, 0x13, 0x00, 0x13, 0x00, 0x1f, 0x00, 0x0c, 0x00, 0x09, 0x00, 0x02, 0x00, 0xe4, 0xff, 0xcf, 0xff, 0xb2, 0xff, 0xa3, 0xff, 0x8d, 0xff, 0x8d, 0xff, 0x7e, 0xff, 0x6e, 0xff, 0x7c, 0xff, 0x79, 0xff, 0x84, 0xff, 0x81, 0xff, 0x9f, 0xff, 0x9b, 0xff, 0xad, 0xff, 0xac, 0xff, 0xb7, 0xff, 0xc1, 0xff, 0xba, 0xff, 0xbc, 0xff, 0xe0, 0xff, 0xd6, 0xff, 0xe6, 0xff, 0xed, 0xff, 0xfe, 0xff, 0xed, 0xff, 0xef, 0xff, 0xe8, 0xff, 0xd4, 0xff, 0xc9, 0xff, 0xbc, 0xff, 0xaf, 0xff, 0xb9, 0xff, 0xb3, 0xff, 0xae, 0xff, 0xd0, 0xff, 0xcb, 0xff, 0xe2, 0xff, 0xdd, 0xff, 0xea, 0xff, 0xdf, 0xff, 0xe7, 0xff, 0xe3, 0xff, 0xd9, 0xff, 0xda, 0xff, 0xdf, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xd8, 0xff, 0xe2, 0xff, 0xe3, 0xff, 0xf5, 0xff, 0xe0, 0xff, 0xf3, 0xff, 0xfa, 0xff, 0xf7, 0xff, 0x02, 0x00, 0x10, 0x00, 0x25, 0x00, 0x35, 0x00, 0x35, 0x00, 0x5b, 0x00, 0x5e, 0x00, 0x6a, 0x00, 0x7e, 0x00, 0x8c, 0x00, 0x92, 0x00, 0x92, 0x00, 0x94, 0x00, 0x78, 0x00, 0x6c, 0x00, 0x3c, 0x00, 0x38, 0x00, 0xfe, 0xff, 0xeb, 0xff, 0xc4, 0xff, 0xb5, 0xff, 0x95, 0xff, 0x8d, 0xff, 0x8e, 0xff, 0x73, 0xff, 0x6a, 0xff, 0x70, 0xff, 0x58, 0xff, 0x53, 0xff, 0x57, 0xff, 0x49, 0xff, 0x57, 0xff, 0x65, 0xff, 0x71, 0xff, 0x7f, 0xff, 0x7d, 0xff, 0x97, 0xff, 0x9a, 0xff, 0x95, 0xff, 0xb3, 0xff, 0xbe, 0xff, 0xc8, 0xff, 0xdd, 0xff, 0xe0, 0xff, 0xd6, 0xff, 0xda, 0xff, 0xdc, 0xff, 0xbc, 0xff, 0xd0, 0xff, 0xbf, 0xff, 0xb1, 0xff, 0xa9, 0xff, 0xaa, 0xff, 0xb0, 0xff, 0xb9, 0xff, 0xb9, 0xff, 0xbd, 0xff, 0xb1, 0xff, 0xaf, 0xff, 0xad, 0xff, 0xad, 0xff, 0xc2, 0xff, 0xb9, 0xff, 0xd4, 0xff, 0xd3, 0xff, 0xd9, 0xff, 0xf4, 0xff, 0x17, 0x00, 0x22, 0x00, 0x3b, 0x00, 0x44, 0x00, 0x3c, 0x00, 0x4d, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x39, 0x00, 0x32, 0x00, 0x28, 0x00, 0x19, 0x00, 0x16, 0x00, 0x05, 0x00, 0xf6, 0xff, 0xf8, 0xff, 0xe4, 0xff, 0xd5, 0xff, 0xd9, 0xff, 0xe6, 0xff, 0xe3, 0xff, 0xed, 0xff, 0xfd, 0xff, 0x08, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x42, 0x00, 0x65, 0x00, 0x82, 0x00, 0x92, 0x00, 0xa6, 0x00, 0xb1, 0x00, 0xc6, 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb0, 0x00, 0x99, 0x00, 0x81, 0x00, 0x77, 0x00, 0x5c, 0x00, 0x45, 0x00, 0x1d, 0x00, 0x04, 0x00, 0xe2, 0xff, 0xb2, 0xff, 0x93, 0xff, 0x6e, 0xff, 0x56, 0xff, 0x29, 0xff, 0x26, 0xff, 0x09, 0xff, 0xfe, 0xfe, 0xed, 0xfe, 0xe2, 0xfe, 0xd2, 0xfe, 0xc4, 0xfe, 0xca, 0xfe, 0xc0, 0xfe, 0xcc, 0xfe, 0xdd, 0xfe, 0xec, 0xfe, 0x0c, 0xff, 0x24, 0xff, 0x30, 0xff, 0x4c, 0xff, 0x63, 0xff, 0x6f, 0xff, 0x6e, 0xff, 0x83, 0xff, 0x8b, 0xff, 0x8b, 0xff, 0xa2, 0xff, 0xb1, 0xff, 0xc2, 0xff, 0xda, 0xff, 0xf8, 0xff, 0x0e, 0x00, 0x14, 0x00, 0x1f, 0x00, 0x25, 0x00, 0x25, 0x00, 0x26, 0x00, 0x39, 0x00, 0x43, 0x00, 0x5e, 0x00, 0x59, 0x00, 0x71, 0x00, 0x70, 0x00, 0x77, 0x00, 0x7f, 0x00, 0x78, 0x00, 0x7c, 0x00, 0x7a, 0x00, 0x67, 0x00, 0x5a, 0x00, 0x40, 0x00, 0x37, 0x00, 0x07, 0x00, 0xf4, 0xff, 0xdd, 0xff, 0xb7, 0xff, 0xac, 0xff, 0x9b, 0xff, 0x9d, 0xff, 0x77, 0xff, 0x7e, 0xff, 0x80, 0xff, 0x92, 0xff, 0x91, 0xff, 0xa9, 0xff, 0xb6, 0xff, 0xbc, 0xff, 0xb5, 0xff, 0xbd, 0xff, 0xae, 0xff, 0xaa, 0xff, 0x9e, 0xff, 0x8d, 0xff, 0xa0, 0xff, 0x91, 0xff, 0xa0, 0xff, 0xa1, 0xff, 0xa3, 0xff, 0xa5, 0xff, 0x99, 0xff, 0xa3, 0xff, 0x9f, 0xff, 0xa8, 0xff, 0xb5, 0xff, 0xbd, 0xff, 0xb2, 0xff, 0xcf, 0xff, 0xdb, 0xff, 0xe3, 0xff, 0xeb, 0xff, 0xeb, 0xff, 0xf1, 0xff, 0xf5, 0xff, 0xe8, 0xff, 0xfd, 0xff, 0xfa, 0xff, 0x03, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x1c, 0x00, 0x11, 0x00, 0x18, 0x00, 0x04, 0x00, 0x06, 0x00, 0xf1, 0xff, 0xfc, 0xff, 0x01, 0x00, 0xfa, 0xff, 0x0b, 0x00, 0x16, 0x00, 0x13, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x1a, 0x00, 0x2c, 0x00, 0x3d, 0x00, 0x52, 0x00, 0x61, 0x00, 0x5d, 0x00, 0x49, 0x00, 0x3e, 0x00, 0x30, 0x00, 0x09, 0x00, 0xff, 0xff, 0xef, 0xff, 0xe1, 0xff, 0xdf, 0xff, 0xc6, 0xff, 0xc2, 0xff, 0xb0, 0xff, 0x9d, 0xff, 0x86, 0xff, 0x73, 0xff, 0x6d, 0xff, 0x6e, 0xff, 0x73, 0xff, 0x7a, 0xff, 0x8d, 0xff, 0x9c, 0xff, 0xb3, 0xff, 0xad, 0xff, 0xc4, 0xff, 0xde, 0xff, 0xdd, 0xff, 0xe9, 0xff, 0xf5, 0xff, 0x03, 0x00, 0x02, 0x00, 0xf2, 0xff, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00, 0xf9, 0xff, 0xfb, 0xff, 0xe6, 0xff, 0xd7, 0xff, 0xca, 0xff, 0xc5, 0xff, 0xa4, 0xff, 0xaa, 0xff, 0x98, 0xff, 0x85, 0xff, 0x7d, 0xff, 0x80, 0xff, 0x78, 0xff, 0x7c, 0xff, 0x7d, 0xff, 0x88, 0xff, 0x96, 0xff, 0xb2, 0xff, 0xb3, 0xff, 0xce, 0xff, 0xdd, 0xff, 0xde, 0xff, 0xed, 0xff, 0xf7, 0xff, 0xf9, 0xff, 0x08, 0x00, 0x09, 0x00, 0x16, 0x00, 0x06, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x16, 0x00, 0x09, 0x00, 0x23, 0x00, 0x1c, 0x00, 0x2a, 0x00, 0x1c, 0x00, 0x1d, 0x00, 0x24, 0x00, 0x09, 0x00, 0x15, 0x00, 0x0d, 0x00, 0x21, 0x00, 0x0c, 0x00, 0x1e, 0x00, 0x09, 0x00, 0x05, 0x00, 0xf3, 0xff, 0xdf, 0xff, 0xca, 0xff, 0xdf, 0xff, 0xd4, 0xff, 0xcc, 0xff, 0xd0, 0xff, 0xd8, 0xff, 0xdc, 0xff, 0xcb, 0xff, 0xdd, 0xff, 0xdc, 0xff, 0xe0, 0xff, 0xd4, 0xff, 0xd5, 0xff, 0xc1, 0xff, 0xb5, 0xff, 0xae, 0xff, 0x8b, 0xff, 0x98, 0xff, 0x79, 0xff, 0x74, 0xff, 0x64, 0xff, 0x63, 0xff, 0x63, 0xff, 0x6f, 0xff, 0x72, 0xff, 0x68, 0xff, 0x6d, 0xff, 0x66, 0xff, 0x68, 0xff, 0x73, 0xff, 0x79, 0xff, 0x94, 0xff, 0x9e, 0xff, 0xb2, 0xff, 0xcd, 0xff, 0xd3, 0xff, 0xea, 0xff, 0xe9, 0xff, 0xfb, 0xff, 0xeb, 0xff, 0xfc, 0xff, 0x10, 0x00, 0x0f, 0x00, 0x20, 0x00, 0x39, 0x00, 0x39, 0x00, 0x4f, 0x00, 0x44, 0x00, 0x51, 0x00, 0x45, 0x00, 0x3f, 0x00, 0x39, 0x00, 0x37, 0x00, 0x38, 0x00, 0x40, 0x00, 0x35, 0x00, 0x28, 0x00, 0x29, 0x00, 0x09, 0x00, 0xf6, 0xff, 0xe8, 0xff, 0xcf, 0xff, 0xcd, 0xff, 0xc2, 0xff, 0xcf, 0xff, 0xc3, 0xff, 0xcd, 0xff, 0xd0, 0xff, 0xcc, 0xff, 0xc9, 0xff, 0xbe, 0xff, 0xb3, 0xff, 0xbb, 0xff, 0xb7, 0xff, 0xa6, 0xff, 0xb7, 0xff, 0xaf, 0xff, 0xc2, 0xff, 0xb7, 0xff, 0xc3, 0xff, 0xd6, 0xff, 0xc8, 0xff, 0xdf, 0xff, 0xf9, 0xff, 0xfe, 0xff, 0x1a, 0x00, 0x2d, 0x00, 0x3b, 0x00, 0x50, 0x00, 0x56, 0x00, 0x54, 0x00, 0x60, 0x00, 0x56, 0x00, 0x58, 0x00, 0x34, 0x00, 0x22, 0x00, 0x11, 0x00, 0xfe, 0xff, 0xe8, 0xff, 0xd5, 0xff, 0xd1, 0xff, 0xcc, 0xff, 0xb6, 0xff, 0xb0, 0xff, 0xb7, 0xff, 0xb4, 0xff, 0xb6, 0xff, 0xad, 0xff, 0x9c, 0xff, 0x9c, 0xff, 0x86, 0xff, 0x70, 0xff, 0x74, 0xff, 0x6f, 0xff, 0x6b, 0xff, 0x62, 0xff, 0x6a, 0xff, 0x85, 0xff, 0x86, 0xff, 0xae, 0xff, 0xb2, 0xff, 0xd3, 0xff, 0xd8, 0xff, 0xdf, 0xff, 0xe0, 0xff, 0xe9, 0xff, 0xfc, 0xff, 0xf5, 0xff, 0x18, 0x00, 0x22, 0x00, 0x2e, 0x00, 0x3c, 0x00, 0x30, 0x00, 0x46, 0x00, 0x48, 0x00, 0x50, 0x00, 0x4b, 0x00, 0x5c, 0x00, 0x63, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x51, 0x00, 0x36, 0x00, 0x21, 0x00, 0x20, 0x00, 0xe7, 0xff, 0xd5, 0xff, 0xc5, 0xff, 0xa9, 0xff, 0x9c, 0xff, 0x91, 0xff, 0x84, 0xff, 0x60, 0xff, 0x5a, 0xff, 0x47, 0xff, 0x4d, 0xff, 0x5b, 0xff, 0x5a, 0xff, 0x73, 0xff, 0x7e, 0xff, 0xa1, 0xff, 0x9f, 0xff, 0xbe, 0xff, 0xd4, 0xff, 0xed, 0xff, 0x07, 0x00, 0x16, 0x00, 0x37, 0x00, 0x4e, 0x00, 0x5a, 0x00, 0x6a, 0x00, 0x81, 0x00, 0x8a, 0x00, 0x9c, 0x00, 0xa0, 0x00, 0xaa, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0x94, 0x00, 0x87, 0x00, 0x6b, 0x00, 0x38, 0x00, 0x12, 0x00, 0xf1, 0xff, 0xd3, 0xff, 0x93, 0xff, 0x80, 0xff, 0x50, 0xff, 0x30, 0xff, 0x0b, 0xff, 0xfd, 0xfe, 0xeb, 0xfe, 0xeb, 0xfe, 0xee, 0xfe, 0xe2, 0xfe, 0xea, 0xfe, 0xf5, 0xfe, 0xfc, 0xfe, 0x08, 0xff, 0x2a, 0xff, 0x36, 0xff, 0x3b, 0xff, 0x5d, 0xff, 0x5f, 0xff, 0x70, 0xff, 0x7e, 0xff, 0x8a, 0xff, 0x9a, 0xff, 0x96, 0xff, 0xae, 0xff, 0xb6, 0xff, 0xb9, 0xff, 0xd0, 0xff, 0xdc, 0xff, 0xec, 0xff, 0xee, 0xff, 0x05, 0x00, 0x18, 0x00, 0x2c, 0x00, 0x2b, 0x00, 0x55, 0x00, 0x3f, 0x00, 0x54, 0x00, 0x45, 0x00, 0x3e, 0x00, 0x41, 0x00, 0x30, 0x00, 0x3d, 0x00, 0x28, 0x00, 0x37, 0x00, 0x22, 0x00, 0x27, 0x00, 0x2b, 0x00, 0x1b, 0x00, 0x1b, 0x00, 0x13, 0x00, 0x19, 0x00, 0x07, 0x00, 0xfb, 0xff, 0xee, 0xff, 0xda, 0xff, 0xc1, 0xff, 0xb3, 0xff, 0xa9, 0xff, 0xaf, 0xff, 0x9e, 0xff, 0xa3, 0xff, 0xa7, 0xff, 0x9b, 0xff, 0x91, 0xff, 0x8b, 0xff, 0x94, 0xff, 0x8b, 0xff, 0x89, 0xff, 0x9a, 0xff, 0x7c, 0xff, 0x83, 0xff, 0x88, 0xff, 0x86, 0xff, 0x8f, 0xff, 0x8c, 0xff, 0xa5, 0xff, 0x9d, 0xff, 0xa7, 0xff, 0xbb, 0xff, 0xcd, 0xff, 0xe2, 0xff, 0xfb, 0xff, 0x11, 0x00, 0x2a, 0x00, 0x28, 0x00, 0x3f, 0x00, 0x4f, 0x00, 0x57, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x71, 0x00, 0x7e, 0x00, 0x77, 0x00, 0x66, 0x00, 0x63, 0x00, 0x49, 0x00, 0x29, 0x00, 0x26, 0x00, 0x09, 0x00, 0xe3, 0xff, 0xe8, 0xff, 0xc8, 0xff, 0xc0, 0xff, 0xb2, 0xff, 0xad, 0xff, 0xa2, 0xff, 0x90, 0xff, 0x91, 0xff, 0x90, 0xff, 0x96, 0xff, 0x95, 0xff, 0xa1, 0xff, 0xa7, 0xff, 0x93, 0xff, 0xa9, 0xff, 0xa8, 0xff, 0x94, 0xff, 0xb3, 0xff, 0x9a, 0xff, 0xa8, 0xff, 0xac, 0xff, 0xbd, 0xff, 0xc8, 0xff, 0xda, 0xff, 0xe5, 0xff, 0xeb, 0xff, 0xf2, 0xff, 0xe8, 0xff, 0xea, 0xff, 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x2b, 0x00, 0x34, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x3c, 0x00, 0x2e, 0x00, 0x39, 0x00, 0x1e, 0x00, 0x20, 0x00, 0x02, 0x00, 0xe7, 0xff, 0xdf, 0xff, 0xcb, 0xff, 0xb2, 0xff, 0xaf, 0xff, 0xa1, 0xff, 0x9a, 0xff, 0xa0, 0xff, 0x9d, 0xff, 0x90, 0xff, 0x9c, 0xff, 0x83, 0xff, 0x8f, 0xff, 0x7f, 0xff, 0x74, 0xff, 0x8b, 0xff, 0xa9, 0xff, 0xaa, 0xff, 0xc3, 0xff, 0xc3, 0xff, 0xd6, 0xff, 0xc7, 0xff, 0xd1, 0xff, 0xd2, 0xff, 0xe2, 0xff, 0xfc, 0xff, 0x0d, 0x00, 0x17, 0x00, 0x38, 0x00, 0x41, 0x00, 0x45, 0x00, 0x5b, 0x00, 0x69, 0x00, 0x6b, 0x00, 0x6a, 0x00, 0x62, 0x00, 0x56, 0x00, 0x38, 0x00, 0x2d, 0x00, 0x0b, 0x00, 0xfe, 0xff, 0xeb, 0xff, 0xd7, 0xff, 0xcb, 0xff, 0xab, 0xff, 0xac, 0xff, 0xa7, 0xff, 0xa4, 0xff, 0x8c, 0xff, 0x8c, 0xff, 0x87, 0xff, 0x80, 0xff, 0x77, 0xff, 0x82, 0xff, 0x88, 0xff, 0x89, 0xff, 0x89, 0xff, 0x94, 0xff, 0x9a, 0xff, 0x95, 0xff, 0xb0, 0xff, 0x9f, 0xff, 0xaf, 0xff, 0xc1, 0xff, 0xc1, 0xff, 0xca, 0xff, 0xe4, 0xff, 0xf7, 0xff, 0xf4, 0xff, 0xff, 0xff, 0x05, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x2b, 0x00, 0x2e, 0x00, 0x24, 0x00, 0x28, 0x00, 0x28, 0x00, 0x17, 0x00, 0x17, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0xf3, 0xff, 0xf7, 0xff, 0xe9, 0xff, 0xf1, 0xff, 0xe1, 0xff, 0xee, 0xff, 0xe6, 0xff, 0xf8, 0xff, 0xf2, 0xff, 0xe9, 0xff, 0x00, 0x00, 0x01, 0x00, 0xf3, 0xff, 0x03, 0x00, 0xff, 0xff, 0x0a, 0x00, 0xf3, 0xff, 0x04, 0x00, 0xfb, 0xff, 0x00, 0x00, 0xe9, 0xff, 0xec, 0xff, 0xd9, 0xff, 0xd9, 0xff, 0xce, 0xff, 0xc6, 0xff, 0xca, 0xff, 0xbf, 0xff, 0xb6, 0xff, 0xaf, 0xff, 0xaf, 0xff, 0x95, 0xff, 0x96, 0xff, 0x9a, 0xff, 0x91, 0xff, 0x94, 0xff, 0x90, 0xff, 0x93, 0xff, 0xa3, 0xff, 0x83, 0xff, 0x94, 0xff, 0x8a, 0xff, 0x75, 0xff, 0x7a, 0xff, 0x85, 0xff, 0x75, 0xff, 0x79, 0xff, 0x7c, 0xff, 0x7d, 0xff, 0x69, 0xff, 0x84, 0xff, 0x67, 0xff, 0x6b, 0xff, 0x82, 0xff, 0x88, 0xff, 0x94, 0xff, 0xa2, 0xff, 0xb8, 0xff, 0xd6, 0xff, 0xf7, 0xff, 0xfe, 0xff, 0x27, 0x00, 0x42, 0x00, 0x67, 0x00, 0x71, 0x00, 0x7b, 0x00, 0x87, 0x00, 0x95, 0x00, 0x84, 0x00, 0x84, 0x00, 0x73, 0x00, 0x6b, 0x00, 0x54, 0x00, 0x3c, 0x00, 0x28, 0x00, 0x13, 0x00, 0x00, 0x00, 0xf1, 0xff, 0xda, 0xff, 0xcd, 0xff, 0xc1, 0xff, 0xb7, 0xff, 0xa3, 0xff, 0x9b, 0xff, 0x96, 0xff, 0x7c, 0xff, 0x98, 0xff, 0x70, 0xff, 0x6c, 0xff, 0x7f, 0xff, 0x6c, 0xff, 0x6f, 0xff, 0x8b, 0xff, 0x94, 0xff, 0x9f, 0xff, 0x9f, 0xff, 0xa4, 0xff, 0xb9, 0xff, 0xae, 0xff, 0xc7, 0xff, 0xd3, 0xff, 0xf1, 0xff, 0xfc, 0xff, 0x16, 0x00, 0x20, 0x00, 0x1d, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x37, 0x00, 0x47, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x46, 0x00, 0x3f, 0x00, 0x32, 0x00, 0x29, 0x00, 0x16, 0x00, 0x12, 0x00, 0x03, 0x00, 0xf0, 0xff, 0xdc, 0xff, 0xdf, 0xff, 0xd1, 0xff, 0xc0, 0xff, 0xc8, 0xff, 0x9f, 0xff, 0xa6, 0xff, 0x8b, 0xff, 0x8d, 0xff, 0x84, 0xff, 0x8d, 0xff, 0x96, 0xff, 0xaa, 0xff, 0xab, 0xff, 0xc6, 0xff, 0xca, 0xff, 0xd6, 0xff, 0xe9, 0xff, 0xe7, 0xff, 0xe6, 0xff, 0xf4, 0xff, 0xf7, 0xff, 0xf9, 0xff, 0xf6, 0xff, 0x03, 0x00, 0xfc, 0xff, 0x1a, 0x00, 0x0c, 0x00, 0x2c, 0x00, 0x2e, 0x00, 0x53, 0x00, 0x66, 0x00, 0x87, 0x00, 0x99, 0x00, 0xaf, 0x00, 0xaa, 0x00, 0xa7, 0x00, 0x95, 0x00, 0x7c, 0x00, 0x4e, 0x00, 0x36, 0x00, 0x03, 0x00, 0xe6, 0xff, 0xc4, 0xff, 0xa9, 0xff, 0x99, 0xff, 0x76, 0xff, 0x69, 0xff, 0x45, 0xff, 0x3a, 0xff, 0x1f, 0xff, 0x0f, 0xff, 0x1b, 0xff, 0x1f, 0xff, 0x1c, 0xff, 0x1c, 0xff, 0x29, 0xff, 0x32, 0xff, 0x34, 0xff, 0x43, 0xff, 0x36, 0xff, 0x4b, 0xff, 0x64, 0xff, 0x73, 0xff, 0x85, 0xff, 0x9e, 0xff, 0xbc, 0xff, 0xd8, 0xff, 0xd8, 0xff, 0xf7, 0xff, 0xef, 0xff, 0xff, 0xff, 0x01, 0x00, 0x0c, 0x00, 0x0a, 0x00, 0x1b, 0x00, 0x25, 0x00, 0x31, 0x00, 0x39, 0x00, 0x40, 0x00, 0x3e, 0x00, 0x4a, 0x00, 0x30, 0x00, 0x29, 0x00, 0x27, 0x00, 0x14, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xef, 0xff, 0xe5, 0xff, 0xd5, 0xff, 0xce, 0xff, 0xb1, 0xff, 0xb7, 0xff, 0xa1, 0xff, 0x9a, 0xff, 0xa2, 0xff, 0x8b, 0xff, 0x93, 0xff, 0x9d, 0xff, 0xa0, 0xff, 0xad, 0xff, 0xaf, 0xff, 0xc0, 0xff, 0xc4, 0xff, 0xbd, 0xff, 0xbb, 0xff, 0xd3, 0xff, 0xdb, 0xff, 0xeb, 0xff, 0xf3, 0xff, 0x02, 0x00, 0x20, 0x00, 0x29, 0x00, 0x25, 0x00, 0x41, 0x00, 0x44, 0x00, 0x50, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x22, 0x00, 0x18, 0x00, 0x13, 0x00, 0x01, 0x00, 0xf9, 0xff, 0xe9, 0xff, 0xdc, 0xff, 0xc5, 0xff, 0xc3, 0xff, 0xb3, 0xff, 0xaa, 0xff, 0xa2, 0xff, 0x9e, 0xff, 0x91, 0xff, 0x97, 0xff, 0x8f, 0xff, 0x87, 0xff, 0x9b, 0xff, 0x8c, 0xff, 0x8c, 0xff, 0x9a, 0xff, 0x83, 0xff, 0x93, 0xff, 0xa3, 0xff, 0xa8, 0xff, 0xaa, 0xff, 0xb5, 0xff, 0xb8, 0xff, 0xbd, 0xff, 0xc1, 0xff, 0xcd, 0xff, 0xd0, 0xff, 0xef, 0xff, 0x03, 0x00, 0x20, 0x00, 0x30, 0x00, 0x4d, 0x00, 0x43, 0x00, 0x42, 0x00, 0x50, 0x00, 0x2a, 0x00, 0x2c, 0x00, 0x2b, 0x00, 0x18, 0x00, 0x13, 0x00, 0xf7, 0xff, 0x02, 0x00, 0xf0, 0xff, 0xea, 0xff, 0xef, 0xff, 0xe2, 0xff, 0xe7, 0xff, 0xef, 0xff, 0xf3, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0x01, 0x00, 0xf4, 0xff, 0xee, 0xff, 0xdb, 0xff, 0xde, 0xff, 0xcd, 0xff, 0xc7, 0xff, 0xcc, 0xff, 0xc3, 0xff, 0xcd, 0xff, 0xd2, 0xff, 0xca, 0xff, 0xdb, 0xff, 0xd0, 0xff, 0xe7, 0xff, 0xe0, 0xff, 0xec, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xf7, 0xff, 0xf6, 0xff, 0xe3, 0xff, 0xe1, 0xff, 0xdb, 0xff, 0xca, 0xff, 0xca, 0xff, 0xad, 0xff, 0xad, 0xff, 0x8f, 0xff, 0x86, 0xff, 0x73, 0xff, 0x7a, 0xff, 0x62, 0xff, 0x5c, 0xff, 0x61, 0xff, 0x5e, 0xff, 0x60, 0xff, 0x54, 0xff, 0x70, 0xff, 0x72, 0xff, 0x8f, 0xff, 0x9a, 0xff, 0xa6, 0xff, 0xc7, 0xff, 0xd8, 0xff, 0xf0, 0xff, 0xfc, 0xff, 0x11, 0x00, 0x31, 0x00, 0x3a, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x5e, 0x00, 0x58, 0x00, 0x50, 0x00, 0x55, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x32, 0x00, 0x29, 0x00, 0x16, 0x00, 0xf8, 0xff, 0xed, 0xff, 0xc4, 0xff, 0xca, 0xff, 0xa4, 0xff, 0xa7, 0xff, 0x9f, 0xff, 0x9b, 0xff, 0x99, 0xff, 0xa7, 0xff, 0xac, 0xff, 0xb0, 0xff, 0xbf, 0xff, 0xbd, 0xff, 0xd2, 0xff, 0xe3, 0xff, 0xe8, 0xff, 0x06, 0x00, 0x07, 0x00, 0x1d, 0x00, 0x19, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x06, 0x00, 0x03, 0x00, 0xf8, 0xff, 0xf2, 0xff, 0xe0, 0xff, 0xd7, 0xff, 0xd3, 0xff, 0xb3, 0xff, 0xc4, 0xff, 0xb7, 0xff, 0xa2, 0xff, 0xac, 0xff, 0xa6, 0xff, 0x9a, 0xff, 0xa4, 0xff, 0x9e, 0xff, 0xb2, 0xff, 0xa7, 0xff, 0xa0, 0xff, 0xbb, 0xff, 0xc9, 0xff, 0xca, 0xff, 0xd8, 0xff, 0xd5, 0xff, 0xdb, 0xff, 0xde, 0xff, 0xce, 0xff, 0xd3, 0xff, 0xd0, 0xff, 0xda, 0xff, 0xcd, 0xff, 0xd0, 0xff, 0xc2, 0xff, 0xd5, 0xff, 0xc7, 0xff, 0xd0, 0xff, 0xc4, 0xff, 0xdb, 0xff, 0xd6, 0xff, 0xcf, 0xff, 0xdb, 0xff, 0xd9, 0xff, 0xd4, 0xff, 0xd4, 0xff, 0xcf, 0xff, 0xcf, 0xff, 0xc5, 0xff, 0xbc, 0xff, 0xc6, 0xff, 0xb7, 0xff, 0xc3, 0xff, 0xc6, 0xff, 0xb9, 0xff, 0xb9, 0xff, 0xba, 0xff, 0xb4, 0xff, 0xa3, 0xff, 0x9a, 0xff, 0xa7, 0xff, 0xa8, 0xff, 0xbb, 0xff, 0xbe, 0xff, 0xc3, 0xff, 0xbd, 0xff, 0xc8, 0xff, 0xcf, 0xff, 0xc8, 0xff, 0xc4, 0xff, 0xd9, 0xff, 0xe4, 0xff, 0xe7, 0xff, 0xf5, 0xff, 0x0a, 0x00, 0x14, 0x00, 0x15, 0x00, 0x19, 0x00, 0x0f, 0x00, 0x04, 0x00, 0xf3, 0xff, 0xea, 0xff, 0xf7, 0xff, 0xed, 0xff, 0xee, 0xff, 0xf9, 0xff, 0xfc, 0xff, 0xf9, 0xff, 0x00, 0x00, 0xfe, 0xff, 0xf7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xf0, 0xff, 0xee, 0xff, 0xf2, 0xff, 0xef, 0xff, 0xe6, 0xff, 0xec, 0xff, 0xf1, 0xff, 0xfe, 0xff, 0xed, 0xff, 0xf3, 0xff, 0xf1, 0xff, 0xf3, 0xff, 0xd6, 0xff, 0xe3, 0xff, 0xd1, 0xff, 0xd0, 0xff, 0xc7, 0xff, 0xc3, 0xff, 0xcf, 0xff, 0xca, 0xff, 0xcf, 0xff, 0xe2, 0xff, 0xd2, 0xff, 0xe1, 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xf3, 0xff, 0xfb, 0xff, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x0a, 0x00, 0xf7, 0xff, 0xfa, 0xff, 0x06, 0x00, 0x07, 0x00, 0xfc, 0xff, 0xf9, 0xff, 0xf6, 0xff, 0xe0, 0xff, 0xe9, 0xff, 0xc4, 0xff, 0xca, 0xff, 0xbd, 0xff, 0xb2, 0xff, 0xb2, 0xff, 0xad, 0xff, 0xb7, 0xff, 0xb5, 0xff, 0xb8, 0xff, 0xd3, 0xff, 0xde, 0xff, 0xf4, 0xff, 0x10, 0x00, 0x1e, 0x00, 0x2f, 0x00, 0x33, 0x00, 0x38, 0x00, 0x2c, 0x00, 0x1e, 0x00, 0x18, 0x00, 0xff, 0xff, 0xfb, 0xff, 0xf2, 0xff, 0xea, 0xff, 0xe0, 0xff, 0xd9, 0xff, 0xe3, 0xff, 0xc9, 0xff, 0xc6, 0xff, 0xd5, 0xff, 0xd6, 0xff, 0xd9, 0xff, 0xea, 0xff, 0xf2, 0xff, 0xf2, 0xff, 0xeb, 0xff, 0xdf, 0xff, 0xe1, 0xff, 0xbe, 0xff, 0xb8, 0xff, 0xaf, 0xff, 0x98, 0xff, 0x96, 0xff, 0x9a, 0xff, 0x9d, 0xff, 0x89, 0xff, 0x95, 0xff, 0x89, 0xff, 0x74, 0xff, 0x77, 0xff, 0x71, 0xff, 0x6a, 0xff, 0x73, 0xff, 0x7d, 0xff, 0x83, 0xff, 0x9f, 0xff, 0xa7, 0xff, 0xc1, 0xff, 0xc8, 0xff, 0xde, 0xff, 0xe6, 0xff, 0xe0, 0xff, 0xe8, 0xff, 0xec, 0xff, 0xe3, 0xff, 0xef, 0xff, 0xde, 0xff, 0xf9, 0xff, 0xf3, 0xff, 0x12, 0x00, 0x04, 0x00, 0x28, 0x00, 0x23, 0x00, 0x39, 0x00, 0x41, 0x00, 0x47, 0x00, 0x4d, 0x00, 0x4e, 0x00, 0x43, 0x00, 0x5c, 0x00, 0x36, 0x00, 0x43, 0x00, 0x32, 0x00, 0x1a, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xf3, 0xff, 0xdc, 0xff, 0xe6, 0xff, 0xdd, 0xff, 0xdb, 0xff, 0xc9, 0xff, 0xc6, 0xff, 0xb5, 0xff, 0xb6, 0xff, 0xab, 0xff, 0x9d, 0xff, 0x9f, 0xff, 0xb5, 0xff, 0xb6, 0xff, 0xb4, 0xff, 0xbd, 0xff, 0xdd, 0xff, 0xd2, 0xff, 0xe3, 0xff, 0xe2, 0xff, 0xf1, 0xff, 0xe6, 0xff, 0xf1, 0xff, 0xe7, 0xff, 0xf3, 0xff, 0xdf, 0xff, 0xe1, 0xff, 0xc5, 0xff, 0xd4, 0xff, 0xb0, 0xff, 0xb3, 0xff, 0xa7, 0xff, 0xa8, 0xff, 0xa7, 0xff, 0xa7, 0xff, 0xad, 0xff, 0x9b, 0xff, 0x98, 0xff, 0x8f, 0xff, 0x83, 0xff, 0x83, 0xff, 0x8c, 0xff, 0x8c, 0xff, 0x9b, 0xff, 0xa2, 0xff, 0xab, 0xff, 0xca, 0xff, 0xd3, 0xff, 0xda, 0xff, 0xf8, 0xff, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x18, 0x00, 0x2e, 0x00, 0x27, 0x00, 0x31, 0x00, 0x43, 0x00, 0x4c, 0x00, 0x3e, 0x00, 0x43, 0x00, 0x41, 0x00, 0x2c, 0x00, 0x0d, 0x00, 0x05, 0x00, 0xe8, 0xff, 0xda, 0xff, 0xd2, 0xff, 0xc3, 0xff, 0xc0, 0xff, 0xbe, 0xff, 0xc2, 0xff, 0xc6, 0xff, 0xb6, 0xff, 0xcd, 0xff, 0xc3, 0xff, 0xcb, 0xff, 0xd2, 0xff, 0xdc, 0xff, 0xcf, 0xff, 0xd0, 0xff, 0xd3, 0xff, 0xc8, 0xff, 0xc0, 0xff, 0xb8, 0xff, 0xc9, 0xff, 0xae, 0xff, 0xb9, 0xff, 0xbb, 0xff, 0xcf, 0xff, 0xcd, 0xff, 0xe3, 0xff, 0xea, 0xff, 0xf1, 0xff, 0xe6, 0xff, 0xe9, 0xff, 0xd8, 0xff, 0xc7, 0xff, 0xc6, 0xff, 0xb4, 0xff, 0xbb, 0xff, 0xb4, 0xff, 0xc0, 0xff, 0xbd, 0xff, 0xcd, 0xff, 0xd2, 0xff, 0xe2, 0xff, 0xf4, 0xff, 0xff, 0xff, 0x0a, 0x00, 0x08, 0x00, 0x07, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0xff, 0xef, 0xff, 0xf9, 0xff, 0xf1, 0xff, 0xf9, 0xff, 0xe7, 0xff, 0xed, 0xff, 0xec, 0xff, 0xec, 0xff, 0xf3, 0xff, 0xfb, 0xff, 0xf4, 0xff, 0x02, 0x00, 0xf3, 0xff, 0xfb, 0xff, 0xfc, 0xff, 0xef, 0xff, 0xef, 0xff, 0xf2, 0xff, 0xe8, 0xff, 0xe9, 0xff, 0xe1, 0xff, 0xe2, 0xff, 0xd7, 0xff, 0xe4, 0xff, 0xc3, 0xff, 0xd1, 0xff, 0xbb, 0xff, 0xcf, 0xff, 0xaf, 0xff, 0xc7, 0xff, 0xd2, 0xff, 0xe6, 0xff, 0xdc, 0xff, 0xed, 0xff, 0xf2, 0xff, 0xe1, 0xff, 0xdf, 0xff, 0xc4, 0xff, 0xbd, 0xff, 0xab, 0xff, 0xa6, 0xff, 0xaa, 0xff, 0x96, 0xff, 0xa8, 0xff, 0xa8, 0xff, 0xbb, 0xff, 0xa9, 0xff, 0xad, 0xff, 0xbd, 0xff, 0xb4, 0xff, 0xc1, 0xff, 0xcd, 0xff, 0xd2, 0xff, 0xe5, 0xff, 0xef, 0xff, 0xf1, 0xff, 0x11, 0x00, 0x0f, 0x00, 0x15, 0x00, 0x21, 0x00, 0x1c, 0x00, 0x2b, 0x00, 0x28, 0x00, 0x22, 0x00, 0x25, 0x00, 0x1a, 0x00, 0x03, 0x00, 0xf9, 0xff, 0xed, 0xff, 0xc3, 0xff, 0xba, 0xff, 0xb4, 0xff, 0x98, 0xff, 0x8e, 0xff, 0x89, 0xff, 0x78, 0xff, 0x85, 0xff, 0x74, 0xff, 0x7b, 0xff, 0x80, 0xff, 0x7f, 0xff, 0x98, 0xff, 0xa7, 0xff, 0xae, 0xff, 0xca, 0xff, 0xc8, 0xff, 0xd5, 0xff, 0xcf, 0xff, 0xcc, 0xff, 0xc9, 0xff, 0xc9, 0xff, 0xc6, 0xff, 0xc9, 0xff, 0xd4, 0xff, 0xdf, 0xff, 0xe0, 0xff, 0xee, 0xff, 0xf1, 0xff, 0x06, 0x00, 0x12, 0x00, 0x16, 0x00, 0x37, 0x00, 0x47, 0x00, 0x51, 0x00, 0x54, 0x00, 0x69, 0x00, 0x59, 0x00, 0x4e, 0x00, 0x44, 0x00, 0x37, 0x00, 0x2b, 0x00, 0x13, 0x00, 0x0f, 0x00, 0xf4, 0xff, 0xfe, 0xff, 0xe5, 0xff, 0xe7, 0xff, 0xe0, 0xff, 0xe4, 0xff, 0xd0, 0xff, 0xcc, 0xff, 0xc6, 0xff, 0xb0, 0xff, 0xac, 0xff, 0xa8, 0xff, 0x9f, 0xff, 0x94, 0xff, 0x9e, 0xff, 0x99, 0xff, 0x9e, 0xff, 0x92, 0xff, 0xa3, 0xff, 0x8d, 0xff, 0x90, 0xff, 0x92, 0xff, 0xa4, 0xff, 0xa5, 0xff, 0xa6, 0xff, 0xad, 0xff, 0xb5, 0xff, 0xb6, 0xff, 0xbe, 0xff, 0xc0, 0xff, 0xd4, 0xff, 0xe1, 0xff, 0xed, 0xff, 0xee, 0xff, 0xe5, 0xff, 0xf3, 0xff, 0xe9, 0xff, 0xdb, 0xff, 0xf3, 0xff, 0xf1, 0xff, 0x00, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x1a, 0x00, 0x19, 0x00, 0x27, 0x00, 0x1d, 0x00, 0x2d, 0x00, 0x24, 0x00, 0x2a, 0x00, 0x20, 0x00, 0x16, 0x00, 0x13, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xd6, 0xff, 0xd5, 0xff, 0xcb, 0xff, 0xc9, 0xff, 0xd1, 0xff, 0xc2, 0xff, 0xc5, 0xff, 0xc2, 0xff, 0xbe, 0xff, 0xc6, 0xff, 0xc7, 0xff, 0xd7, 0xff, 0xe4, 0xff, 0xdd, 0xff, 0xfe, 0xff, 0x04, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x14, 0x00, 0x04, 0x00, 0xfe, 0xff, 0xf7, 0xff, 0xf6, 0xff, 0xd6, 0xff, 0xd5, 0xff, 0xc8, 0xff, 0xa6, 0xff, 0xaa, 0xff, 0x91, 0xff, 0x91, 0xff, 0x8e, 0xff, 0x84, 0xff, 0x90, 0xff, 0x85, 0xff, 0x84, 0xff, 0x8c, 0xff, 0x8c, 0xff, 0x8a, 0xff, 0x92, 0xff, 0x83, 0xff, 0x82, 0xff, 0x94, 0xff, 0x84, 0xff, 0x92, 0xff, 0x8b, 0xff, 0x93, 0xff, 0x98, 0xff, 0x9e, 0xff, 0xb8, 0xff, 0xa3, 0xff, 0xbe, 0xff, 0xd1, 0xff, 0xef, 0xff, 0xec, 0xff, 0x03, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x33, 0x00, 0x37, 0x00, 0x42, 0x00, 0x5e, 0x00, 0x6a, 0x00, 0x71, 0x00, 0x87, 0x00, 0x97, 0x00, 0xa9, 0x00, 0x9e, 0x00, 0x9e, 0x00, 0xa1, 0x00, 0x92, 0x00, 0x69, 0x00, 0x68, 0x00, 0x42, 0x00, 0x23, 0x00, 0xf5, 0xff, 0xee, 0xff, 0xc8, 0xff, 0x9c, 0xff, 0x92, 0xff, 0x7e, 0xff, 0x5e, 0xff, 0x53, 0xff, 0x41, 0xff, 0x49, 0xff, 0x33, 0xff, 0x3a, 0xff, 0x31, 0xff, 0x37, 0xff, 0x2d, 0xff, 0x48, 0xff, 0x3e, 0xff, 0x39, 0xff, 0x57, 0xff, 0x61, 0xff, 0x72, 0xff, 0x7b, 0xff, 0x8f, 0xff, 0x97, 0xff, 0xa3, 0xff, 0xad, 0xff, 0xb2, 0xff, 0xd1, 0xff, 0xcd, 0xff, 0xd5, 0xff, 0xfa, 0xff, 0xf9, 0xff, 0x03, 0x00 }; constexpr unsigned int cp909_raw_len = 39348; ================================================ FILE: lib/clouds/dsp/fx/diffuser.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // AP diffusion network. #ifndef CLOUDS_DSP_FX_DIFFUSER_H_ #define CLOUDS_DSP_FX_DIFFUSER_H_ #include "stmlib/stmlib.h" #include "clouds/dsp/fx/fx_engine.h" namespace clouds { class Diffuser { public: Diffuser() { } ~Diffuser() { } void Init(uint16_t* buffer) { engine_.Init(buffer); } void Process(float* in_out_l, float* in_out_r, size_t size) { typedef E::Reserve<126, E::Reserve<180, E::Reserve<269, E::Reserve<444, E::Reserve<151, E::Reserve<205, E::Reserve<245, E::Reserve<405> > > > > > > > Memory; E::DelayLine apl1; E::DelayLine apl2; E::DelayLine apl3; E::DelayLine apl4; E::DelayLine apr1; E::DelayLine apr2; E::DelayLine apr3; E::DelayLine apr4; E::Context c; const float kap = 0.625f; while (size--) { engine_.Start(&c); float wet = 0.0f; c.Read(*in_out_l); c.Read(apl1 TAIL, kap); c.WriteAllPass(apl1, -kap); c.Read(apl2 TAIL, kap); c.WriteAllPass(apl2, -kap); c.Read(apl3 TAIL, kap); c.WriteAllPass(apl3, -kap); c.Read(apl4 TAIL, kap); c.WriteAllPass(apl4, -kap); c.Write(wet, 0.0f); *in_out_l += amount_ * (wet - *in_out_l); c.Read(*in_out_r); c.Read(apr1 TAIL, kap); c.WriteAllPass(apr1, -kap); c.Read(apr2 TAIL, kap); c.WriteAllPass(apr2, -kap); c.Read(apr3 TAIL, kap); c.WriteAllPass(apr3, -kap); c.Read(apr4 TAIL, kap); c.WriteAllPass(apr4, -kap); c.Write(wet, 0.0f); *in_out_r += amount_ * (wet - *in_out_r); ++in_out_l; ++in_out_r; } } void set_amount(float amount) { amount_ = amount; } private: typedef FxEngine<2048, FORMAT_16_BIT> E; E engine_; float amount_; DISALLOW_COPY_AND_ASSIGN(Diffuser); }; } // namespace clouds #endif // CLOUDS_DSP_FX_DIFFUSER_H_ ================================================ FILE: lib/clouds/dsp/fx/fx_engine.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Base class for building reverbs. #ifndef CLOUDS_DSP_FX_FX_ENGINE_H_ #define CLOUDS_DSP_FX_FX_ENGINE_H_ #include #include "stmlib/stmlib.h" #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/cosine_oscillator.h" namespace clouds { #define TAIL , -1 enum Format { FORMAT_12_BIT, FORMAT_16_BIT, FORMAT_32_BIT }; enum LFOIndex { LFO_1, LFO_2 }; template struct DataType { }; template<> struct DataType { typedef uint16_t T; static inline float Decompress(T value) { return static_cast(static_cast(value)) / 4096.0f; } static inline T Compress(float value) { return static_cast( stmlib::Clip16(static_cast(value * 4096.0f))); } }; template<> struct DataType { typedef uint16_t T; static inline float Decompress(T value) { return static_cast(static_cast(value)) / 32768.0f; } static inline T Compress(float value) { return static_cast( stmlib::Clip16(static_cast(value * 32768.0f))); } }; template<> struct DataType { typedef float T; static inline float Decompress(T value) { return value;; } static inline T Compress(float value) { return value; } }; template< size_t size, Format format = FORMAT_12_BIT> class FxEngine { public: typedef typename DataType::T T; FxEngine() { } ~FxEngine() { } void Init(T* buffer) { buffer_ = buffer; Clear(); } void Clear() { std::fill(&buffer_[0], &buffer_[size], 0); write_ptr_ = 0; } struct Empty { }; template struct Reserve { typedef T Tail; enum { length = l }; }; template struct DelayLine { enum { length = DelayLine::length, base = DelayLine::base + DelayLine::length + 1 }; }; template struct DelayLine { enum { length = Memory::length, base = 0 }; }; class Context { friend class FxEngine; public: Context() { } ~Context() { } inline void Load(float value) { accumulator_ = value; } inline void Read(float value, float scale) { accumulator_ += value * scale; } inline void Read(float value) { accumulator_ += value; } inline void Write(float& value) { value = accumulator_; } inline void Write(float& value, float scale) { value = accumulator_; accumulator_ *= scale; } template inline void Write(D& d, int32_t offset, float scale) { STATIC_ASSERT(D::base + D::length <= size, delay_memory_full); T w = DataType::Compress(accumulator_); if (offset == -1) { buffer_[(write_ptr_ + D::base + D::length - 1) & MASK] = w; } else { buffer_[(write_ptr_ + D::base + offset) & MASK] = w; } accumulator_ *= scale; } template inline void Write(D& d, float scale) { Write(d, 0, scale); } template inline void WriteAllPass(D& d, int32_t offset, float scale) { Write(d, offset, scale); accumulator_ += previous_read_; } template inline void WriteAllPass(D& d, float scale) { WriteAllPass(d, 0, scale); } template inline void Read(D& d, int32_t offset, float scale) { STATIC_ASSERT(D::base + D::length <= size, delay_memory_full); T r; if (offset == -1) { r = buffer_[(write_ptr_ + D::base + D::length - 1) & MASK]; } else { r = buffer_[(write_ptr_ + D::base + offset) & MASK]; } float r_f = DataType::Decompress(r); previous_read_ = r_f; accumulator_ += r_f * scale; } template inline void Read(D& d, float scale) { Read(d, 0, scale); } inline void Lp(float& state, float coefficient) { state += coefficient * (accumulator_ - state); accumulator_ = state; } inline void Hp(float& state, float coefficient) { state += coefficient * (accumulator_ - state); accumulator_ -= state; } template inline void Interpolate(D& d, float offset, float scale) { STATIC_ASSERT(D::base + D::length <= size, delay_memory_full); MAKE_INTEGRAL_FRACTIONAL(offset); float a = DataType::Decompress( buffer_[(write_ptr_ + offset_integral + D::base) & MASK]); float b = DataType::Decompress( buffer_[(write_ptr_ + offset_integral + D::base + 1) & MASK]); float x = a + (b - a) * offset_fractional; previous_read_ = x; accumulator_ += x * scale; } template inline void Interpolate( D& d, float offset, LFOIndex index, float amplitude, float scale) { STATIC_ASSERT(D::base + D::length <= size, delay_memory_full); offset += amplitude * lfo_value_[index]; MAKE_INTEGRAL_FRACTIONAL(offset); float a = DataType::Decompress( buffer_[(write_ptr_ + offset_integral + D::base) & MASK]); float b = DataType::Decompress( buffer_[(write_ptr_ + offset_integral + D::base + 1) & MASK]); float x = a + (b - a) * offset_fractional; previous_read_ = x; accumulator_ += x * scale; } private: float accumulator_; float previous_read_; float lfo_value_[2]; T* buffer_; int32_t write_ptr_; DISALLOW_COPY_AND_ASSIGN(Context); }; inline void SetLFOFrequency(LFOIndex index, float frequency) { lfo_[index].template Init( frequency * 32.0f); } inline void Start(Context* c) { --write_ptr_; if (write_ptr_ < 0) { write_ptr_ += size; } c->accumulator_ = 0.0f; c->previous_read_ = 0.0f; c->buffer_ = buffer_; c->write_ptr_ = write_ptr_; if ((write_ptr_ & 31) == 0) { c->lfo_value_[0] = lfo_[0].Next(); c->lfo_value_[1] = lfo_[1].Next(); } else { c->lfo_value_[0] = lfo_[0].value(); c->lfo_value_[1] = lfo_[1].value(); } } private: enum { MASK = size - 1 }; int32_t write_ptr_; T* buffer_; stmlib::CosineOscillator lfo_[2]; DISALLOW_COPY_AND_ASSIGN(FxEngine); }; } // namespace clouds #endif // CLOUDS_DSP_FX_FX_ENGINE_H_ ================================================ FILE: lib/clouds/dsp/fx/pitch_shifter.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Pitch shifter. #ifndef CLOUDS_DSP_FX_PITCH_SHIFTER_H_ #define CLOUDS_DSP_FX_PITCH_SHIFTER_H_ #include "stmlib/stmlib.h" #include "clouds/dsp/fx/fx_engine.h" namespace clouds { class PitchShifter { public: PitchShifter() { } ~PitchShifter() { } void Init(uint16_t* buffer) { engine_.Init(buffer); phase_ = 0; size_ = 2047.0f; } void Clear() { engine_.Clear(); } inline void Process(float *in_out_l, float *in_out_r, size_t size) { while (size--) { Process(*in_out_l, *in_out_r); ++in_out_l; ++in_out_r; } } void Process(float& in_out_l, float& in_out_r) { typedef E::Reserve<2047, E::Reserve<2047> > Memory; E::DelayLine left; E::DelayLine right; E::Context c; engine_.Start(&c); phase_ += (1.0f - ratio_) / size_; if (phase_ >= 1.0f) { phase_ -= 1.0f; } if (phase_ <= 0.0f) { phase_ += 1.0f; } float tri = 2.0f * (phase_ >= 0.5f ? 1.0f - phase_ : phase_); float phase = phase_ * size_; float half = phase + size_ * 0.5f; if (half >= size_) { half -= size_; } c.Read(in_out_l, 1.0f); c.Write(left, 0.0f); c.Interpolate(left, phase, tri); c.Interpolate(left, half, 1.0f - tri); c.Write(in_out_l, 0.0f); c.Read(in_out_r, 1.0f); c.Write(right, 0.0f); c.Interpolate(right, phase, tri); c.Interpolate(right, half, 1.0f - tri); c.Write(in_out_r, 0.0f); } inline void set_ratio(float ratio) { ratio_ = ratio; } inline void set_size(float size) { float target_size = 128.0f + (2047.0f - 128.0f) * size * size * size; ONE_POLE(size_, target_size, 0.05f) } private: typedef FxEngine<4096, FORMAT_16_BIT> E; E engine_; float phase_; float ratio_; float size_; DISALLOW_COPY_AND_ASSIGN(PitchShifter); }; } // namespace clouds #endif // CLOUDS_DSP_FX_MINI_CHORUS_H_ ================================================ FILE: lib/clouds/dsp/fx/reverb.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Reverb. #ifndef CLOUDS_DSP_FX_REVERB_H_ #define CLOUDS_DSP_FX_REVERB_H_ #include "stmlib/stmlib.h" #include "clouds/dsp/fx/fx_engine.h" namespace clouds { class Reverb { public: Reverb() { } ~Reverb() { } void Init(uint16_t* buffer) { engine_.Init(buffer); engine_.SetLFOFrequency(LFO_1, 0.5f / 32000.0f); engine_.SetLFOFrequency(LFO_2, 0.3f / 32000.0f); lp_ = 0.7f; diffusion_ = 0.625f; } void Process(float* in_out_l, float* in_out_r, size_t size) { // This is the Griesinger topology described in the Dattorro paper // (4 AP diffusers on the input, then a loop of 2x 2AP+1Delay). // Modulation is applied in the loop of the first diffuser AP for additional // smearing; and to the two long delays for a slow shimmer/chorus effect. typedef E::Reserve<113, E::Reserve<162, E::Reserve<241, E::Reserve<399, E::Reserve<1653, E::Reserve<2038, E::Reserve<3411, E::Reserve<1913, E::Reserve<1663, E::Reserve<4782> > > > > > > > > > Memory; E::DelayLine ap1; E::DelayLine ap2; E::DelayLine ap3; E::DelayLine ap4; E::DelayLine dap1a; E::DelayLine dap1b; E::DelayLine del1; E::DelayLine dap2a; E::DelayLine dap2b; E::DelayLine del2; E::Context c; const float kap = diffusion_; const float klp = lp_; const float krt = reverb_time_; const float amount = amount_; const float gain = input_gain_; float lp_1 = lp_decay_1_; float lp_2 = lp_decay_2_; while (size--) { float wet; float apout = 0.0f; engine_.Start(&c); // Smear AP1 inside the loop. c.Interpolate(ap1, 10.0f, LFO_1, 60.0f, 1.0f); c.Write(ap1, 100, 0.0f); c.Read(*in_out_l + *in_out_r, gain); // Diffuse through 4 allpasses. c.Read(ap1 TAIL, kap); c.WriteAllPass(ap1, -kap); c.Read(ap2 TAIL, kap); c.WriteAllPass(ap2, -kap); c.Read(ap3 TAIL, kap); c.WriteAllPass(ap3, -kap); c.Read(ap4 TAIL, kap); c.WriteAllPass(ap4, -kap); c.Write(apout); // Main reverb loop. c.Load(apout); c.Interpolate(del2, 4680.0f, LFO_2, 100.0f, krt); c.Lp(lp_1, klp); c.Read(dap1a TAIL, -kap); c.WriteAllPass(dap1a, kap); c.Read(dap1b TAIL, kap); c.WriteAllPass(dap1b, -kap); c.Write(del1, 2.0f); c.Write(wet, 0.0f); *in_out_l += (wet - *in_out_l) * amount; c.Load(apout); // c.Interpolate(del1, 4450.0f, LFO_1, 50.0f, krt); c.Read(del1 TAIL, krt); c.Lp(lp_2, klp); c.Read(dap2a TAIL, kap); c.WriteAllPass(dap2a, -kap); c.Read(dap2b TAIL, -kap); c.WriteAllPass(dap2b, kap); c.Write(del2, 2.0f); c.Write(wet, 0.0f); *in_out_r += (wet - *in_out_r) * amount; ++in_out_r; ++in_out_l; } lp_decay_1_ = lp_1; lp_decay_2_ = lp_2; } inline void set_amount(float amount) { amount_ = amount; } inline void set_input_gain(float input_gain) { input_gain_ = input_gain; } inline void set_time(float reverb_time) { reverb_time_ = reverb_time; } inline void set_diffusion(float diffusion) { diffusion_ = diffusion; } inline void set_lp(float lp) { lp_ = lp; } private: typedef FxEngine<16384, FORMAT_16_BIT> E; E engine_; float amount_; float input_gain_; float reverb_time_; float diffusion_; float lp_; float lp_decay_1_; float lp_decay_2_; DISALLOW_COPY_AND_ASSIGN(Reverb); }; } // namespace clouds #endif // CLOUDS_DSP_FX_REVERB_H_ ================================================ FILE: lib/drumsynth/drumsynth.cpp ================================================ // Copyright (C)2021 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #define private public #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/filter.h" #include "plaits/dsp/oscillator/oscillator.h" #include "plaits/resources.h" #include "misc/noise.hxx" #include "misc/Biquad.h" #include "drumsynth.h" #include "string.h" #include "misc/cubic_spline.hxx" #ifndef CONSTRAIN #define CONSTRAIN(x, min, max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))) #endif #ifndef __SAMPLE_RATE constexpr float __SAMPLE_RATE = 48000.f; #endif inline float dB2amp(float dB) { return expf(dB * 0.11512925464970228420089957273422f); // return pow(10.0, (0.05*dB)); // naive, inefficient version } class Envelope { const EnvArgs *args_; public: void init(const EnvArgs *args) { args_ = args; value_ = 0.f; e_ = 0.0001f; c_ = 1.0f; segment_ = 0; if (args_->n == 0) { value_ = 1.f; pos_ = 0; len_ = 0; } else if (args_->n == 1) { value_ = args_->xy[0].v; pos_ = 0; len_ = 0; } else { if (args_->xy[0].t == 0) value_ = args_->xy[0].v; } } // e = s * c ^ l inline float calc_c(float start, float end, int len) { if (fabsf(start - end) < __FLT_EPSILON__) return 1.f; else { return powf(e_ + (end / start), 1.0f / len); } } inline void process(uint32_t t, float stretch) { if (t == 0) // restart { pos_ = 0; len_ = 0; segment_ = 0; } if (pos_ < len_) { value_ *= c_; ++pos_; } else if (segment_ < (args_->n - 1)) { int32_t i = segment_; while (i++ < (args_->n - 2)) if (args_->xy[i - 1].v < args_->xy[i].v) { stretch = 1; break; } pos_ = 0; len_ = (args_->xy[segment_ + 1].t - args_->xy[segment_].t) * stretch; value_ = args_->xy[segment_].v; c_ = calc_c(value_, args_->xy[segment_ + 1].v, len_); segment_++; } } inline bool finished() { return pos_ != 0 && pos_ == len_; } inline float value() { return value_; } private: int32_t segment_; uint32_t len_; uint32_t pos_; float value_; float c_; float e_; }; class Oscillator { public: void Init(float freq) { pw_ = 0.5f; phase_inc_ = freq / __SAMPLE_RATE; f_ = freq; osc.Init(); } inline void reset() { osc.Init(); } inline void pitch(float pitch) { phase_inc_ = f_ * pitch / __SAMPLE_RATE; } inline void duty(float duty) { pw_ = duty; } inline void Square(float &out) { this->osc.Render(phase_inc_, pw_, &out, 1); } inline void Saw(float &out) { this->osc.Render(phase_inc_, pw_, &out, 1); } inline void Tri(float &out) { this->osc.Render(phase_inc_, pw_, &out, 1); } // float fm = 2.f; // float fm_amp = 0.05f; // float fm_phase = 0.5f; inline void Metallic(float &out2) { float out = osc.phase_ < pw_ ? 1.f : -1.f; // float fm_ = stmlib::Interpolate(plaits::lut_sine, fm_phase, 1024.0f) * fm_amp; // fm_phase += phase_inc_ / fm; // if (fm_phase > 1.0f) // fm_phase -= 1.00f; osc.phase_ += phase_inc_; // * (1.f + fm_); if (osc.phase_ > 1.0f) osc.phase_ -= 1.00f; out2 += out; } inline void Sine(float &out) { // #define PI_F 3.1415927410125732421875f // out = sinf((0.25f + osc.phase_) * PI_F * 2.f); out = -stmlib::Interpolate(plaits::lut_sine + 128, osc.phase_, 512.0f); osc.phase_ += phase_inc_; if (osc.phase_ > 1.0f) osc.phase_ -= 1.0f; } private: float phase_inc_, pw_, f_, amp2_; plaits::Oscillator osc; }; struct drum_synth_Part { Oscillator *_osc = nullptr; stmlib::DCBlocker _dc_blocker; WhiteNoise noise = {}; Envelope _amp = {}; Envelope _pitch = {}; Envelope _vca = {}; Biquad biquad1 = {}; Biquad biquad2 = {}; std::pair biquadA[2] = {}; std::pair biquadB[2] = {}; const PartArgs *part; float amp = 1.f; cspline waveshaper = {}; void init(const PartArgs *part) { this->part = part; _amp.init(&part->osc_amp); _pitch.init(&part->osc_pitch); _vca.init(&part->vca); _dc_blocker.Init(0.99f); const auto &a = part->bq1; if (a.mode) biquad1.setBiquad(a.mode - 1, a.f / __SAMPLE_RATE, a.q, a.g); const auto &b = part->bq2; if (b.mode) biquad2.setBiquad(b.mode - 1, b.f / __SAMPLE_RATE, b.q, b.g); if (part->osc.type == OSC_METALLIC) { amp = dB2amp(-26.f); float r = (logf(part->osc.fb) - logf(part->osc.fa)) / (part->osc.n - 1); for (size_t i = 0; i < part->osc.n; i++) { float f = i == 0 ? 1 : expf(r * i); _osc[i].Init(part->osc.fa * f); _osc[i].duty(part->osc.duty); } } else { amp = 1.f - __FLT_EPSILON__; // 0.4380016479995117f; _osc[0].Init(part->osc.fa); } if (part->ws.n) { cspline_init(&this->waveshaper, &part->ws.xy[0].x, &part->ws.xy[0].y, part->ws.n, 2); } } void free() { if (part->ws.n) cspline_free(&this->waveshaper); } float waveshaper_transform(float a) { CONSTRAIN(a, -1.f + __FLT_EPSILON__, 1.f - __FLT_EPSILON__); a = cspline_eval(&this->waveshaper, a); CONSTRAIN(a, -1.f + __FLT_EPSILON__, 1.f - __FLT_EPSILON__); return a; } inline void reset() { for (size_t j = 0; j < this->part->osc.n; j++) this->_osc[j].reset(); memset(&this->biquadA, 0, sizeof(this->biquadA)); memset(&this->biquadB, 0, sizeof(this->biquadB)); } uint32_t last_f = 0; inline void process_frame(float f, const DrumParams *params, float *outL, float *outR, size_t size) { uint32_t t = params->t; float osc = 0; float osc2 = 0; uint32_t ff = f * __SAMPLE_RATE; // if (t > 0 && this->_amp.finished() && this->_vca.finished()) // { // return; // } while (size--) { this->_amp.process(t, params->decay); this->_vca.process(t, params->decay); this->_pitch.process(t, params->decay); ++t; float vca = this->_vca.value(); if( vca < (1.f / INT16_MAX)) { *outL++ = 0.f; *outR++ = 0.f; continue; } // if (this->_amp.value() < (1.f / INT16_MAX) || this->_vca.value() < (1.f / INT16_MAX)) // { // out++; // continue; // } switch (part->osc.type) { case OSC_NOISE1: case OSC_NOISE2: { float a = this->noise.nextf(-1, 1); float b = this->noise.nextf(-1, 1); float st = 0.5f - (params->stereo / 2); osc = (a * (1 - st) + b * st); osc2 = (b * (1 - st) + a * st); } break; case OSC_METALLIC: osc = 0; for (size_t j = 0; j < part->osc.n; j++) { // this->_osc[j].pitch(this->_pitch.value() * f); this->_osc[j].pitch(f); this->_osc[j].Metallic(osc); } _dc_blocker.Process(&osc, 1); break; case OSC_SINE: this->_osc[0].pitch(this->_pitch.value() * f); this->_osc[0].Sine(osc); break; case OSC_SQUARE: this->_osc[0].pitch(this->_pitch.value() * f); this->_osc[0].Square(osc); break; case OSC_SAW: this->_osc[0].pitch(this->_pitch.value() * f); this->_osc[0].Saw(osc); break; case OSC_TRI: this->_osc[0].pitch(this->_pitch.value() * f); this->_osc[0].Tri(osc); break; default: return; } if (part->flags & BIQUAD_SERIAL) { osc *= amp; osc *= this->_amp.value(); if (part->bq1.mode) { if (last_f != ff) { this->biquad1.setFc(part->bq1.f / __SAMPLE_RATE * f); } osc = this->biquad1.process(osc, this->biquadA[0].first, this->biquadA[0].second); if (part->bq1.mode < BIQUAD_NOTCH) osc *= part->bq1.g; } if (part->ws.n) osc = waveshaper_transform(osc); if (part->bq2.mode) { if (last_f != ff) { this->biquad2.setFc(part->bq2.f / __SAMPLE_RATE * f); } osc = this->biquad2.process(osc, this->biquadA[1].first, this->biquadA[1].second); if (part->bq2.mode < BIQUAD_NOTCH) osc *= part->bq2.g; } if (params->stereo > 0 && (part->osc.type == OSC_NOISE1 || part->osc.type == OSC_NOISE2)) { osc2 *= amp; osc2 *= this->_amp.value(); if (part->bq1.mode) { osc2 = this->biquad1.process(osc2, this->biquadB[0].first, this->biquadB[0].second); if (part->bq1.mode < BIQUAD_NOTCH) osc2 *= part->bq1.g; } if (part->ws.n) osc2 = waveshaper_transform(osc2); if (part->bq2.mode) { osc2 = this->biquad2.process(osc2, this->biquadB[1].first, this->biquadB[1].second); if (part->bq2.mode < BIQUAD_NOTCH) osc2 *= part->bq2.g; } } else { osc2 = osc; } } else if (part->flags & BIQUAD_PARALLEL) { if (part->bq1.mode) osc = this->biquad1.process(osc) * part->bq1.g; if (part->bq2.mode) osc = this->biquad2.process(osc) * part->bq2.g; if (part->ws.n) osc = waveshaper_transform(osc); osc2 = osc; } *outL++ = osc * vca * part->level * params->levelL * 0.8f; *outR++ = osc2 * vca * part->level * params->levelR * 0.8f; CONSTRAIN(*(outL - 1), -1.f, 1.f); CONSTRAIN(*(outR - 1), -1.f, 1.f); } last_f = ff; } }; extern "C" DrumSynth drum_synth_init(const DrumModel *inst, void *(*malloc)(size_t size)) { if (malloc == nullptr) malloc = ::malloc; const size_t malloc_size = (sizeof(inst->n) + (sizeof(drum_synth_Part) * inst->n)); if (auto p = (DrumSynth)malloc(malloc_size)) { p[0] = inst->n; auto _part = (drum_synth_Part *)&p[1]; for (size_t i = 0; i < inst->n; i++) { new (&_part[i]) drum_synth_Part(); auto osc_n = std::max(1, inst->part[i].osc.n); _part[i]._osc = new (malloc(sizeof(Oscillator) * osc_n)) Oscillator[osc_n]{}; _part[i].init(&inst->part[i]); } return p; } return nullptr; } extern "C" void drum_synth_deinit(DrumSynth p, void (*free)(void* ptr)) { if (free == nullptr) free = ::free; if (p) { size_t n = p[0]; auto _part = (drum_synth_Part *)&p[1]; for (size_t i = 0; i < n; i++) { free(_part[i]._osc); } free(p); } } extern "C" void drum_synth_reset(DrumSynth inst) { if (inst) { auto _part = (drum_synth_Part *)&inst[1]; for (size_t e = 0; e < inst[0]; e++) { _part[e].reset(); } } } extern "C" void drum_synth_process_frame(DrumSynth inst, int part, float freq, const DrumParams *params, float *outL, float *outR, size_t size) { if (inst) { auto _part = (drum_synth_Part *)&inst[1]; if (part >= 0) { _part[part].process_frame(freq, params, outL, outR, size); } else { float tmpL[size]; float tmpR[size]; size_t skip = -1; for (size_t part = 0; part < inst[0]; part++) { if (skip == part) continue; _part[part].process_frame(freq, params, tmpL, tmpR, size); if (part == 0 && _part[part].part->amp_mod.dest != 0) { skip = _part[part].part->amp_mod.dest; float modL[size]; float modR[size]; _part[_part[part].part->amp_mod.dest].process_frame(freq, params, modL, modR, size); for (size_t j = 0; j < size; j++) { outL[j] += tmpL[j] * modL[j]; outR[j] += tmpR[j] * modR[j]; } } else { for (size_t j = 0; j < size; j++) { outL[j] += tmpL[j]; outR[j] += tmpR[j]; } } } } } } extern "C" int drum_synth_load_models(const uint8_t *drumkit, DrumModel _instModel[16], void *(*malloc)(size_t size)) { if (drumkit == nullptr) return 0; if (drumkit[0] == '!' && drumkit[1] == 'R' && drumkit[2] == 'C' && drumkit[3] == '8') drumkit += 4; else return 0; int inst_count = 0; const uint8_t *p = drumkit; p += 4; for (size_t i = 0; i < drumkit[0]; i++) { _instModel[i].name = reinterpret_cast(p); p += 11; _instModel[i].midi_note = *reinterpret_cast(p); p += sizeof(uint8_t); _instModel[i].n = *reinterpret_cast(p); p += sizeof(_instModel[i].n); PartArgs *part = new (malloc(sizeof(PartArgs) * _instModel[i].n)) PartArgs[_instModel[i].n]{}; _instModel[i].part = part; for (size_t j = 0; j < _instModel[i].n; j++) { part->flags = *reinterpret_cast(p); p += sizeof(part->flags); part->osc = *reinterpret_cast(p); p += sizeof(part->osc); part->osc_pitch.n = *reinterpret_cast(p); p += sizeof(part->osc_pitch.n); part->osc_pitch.xy = reinterpret_cast(p); if (part->osc_pitch.xy[part->osc_pitch.n - 1].t > 0) { // OK } int k = part->osc_pitch.n; p += sizeof(EnvXY) * k; part->osc_amp.n = *reinterpret_cast(p); p += sizeof(part->osc_amp.n); part->osc_amp.xy = reinterpret_cast(p); if (part->osc_amp.xy[part->osc_amp.n - 1].t > 0) { // OK } k = part->osc_amp.n; p += sizeof(EnvXY) * k; part->vca.n = *reinterpret_cast(p); p += sizeof(part->vca.n); part->vca.xy = reinterpret_cast(p); if (part->vca.xy[part->vca.n - 1].t > 0) { // OK } k = part->vca.n; p += sizeof(EnvXY) * k; part->bq1 = *reinterpret_cast(p); p += sizeof(BiquadArgs); part->bq2 = *reinterpret_cast(p); p += sizeof(BiquadArgs); part->ws.n = *reinterpret_cast(p); p += sizeof(part->ws.n); part->ws.xy = reinterpret_cast(p); if (part->ws.xy[part->ws.n - 1].x > 0) { // OK } k = part->ws.n; p += sizeof(WS_XY) * k; if (part->flags & VCF) { part->vcf = reinterpret_cast(p); p += sizeof(*part->vcf); part->vcf_env.n = *reinterpret_cast(p); p += sizeof(part->vcf_env.n); part->vcf_env.xy = reinterpret_cast(p); if (part->vcf_env.xy[part->vcf_env.n - 1].t > 0) { // OK } k = part->vcf_env.n; p += sizeof(EnvXY) * k; } part->amp_mod.dest = *reinterpret_cast(p); p += sizeof(part->amp_mod.dest); part->amp_mod.offset = *reinterpret_cast(p); p += sizeof(part->amp_mod.offset); part->level = *reinterpret_cast(p); p += sizeof(part->level); part++; } inst_count++; } return inst_count; } float drum_synth_process_ws(DrumSynth inst, int part, float x) { auto _part = (drum_synth_Part *)&inst[1]; if (part >= 0 && _part[part].part->ws.n) { return _part[part].waveshaper_transform(x); } return x; } ================================================ FILE: lib/drumsynth/drumsynth.h ================================================ // Copyright (C)2021 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #pragma once #include #include #include struct EnvXY { uint32_t t; float v; }; struct EnvArgs { int32_t n; const EnvXY *xy; //[16]; }; struct WS_XY { float x; float y; }; struct WSArgs { uint32_t n; const WS_XY *xy; //[8]; }; enum BiquadMode : uint32_t { BIQUAD_THRU = 0, BIQUAD_LP, BIQUAD_HP, BIQUAD_BP, BIQUAD_NOTCH, BIQUAD_PKG, BIQUAD_LSV, BIQUAD_HSV, }; struct BiquadArgs { BiquadMode mode; float f; float q; float g; }; enum OscType : uint32_t { OSC_NONE = 0, OSC_SINE = 1, OSC_SAW, OSC_TRI, OSC_SQUARE, OSC_METALLIC, OSC_NOISE1, OSC_NOISE2, OSC_NOISE3, OSC_NOISE_NES, OSC_NOISE_SID, }; struct OscArgs { OscType type; float fa; float fb; float duty; uint32_t n; }; struct AmpMod { uint32_t dest; float offset; }; struct VCFArgs { float cutoff; float res; float envDepth; float velDepth; }; enum PartFlags : uint32_t { BIQUAD_SERIAL = 1 << 1, BIQUAD_PARALLEL = 1 << 2, VCF = 1 << 3, }; struct PartArgs { PartFlags flags; OscArgs osc; EnvArgs osc_pitch; EnvArgs osc_amp; EnvArgs vca; BiquadArgs bq1; BiquadArgs bq2; WSArgs ws; const VCFArgs *vcf; EnvArgs vcf_env; AmpMod amp_mod; float level; }; struct DrumModel { const char *name; uint8_t midi_note; size_t n; const PartArgs *part; }; struct DrumParams { uint32_t t; float attack; float decay; float stereo; float levelL; float levelR; }; struct DrumKit { int n; const DrumModel *inst; }; typedef uint32_t *DrumSynth; extern "C" { DrumSynth drum_synth_init(const DrumModel *inst, void *(*malloc)(size_t size)); void drum_synth_deinit(DrumSynth inst, void (*free)(void* ptr)); void drum_synth_process_frame(DrumSynth inst, int part, float freq, const DrumParams *params, float *outL, float *outR, size_t size); void drum_synth_reset(DrumSynth inst); int drum_synth_load_models(const uint8_t *drumkit, DrumModel _instModel[16], void *(*malloc)(size_t size)); } ================================================ FILE: lib/drumsynth/drumsynth_claps.h ================================================ #include #ifndef FLASHMEM #include "pgmspace.h" #endif const uint8_t drum_synth_claps[] FLASHMEM = { 0xa, 0x0, 0x0, 0x0, 0x43, 0x6c, 0x61, 0x70, 0x39, 0x30, 0x39, 0x0, 0x43, 0x6c, 0x61, 0x70, 0x3, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xdf, 0x1, 0x0, 0x0, 0x56, 0x38, 0x81, 0x3d, 0xe0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xbf, 0x3, 0x0, 0x0, 0x56, 0x38, 0x81, 0x3d, 0xc0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x2f, 0x6, 0x0, 0x0, 0x56, 0x38, 0x81, 0x3d, 0x30, 0x6, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xbf, 0x2d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x80, 0x9, 0x44, 0x2f, 0xdd, 0xe4, 0x3e, 0x7, 0xb7, 0x5, 0x40, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x63, 0x44, 0xba, 0x49, 0x8c, 0x3f, 0xbf, 0xc2, 0x20, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x40, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xdf, 0x1, 0x0, 0x0, 0x56, 0x38, 0x81, 0x3d, 0xe0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xbf, 0x3, 0x0, 0x0, 0x56, 0x38, 0x81, 0x3d, 0xc0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x2f, 0x6, 0x0, 0x0, 0x56, 0x38, 0x81, 0x3d, 0x30, 0x6, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xbf, 0x2d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x40, 0xfa, 0x45, 0xaa, 0xf1, 0x82, 0x3f, 0x4f, 0x8, 0x86, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x63, 0x60, 0x34, 0x3f, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x80, 0x5b, 0x44, 0x8, 0xac, 0xac, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x54, 0x44, 0x8, 0xac, 0xac, 0x3f, 0x7, 0xb7, 0x5, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0x43, 0x7, 0x3f, 0x43, 0x6c, 0x61, 0x70, 0x38, 0x30, 0x38, 0x0, 0x43, 0x50, 0x38, 0x30, 0x2, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x40, 0x2, 0x0, 0x0, 0x6c, 0xc0, 0x7d, 0x3d, 0x70, 0x2, 0x0, 0x0, 0x36, 0x7, 0x5f, 0x3f, 0xb0, 0x4, 0x0, 0x0, 0xdf, 0xca, 0x54, 0x3d, 0xe0, 0x4, 0x0, 0x0, 0x30, 0xf2, 0x6e, 0x3f, 0x20, 0x7, 0x0, 0x0, 0x6c, 0xc0, 0x7d, 0x3d, 0x50, 0x7, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x20, 0x40, 0x0, 0x0, 0xac, 0xc5, 0x27, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xd0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x10, 0x86, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x44, 0x7d, 0x3f, 0xf5, 0x3e, 0x49, 0x4, 0xc, 0x40, 0x3, 0x0, 0x0, 0x0, 0x0, 0x40, 0x73, 0x44, 0x31, 0x8, 0xc, 0x40, 0x7b, 0x86, 0x19, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x40, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xac, 0xc5, 0x27, 0x37, 0xe0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x50, 0xa5, 0x1, 0x0, 0xac, 0xc5, 0x27, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x80, 0x77, 0x44, 0x66, 0x66, 0x96, 0x3f, 0x65, 0x7a, 0x74, 0x3f, 0x3, 0x0, 0x0, 0x0, 0x0, 0x40, 0x73, 0x44, 0xaa, 0xf1, 0x82, 0x3f, 0x4f, 0x8, 0x86, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa6, 0x84, 0xbf, 0x3e, 0x43, 0x50, 0x38, 0x30, 0x38, 0x5f, 0x34, 0x5f, 0x31, 0x34, 0x0, 0x43, 0x2, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x32, 0x3, 0x0, 0x0, 0xa5, 0x30, 0x1f, 0x3e, 0x43, 0x3, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x53, 0x6, 0x0, 0x0, 0xa5, 0x30, 0x1f, 0x3e, 0x65, 0x6, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xcb, 0x9, 0x0, 0x0, 0x63, 0x80, 0xc4, 0x3d, 0xee, 0x9, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xcb, 0x4f, 0x0, 0x0, 0x8b, 0xe1, 0x6a, 0x38, 0x7d, 0x76, 0x1, 0x0, 0xac, 0xc5, 0x27, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x15, 0x26, 0x1a, 0x44, 0x44, 0xfb, 0x82, 0x3f, 0x6b, 0x9e, 0xeb, 0x3f, 0x3, 0x0, 0x0, 0x0, 0x88, 0xfc, 0x30, 0x44, 0x7b, 0xbe, 0x16, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x40, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23, 0x69, 0xb7, 0x3d, 0x32, 0xd, 0x0, 0x0, 0x3a, 0x7, 0x5f, 0x3f, 0x7d, 0x76, 0x1, 0x0, 0xac, 0xc5, 0x27, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xab, 0xbd, 0x59, 0x44, 0xf, 0x63, 0x96, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd, 0xcc, 0x8c, 0x3f, 0x43, 0x50, 0x38, 0x30, 0x38, 0x31, 0x30, 0x5f, 0x33, 0x30, 0x0, 0x43, 0x3, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x14, 0x4, 0x0, 0x0, 0xed, 0xf3, 0xd0, 0x3e, 0x24, 0x7, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x55, 0xd, 0x0, 0x0, 0xdc, 0xd5, 0x2b, 0x3d, 0x37, 0xe, 0x0, 0x0, 0x90, 0x4d, 0x42, 0x3f, 0xae, 0x14, 0x0, 0x0, 0x75, 0x75, 0xc7, 0x3b, 0xd6, 0x15, 0x0, 0x0, 0x2a, 0x0, 0x1e, 0x3f, 0x7b, 0x25, 0x0, 0x0, 0xa4, 0x8c, 0x38, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x81, 0x21, 0x16, 0x44, 0x2e, 0x4, 0xb9, 0x3f, 0x60, 0xaf, 0x8b, 0x40, 0x2, 0x0, 0x0, 0x0, 0x3e, 0xde, 0x20, 0x44, 0x25, 0xe6, 0xf3, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd, 0xcc, 0x4, 0x40, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x65, 0x36, 0x48, 0x3b, 0x55, 0x3, 0x0, 0x0, 0x0, 0x38, 0x76, 0x3b, 0xcf, 0x3, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xa8, 0x9, 0x0, 0x0, 0x1a, 0x19, 0x64, 0x3c, 0x11, 0xa, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x6, 0x12, 0x0, 0x0, 0x12, 0x30, 0xba, 0x3b, 0x29, 0x12, 0x0, 0x0, 0xd1, 0xe9, 0xa9, 0x3e, 0x65, 0x56, 0x0, 0x0, 0xa4, 0x8c, 0x38, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x80, 0x57, 0x5f, 0x44, 0xd6, 0xab, 0x2, 0x40, 0xb7, 0x5e, 0x68, 0x40, 0x3, 0x0, 0x0, 0x0, 0xd8, 0x7b, 0x73, 0x44, 0xd2, 0xaa, 0xac, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x54, 0xe3, 0xc1, 0x3f, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23, 0x69, 0xb7, 0x3d, 0x92, 0x12, 0x0, 0x0, 0x30, 0xf2, 0x6e, 0x3f, 0x65, 0x56, 0x0, 0x0, 0xb6, 0x86, 0xd2, 0x3d, 0x7d, 0x76, 0x1, 0x0, 0xac, 0xc5, 0x27, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x5b, 0x48, 0xa3, 0x44, 0xf, 0x63, 0x96, 0x3f, 0xb6, 0xf6, 0x92, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xdd, 0x24, 0x2, 0x40, 0x43, 0x50, 0x38, 0x30, 0x38, 0x5f, 0x32, 0x5f, 0x31, 0x38, 0x0, 0x43, 0x2, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xb8, 0x2, 0x0, 0x0, 0x57, 0x41, 0x8c, 0x3c, 0xfe, 0x2, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xa5, 0x5, 0x0, 0x0, 0x96, 0xea, 0x82, 0x3c, 0xd, 0x6, 0x0, 0x0, 0x30, 0xf2, 0x6e, 0x3f, 0x63, 0x9, 0x0, 0x0, 0xa7, 0xc9, 0xc, 0x3c, 0xee, 0x9, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xcb, 0x4f, 0x0, 0x0, 0x8b, 0xe1, 0x6a, 0x38, 0x7d, 0x76, 0x1, 0x0, 0xac, 0xc5, 0x27, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x9e, 0xf0, 0x85, 0x44, 0xc7, 0x13, 0x2d, 0x3f, 0x69, 0x1b, 0xf1, 0x3f, 0x2, 0x0, 0x0, 0x0, 0x9, 0x42, 0x6, 0x44, 0x20, 0xb8, 0x46, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x40, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23, 0x69, 0xb7, 0x3d, 0x51, 0x9, 0x0, 0x0, 0x24, 0x7b, 0x0, 0x3f, 0xc3, 0x8, 0x1, 0x0, 0xac, 0xc5, 0x27, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x9e, 0xf0, 0x85, 0x44, 0xf, 0x63, 0x96, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x33, 0x33, 0x53, 0x3f, 0x43, 0x50, 0x38, 0x30, 0x38, 0x5f, 0x38, 0x5f, 0x33, 0x33, 0x0, 0x43, 0x2, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xf, 0x3, 0x0, 0x0, 0xa5, 0x30, 0x1f, 0x3e, 0x55, 0x3, 0x0, 0x0, 0x3a, 0x7, 0x5f, 0x3f, 0x1f, 0x6, 0x0, 0x0, 0x2a, 0xc4, 0x43, 0x3e, 0x76, 0x6, 0x0, 0x0, 0x30, 0xf2, 0x6e, 0x3f, 0x1d, 0x9, 0x0, 0x0, 0xe1, 0x95, 0x14, 0x3e, 0x51, 0x9, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xd6, 0xb, 0x0, 0x0, 0xed, 0xf3, 0xd0, 0x3e, 0xe7, 0xb, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x55, 0xd, 0x0, 0x0, 0xca, 0xdd, 0xdf, 0x3e, 0xf7, 0xe, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xfe, 0x38, 0x1, 0x0, 0xa4, 0x8c, 0x38, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x88, 0xfc, 0x30, 0x44, 0x6c, 0x7a, 0x74, 0x3f, 0xa9, 0x84, 0xbf, 0x3f, 0x3, 0x0, 0x0, 0x0, 0x48, 0x6f, 0x50, 0x44, 0x6c, 0x7a, 0x74, 0x3f, 0xf6, 0xeb, 0xe8, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x33, 0x33, 0x3, 0x40, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23, 0x69, 0xb7, 0x3d, 0x14, 0x4, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xe2, 0x96, 0x0, 0x0, 0xff, 0x3e, 0xe3, 0x3c, 0x7d, 0x76, 0x1, 0x0, 0xac, 0xc5, 0x27, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xb0, 0x7c, 0xa0, 0x44, 0xf, 0x63, 0x96, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x79, 0xe9, 0x66, 0x3f, 0x43, 0x50, 0x38, 0x30, 0x38, 0x5f, 0x35, 0x5f, 0x34, 0x32, 0x0, 0x43, 0x3, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x42, 0x6, 0x0, 0x0, 0xfb, 0xe8, 0x54, 0x3c, 0x53, 0x6, 0x0, 0x0, 0x30, 0xf2, 0x6e, 0x3f, 0xa1, 0xb, 0x0, 0x0, 0x93, 0x8e, 0x72, 0x3d, 0x7b, 0x25, 0x0, 0x0, 0xa4, 0x8c, 0x38, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xab, 0xbd, 0x59, 0x44, 0x2e, 0x4, 0xb9, 0x3f, 0x50, 0x56, 0x28, 0x40, 0x2, 0x0, 0x0, 0x0, 0xf7, 0xa4, 0x3d, 0x44, 0x25, 0xe6, 0xf3, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x3f, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x65, 0x36, 0x48, 0x3b, 0x43, 0x3, 0x0, 0x0, 0xb2, 0xd5, 0x65, 0x3b, 0x55, 0x3, 0x0, 0x0, 0x3a, 0x7, 0x5f, 0x3f, 0x40, 0x9, 0x0, 0x0, 0xc3, 0xd4, 0x16, 0x3c, 0x51, 0x9, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x65, 0x56, 0x0, 0x0, 0xa4, 0x8c, 0x38, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x9e, 0xf0, 0x85, 0x44, 0x64, 0x59, 0x8c, 0x3f, 0x60, 0xe5, 0xa4, 0x3f, 0x3, 0x0, 0x0, 0x0, 0x9e, 0xf0, 0x85, 0x44, 0xd2, 0xaa, 0xac, 0x3f, 0x95, 0x9d, 0x12, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x3f, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23, 0x69, 0xb7, 0x3d, 0x92, 0x12, 0x0, 0x0, 0x30, 0xf2, 0x6e, 0x3f, 0x3b, 0x4e, 0x0, 0x0, 0x3d, 0x62, 0x74, 0x3c, 0x7d, 0x76, 0x1, 0x0, 0xac, 0xc5, 0x27, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xf6, 0x31, 0xbd, 0x44, 0xf, 0x63, 0x96, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x85, 0xeb, 0x81, 0x3f, 0x43, 0x50, 0x38, 0x56, 0x4f, 0x70, 0x6e, 0x5f, 0x31, 0x35, 0x0, 0x43, 0x2, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xf, 0x3, 0x0, 0x0, 0xa5, 0x30, 0x1f, 0x3e, 0x55, 0x3, 0x0, 0x0, 0x3a, 0x7, 0x5f, 0x3f, 0x1f, 0x6, 0x0, 0x0, 0x2a, 0xc4, 0x43, 0x3e, 0x76, 0x6, 0x0, 0x0, 0x30, 0xf2, 0x6e, 0x3f, 0x1d, 0x9, 0x0, 0x0, 0xe1, 0x95, 0x14, 0x3e, 0x51, 0x9, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xd6, 0xb, 0x0, 0x0, 0xed, 0xf3, 0xd0, 0x3e, 0xe7, 0xb, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x55, 0xd, 0x0, 0x0, 0xca, 0xdd, 0xdf, 0x3e, 0xf7, 0xe, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xfe, 0x38, 0x1, 0x0, 0xa4, 0x8c, 0x38, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x88, 0xfc, 0x30, 0x44, 0x6c, 0x7a, 0x74, 0x3f, 0xa9, 0x84, 0xbf, 0x3f, 0x3, 0x0, 0x0, 0x0, 0xea, 0x84, 0x8f, 0x44, 0x6c, 0x7a, 0x74, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x40, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23, 0x69, 0xb7, 0x3d, 0x14, 0x4, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xe2, 0x96, 0x0, 0x0, 0xff, 0x3e, 0xe3, 0x3c, 0x7d, 0x76, 0x1, 0x0, 0xac, 0xc5, 0x27, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xf6, 0x31, 0xbd, 0x44, 0xf, 0x63, 0x96, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd, 0xcc, 0x8c, 0x3f, 0x43, 0x50, 0x38, 0x30, 0x38, 0x5f, 0x36, 0x5f, 0x34, 0x32, 0x0, 0x43, 0x2, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x32, 0x3, 0x0, 0x0, 0x1f, 0xbb, 0xb, 0x3d, 0x43, 0x3, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x53, 0x6, 0x0, 0x0, 0x4c, 0x19, 0x38, 0x3d, 0x65, 0x6, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xe9, 0x8, 0x0, 0x0, 0x0, 0xca, 0x9f, 0x3d, 0xfa, 0x8, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0xcb, 0x4f, 0x0, 0x0, 0x8b, 0xe1, 0x6a, 0x38, 0x7d, 0x76, 0x1, 0x0, 0xac, 0xc5, 0x27, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x5b, 0x48, 0xa3, 0x44, 0xd2, 0xaa, 0xac, 0x3f, 0x50, 0x56, 0x28, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x89, 0x41, 0xe0, 0x3f, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23, 0x69, 0xb7, 0x3d, 0x92, 0x12, 0x0, 0x0, 0x30, 0xf2, 0x6e, 0x3f, 0x3b, 0x4e, 0x0, 0x0, 0x3d, 0x62, 0x74, 0x3c, 0x7d, 0x76, 0x1, 0x0, 0xac, 0xc5, 0x27, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xf6, 0x31, 0xbd, 0x44, 0xf, 0x63, 0x96, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0x2d, 0x9a, 0x3f, 0x43, 0x50, 0x52, 0x4e, 0x44, 0x30, 0x0, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x2, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x42, 0x6, 0x0, 0x0, 0xfb, 0xe8, 0x54, 0x3c, 0x53, 0x6, 0x0, 0x0, 0x30, 0xf2, 0x6e, 0x3f, 0xa1, 0xb, 0x0, 0x0, 0x93, 0x8e, 0x72, 0x3d, 0x7b, 0x25, 0x0, 0x0, 0xa4, 0x8c, 0x38, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xab, 0xbd, 0x59, 0x44, 0x2e, 0x4, 0xb9, 0x3f, 0x69, 0x53, 0xbd, 0x3f, 0x2, 0x0, 0x0, 0x0, 0xf7, 0xa4, 0x3d, 0x44, 0x25, 0xe6, 0xf3, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x33, 0x33, 0x3, 0x40, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23, 0x69, 0xb7, 0x3d, 0x92, 0x12, 0x0, 0x0, 0x30, 0xf2, 0x6e, 0x3f, 0x3b, 0x4e, 0x0, 0x0, 0x3d, 0x62, 0x74, 0x3c, 0x7d, 0x76, 0x1, 0x0, 0xac, 0xc5, 0x27, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xf6, 0x31, 0xbd, 0x44, 0xf, 0x63, 0x96, 0x3f, 0x0, 0x0, 0x80, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd, 0xcc, 0x8c, 0x3f, 0x0, 0x0, 0x0, 0x0, }; ================================================ FILE: lib/faust/build.sh ================================================ for f in *.dsp; do faust ./$f -lang c > ./$f.h done ================================================ FILE: lib/faust/djembe.dsp ================================================ //faust ./djembe.dsp -cn djembe > ./djembe.hxx import("stdfaust.lib"); freq = hslider("Freq",0.5,0,1000,0.01):si.smoo; strikePosition = hslider("Pos",0.5,0,1,0.00001):si.smoo; strikeSharpness = hslider("Sharpness",0.5,0,5,0.00001):si.smoo; gain = 3; trigger = button("trigger"); process = pm.djembe(freq,strikePosition,strikeSharpness,gain,trigger); ================================================ FILE: lib/faust/djembe.dsp.h ================================================ /* ------------------------------------------------------------ name: "djembe" Code generated with Faust 2.37.3 (https://faust.grame.fr) Compilation options: -lang c -es 1 -single -ftz 0 ------------------------------------------------------------ */ #ifndef __mydsp_H__ #define __mydsp_H__ #ifndef FAUSTFLOAT #define FAUSTFLOAT float #endif #ifdef __cplusplus extern "C" { #endif #include #include #include static float mydsp_faustpower2_f(float value) { return (value * value); } #ifndef FAUSTCLASS #define FAUSTCLASS mydsp #endif #ifdef __APPLE__ #define exp10f __exp10f #define exp10 __exp10 #endif typedef struct { int iRec3[2]; int fSampleRate; float fConst1; float fConst2; FAUSTFLOAT fHslider0; float fConst3; float fRec4[2]; float fRec2[3]; float fRec1[3]; FAUSTFLOAT fButton0; float fVec0[2]; int iRec5[2]; float fConst4; FAUSTFLOAT fHslider1; float fRec6[2]; float fConst6; float fConst7; FAUSTFLOAT fHslider2; float fRec7[2]; float fConst8; float fRec0[3]; float fConst10; float fConst11; float fRec8[3]; float fConst13; float fConst14; float fRec9[3]; float fConst16; float fConst17; float fRec10[3]; float fConst19; float fConst20; float fRec11[3]; float fConst22; float fConst23; float fRec12[3]; float fConst25; float fConst26; float fRec13[3]; float fConst28; float fConst29; float fRec14[3]; float fConst31; float fConst32; float fRec15[3]; float fConst34; float fConst35; float fRec16[3]; float fConst37; float fConst38; float fRec17[3]; float fConst40; float fConst41; float fRec18[3]; float fConst43; float fConst44; float fRec19[3]; float fConst46; float fConst47; float fRec20[3]; float fConst49; float fConst50; float fRec21[3]; float fConst52; float fConst53; float fRec22[3]; float fConst55; float fConst56; float fRec23[3]; float fConst58; float fConst59; float fRec24[3]; float fConst61; float fConst62; float fRec25[3]; float fConst64; float fConst65; float fRec26[3]; } mydsp; mydsp* newmydsp() { mydsp* dsp = (mydsp*)calloc(1, sizeof(mydsp)); return dsp; } void deletemydsp(mydsp* dsp) { free(dsp); } void metadatamydsp(MetaGlue* m) { m->declare(m->metaInterface, "compile_options", "-lang c -es 1 -single -ftz 0"); m->declare(m->metaInterface, "envelopes.lib/ar:author", "Yann Orlarey, Stéphane Letz"); m->declare(m->metaInterface, "envelopes.lib/author", "GRAME"); m->declare(m->metaInterface, "envelopes.lib/copyright", "GRAME"); m->declare(m->metaInterface, "envelopes.lib/license", "LGPL with exception"); m->declare(m->metaInterface, "envelopes.lib/name", "Faust Envelope Library"); m->declare(m->metaInterface, "envelopes.lib/version", "0.1"); m->declare(m->metaInterface, "filename", "djembe.dsp"); m->declare(m->metaInterface, "filters.lib/fir:author", "Julius O. Smith III"); m->declare(m->metaInterface, "filters.lib/fir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); m->declare(m->metaInterface, "filters.lib/fir:license", "MIT-style STK-4.3 license"); m->declare(m->metaInterface, "filters.lib/highpass:author", "Julius O. Smith III"); m->declare(m->metaInterface, "filters.lib/highpass:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); m->declare(m->metaInterface, "filters.lib/iir:author", "Julius O. Smith III"); m->declare(m->metaInterface, "filters.lib/iir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); m->declare(m->metaInterface, "filters.lib/iir:license", "MIT-style STK-4.3 license"); m->declare(m->metaInterface, "filters.lib/lowpass0_highpass1", "Copyright (C) 2003-2019 by Julius O. Smith III "); m->declare(m->metaInterface, "filters.lib/lowpass0_highpass1:author", "Julius O. Smith III"); m->declare(m->metaInterface, "filters.lib/lowpass:author", "Julius O. Smith III"); m->declare(m->metaInterface, "filters.lib/lowpass:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); m->declare(m->metaInterface, "filters.lib/lowpass:license", "MIT-style STK-4.3 license"); m->declare(m->metaInterface, "filters.lib/name", "Faust Filters Library"); m->declare(m->metaInterface, "filters.lib/tf2:author", "Julius O. Smith III"); m->declare(m->metaInterface, "filters.lib/tf2:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); m->declare(m->metaInterface, "filters.lib/tf2:license", "MIT-style STK-4.3 license"); m->declare(m->metaInterface, "filters.lib/tf2s:author", "Julius O. Smith III"); m->declare(m->metaInterface, "filters.lib/tf2s:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); m->declare(m->metaInterface, "filters.lib/tf2s:license", "MIT-style STK-4.3 license"); m->declare(m->metaInterface, "filters.lib/version", "0.3"); m->declare(m->metaInterface, "maths.lib/author", "GRAME"); m->declare(m->metaInterface, "maths.lib/copyright", "GRAME"); m->declare(m->metaInterface, "maths.lib/license", "LGPL with exception"); m->declare(m->metaInterface, "maths.lib/name", "Faust Math Library"); m->declare(m->metaInterface, "maths.lib/version", "2.5"); m->declare(m->metaInterface, "name", "djembe"); m->declare(m->metaInterface, "noises.lib/name", "Faust Noise Generator Library"); m->declare(m->metaInterface, "noises.lib/version", "0.1"); m->declare(m->metaInterface, "physmodels.lib/name", "Faust Physical Models Library"); m->declare(m->metaInterface, "physmodels.lib/version", "0.1"); m->declare(m->metaInterface, "platform.lib/name", "Generic Platform Library"); m->declare(m->metaInterface, "platform.lib/version", "0.2"); m->declare(m->metaInterface, "signals.lib/name", "Faust Signal Routing Library"); m->declare(m->metaInterface, "signals.lib/version", "0.1"); } int getSampleRatemydsp(mydsp* dsp) { return dsp->fSampleRate; } int getNumInputsmydsp(mydsp* dsp) { return 0; } int getNumOutputsmydsp(mydsp* dsp) { return 1; } void classInitmydsp(int sample_rate) { } void instanceResetUserInterfacemydsp(mydsp* dsp) { dsp->fHslider0 = (FAUSTFLOAT)0.5f; dsp->fButton0 = (FAUSTFLOAT)0.0f; dsp->fHslider1 = (FAUSTFLOAT)0.5f; dsp->fHslider2 = (FAUSTFLOAT)0.5f; } void instanceClearmydsp(mydsp* dsp) { /* C99 loop */ { int l0; for (l0 = 0; (l0 < 2); l0 = (l0 + 1)) { dsp->iRec3[l0] = 0; } } /* C99 loop */ { int l1; for (l1 = 0; (l1 < 2); l1 = (l1 + 1)) { dsp->fRec4[l1] = 0.0f; } } /* C99 loop */ { int l2; for (l2 = 0; (l2 < 3); l2 = (l2 + 1)) { dsp->fRec2[l2] = 0.0f; } } /* C99 loop */ { int l3; for (l3 = 0; (l3 < 3); l3 = (l3 + 1)) { dsp->fRec1[l3] = 0.0f; } } /* C99 loop */ { int l4; for (l4 = 0; (l4 < 2); l4 = (l4 + 1)) { dsp->fVec0[l4] = 0.0f; } } /* C99 loop */ { int l5; for (l5 = 0; (l5 < 2); l5 = (l5 + 1)) { dsp->iRec5[l5] = 0; } } /* C99 loop */ { int l6; for (l6 = 0; (l6 < 2); l6 = (l6 + 1)) { dsp->fRec6[l6] = 0.0f; } } /* C99 loop */ { int l7; for (l7 = 0; (l7 < 2); l7 = (l7 + 1)) { dsp->fRec7[l7] = 0.0f; } } /* C99 loop */ { int l8; for (l8 = 0; (l8 < 3); l8 = (l8 + 1)) { dsp->fRec0[l8] = 0.0f; } } /* C99 loop */ { int l9; for (l9 = 0; (l9 < 3); l9 = (l9 + 1)) { dsp->fRec8[l9] = 0.0f; } } /* C99 loop */ { int l10; for (l10 = 0; (l10 < 3); l10 = (l10 + 1)) { dsp->fRec9[l10] = 0.0f; } } /* C99 loop */ { int l11; for (l11 = 0; (l11 < 3); l11 = (l11 + 1)) { dsp->fRec10[l11] = 0.0f; } } /* C99 loop */ { int l12; for (l12 = 0; (l12 < 3); l12 = (l12 + 1)) { dsp->fRec11[l12] = 0.0f; } } /* C99 loop */ { int l13; for (l13 = 0; (l13 < 3); l13 = (l13 + 1)) { dsp->fRec12[l13] = 0.0f; } } /* C99 loop */ { int l14; for (l14 = 0; (l14 < 3); l14 = (l14 + 1)) { dsp->fRec13[l14] = 0.0f; } } /* C99 loop */ { int l15; for (l15 = 0; (l15 < 3); l15 = (l15 + 1)) { dsp->fRec14[l15] = 0.0f; } } /* C99 loop */ { int l16; for (l16 = 0; (l16 < 3); l16 = (l16 + 1)) { dsp->fRec15[l16] = 0.0f; } } /* C99 loop */ { int l17; for (l17 = 0; (l17 < 3); l17 = (l17 + 1)) { dsp->fRec16[l17] = 0.0f; } } /* C99 loop */ { int l18; for (l18 = 0; (l18 < 3); l18 = (l18 + 1)) { dsp->fRec17[l18] = 0.0f; } } /* C99 loop */ { int l19; for (l19 = 0; (l19 < 3); l19 = (l19 + 1)) { dsp->fRec18[l19] = 0.0f; } } /* C99 loop */ { int l20; for (l20 = 0; (l20 < 3); l20 = (l20 + 1)) { dsp->fRec19[l20] = 0.0f; } } /* C99 loop */ { int l21; for (l21 = 0; (l21 < 3); l21 = (l21 + 1)) { dsp->fRec20[l21] = 0.0f; } } /* C99 loop */ { int l22; for (l22 = 0; (l22 < 3); l22 = (l22 + 1)) { dsp->fRec21[l22] = 0.0f; } } /* C99 loop */ { int l23; for (l23 = 0; (l23 < 3); l23 = (l23 + 1)) { dsp->fRec22[l23] = 0.0f; } } /* C99 loop */ { int l24; for (l24 = 0; (l24 < 3); l24 = (l24 + 1)) { dsp->fRec23[l24] = 0.0f; } } /* C99 loop */ { int l25; for (l25 = 0; (l25 < 3); l25 = (l25 + 1)) { dsp->fRec24[l25] = 0.0f; } } /* C99 loop */ { int l26; for (l26 = 0; (l26 < 3); l26 = (l26 + 1)) { dsp->fRec25[l26] = 0.0f; } } /* C99 loop */ { int l27; for (l27 = 0; (l27 < 3); l27 = (l27 + 1)) { dsp->fRec26[l27] = 0.0f; } } } void instanceConstantsmydsp(mydsp* dsp, int sample_rate) { dsp->fSampleRate = sample_rate; float fConst0 = fminf(192000.0f, fmaxf(1.0f, (float)dsp->fSampleRate)); dsp->fConst1 = (3.14159274f / fConst0); dsp->fConst2 = (44.0999985f / fConst0); dsp->fConst3 = (1.0f - dsp->fConst2); dsp->fConst4 = (0.00200000009f * fConst0); float fConst5 = powf(0.00100000005f, (1.66666663f / fConst0)); dsp->fConst6 = (0.0f - (2.0f * fConst5)); dsp->fConst7 = (6.28318548f / fConst0); dsp->fConst8 = mydsp_faustpower2_f(fConst5); float fConst9 = powf(0.00100000005f, (1.75438595f / fConst0)); dsp->fConst10 = (0.0f - (2.0f * fConst9)); dsp->fConst11 = mydsp_faustpower2_f(fConst9); float fConst12 = powf(0.00100000005f, (1.85185182f / fConst0)); dsp->fConst13 = (0.0f - (2.0f * fConst12)); dsp->fConst14 = mydsp_faustpower2_f(fConst12); float fConst15 = powf(0.00100000005f, (1.96078432f / fConst0)); dsp->fConst16 = (0.0f - (2.0f * fConst15)); dsp->fConst17 = mydsp_faustpower2_f(fConst15); float fConst18 = powf(0.00100000005f, (2.08333325f / fConst0)); dsp->fConst19 = (0.0f - (2.0f * fConst18)); dsp->fConst20 = mydsp_faustpower2_f(fConst18); float fConst21 = powf(0.00100000005f, (2.22222233f / fConst0)); dsp->fConst22 = (0.0f - (2.0f * fConst21)); dsp->fConst23 = mydsp_faustpower2_f(fConst21); float fConst24 = powf(0.00100000005f, (2.38095236f / fConst0)); dsp->fConst25 = (0.0f - (2.0f * fConst24)); dsp->fConst26 = mydsp_faustpower2_f(fConst24); float fConst27 = powf(0.00100000005f, (2.56410265f / fConst0)); dsp->fConst28 = (0.0f - (2.0f * fConst27)); dsp->fConst29 = mydsp_faustpower2_f(fConst27); float fConst30 = powf(0.00100000005f, (2.77777767f / fConst0)); dsp->fConst31 = (0.0f - (2.0f * fConst30)); dsp->fConst32 = mydsp_faustpower2_f(fConst30); float fConst33 = powf(0.00100000005f, (3.030303f / fConst0)); dsp->fConst34 = (0.0f - (2.0f * fConst33)); dsp->fConst35 = mydsp_faustpower2_f(fConst33); float fConst36 = powf(0.00100000005f, (3.33333325f / fConst0)); dsp->fConst37 = (0.0f - (2.0f * fConst36)); dsp->fConst38 = mydsp_faustpower2_f(fConst36); float fConst39 = powf(0.00100000005f, (3.70370364f / fConst0)); dsp->fConst40 = (0.0f - (2.0f * fConst39)); dsp->fConst41 = mydsp_faustpower2_f(fConst39); float fConst42 = powf(0.00100000005f, (4.16666651f / fConst0)); dsp->fConst43 = (0.0f - (2.0f * fConst42)); dsp->fConst44 = mydsp_faustpower2_f(fConst42); float fConst45 = powf(0.00100000005f, (4.76190472f / fConst0)); dsp->fConst46 = (0.0f - (2.0f * fConst45)); dsp->fConst47 = mydsp_faustpower2_f(fConst45); float fConst48 = powf(0.00100000005f, (5.55555534f / fConst0)); dsp->fConst49 = (0.0f - (2.0f * fConst48)); dsp->fConst50 = mydsp_faustpower2_f(fConst48); float fConst51 = powf(0.00100000005f, (6.66666651f / fConst0)); dsp->fConst52 = (0.0f - (2.0f * fConst51)); dsp->fConst53 = mydsp_faustpower2_f(fConst51); float fConst54 = powf(0.00100000005f, (8.33333302f / fConst0)); dsp->fConst55 = (0.0f - (2.0f * fConst54)); dsp->fConst56 = mydsp_faustpower2_f(fConst54); float fConst57 = powf(0.00100000005f, (11.1111107f / fConst0)); dsp->fConst58 = (0.0f - (2.0f * fConst57)); dsp->fConst59 = mydsp_faustpower2_f(fConst57); float fConst60 = powf(0.00100000005f, (16.666666f / fConst0)); dsp->fConst61 = (0.0f - (2.0f * fConst60)); dsp->fConst62 = mydsp_faustpower2_f(fConst60); float fConst63 = powf(0.00100000005f, (33.3333321f / fConst0)); dsp->fConst64 = (0.0f - (2.0f * fConst63)); dsp->fConst65 = mydsp_faustpower2_f(fConst63); } void instanceInitmydsp(mydsp* dsp, int sample_rate) { instanceConstantsmydsp(dsp, sample_rate); instanceResetUserInterfacemydsp(dsp); instanceClearmydsp(dsp); } void initmydsp(mydsp* dsp, int sample_rate) { classInitmydsp(sample_rate); instanceInitmydsp(dsp, sample_rate); } void buildUserInterfacemydsp(mydsp* dsp, UIGlue* ui_interface) { ui_interface->openVerticalBox(ui_interface->uiInterface, "djembe"); ui_interface->addHorizontalSlider(ui_interface->uiInterface, "Freq", &dsp->fHslider2, (FAUSTFLOAT)0.5f, (FAUSTFLOAT)0.0f, (FAUSTFLOAT)1000.0f, (FAUSTFLOAT)0.00999999978f); ui_interface->addHorizontalSlider(ui_interface->uiInterface, "Pos", &dsp->fHslider0, (FAUSTFLOAT)0.5f, (FAUSTFLOAT)0.0f, (FAUSTFLOAT)1.0f, (FAUSTFLOAT)9.99999975e-06f); ui_interface->addHorizontalSlider(ui_interface->uiInterface, "Sharpness", &dsp->fHslider1, (FAUSTFLOAT)0.5f, (FAUSTFLOAT)0.0f, (FAUSTFLOAT)5.0f, (FAUSTFLOAT)9.99999975e-06f); ui_interface->addButton(ui_interface->uiInterface, "trigger", &dsp->fButton0); ui_interface->closeBox(ui_interface->uiInterface); } void computemydsp(mydsp* dsp, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { FAUSTFLOAT* output0 = outputs[0]; float fSlow0 = (dsp->fConst2 * (float)dsp->fHslider0); float fSlow1 = (float)dsp->fButton0; float fSlow2 = (dsp->fConst2 * (float)dsp->fHslider1); float fSlow3 = (dsp->fConst2 * (float)dsp->fHslider2); /* C99 loop */ { int i0; for (i0 = 0; (i0 < count); i0 = (i0 + 1)) { dsp->iRec3[0] = ((1103515245 * dsp->iRec3[1]) + 12345); dsp->fRec4[0] = (fSlow0 + (dsp->fConst3 * dsp->fRec4[1])); float fTemp0 = tanf((dsp->fConst1 * ((500.0f * dsp->fRec4[0]) + 40.0f))); float fTemp1 = (1.0f / fTemp0); float fTemp2 = mydsp_faustpower2_f(fTemp0); float fTemp3 = (((fTemp1 + 1.41421354f) / fTemp0) + 1.0f); dsp->fRec2[0] = ((4.65661287e-10f * (float)dsp->iRec3[0]) - (((dsp->fRec2[2] * (((fTemp1 + -1.41421354f) / fTemp0) + 1.0f)) + (2.0f * (dsp->fRec2[1] * (1.0f - (1.0f / fTemp2))))) / fTemp3)); float fTemp4 = tanf((dsp->fConst1 * ((15000.0f * dsp->fRec4[0]) + 500.0f))); float fTemp5 = (1.0f / fTemp4); float fTemp6 = (((fTemp5 + 1.41421354f) / fTemp4) + 1.0f); dsp->fRec1[0] = (((((dsp->fRec2[1] * (0.0f - (2.0f / fTemp2))) + (dsp->fRec2[0] / fTemp2)) + (dsp->fRec2[2] / fTemp2)) / fTemp3) - (((dsp->fRec1[2] * (((fTemp5 + -1.41421354f) / fTemp4) + 1.0f)) + (2.0f * (dsp->fRec1[1] * (1.0f - (1.0f / mydsp_faustpower2_f(fTemp4)))))) / fTemp6)); dsp->fVec0[0] = fSlow1; dsp->iRec5[0] = (((dsp->iRec5[1] + (dsp->iRec5[1] > 0)) * (fSlow1 <= dsp->fVec0[1])) + (fSlow1 > dsp->fVec0[1])); dsp->fRec6[0] = (fSlow2 + (dsp->fConst3 * dsp->fRec6[1])); float fTemp7 = ((float)dsp->iRec5[0] / fmaxf(1.0f, (dsp->fConst4 * dsp->fRec6[0]))); float fTemp8 = (3.0f * (((dsp->fRec1[2] + (dsp->fRec1[0] + (2.0f * dsp->fRec1[1]))) * fmaxf(0.0f, fminf(fTemp7, (2.0f - fTemp7)))) / fTemp6)); dsp->fRec7[0] = (fSlow3 + (dsp->fConst3 * dsp->fRec7[1])); dsp->fRec0[0] = (fTemp8 - ((dsp->fConst6 * (dsp->fRec0[1] * cosf((dsp->fConst7 * dsp->fRec7[0])))) + (dsp->fConst8 * dsp->fRec0[2]))); dsp->fRec8[0] = (fTemp8 - ((dsp->fConst10 * (dsp->fRec8[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 200.0f))))) + (dsp->fConst11 * dsp->fRec8[2]))); dsp->fRec9[0] = (fTemp8 - ((dsp->fConst13 * (dsp->fRec9[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 400.0f))))) + (dsp->fConst14 * dsp->fRec9[2]))); dsp->fRec10[0] = (fTemp8 - ((dsp->fConst16 * (dsp->fRec10[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 600.0f))))) + (dsp->fConst17 * dsp->fRec10[2]))); dsp->fRec11[0] = (fTemp8 - ((dsp->fConst19 * (dsp->fRec11[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 800.0f))))) + (dsp->fConst20 * dsp->fRec11[2]))); dsp->fRec12[0] = (fTemp8 - ((dsp->fConst22 * (dsp->fRec12[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 1000.0f))))) + (dsp->fConst23 * dsp->fRec12[2]))); dsp->fRec13[0] = (fTemp8 - ((dsp->fConst25 * (dsp->fRec13[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 1200.0f))))) + (dsp->fConst26 * dsp->fRec13[2]))); dsp->fRec14[0] = (fTemp8 - ((dsp->fConst28 * (dsp->fRec14[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 1400.0f))))) + (dsp->fConst29 * dsp->fRec14[2]))); dsp->fRec15[0] = (fTemp8 - ((dsp->fConst31 * (dsp->fRec15[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 1600.0f))))) + (dsp->fConst32 * dsp->fRec15[2]))); dsp->fRec16[0] = (fTemp8 - ((dsp->fConst34 * (dsp->fRec16[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 1800.0f))))) + (dsp->fConst35 * dsp->fRec16[2]))); dsp->fRec17[0] = (fTemp8 - ((dsp->fConst37 * (dsp->fRec17[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 2000.0f))))) + (dsp->fConst38 * dsp->fRec17[2]))); dsp->fRec18[0] = (fTemp8 - ((dsp->fConst40 * (dsp->fRec18[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 2200.0f))))) + (dsp->fConst41 * dsp->fRec18[2]))); dsp->fRec19[0] = (fTemp8 - ((dsp->fConst43 * (dsp->fRec19[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 2400.0f))))) + (dsp->fConst44 * dsp->fRec19[2]))); dsp->fRec20[0] = (fTemp8 - ((dsp->fConst46 * (dsp->fRec20[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 2600.0f))))) + (dsp->fConst47 * dsp->fRec20[2]))); dsp->fRec21[0] = (fTemp8 - ((dsp->fConst49 * (dsp->fRec21[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 2800.0f))))) + (dsp->fConst50 * dsp->fRec21[2]))); dsp->fRec22[0] = (fTemp8 - ((dsp->fConst52 * (dsp->fRec22[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 3000.0f))))) + (dsp->fConst53 * dsp->fRec22[2]))); dsp->fRec23[0] = (fTemp8 - ((dsp->fConst55 * (dsp->fRec23[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 3200.0f))))) + (dsp->fConst56 * dsp->fRec23[2]))); dsp->fRec24[0] = (fTemp8 - ((dsp->fConst58 * (dsp->fRec24[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 3400.0f))))) + (dsp->fConst59 * dsp->fRec24[2]))); dsp->fRec25[0] = (fTemp8 - ((dsp->fConst61 * (dsp->fRec25[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 3600.0f))))) + (dsp->fConst62 * dsp->fRec25[2]))); dsp->fRec26[0] = (fTemp8 - ((dsp->fConst64 * (dsp->fRec26[1] * cosf((dsp->fConst7 * (dsp->fRec7[0] + 3800.0f))))) + (dsp->fConst65 * dsp->fRec26[2]))); output0[i0] = (FAUSTFLOAT)(0.0500000007f * ((((((((((((((((((((dsp->fRec0[0] + (0.25f * (dsp->fRec8[0] - dsp->fRec8[2]))) + (0.111111112f * (dsp->fRec9[0] - dsp->fRec9[2]))) + (0.0625f * (dsp->fRec10[0] - dsp->fRec10[2]))) + (0.0399999991f * (dsp->fRec11[0] - dsp->fRec11[2]))) + (0.027777778f * (dsp->fRec12[0] - dsp->fRec12[2]))) + (0.0204081628f * (dsp->fRec13[0] - dsp->fRec13[2]))) + (0.015625f * (dsp->fRec14[0] - dsp->fRec14[2]))) + (0.0123456791f * (dsp->fRec15[0] - dsp->fRec15[2]))) + (0.00999999978f * (dsp->fRec16[0] - dsp->fRec16[2]))) + (0.00826446246f * (dsp->fRec17[0] - dsp->fRec17[2]))) + (0.0069444445f * (dsp->fRec18[0] - dsp->fRec18[2]))) + (0.00591715984f * (dsp->fRec19[0] - dsp->fRec19[2]))) + (0.00510204071f * (dsp->fRec20[0] - dsp->fRec20[2]))) + (0.00444444455f * (dsp->fRec21[0] - dsp->fRec21[2]))) + (0.00390625f * (dsp->fRec22[0] - dsp->fRec22[2]))) + (0.00346020772f * (dsp->fRec23[0] - dsp->fRec23[2]))) + (0.00308641978f * (dsp->fRec24[0] - dsp->fRec24[2]))) + (0.00277008303f * (dsp->fRec25[0] - dsp->fRec25[2]))) + (0.00249999994f * (dsp->fRec26[0] - dsp->fRec26[2]))) - dsp->fRec0[2])); dsp->iRec3[1] = dsp->iRec3[0]; dsp->fRec4[1] = dsp->fRec4[0]; dsp->fRec2[2] = dsp->fRec2[1]; dsp->fRec2[1] = dsp->fRec2[0]; dsp->fRec1[2] = dsp->fRec1[1]; dsp->fRec1[1] = dsp->fRec1[0]; dsp->fVec0[1] = dsp->fVec0[0]; dsp->iRec5[1] = dsp->iRec5[0]; dsp->fRec6[1] = dsp->fRec6[0]; dsp->fRec7[1] = dsp->fRec7[0]; dsp->fRec0[2] = dsp->fRec0[1]; dsp->fRec0[1] = dsp->fRec0[0]; dsp->fRec8[2] = dsp->fRec8[1]; dsp->fRec8[1] = dsp->fRec8[0]; dsp->fRec9[2] = dsp->fRec9[1]; dsp->fRec9[1] = dsp->fRec9[0]; dsp->fRec10[2] = dsp->fRec10[1]; dsp->fRec10[1] = dsp->fRec10[0]; dsp->fRec11[2] = dsp->fRec11[1]; dsp->fRec11[1] = dsp->fRec11[0]; dsp->fRec12[2] = dsp->fRec12[1]; dsp->fRec12[1] = dsp->fRec12[0]; dsp->fRec13[2] = dsp->fRec13[1]; dsp->fRec13[1] = dsp->fRec13[0]; dsp->fRec14[2] = dsp->fRec14[1]; dsp->fRec14[1] = dsp->fRec14[0]; dsp->fRec15[2] = dsp->fRec15[1]; dsp->fRec15[1] = dsp->fRec15[0]; dsp->fRec16[2] = dsp->fRec16[1]; dsp->fRec16[1] = dsp->fRec16[0]; dsp->fRec17[2] = dsp->fRec17[1]; dsp->fRec17[1] = dsp->fRec17[0]; dsp->fRec18[2] = dsp->fRec18[1]; dsp->fRec18[1] = dsp->fRec18[0]; dsp->fRec19[2] = dsp->fRec19[1]; dsp->fRec19[1] = dsp->fRec19[0]; dsp->fRec20[2] = dsp->fRec20[1]; dsp->fRec20[1] = dsp->fRec20[0]; dsp->fRec21[2] = dsp->fRec21[1]; dsp->fRec21[1] = dsp->fRec21[0]; dsp->fRec22[2] = dsp->fRec22[1]; dsp->fRec22[1] = dsp->fRec22[0]; dsp->fRec23[2] = dsp->fRec23[1]; dsp->fRec23[1] = dsp->fRec23[0]; dsp->fRec24[2] = dsp->fRec24[1]; dsp->fRec24[1] = dsp->fRec24[0]; dsp->fRec25[2] = dsp->fRec25[1]; dsp->fRec25[1] = dsp->fRec25[0]; dsp->fRec26[2] = dsp->fRec26[1]; dsp->fRec26[1] = dsp->fRec26[0]; } } } #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/faust/rev_dattorro.dsp ================================================ //faust ./rev_dattorro.dsp -cn rev_dattorro > ./rev_dattorro.hxx import("stdfaust.lib"); dw = hslider("[0]D/W",0.5,0,1,0.0001):si.smoo; decay = hslider("[1]Decay",0.5,0,1,0.0001):si.smoo; damping = hslider("[2]Damp",0.5,0,1,0.0001):si.smoo; bw = hslider("[3]BW",0.5,0,1,0.0001):si.smoo; diffd= hslider("[4]DDiff",0.5,0.01,0.99,0.0001):si.smoo; diffi = hslider("[5]IDiff",0.5,0.01,0.99,0.0001):si.smoo; pre_delay = 24; process = _,_ <: (_,_ <:re.dattorro_rev(pre_delay, bw, diffi, diffi, decay, diffd, diffd, damping) : (*(dw),*(dw))), *(1-dw), *(1-dw) :> _,_; ================================================ FILE: lib/faust/rev_dattorro.dsp.h ================================================ /* ------------------------------------------------------------ name: "rev_dattorro" Code generated with Faust 2.37.3 (https://faust.grame.fr) Compilation options: -lang c -es 1 -single -ftz 0 ------------------------------------------------------------ */ #ifndef __mydsp_H__ #define __mydsp_H__ #ifndef FAUSTFLOAT #define FAUSTFLOAT float #endif #ifdef __cplusplus extern "C" { #endif #include #include #include #ifndef FAUSTCLASS #define FAUSTCLASS mydsp #endif #ifdef __APPLE__ #define exp10f __exp10f #define exp10 __exp10 #endif typedef struct { int fSampleRate; float fConst0; FAUSTFLOAT fHslider0; float fConst1; float fRec11[2]; int IOTA; float fVec0[32]; float fRec10[3]; FAUSTFLOAT fHslider1; float fRec12[2]; float fVec1[256]; float fRec8[2]; float fVec2[128]; float fRec6[2]; float fVec3[512]; float fRec4[2]; float fVec4[512]; float fRec2[2]; FAUSTFLOAT fHslider2; float fRec13[2]; FAUSTFLOAT fHslider3; float fRec17[2]; FAUSTFLOAT fHslider4; float fRec20[2]; float fVec5[1024]; float fRec18[2]; float fVec6[8192]; float fRec16[2]; float fVec7[4096]; float fRec14[2]; float fVec8[4096]; float fRec0[2]; float fVec9[1024]; float fRec24[2]; float fVec10[8192]; float fRec23[2]; float fVec11[2048]; float fRec21[2]; float fVec12[2048]; float fRec1[2]; FAUSTFLOAT fHslider5; float fRec26[2]; } mydsp; mydsp* newmydsp() { mydsp* dsp = (mydsp*)calloc(1, sizeof(mydsp)); return dsp; } void deletemydsp(mydsp* dsp) { free(dsp); } void metadatamydsp(MetaGlue* m) { m->declare(m->metaInterface, "basics.lib/name", "Faust Basic Element Library"); m->declare(m->metaInterface, "basics.lib/version", "0.2"); m->declare(m->metaInterface, "compile_options", "-lang c -es 1 -single -ftz 0"); m->declare(m->metaInterface, "filename", "rev_dattorro.dsp"); m->declare(m->metaInterface, "maths.lib/author", "GRAME"); m->declare(m->metaInterface, "maths.lib/copyright", "GRAME"); m->declare(m->metaInterface, "maths.lib/license", "LGPL with exception"); m->declare(m->metaInterface, "maths.lib/name", "Faust Math Library"); m->declare(m->metaInterface, "maths.lib/version", "2.5"); m->declare(m->metaInterface, "name", "rev_dattorro"); m->declare(m->metaInterface, "platform.lib/name", "Generic Platform Library"); m->declare(m->metaInterface, "platform.lib/version", "0.2"); m->declare(m->metaInterface, "reverbs.lib/dattorro_rev:author", "Jakob Zerbian"); m->declare(m->metaInterface, "reverbs.lib/dattorro_rev:license", "MIT-style STK-4.3 license"); m->declare(m->metaInterface, "reverbs.lib/name", "Faust Reverb Library"); m->declare(m->metaInterface, "reverbs.lib/version", "0.2"); m->declare(m->metaInterface, "routes.lib/name", "Faust Signal Routing Library"); m->declare(m->metaInterface, "routes.lib/version", "0.2"); m->declare(m->metaInterface, "signals.lib/name", "Faust Signal Routing Library"); m->declare(m->metaInterface, "signals.lib/version", "0.1"); } int getSampleRatemydsp(mydsp* dsp) { return dsp->fSampleRate; } int getNumInputsmydsp(mydsp* dsp) { return 2; } int getNumOutputsmydsp(mydsp* dsp) { return 2; } void classInitmydsp(int sample_rate) { } void instanceResetUserInterfacemydsp(mydsp* dsp) { dsp->fHslider0 = (FAUSTFLOAT)0.5f; dsp->fHslider1 = (FAUSTFLOAT)0.5f; dsp->fHslider2 = (FAUSTFLOAT)0.5f; dsp->fHslider3 = (FAUSTFLOAT)0.5f; dsp->fHslider4 = (FAUSTFLOAT)0.5f; dsp->fHslider5 = (FAUSTFLOAT)0.5f; } void instanceClearmydsp(mydsp* dsp) { /* C99 loop */ { int l0; for (l0 = 0; (l0 < 2); l0 = (l0 + 1)) { dsp->fRec11[l0] = 0.0f; } } dsp->IOTA = 0; /* C99 loop */ { int l1; for (l1 = 0; (l1 < 32); l1 = (l1 + 1)) { dsp->fVec0[l1] = 0.0f; } } /* C99 loop */ { int l2; for (l2 = 0; (l2 < 3); l2 = (l2 + 1)) { dsp->fRec10[l2] = 0.0f; } } /* C99 loop */ { int l3; for (l3 = 0; (l3 < 2); l3 = (l3 + 1)) { dsp->fRec12[l3] = 0.0f; } } /* C99 loop */ { int l4; for (l4 = 0; (l4 < 256); l4 = (l4 + 1)) { dsp->fVec1[l4] = 0.0f; } } /* C99 loop */ { int l5; for (l5 = 0; (l5 < 2); l5 = (l5 + 1)) { dsp->fRec8[l5] = 0.0f; } } /* C99 loop */ { int l6; for (l6 = 0; (l6 < 128); l6 = (l6 + 1)) { dsp->fVec2[l6] = 0.0f; } } /* C99 loop */ { int l7; for (l7 = 0; (l7 < 2); l7 = (l7 + 1)) { dsp->fRec6[l7] = 0.0f; } } /* C99 loop */ { int l8; for (l8 = 0; (l8 < 512); l8 = (l8 + 1)) { dsp->fVec3[l8] = 0.0f; } } /* C99 loop */ { int l9; for (l9 = 0; (l9 < 2); l9 = (l9 + 1)) { dsp->fRec4[l9] = 0.0f; } } /* C99 loop */ { int l10; for (l10 = 0; (l10 < 512); l10 = (l10 + 1)) { dsp->fVec4[l10] = 0.0f; } } /* C99 loop */ { int l11; for (l11 = 0; (l11 < 2); l11 = (l11 + 1)) { dsp->fRec2[l11] = 0.0f; } } /* C99 loop */ { int l12; for (l12 = 0; (l12 < 2); l12 = (l12 + 1)) { dsp->fRec13[l12] = 0.0f; } } /* C99 loop */ { int l13; for (l13 = 0; (l13 < 2); l13 = (l13 + 1)) { dsp->fRec17[l13] = 0.0f; } } /* C99 loop */ { int l14; for (l14 = 0; (l14 < 2); l14 = (l14 + 1)) { dsp->fRec20[l14] = 0.0f; } } /* C99 loop */ { int l15; for (l15 = 0; (l15 < 1024); l15 = (l15 + 1)) { dsp->fVec5[l15] = 0.0f; } } /* C99 loop */ { int l16; for (l16 = 0; (l16 < 2); l16 = (l16 + 1)) { dsp->fRec18[l16] = 0.0f; } } /* C99 loop */ { int l17; for (l17 = 0; (l17 < 8192); l17 = (l17 + 1)) { dsp->fVec6[l17] = 0.0f; } } /* C99 loop */ { int l18; for (l18 = 0; (l18 < 2); l18 = (l18 + 1)) { dsp->fRec16[l18] = 0.0f; } } /* C99 loop */ { int l19; for (l19 = 0; (l19 < 4096); l19 = (l19 + 1)) { dsp->fVec7[l19] = 0.0f; } } /* C99 loop */ { int l20; for (l20 = 0; (l20 < 2); l20 = (l20 + 1)) { dsp->fRec14[l20] = 0.0f; } } /* C99 loop */ { int l21; for (l21 = 0; (l21 < 4096); l21 = (l21 + 1)) { dsp->fVec8[l21] = 0.0f; } } /* C99 loop */ { int l22; for (l22 = 0; (l22 < 2); l22 = (l22 + 1)) { dsp->fRec0[l22] = 0.0f; } } /* C99 loop */ { int l23; for (l23 = 0; (l23 < 1024); l23 = (l23 + 1)) { dsp->fVec9[l23] = 0.0f; } } /* C99 loop */ { int l24; for (l24 = 0; (l24 < 2); l24 = (l24 + 1)) { dsp->fRec24[l24] = 0.0f; } } /* C99 loop */ { int l25; for (l25 = 0; (l25 < 8192); l25 = (l25 + 1)) { dsp->fVec10[l25] = 0.0f; } } /* C99 loop */ { int l26; for (l26 = 0; (l26 < 2); l26 = (l26 + 1)) { dsp->fRec23[l26] = 0.0f; } } /* C99 loop */ { int l27; for (l27 = 0; (l27 < 2048); l27 = (l27 + 1)) { dsp->fVec11[l27] = 0.0f; } } /* C99 loop */ { int l28; for (l28 = 0; (l28 < 2); l28 = (l28 + 1)) { dsp->fRec21[l28] = 0.0f; } } /* C99 loop */ { int l29; for (l29 = 0; (l29 < 2048); l29 = (l29 + 1)) { dsp->fVec12[l29] = 0.0f; } } /* C99 loop */ { int l30; for (l30 = 0; (l30 < 2); l30 = (l30 + 1)) { dsp->fRec1[l30] = 0.0f; } } /* C99 loop */ { int l31; for (l31 = 0; (l31 < 2); l31 = (l31 + 1)) { dsp->fRec26[l31] = 0.0f; } } } void instanceConstantsmydsp(mydsp* dsp, int sample_rate) { dsp->fSampleRate = sample_rate; dsp->fConst0 = (44.0999985f / fminf(192000.0f, fmaxf(1.0f, (float)dsp->fSampleRate))); dsp->fConst1 = (1.0f - dsp->fConst0); } void instanceInitmydsp(mydsp* dsp, int sample_rate) { instanceConstantsmydsp(dsp, sample_rate); instanceResetUserInterfacemydsp(dsp); instanceClearmydsp(dsp); } void initmydsp(mydsp* dsp, int sample_rate) { classInitmydsp(sample_rate); instanceInitmydsp(dsp, sample_rate); } void buildUserInterfacemydsp(mydsp* dsp, UIGlue* ui_interface) { ui_interface->openVerticalBox(ui_interface->uiInterface, "rev_dattorro"); ui_interface->declare(ui_interface->uiInterface, &dsp->fHslider5, "0", ""); ui_interface->addHorizontalSlider(ui_interface->uiInterface, "D/W", &dsp->fHslider5, (FAUSTFLOAT)0.5f, (FAUSTFLOAT)0.0f, (FAUSTFLOAT)1.0f, (FAUSTFLOAT)9.99999975e-05f); ui_interface->declare(ui_interface->uiInterface, &dsp->fHslider2, "1", ""); ui_interface->addHorizontalSlider(ui_interface->uiInterface, "Decay", &dsp->fHslider2, (FAUSTFLOAT)0.5f, (FAUSTFLOAT)0.0f, (FAUSTFLOAT)1.0f, (FAUSTFLOAT)9.99999975e-05f); ui_interface->declare(ui_interface->uiInterface, &dsp->fHslider3, "2", ""); ui_interface->addHorizontalSlider(ui_interface->uiInterface, "Damp", &dsp->fHslider3, (FAUSTFLOAT)0.5f, (FAUSTFLOAT)0.0f, (FAUSTFLOAT)1.0f, (FAUSTFLOAT)9.99999975e-05f); ui_interface->declare(ui_interface->uiInterface, &dsp->fHslider0, "3", ""); ui_interface->addHorizontalSlider(ui_interface->uiInterface, "BW", &dsp->fHslider0, (FAUSTFLOAT)0.5f, (FAUSTFLOAT)0.0f, (FAUSTFLOAT)1.0f, (FAUSTFLOAT)9.99999975e-05f); ui_interface->declare(ui_interface->uiInterface, &dsp->fHslider4, "4", ""); ui_interface->addHorizontalSlider(ui_interface->uiInterface, "DDiff", &dsp->fHslider4, (FAUSTFLOAT)0.5f, (FAUSTFLOAT)0.00999999978f, (FAUSTFLOAT)0.99000001f, (FAUSTFLOAT)9.99999975e-05f); ui_interface->declare(ui_interface->uiInterface, &dsp->fHslider1, "5", ""); ui_interface->addHorizontalSlider(ui_interface->uiInterface, "IDiff", &dsp->fHslider1, (FAUSTFLOAT)0.5f, (FAUSTFLOAT)0.00999999978f, (FAUSTFLOAT)0.99000001f, (FAUSTFLOAT)9.99999975e-05f); ui_interface->closeBox(ui_interface->uiInterface); } void computemydsp(mydsp* dsp, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { FAUSTFLOAT* input0 = inputs[0]; FAUSTFLOAT* input1 = inputs[1]; FAUSTFLOAT* output0 = outputs[0]; FAUSTFLOAT* output1 = outputs[1]; float fSlow0 = (dsp->fConst0 * (float)dsp->fHslider0); float fSlow1 = (dsp->fConst0 * (float)dsp->fHslider1); float fSlow2 = (dsp->fConst0 * (float)dsp->fHslider2); float fSlow3 = (dsp->fConst0 * (float)dsp->fHslider3); float fSlow4 = (dsp->fConst0 * (float)dsp->fHslider4); float fSlow5 = (dsp->fConst0 * (float)dsp->fHslider5); /* C99 loop */ { int i0; for (i0 = 0; (i0 < count); i0 = (i0 + 1)) { dsp->fRec11[0] = (fSlow0 + (dsp->fConst1 * dsp->fRec11[1])); float fTemp0 = (float)input0[i0]; float fTemp1 = (float)input1[i0]; dsp->fVec0[(dsp->IOTA & 31)] = (fTemp0 + fTemp1); dsp->fRec10[0] = (((1.0f - dsp->fRec11[0]) * dsp->fRec10[2]) + (0.5f * (dsp->fRec11[0] * dsp->fVec0[((dsp->IOTA - 24) & 31)]))); dsp->fRec12[0] = (fSlow1 + (dsp->fConst1 * dsp->fRec12[1])); float fTemp2 = (dsp->fRec10[0] - (dsp->fRec12[0] * dsp->fRec8[1])); dsp->fVec1[(dsp->IOTA & 255)] = fTemp2; dsp->fRec8[0] = dsp->fVec1[((dsp->IOTA - 142) & 255)]; float fRec9 = (dsp->fRec12[0] * fTemp2); float fTemp3 = ((fRec9 + dsp->fRec8[1]) - (dsp->fRec12[0] * dsp->fRec6[1])); dsp->fVec2[(dsp->IOTA & 127)] = fTemp3; dsp->fRec6[0] = dsp->fVec2[((dsp->IOTA - 107) & 127)]; float fRec7 = (dsp->fRec12[0] * fTemp3); float fTemp4 = ((fRec7 + dsp->fRec6[1]) - (dsp->fRec12[0] * dsp->fRec4[1])); dsp->fVec3[(dsp->IOTA & 511)] = fTemp4; dsp->fRec4[0] = dsp->fVec3[((dsp->IOTA - 379) & 511)]; float fRec5 = (dsp->fRec12[0] * fTemp4); float fTemp5 = ((fRec5 + dsp->fRec4[1]) - (dsp->fRec12[0] * dsp->fRec2[1])); dsp->fVec4[(dsp->IOTA & 511)] = fTemp5; dsp->fRec2[0] = dsp->fVec4[((dsp->IOTA - 277) & 511)]; float fRec3 = (dsp->fRec12[0] * fTemp5); dsp->fRec13[0] = (fSlow2 + (dsp->fConst1 * dsp->fRec13[1])); dsp->fRec17[0] = (fSlow3 + (dsp->fConst1 * dsp->fRec17[1])); float fTemp6 = (1.0f - dsp->fRec17[0]); dsp->fRec20[0] = (fSlow4 + (dsp->fConst1 * dsp->fRec20[1])); float fTemp7 = ((dsp->fRec20[0] * dsp->fRec18[1]) + dsp->fRec1[1]); dsp->fVec5[(dsp->IOTA & 1023)] = fTemp7; dsp->fRec18[0] = dsp->fVec5[((dsp->IOTA - 908) & 1023)]; float fRec19 = (0.0f - (dsp->fRec20[0] * fTemp7)); dsp->fVec6[(dsp->IOTA & 8191)] = (fRec19 + dsp->fRec18[1]); dsp->fRec16[0] = ((dsp->fRec17[0] * dsp->fRec16[1]) + (fTemp6 * dsp->fVec6[((dsp->IOTA - 4217) & 8191)])); float fTemp8 = ((dsp->fRec16[0] * dsp->fRec13[0]) - (dsp->fRec20[0] * dsp->fRec14[1])); dsp->fVec7[(dsp->IOTA & 4095)] = fTemp8; dsp->fRec14[0] = dsp->fVec7[((dsp->IOTA - 2656) & 4095)]; float fRec15 = (dsp->fRec20[0] * fTemp8); dsp->fVec8[(dsp->IOTA & 4095)] = (fRec15 + dsp->fRec14[1]); dsp->fRec0[0] = (dsp->fRec2[1] + (fRec3 + (dsp->fRec13[0] * dsp->fVec8[((dsp->IOTA - 2656) & 4095)]))); float fTemp9 = ((dsp->fRec20[0] * dsp->fRec24[1]) + dsp->fRec0[1]); dsp->fVec9[(dsp->IOTA & 1023)] = fTemp9; dsp->fRec24[0] = dsp->fVec9[((dsp->IOTA - 672) & 1023)]; float fRec25 = (0.0f - (dsp->fRec20[0] * fTemp9)); dsp->fVec10[(dsp->IOTA & 8191)] = (fRec25 + dsp->fRec24[1]); dsp->fRec23[0] = ((dsp->fRec17[0] * dsp->fRec23[1]) + (fTemp6 * dsp->fVec10[((dsp->IOTA - 4453) & 8191)])); float fTemp10 = ((dsp->fRec13[0] * dsp->fRec23[0]) - (dsp->fRec20[0] * dsp->fRec21[1])); dsp->fVec11[(dsp->IOTA & 2047)] = fTemp10; dsp->fRec21[0] = dsp->fVec11[((dsp->IOTA - 1800) & 2047)]; float fRec22 = (dsp->fRec20[0] * fTemp10); dsp->fVec12[(dsp->IOTA & 2047)] = (fRec22 + dsp->fRec21[1]); dsp->fRec1[0] = ((fRec3 + dsp->fRec2[1]) + (dsp->fRec13[0] * dsp->fVec12[((dsp->IOTA - 1800) & 2047)])); dsp->fRec26[0] = (fSlow5 + (dsp->fConst1 * dsp->fRec26[1])); float fTemp11 = (1.0f - dsp->fRec26[0]); output0[i0] = (FAUSTFLOAT)((dsp->fRec0[0] * dsp->fRec26[0]) + (fTemp0 * fTemp11)); output1[i0] = (FAUSTFLOAT)((fTemp1 * fTemp11) + (dsp->fRec26[0] * dsp->fRec1[0])); dsp->fRec11[1] = dsp->fRec11[0]; dsp->IOTA = (dsp->IOTA + 1); dsp->fRec10[2] = dsp->fRec10[1]; dsp->fRec10[1] = dsp->fRec10[0]; dsp->fRec12[1] = dsp->fRec12[0]; dsp->fRec8[1] = dsp->fRec8[0]; dsp->fRec6[1] = dsp->fRec6[0]; dsp->fRec4[1] = dsp->fRec4[0]; dsp->fRec2[1] = dsp->fRec2[0]; dsp->fRec13[1] = dsp->fRec13[0]; dsp->fRec17[1] = dsp->fRec17[0]; dsp->fRec20[1] = dsp->fRec20[0]; dsp->fRec18[1] = dsp->fRec18[0]; dsp->fRec16[1] = dsp->fRec16[0]; dsp->fRec14[1] = dsp->fRec14[0]; dsp->fRec0[1] = dsp->fRec0[0]; dsp->fRec24[1] = dsp->fRec24[0]; dsp->fRec23[1] = dsp->fRec23[0]; dsp->fRec21[1] = dsp->fRec21[0]; dsp->fRec1[1] = dsp->fRec1[0]; dsp->fRec26[1] = dsp->fRec26[0]; } } } #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/faust/ui.hxx ================================================ #include struct MetaGlue { const char *metaInterface; void declare(const char *ui, const char *key, const char *value) { } }; struct UIGlue { const char *uiInterface; void openTabBox(const char *ui, const char *label){}; void openVerticalBox(const char *ui, const char *title){}; void openHorizontalBox(const char *ui, const char *title){}; void closeBox(const char *ui){}; void declare(const char *ui, float *zone, const char *key, const char *val) {} void addNumEntry(const char *ui, const char *label, float *zone, float init, float min, float max, float step); void addHorizontalSlider(const char *ui, const char *label, float *zone, float init, float min, float max, float step); void addVerticalSlider(const char *ui, const char *label, float *zone, float init, float min, float max, float step); void addButton(const char *ui, const char *label, float *zone); void addCheckButton(const char *ui, const char *label, float *zone); // -- passive widgets void addHorizontalBargraph(const char *ui, const char *label, float *zone, float min, float max){}; void addVerticalBargraph(const char *ui, const char *label, float *zone, float min, float max){}; // -- soundfiles //void addSoundfile(const char *label, const char *filename, Soundfile **sf_zone){}; }; constexpr float base_frequency = 440.f; constexpr float base_pitch = 69.f; float note_to_frequency(float note) { return base_frequency * powf(2.f, (note - base_pitch) / 12.f); } ================================================ FILE: lib/fft/fft4g.c ================================================ /* * http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html * Copyright Takuya OOURA, 1996-2001 * * You may use, copy, modify and distribute this code for any purpose (include * commercial use) and without fee. Please refer to this package when you modify * this code. * * Changes: * replaced "double to float" by eh2k. */ /* Fast Fourier/Cosine/Sine Transform dimension :one data length :power of 2 decimation :frequency radix :4, 2 data :inplace table :use functions cdft: Complex Discrete Fourier Transform rdft: Real Discrete Fourier Transform ddct: Discrete Cosine Transform ddst: Discrete Sine Transform dfct: Cosine Transform of RDFT (Real Symmetric DFT) dfst: Sine Transform of RDFT (Real Anti-symmetric DFT) function prototypes void cdft(int, int, double *, int *, double *); void rdft(int, int, double *, int *, double *); void ddct(int, int, double *, int *, double *); void ddst(int, int, double *, int *, double *); void dfct(int, double *, double *, int *, double *); void dfst(int, double *, double *, int *, double *); -------- Complex DFT (Discrete Fourier Transform) -------- [definition] X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k ip[0] = 0; // first time only cdft(2*n, 1, a, ip, w); ip[0] = 0; // first time only cdft(2*n, -1, a, ip, w); [parameters] 2*n :data length (int) n >= 1, n = power of 2 a[0...2*n-1] :input/output data (double *) input data a[2*j] = Re(x[j]), a[2*j+1] = Im(x[j]), 0<=j= 2+sqrt(n) strictly, length of ip >= 2+(1<<(int)(log(n+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n/2-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of cdft(2*n, -1, a, ip, w); is cdft(2*n, 1, a, ip, w); for (j = 0; j <= 2 * n - 1; j++) { a[j] *= 1.0 / n; } . -------- Real DFT / Inverse of Real DFT -------- [definition] RDFT R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2 I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0 IRDFT (excluding scale) a[k] = (R[0] + R[n/2]*cos(pi*k))/2 + sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) + sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k ip[0] = 0; // first time only rdft(n, 1, a, ip, w); ip[0] = 0; // first time only rdft(n, -1, a, ip, w); [parameters] n :data length (int) n >= 2, n = power of 2 a[0...n-1] :input/output data (double *) output data a[2*k] = R[k], 0<=k input data a[2*j] = R[j], 0<=j= 2+sqrt(n/2) strictly, length of ip >= 2+(1<<(int)(log(n/2+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n/2-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of rdft(n, 1, a, ip, w); is rdft(n, -1, a, ip, w); for (j = 0; j <= n - 1; j++) { a[j] *= 2.0 / n; } . -------- DCT (Discrete Cosine Transform) / Inverse of DCT -------- [definition] IDCT (excluding scale) C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k DCT C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k ip[0] = 0; // first time only ddct(n, 1, a, ip, w); ip[0] = 0; // first time only ddct(n, -1, a, ip, w); [parameters] n :data length (int) n >= 2, n = power of 2 a[0...n-1] :input/output data (double *) output data a[k] = C[k], 0<=k= 2+sqrt(n/2) strictly, length of ip >= 2+(1<<(int)(log(n/2+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n*5/4-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of ddct(n, -1, a, ip, w); is a[0] *= 0.5; ddct(n, 1, a, ip, w); for (j = 0; j <= n - 1; j++) { a[j] *= 2.0 / n; } . -------- DST (Discrete Sine Transform) / Inverse of DST -------- [definition] IDST (excluding scale) S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k DST S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0 ip[0] = 0; // first time only ddst(n, 1, a, ip, w); ip[0] = 0; // first time only ddst(n, -1, a, ip, w); [parameters] n :data length (int) n >= 2, n = power of 2 a[0...n-1] :input/output data (double *) input data a[j] = A[j], 0 output data a[k] = S[k], 0= 2+sqrt(n/2) strictly, length of ip >= 2+(1<<(int)(log(n/2+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n*5/4-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of ddst(n, -1, a, ip, w); is a[0] *= 0.5; ddst(n, 1, a, ip, w); for (j = 0; j <= n - 1; j++) { a[j] *= 2.0 / n; } . -------- Cosine Transform of RDFT (Real Symmetric DFT) -------- [definition] C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n [usage] ip[0] = 0; // first time only dfct(n, a, t, ip, w); [parameters] n :data length - 1 (int) n >= 2, n = power of 2 a[0...n] :input/output data (double *) output data a[k] = C[k], 0<=k<=n t[0...n/2] :work area (double *) ip[0...*] :work area for bit reversal (int *) length of ip >= 2+sqrt(n/4) strictly, length of ip >= 2+(1<<(int)(log(n/4+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n*5/8-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of a[0] *= 0.5; a[n] *= 0.5; dfct(n, a, t, ip, w); is a[0] *= 0.5; a[n] *= 0.5; dfct(n, a, t, ip, w); for (j = 0; j <= n; j++) { a[j] *= 2.0 / n; } . -------- Sine Transform of RDFT (Real Anti-symmetric DFT) -------- [definition] S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0= 2, n = power of 2 a[0...n-1] :input/output data (double *) output data a[k] = S[k], 0= 2+sqrt(n/4) strictly, length of ip >= 2+(1<<(int)(log(n/4+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n*5/8-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of dfst(n, a, t, ip, w); is dfst(n, a, t, ip, w); for (j = 1; j <= n - 1; j++) { a[j] *= 2.0 / n; } . Appendix : The cos/sin table is recalculated when the larger table required. w[] and ip[] are compatible with all routines. */ void cdft(int n, int isgn, float *a, int *ip, float *w) { void makewt(int nw, int *ip, float *w); void bitrv2(int n, int *ip, float *a); void bitrv2conj(int n, int *ip, float *a); void cftfsub(int n, float *a, float *w); void cftbsub(int n, float *a, float *w); if (n > (ip[0] << 2)) { makewt(n >> 2, ip, w); } if (n > 4) { if (isgn >= 0) { bitrv2(n, ip + 2, a); cftfsub(n, a, w); } else { bitrv2conj(n, ip + 2, a); cftbsub(n, a, w); } } else if (n == 4) { cftfsub(n, a, w); } } void rdft(int n, int isgn, float *a, int *ip, float *w) { void makewt(int nw, int *ip, float *w); void makect(int nc, int *ip, float *c); void bitrv2(int n, int *ip, float *a); void cftfsub(int n, float *a, float *w); void cftbsub(int n, float *a, float *w); void rftfsub(int n, float *a, int nc, float *c); void rftbsub(int n, float *a, int nc, float *c); int nw, nc; float xi; nw = ip[0]; if (n > (nw << 2)) { nw = n >> 2; makewt(nw, ip, w); } nc = ip[1]; if (n > (nc << 2)) { nc = n >> 2; makect(nc, ip, w + nw); } if (isgn >= 0) { if (n > 4) { bitrv2(n, ip + 2, a); cftfsub(n, a, w); rftfsub(n, a, nc, w + nw); } else if (n == 4) { cftfsub(n, a, w); } xi = a[0] - a[1]; a[0] += a[1]; a[1] = xi; } else { a[1] = 0.5 * (a[0] - a[1]); a[0] -= a[1]; if (n > 4) { rftbsub(n, a, nc, w + nw); bitrv2(n, ip + 2, a); cftbsub(n, a, w); } else if (n == 4) { cftfsub(n, a, w); } } } void ddct(int n, int isgn, float *a, int *ip, float *w) { void makewt(int nw, int *ip, float *w); void makect(int nc, int *ip, float *c); void bitrv2(int n, int *ip, float *a); void cftfsub(int n, float *a, float *w); void cftbsub(int n, float *a, float *w); void rftfsub(int n, float *a, int nc, float *c); void rftbsub(int n, float *a, int nc, float *c); void dctsub(int n, float *a, int nc, float *c); int j, nw, nc; float xr; nw = ip[0]; if (n > (nw << 2)) { nw = n >> 2; makewt(nw, ip, w); } nc = ip[1]; if (n > nc) { nc = n; makect(nc, ip, w + nw); } if (isgn < 0) { xr = a[n - 1]; for (j = n - 2; j >= 2; j -= 2) { a[j + 1] = a[j] - a[j - 1]; a[j] += a[j - 1]; } a[1] = a[0] - xr; a[0] += xr; if (n > 4) { rftbsub(n, a, nc, w + nw); bitrv2(n, ip + 2, a); cftbsub(n, a, w); } else if (n == 4) { cftfsub(n, a, w); } } dctsub(n, a, nc, w + nw); if (isgn >= 0) { if (n > 4) { bitrv2(n, ip + 2, a); cftfsub(n, a, w); rftfsub(n, a, nc, w + nw); } else if (n == 4) { cftfsub(n, a, w); } xr = a[0] - a[1]; a[0] += a[1]; for (j = 2; j < n; j += 2) { a[j - 1] = a[j] - a[j + 1]; a[j] += a[j + 1]; } a[n - 1] = xr; } } void ddst(int n, int isgn, float *a, int *ip, float *w) { void makewt(int nw, int *ip, float *w); void makect(int nc, int *ip, float *c); void bitrv2(int n, int *ip, float *a); void cftfsub(int n, float *a, float *w); void cftbsub(int n, float *a, float *w); void rftfsub(int n, float *a, int nc, float *c); void rftbsub(int n, float *a, int nc, float *c); void dstsub(int n, float *a, int nc, float *c); int j, nw, nc; float xr; nw = ip[0]; if (n > (nw << 2)) { nw = n >> 2; makewt(nw, ip, w); } nc = ip[1]; if (n > nc) { nc = n; makect(nc, ip, w + nw); } if (isgn < 0) { xr = a[n - 1]; for (j = n - 2; j >= 2; j -= 2) { a[j + 1] = -a[j] - a[j - 1]; a[j] -= a[j - 1]; } a[1] = a[0] + xr; a[0] -= xr; if (n > 4) { rftbsub(n, a, nc, w + nw); bitrv2(n, ip + 2, a); cftbsub(n, a, w); } else if (n == 4) { cftfsub(n, a, w); } } dstsub(n, a, nc, w + nw); if (isgn >= 0) { if (n > 4) { bitrv2(n, ip + 2, a); cftfsub(n, a, w); rftfsub(n, a, nc, w + nw); } else if (n == 4) { cftfsub(n, a, w); } xr = a[0] - a[1]; a[0] += a[1]; for (j = 2; j < n; j += 2) { a[j - 1] = -a[j] - a[j + 1]; a[j] -= a[j + 1]; } a[n - 1] = -xr; } } void dfct(int n, float *a, float *t, int *ip, float *w) { void makewt(int nw, int *ip, float *w); void makect(int nc, int *ip, float *c); void bitrv2(int n, int *ip, float *a); void cftfsub(int n, float *a, float *w); void rftfsub(int n, float *a, int nc, float *c); void dctsub(int n, float *a, int nc, float *c); int j, k, l, m, mh, nw, nc; float xr, xi, yr, yi; nw = ip[0]; if (n > (nw << 3)) { nw = n >> 3; makewt(nw, ip, w); } nc = ip[1]; if (n > (nc << 1)) { nc = n >> 1; makect(nc, ip, w + nw); } m = n >> 1; yi = a[m]; xi = a[0] + a[n]; a[0] -= a[n]; t[0] = xi - yi; t[m] = xi + yi; if (n > 2) { mh = m >> 1; for (j = 1; j < mh; j++) { k = m - j; xr = a[j] - a[n - j]; xi = a[j] + a[n - j]; yr = a[k] - a[n - k]; yi = a[k] + a[n - k]; a[j] = xr; a[k] = yr; t[j] = xi - yi; t[k] = xi + yi; } t[mh] = a[mh] + a[n - mh]; a[mh] -= a[n - mh]; dctsub(m, a, nc, w + nw); if (m > 4) { bitrv2(m, ip + 2, a); cftfsub(m, a, w); rftfsub(m, a, nc, w + nw); } else if (m == 4) { cftfsub(m, a, w); } a[n - 1] = a[0] - a[1]; a[1] = a[0] + a[1]; for (j = m - 2; j >= 2; j -= 2) { a[2 * j + 1] = a[j] + a[j + 1]; a[2 * j - 1] = a[j] - a[j + 1]; } l = 2; m = mh; while (m >= 2) { dctsub(m, t, nc, w + nw); if (m > 4) { bitrv2(m, ip + 2, t); cftfsub(m, t, w); rftfsub(m, t, nc, w + nw); } else if (m == 4) { cftfsub(m, t, w); } a[n - l] = t[0] - t[1]; a[l] = t[0] + t[1]; k = 0; for (j = 2; j < m; j += 2) { k += l << 2; a[k - l] = t[j] - t[j + 1]; a[k + l] = t[j] + t[j + 1]; } l <<= 1; mh = m >> 1; for (j = 0; j < mh; j++) { k = m - j; t[j] = t[m + k] - t[m + j]; t[k] = t[m + k] + t[m + j]; } t[mh] = t[m + mh]; m = mh; } a[l] = t[0]; a[n] = t[2] - t[1]; a[0] = t[2] + t[1]; } else { a[1] = a[0]; a[2] = t[0]; a[0] = t[1]; } } void dfst(int n, float *a, float *t, int *ip, float *w) { void makewt(int nw, int *ip, float *w); void makect(int nc, int *ip, float *c); void bitrv2(int n, int *ip, float *a); void cftfsub(int n, float *a, float *w); void rftfsub(int n, float *a, int nc, float *c); void dstsub(int n, float *a, int nc, float *c); int j, k, l, m, mh, nw, nc; float xr, xi, yr, yi; nw = ip[0]; if (n > (nw << 3)) { nw = n >> 3; makewt(nw, ip, w); } nc = ip[1]; if (n > (nc << 1)) { nc = n >> 1; makect(nc, ip, w + nw); } if (n > 2) { m = n >> 1; mh = m >> 1; for (j = 1; j < mh; j++) { k = m - j; xr = a[j] + a[n - j]; xi = a[j] - a[n - j]; yr = a[k] + a[n - k]; yi = a[k] - a[n - k]; a[j] = xr; a[k] = yr; t[j] = xi + yi; t[k] = xi - yi; } t[0] = a[mh] - a[n - mh]; a[mh] += a[n - mh]; a[0] = a[m]; dstsub(m, a, nc, w + nw); if (m > 4) { bitrv2(m, ip + 2, a); cftfsub(m, a, w); rftfsub(m, a, nc, w + nw); } else if (m == 4) { cftfsub(m, a, w); } a[n - 1] = a[1] - a[0]; a[1] = a[0] + a[1]; for (j = m - 2; j >= 2; j -= 2) { a[2 * j + 1] = a[j] - a[j + 1]; a[2 * j - 1] = -a[j] - a[j + 1]; } l = 2; m = mh; while (m >= 2) { dstsub(m, t, nc, w + nw); if (m > 4) { bitrv2(m, ip + 2, t); cftfsub(m, t, w); rftfsub(m, t, nc, w + nw); } else if (m == 4) { cftfsub(m, t, w); } a[n - l] = t[1] - t[0]; a[l] = t[0] + t[1]; k = 0; for (j = 2; j < m; j += 2) { k += l << 2; a[k - l] = -t[j] - t[j + 1]; a[k + l] = t[j] - t[j + 1]; } l <<= 1; mh = m >> 1; for (j = 1; j < mh; j++) { k = m - j; t[j] = t[m + k] + t[m + j]; t[k] = t[m + k] - t[m + j]; } t[0] = t[m + mh]; m = mh; } a[l] = t[0]; } a[0] = 0; } /* -------- initializing routines -------- */ #include void makewt(int nw, int *ip, float *w) { void bitrv2(int n, int *ip, float *a); int j, nwh; float delta, x, y; ip[0] = nw; ip[1] = 1; if (nw > 2) { nwh = nw >> 1; delta = atan(1.0) / nwh; w[0] = 1; w[1] = 0; w[nwh] = cos(delta * nwh); w[nwh + 1] = w[nwh]; if (nwh > 2) { for (j = 2; j < nwh; j += 2) { x = cos(delta * j); y = sin(delta * j); w[j] = x; w[j + 1] = y; w[nw - j] = y; w[nw - j + 1] = x; } bitrv2(nw, ip + 2, w); } } } void makect(int nc, int *ip, float *c) { int j, nch; float delta; ip[1] = nc; if (nc > 1) { nch = nc >> 1; delta = atanf(1.0) / nch; c[0] = cosf(delta * nch); c[nch] = 0.5 * c[0]; for (j = 1; j < nch; j++) { c[j] = 0.5 * cosf(delta * j); c[nc - j] = 0.5 * sinf(delta * j); } } } /* -------- child routines -------- */ void bitrv2(int n, int *ip, float *a) { int j, j1, k, k1, l, m, m2; float xr, xi, yr, yi; ip[0] = 0; l = n; m = 1; while ((m << 3) < l) { l >>= 1; for (j = 0; j < m; j++) { ip[m + j] = ip[j] + l; } m <<= 1; } m2 = 2 * m; if ((m << 3) == l) { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 2 * j + ip[k]; k1 = 2 * k + ip[j]; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += 2 * m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 -= m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += 2 * m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } j1 = 2 * k + m2 + ip[k]; k1 = j1 + m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } } else { for (k = 1; k < m; k++) { for (j = 0; j < k; j++) { j1 = 2 * j + ip[k]; k1 = 2 * k + ip[j]; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } } } } void bitrv2conj(int n, int *ip, float *a) { int j, j1, k, k1, l, m, m2; float xr, xi, yr, yi; ip[0] = 0; l = n; m = 1; while ((m << 3) < l) { l >>= 1; for (j = 0; j < m; j++) { ip[m + j] = ip[j] + l; } m <<= 1; } m2 = 2 * m; if ((m << 3) == l) { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 2 * j + ip[k]; k1 = 2 * k + ip[j]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += 2 * m2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 -= m2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += 2 * m2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 2 * k + ip[k]; a[k1 + 1] = -a[k1 + 1]; j1 = k1 + m2; k1 = j1 + m2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; k1 += m2; a[k1 + 1] = -a[k1 + 1]; } } else { a[1] = -a[1]; a[m2 + 1] = -a[m2 + 1]; for (k = 1; k < m; k++) { for (j = 0; j < k; j++) { j1 = 2 * j + ip[k]; k1 = 2 * k + ip[j]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += m2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 2 * k + ip[k]; a[k1 + 1] = -a[k1 + 1]; a[k1 + m2 + 1] = -a[k1 + m2 + 1]; } } } void cftfsub(int n, float *a, float *w) { void cft1st(int n, float *a, float *w); void cftmdl(int n, int l, float *a, float *w); int j, j1, j2, j3, l; float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; l = 2; if (n > 8) { cft1st(n, a, w); l = 8; while ((l << 2) < n) { cftmdl(n, l, a, w); l <<= 2; } } if ((l << 2) == n) { for (j = 0; j < l; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j2] = x0r - x2r; a[j2 + 1] = x0i - x2i; a[j1] = x1r - x3i; a[j1 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; } } else { for (j = 0; j < l; j += 2) { j1 = j + l; x0r = a[j] - a[j1]; x0i = a[j + 1] - a[j1 + 1]; a[j] += a[j1]; a[j + 1] += a[j1 + 1]; a[j1] = x0r; a[j1 + 1] = x0i; } } } void cftbsub(int n, float *a, float *w) { void cft1st(int n, float *a, float *w); void cftmdl(int n, int l, float *a, float *w); int j, j1, j2, j3, l; float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; l = 2; if (n > 8) { cft1st(n, a, w); l = 8; while ((l << 2) < n) { cftmdl(n, l, a, w); l <<= 2; } } if ((l << 2) == n) { for (j = 0; j < l; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = -a[j + 1] - a[j1 + 1]; x1r = a[j] - a[j1]; x1i = -a[j + 1] + a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i - x2i; a[j2] = x0r - x2r; a[j2 + 1] = x0i + x2i; a[j1] = x1r - x3i; a[j1 + 1] = x1i - x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i + x3r; } } else { for (j = 0; j < l; j += 2) { j1 = j + l; x0r = a[j] - a[j1]; x0i = -a[j + 1] + a[j1 + 1]; a[j] += a[j1]; a[j + 1] = -a[j + 1] - a[j1 + 1]; a[j1] = x0r; a[j1 + 1] = x0i; } } } void cft1st(int n, float *a, float *w) { int j, k1, k2; float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; x0r = a[0] + a[2]; x0i = a[1] + a[3]; x1r = a[0] - a[2]; x1i = a[1] - a[3]; x2r = a[4] + a[6]; x2i = a[5] + a[7]; x3r = a[4] - a[6]; x3i = a[5] - a[7]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[4] = x0r - x2r; a[5] = x0i - x2i; a[2] = x1r - x3i; a[3] = x1i + x3r; a[6] = x1r + x3i; a[7] = x1i - x3r; wk1r = w[2]; x0r = a[8] + a[10]; x0i = a[9] + a[11]; x1r = a[8] - a[10]; x1i = a[9] - a[11]; x2r = a[12] + a[14]; x2i = a[13] + a[15]; x3r = a[12] - a[14]; x3i = a[13] - a[15]; a[8] = x0r + x2r; a[9] = x0i + x2i; a[12] = x2i - x0i; a[13] = x0r - x2r; x0r = x1r - x3i; x0i = x1i + x3r; a[10] = wk1r * (x0r - x0i); a[11] = wk1r * (x0r + x0i); x0r = x3i + x1r; x0i = x3r - x1i; a[14] = wk1r * (x0i - x0r); a[15] = wk1r * (x0i + x0r); k1 = 0; for (j = 16; j < n; j += 16) { k1 += 2; k2 = 2 * k1; wk2r = w[k1]; wk2i = w[k1 + 1]; wk1r = w[k2]; wk1i = w[k2 + 1]; wk3r = wk1r - 2 * wk2i * wk1i; wk3i = 2 * wk2i * wk1r - wk1i; x0r = a[j] + a[j + 2]; x0i = a[j + 1] + a[j + 3]; x1r = a[j] - a[j + 2]; x1i = a[j + 1] - a[j + 3]; x2r = a[j + 4] + a[j + 6]; x2i = a[j + 5] + a[j + 7]; x3r = a[j + 4] - a[j + 6]; x3i = a[j + 5] - a[j + 7]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j + 4] = wk2r * x0r - wk2i * x0i; a[j + 5] = wk2r * x0i + wk2i * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j + 2] = wk1r * x0r - wk1i * x0i; a[j + 3] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j + 6] = wk3r * x0r - wk3i * x0i; a[j + 7] = wk3r * x0i + wk3i * x0r; wk1r = w[k2 + 2]; wk1i = w[k2 + 3]; wk3r = wk1r - 2 * wk2r * wk1i; wk3i = 2 * wk2r * wk1r - wk1i; x0r = a[j + 8] + a[j + 10]; x0i = a[j + 9] + a[j + 11]; x1r = a[j + 8] - a[j + 10]; x1i = a[j + 9] - a[j + 11]; x2r = a[j + 12] + a[j + 14]; x2i = a[j + 13] + a[j + 15]; x3r = a[j + 12] - a[j + 14]; x3i = a[j + 13] - a[j + 15]; a[j + 8] = x0r + x2r; a[j + 9] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j + 12] = -wk2i * x0r - wk2r * x0i; a[j + 13] = -wk2i * x0i + wk2r * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j + 10] = wk1r * x0r - wk1i * x0i; a[j + 11] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j + 14] = wk3r * x0r - wk3i * x0i; a[j + 15] = wk3r * x0i + wk3i * x0r; } } void cftmdl(int n, int l, float *a, float *w) { int j, j1, j2, j3, k, k1, k2, m, m2; float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; m = l << 2; for (j = 0; j < l; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j2] = x0r - x2r; a[j2 + 1] = x0i - x2i; a[j1] = x1r - x3i; a[j1 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; } wk1r = w[2]; for (j = m; j < l + m; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j2] = x2i - x0i; a[j2 + 1] = x0r - x2r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * (x0r - x0i); a[j1 + 1] = wk1r * (x0r + x0i); x0r = x3i + x1r; x0i = x3r - x1i; a[j3] = wk1r * (x0i - x0r); a[j3 + 1] = wk1r * (x0i + x0r); } k1 = 0; m2 = 2 * m; for (k = m2; k < n; k += m2) { k1 += 2; k2 = 2 * k1; wk2r = w[k1]; wk2i = w[k1 + 1]; wk1r = w[k2]; wk1i = w[k2 + 1]; wk3r = wk1r - 2 * wk2i * wk1i; wk3i = 2 * wk2i * wk1r - wk1i; for (j = k; j < l + k; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j2] = wk2r * x0r - wk2i * x0i; a[j2 + 1] = wk2r * x0i + wk2i * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * x0r - wk1i * x0i; a[j1 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r - wk3i * x0i; a[j3 + 1] = wk3r * x0i + wk3i * x0r; } wk1r = w[k2 + 2]; wk1i = w[k2 + 3]; wk3r = wk1r - 2 * wk2r * wk1i; wk3i = 2 * wk2r * wk1r - wk1i; for (j = k + m; j < l + (k + m); j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j2] = -wk2i * x0r - wk2r * x0i; a[j2 + 1] = -wk2i * x0i + wk2r * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * x0r - wk1i * x0i; a[j1 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r - wk3i * x0i; a[j3 + 1] = wk3r * x0i + wk3i * x0r; } } } void rftfsub(int n, float *a, int nc, float *c) { int j, k, kk, ks, m; float wkr, wki, xr, xi, yr, yi; m = n >> 1; ks = 2 * nc / m; kk = 0; for (j = 2; j < m; j += 2) { k = n - j; kk += ks; wkr = 0.5 - c[nc - kk]; wki = c[kk]; xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr - wki * xi; yi = wkr * xi + wki * xr; a[j] -= yr; a[j + 1] -= yi; a[k] += yr; a[k + 1] -= yi; } } void rftbsub(int n, float *a, int nc, float *c) { int j, k, kk, ks, m; float wkr, wki, xr, xi, yr, yi; a[1] = -a[1]; m = n >> 1; ks = 2 * nc / m; kk = 0; for (j = 2; j < m; j += 2) { k = n - j; kk += ks; wkr = 0.5 - c[nc - kk]; wki = c[kk]; xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr + wki * xi; yi = wkr * xi - wki * xr; a[j] -= yr; a[j + 1] = yi - a[j + 1]; a[k] += yr; a[k + 1] = yi - a[k + 1]; } a[m + 1] = -a[m + 1]; } void dctsub(int n, float *a, int nc, float *c) { int j, k, kk, ks, m; float wkr, wki, xr; m = n >> 1; ks = nc / n; kk = 0; for (j = 1; j < m; j++) { k = n - j; kk += ks; wkr = c[kk] - c[nc - kk]; wki = c[kk] + c[nc - kk]; xr = wki * a[j] - wkr * a[k]; a[j] = wkr * a[j] + wki * a[k]; a[k] = xr; } a[m] *= c[0]; } void dstsub(int n, float *a, int nc, float *c) { int j, k, kk, ks, m; float wkr, wki, xr; m = n >> 1; ks = nc / n; kk = 0; for (j = 1; j < m; j++) { k = n - j; kk += ks; wkr = c[kk] - c[nc - kk]; wki = c[kk] + c[nc - kk]; xr = wki * a[k] - wkr * a[j]; a[k] = wkr * a[k] + wki * a[j]; a[j] = xr; } a[m] *= c[0]; } ================================================ FILE: lib/fft/fft4g.h ================================================ /* * http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html * Copyright Takuya OOURA, 1996-2001 * * You may use, copy, modify and distribute this code for any purpose (include * commercial use) and without fee. Please refer to this package when you modify * this code. * * Changes: * replaced "double to float" by eh2k. */ #include __BEGIN_DECLS void rdft(int n, int isgn, float *a, int *ip, float *w); void cdft(int n, int isgn, float *a, int *ip, float *w); __END_DECLS ================================================ FILE: lib/fv1/README.md ================================================ # FV-1.emu The [Spin Semi FV-1 DSP chip](http://www.spinsemi.com/products.html) emulator. #### HowTo | Knowledge * [DSP Basics](http://www.spinsemi.com/knowledge_base/dsp_basics.html) * [Audio Effects](http://www.spinsemi.com/knowledge_base/effects.html) * [Programming the FV-1](http://www.spinsemi.com/knowledge_base/pgm_quick.html) * [The FV-1 Architecture overview](http://www.spinsemi.com/knowledge_base/arch.html) * [FV-1 Instructions and Syntax](http://www.spinsemi.com/knowledge_base/inst_syntax.html) * [Coding Examples](http://www.spinsemi.com/knowledge_base/coding_examples.html) * [Algorithm development Support Forum](http://www.spinsemi.com/forum/viewforum.php?f=4) #### PDF | Datasheets * [CheatSheet](http://www.spinsemi.com/knowledge_base/cheat.html) * [SPINAsmUserManual.pdf](http://www.spinsemi.com/Products/datasheets/spn1001-dev/SPINAsmUserManual.pdf) * [AN-0001.pdf](http://www.spinsemi.com/Products/appnotes/spn1001/AN-0001.pdf) #### Effects | DSP Programs * [OEM Programs by Keith Barr](http://www.spinsemi.com/get_spn.php?spn=oem1.zip&prodnum=SPN1001) * [Free DSP Programs](http://www.spinsemi.com/programs.php) * https://mstratman.github.io/fv1-programs/ * https://github.com/HolyCityAudio/SpinCAD-Designer ================================================ FILE: lib/fv1/factory.json ================================================ [ { "name": "FV1/Gated-Reverb", "pot0": "PreD", "pot1": "G-Time", "pot2": "Damp", "url": "https://raw.githubusercontent.com/eh2k/squares-and-circles/main/lib/fv1/spn/OEM1_4.spn" }, { "name": "FV1/Reverb-HP-LP", "pot0": "Reverb", "pot1": "HP", "pot2": "LP", "url": "https://raw.githubusercontent.com/eh2k/squares-and-circles/main/lib/fv1/spn/dance_ir_h_l.spn" } ] ================================================ FILE: lib/fv1/spn/OEM1_4.spn ================================================ ;OEM1_4 Gated Reverb ;pot0 = gate time ;pot1 = predelay ;pot2 = damping ;gated reverb by FIR technique. Good for percussion, but signal levels may ;accumulate with continuous program. ;Input is mono, for use with portable mixer sends. Output is spread into stereo space. ;Gate time is variable from 115mS to 307mS (Fs=46608KHz) or 162mS to 436mS (Fs=32768KHz) ;Predelay is variable from 0 to 87mS (Fs=46608KHz), or 0 to 125mS (Fs=32768KHz) ;Damping filter within FIR delay increases with clockwise rotation of pot2 ;memory declarations: mem pdel 4100 mem gdel 15000 mem lap1 234 mem lap2 446 mem lap3 552 mem rap1 201 mem rap2 389 mem rap3 627 ;register declarations: equ temp reg0 equ gout reg1 equ fil1 reg2 equ fil2 reg3 equ fil3 reg4 equ fil4 reg5 constants: equ kap 0.6 ;do variable predelay: skp run,1 wldr rmp0,0,4096 ;initialize predelay rdax adcl,0.25 ;put inputs into predelay rdax adcr,0.25 ;headroom space wra pdel,0 cho rda,rmp0,reg|compc,pdel ;get outputs from predelay, interpolated cho rda,rmp0,0,pdel+1 wra gdel,0 ;write predelay output to gate delay memory cho rdal,rmp0 ;read current predelay pointer rdax pot1,-0.5 ;subtract pot for servo control of pointer wrax rmp0_rate,0 ;maintain predelay pointer ;prepare for decay time setting; ;analyze pot value and jump to proper location: ;jump only when ACC is zero, as this is carried into audio calculations rdax pot0,1 and %01111000_000000000_00000000 ;mask upper 4 bits sof 1,-15/16 skp gez,p1 sof 1,1/16 skp gez,p2 sof 1,1/16 skp gez,p3 sof 1,1/16 skp gez,p4 sof 1,1/16 skp gez,p5 sof 1,1/16 skp gez,p6 sof 1,1/16 skp gez,p7 sof 1,1/16 skp gez,p8 sof 1,1/16 skp gez,p9 sof 1,1/16 skp gez,p10 sof 1,1/16 skp gez,p11 sof 1,1/16 skp gez,p12 sof 1,1/16 skp gez,p13 sof 1,1/16 skp gez,p14 sof 1,1/16 skp gez,p15 sof 1,1/16 skp gez,p16 sof 1,1/16 skp gez,p17 sof 1,1/16 skp gez,p18 sof 1,1/16 skp gez,p19 sof 1,1/16 skp gez,p20 p1: rda gdel+14334,0.4 p2: rda gdel+14023,0.5 p3: rda gdel+13508,0.4 p4: rda gdel+13101,0.5 p5: rda gdel+12760,0.5 p6: rda gdel+12120,0.4 p7: rda gdel+11765,0.5 p8: rda gdel+11312,0.5 p9: rda gdel+10750,0.5 p10: rda gdel+10212,0.5 p11: rda gdel+9705,0.5 p12: rda gdel+9367,0.5 p13: rda gdel+8905,0.4 p14: rda gdel+8575,0.5 p15: rda gdel+8215,0.5 p16: rda gdel+7412,0.4 p17: rda gdel+7144,0.5 p18: rda gdel+6513,0.5 p19: rda gdel+5822,0.5 p20: rda gdel+5320,0.5 rda gdel+5138,0.5 rda gdel+4576,0.5 rda gdel+3907,0.4 rda gdel+3420,0.5 rda gdel+2974,0.5 rda gdel+2530,0.5 rda gdel+2110,0.5 rda gdel+1340,0.5 rda gdel+923,0.5 rda gdel+500,0.5 rda gdel,0.6 wrax gout,1 rda lap1#,kap ;spread outputs and smear with allpasses wrap lap1,-kap rda lap2#,kap wrap lap2,-kap rda lap3#,kap wrap lap3,-kap wrax dacl,0 rdax gout,1 rda rap1#,kap wrap rap1,-kap rda rap2#,kap wrap rap2,-kap rda rap3#,kap wrap rap3,-kap wrax dacr,0 ;now insert lp filters into gate delay, adjustable by pot2: rda gdel+2500,-1 rdfx fil1,0.5 wrhx fil1,-1 mulx pot2 rda gdel+2500,1 wra gdel+2500,0 rda gdel+4500,-1 rdfx fil2,0.4 wrhx fil2,-1 mulx pot2 rda gdel+4500,1 wra gdel+4500,0 rda gdel+7000,-1 rdfx fil1,0.3 wrhx fil1,-1 mulx pot2 rda gdel+7000,1 wra gdel+7000,0 rda gdel+10000,-1 rdfx fil1,0.2 wrhx fil1,-1 mulx pot2 rda gdel+10000,1 wra gdel+10000,0 ================================================ FILE: lib/fv1/spn/dance_ir_h_l.spn ================================================ ;dance patchfor disco mixers: ;pot1 = Reverb to infinite RT, scales in and out levels ;pot2 = High pass filter (2 pole peaking, 8 ocatves) ;pot3 = Low pass filter (2 pole peaking, 8 ocatves) ;filters are great for actively modifying program material; ;reveb can capture tonality for filter manipulation. ;beware, infinite reverb turns off input! equ krt reg0 equ kin reg1 equ kmix reg2 equ hpal reg3 equ hpbl reg4 equ lpal reg5 equ lpbl reg6 equ hpar reg7 equ hpbr reg8 equ lpar reg9 equ lpbr reg10 equ kfh reg11 equ kfl reg12 equ temp reg13 equ rmixl reg14 equ rmixr reg15 equ hpoutl reg16 equ hpoutr reg17 equ hbyp reg18 equ lbyp reg19 mem ap1 202 mem ap2 541 mem ap3 1157 mem ap4 1903 mem dap1a 2204 mem dap1b 3301 mem del1 4456 mem dap2a 3532 mem dap2b 3201 mem del2 6325 equ kap 0.6 equ kql -0.2 equ kqh -0.2 ;prepare pots to affect control variables: ;pot0 controls reverb time, but also affects input drive level; ;reveb time is moderate up to about mid position, then increases ;to infinity (or nearly) at full position. ;input drive is constant, but decreases at the full pot0 position. ;output mix is varied over the first half of pot0, then remains ;high to the end of pot0's range. rdax pot0,1.999 ;get pot0, clip the upper half of pot0's range. wrax kmix,0 ;write the output mix value rdax pot0,-1 ;get pot0 again, 0 to -1 sof 1,0.999 ;now +1 to 0 sof 1.999,0 ;now +1 until midpint, then decreases to 0 wrax kin,0 ;write the input attenuator value rdax pot0,1 ;get pot0 again wrax krt,1 ;save in krt, keep in ACC sof 1,-0.5 ;subtract 1/2 skp gez,2 ;skp if pot is in upper half of range sof 0,0.5 ;load accumulator with +0.5 wrax krt,0 ;overwrite if pot is in lower half of range ;now prepare pot1 for HP sweeping. ;both frequency controls are exponential, and frequency increases ;with clockwise pot rotation. Target Kf ranges are from .001 to 1.0 clr rdax pot1,1 ;get pot1 sof 0.5,-0.5 ;ranges -0.5 to 0 exp 1,0 wrax kfh,0 ;write to HP filter control rdax pot2,1 ;get pot2 sof 0.5,-0.5 ;ranges -0.5 to 0 exp 1,0 wrax kfl,0 ;write to LP filter control ;now derive filter bypass functions (at open conditions) rdax pot1,-1 sof 1,0.999 ;ranges +1 to 0 wrax temp,1 mulx temp mulx temp wrax hbyp,0 rdax pot2,1 ;read pot2 (LP) again mulx pot2 mulx pot2 mulx pot2 wrax lbyp,0 ;now do reverb, simple, twin loop, mono drive: rdax adcl,0.25 rdax adcr,0.25 ;get inputs, leave headroom mulx kin ;scale by input attenuator rda ap1#,kap ;4 all passes: wrap ap1,-kap rda ap2#,kap wrap ap2,-kap rda ap3#,kap wrap ap3,-kap rda ap4#,kap wrap ap4,-kap wrax temp,0 ;write ap output to temp reg rda del2#,1 mulx krt rdax temp,1 rda dap1a#,kap wrap dap1a,-kap rda dap1b#,kap wrap dap1b,-kap wra del1,0 rda del1#,1 mulx krt rdax temp,1 rda dap2a#,kap wrap dap2a,-kap rda dap2b#,kap wrap dap2b,-kap wra del2,0 ;now mix the inputs with the reverb: rdax adcl,-1 rda del1,1.5 mulx pot0 rdax adcl,1 wrax rmixl,0 rdax adcr,-1 rda del2,1.5 mulx pot0 rdax adcr,1 wrax rmixr,0 ;Reverb outputs are at rmixl and rmixr. ;now do two filters, start with the high pass, stereo. ;use the reveb mix for inputs, cascade the filter banks. rdax hpal,1 mulx kfh rdax hpbl,1 wrax hpbl,-1 rdax hpal,kqh rdax rmixl,1 wrax hpoutl,1 ;HP output mulx kfh rdax hpal,1 wrax hpal,0 rdax hpar,1 mulx kfh rdax hpbr,1 wrax hpbr,-1 rdax hpar,kqh rdax rmixr,1 wrax hpoutr,1 ;HP output mulx kfh rdax hpar,1 wrax hpar,0 ;bypass if pot1 is fully counterclockwise: rdax hpoutl,-1 rdax rmixl,1 mulx hbyp rdax hpoutl,1 wrax hpoutl,0 rdax hpoutr,-1 rdax rmixr,1 mulx hbyp rdax hpoutr,1 wrax hpoutr,0 ;now do cascaded low pass: rdax lpal,1 mulx kfl rdax lpbl,1 wrax lpbl,-1 rdax lpal,kql rdax hpoutl,1 mulx kfl rdax lpal,1 wrax lpal,0 rdax lpar,1 mulx kfl rdax lpbr,1 wrax lpbr,-1 rdax lpar,kql rdax hpoutr,1 mulx kfl rdax lpar,1 wrax lpar,0 rdax lpbl,-1 rdax hpoutl,1 mulx lbyp rdax lpbl,1 wrax dacl,0 rdax lpbr,-1 rdax hpoutr,1 mulx lbyp rdax lpbr,1 wrax dacr,0 ================================================ FILE: lib/marbles/note_filter.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Low pass filter for getting stable pitch data. #ifndef MARBLES_NOTE_FILTER_H_ #define MARBLES_NOTE_FILTER_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/delay_line.h" namespace marbles { // Note: this is a "slow" filter, since it takes about 10 samples to catch // up with an edge in the input signal. class NoteFilter { public: enum { N = 7 // Median filter order }; NoteFilter() { } ~NoteFilter() { } void Init() { lp_1_ = 0.0f; lp_2_ = 0.0f; std::fill(&previous_values_[0], &previous_values_[N], 0.0f); } inline float Process(float value) { float sorted_values[N]; std::rotate( &previous_values_[0], &previous_values_[1], &previous_values_[N]); previous_values_[N - 1] = value; std::copy(&previous_values_[0], &previous_values_[N], &sorted_values[0]); std::sort(&sorted_values[0], &sorted_values[N]); value = sorted_values[(N - 1) / 2]; const float kLPCoefficient = 0.65f; ONE_POLE(lp_1_, value, kLPCoefficient); ONE_POLE(lp_2_, lp_1_, kLPCoefficient); return lp_2_; } private: float previous_values_[N]; float lp_1_; float lp_2_; DISALLOW_COPY_AND_ASSIGN(NoteFilter); }; } // namespace marbles #endif // MARBLES_NOTE_FILTER_H_ ================================================ FILE: lib/marbles/ramp/ramp.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Timing information is represented as a ramp from 0.0 to kMaxRampValue #ifndef MARBLES_RAMP_RAMP_H_ #define MARBLES_RAMP_RAMP_H_ #include "stmlib/stmlib.h" namespace marbles { const float kMaxRampValue = 0.9999f; } // namespace marbles #endif // MARBLES_RAMP_RAMP_H_ ================================================ FILE: lib/marbles/ramp/ramp_divider.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Generates a ramp whose frequency is p/q times the frequency of the input. // Phase is synchronized. #ifndef MARBLES_RAMP_RAMP_DIVIDER_H_ #define MARBLES_RAMP_RAMP_DIVIDER_H_ #include "stmlib/stmlib.h" #include #include "marbles/ramp/ramp.h" namespace marbles { struct Ratio { float to_float() { return static_cast(p) / static_cast(q); } int p; int q; template void Simplify() { while ((p % n) == 0 && (q % n) == 0) { p /= n; q /= n; } } }; class RampDivider { public: RampDivider() { } ~RampDivider() { } void Init() { phase_ = 0.0f; train_phase_ = 0.0f; max_train_phase_ = 1.0f; f_ratio_ = 0.99999f; reset_counter_ = 1; } void Process(Ratio ratio, const float* in, float* out, size_t size) { while (size--) { float new_phase = *in++; float frequency = new_phase - phase_; if (frequency < 0.0f) { frequency += 1.0f; --reset_counter_; if (!reset_counter_) { train_phase_ = new_phase; reset_counter_ = ratio.q; f_ratio_ = ratio.to_float() * kMaxRampValue; frequency = 0.0f; max_train_phase_ = static_cast(ratio.q); } } train_phase_ += frequency; if (train_phase_ >= max_train_phase_) { train_phase_ = max_train_phase_; } float output_phase = train_phase_ * f_ratio_; output_phase -= static_cast(static_cast(output_phase)); *out++ = output_phase; phase_ = new_phase; } } private: float phase_; float train_phase_; float max_train_phase_; float f_ratio_; int reset_counter_; DISALLOW_COPY_AND_ASSIGN(RampDivider); }; } // namespace marbles #endif // MARBLES_RAMP_RAMP_DIVIDER_H_ ================================================ FILE: lib/marbles/ramp/ramp_extractor.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Recovers a ramp from a clock input by guessing at what time the next edge // will occur. Prediction strategies: // - Moving average of previous intervals. // - Trigram model on quantized intervals. // - Periodic rhythmic pattern. // - Assume that the pulse width is constant, deduct the period from the on time // and the pulse width. #include "marbles/ramp/ramp_extractor.h" #include #include "marbles/ramp/ramp.h" #include "stmlib/dsp/dsp.h" namespace marbles { using namespace std; using namespace stmlib; const float kLogOneFourth = 1.189207115f; const float kPulseWidthTolerance = 0.05f; inline bool IsWithinTolerance(float x, float y, float error) { return x >= y * (1.0f - error) && x <= y * (1.0f + error); } void RampExtractor::Init(float max_frequency) { max_frequency_ = max_frequency; audio_rate_period_ = 1.0f / (100.0f / 32000.0f); audio_rate_period_hysteresis_ = audio_rate_period_; Reset(); } void RampExtractor::Reset() { audio_rate_ = false; train_phase_ = 0.0f; target_frequency_ = frequency_ = 0.0001f; lp_coefficient_ = 0.5f; next_max_train_phase_ = max_train_phase_ = 0.999f; next_f_ratio_ = f_ratio_ = 1.0f; reset_counter_ = 1; reset_frequency_ = 0.0f; reset_interval_ = 32000 * 3; Pulse p; p.bucket = 1; p.on_duration = 2000; p.total_duration = 4000; p.pulse_width = 0.5f; fill(&history_[0], &history_[kHistorySize], p); current_pulse_ = 0; next_bucket_ = 48.0f; average_pulse_width_ = 0.0f; fill(&predicted_period_[0], &predicted_period_[PREDICTOR_LAST], 4000.0f); fill(&prediction_accuracy_[0], &prediction_accuracy_[PREDICTOR_LAST], 0.0f); fill( &prediction_hash_table_[0], &prediction_hash_table_[kHashTableSize], 0.0f); } float RampExtractor::ComputeAveragePulseWidth(float tolerance) const { float sum = 0.0f; for (size_t i = 0; i < kHistorySize; ++i) { if (!IsWithinTolerance(history_[i].pulse_width, history_[current_pulse_].pulse_width, tolerance)) { return 0.0f; } sum += history_[i].pulse_width; } return sum / static_cast(kHistorySize); } RampExtractor::Prediction RampExtractor::PredictNextPeriod() { float last_period = static_cast(history_[current_pulse_].total_duration); Predictor best_predictor = PREDICTOR_FAST_MOVING_AVERAGE; for (int i = PREDICTOR_FAST_MOVING_AVERAGE; i < PREDICTOR_LAST; ++i) { float error = (predicted_period_[i] - last_period) / (last_period + 0.01f); // Scoring function: 10% error is half as good as 0% error. float accuracy = 1.0f / (1.0f + 100.0f * error * error); // Slowly trust good predictors, quickly demote predictors who make errors. SLOPE(prediction_accuracy_[i], accuracy, 0.1f, 0.5f); // (Ugly code but I don't want virtuals for these.) switch (i) { case PREDICTOR_SLOW_MOVING_AVERAGE: ONE_POLE(predicted_period_[i], last_period, 0.1f); break; case PREDICTOR_FAST_MOVING_AVERAGE: ONE_POLE(predicted_period_[i], last_period, 0.5f); break; case PREDICTOR_HASH: { size_t t_2 = (current_pulse_ - 2 + kHistorySize) % kHistorySize; size_t t_1 = (current_pulse_ - 1 + kHistorySize) % kHistorySize; size_t t_0 = current_pulse_; size_t hash = history_[t_1].bucket + 17 * history_[t_2].bucket; ONE_POLE( prediction_hash_table_[hash % kHashTableSize], last_period, 0.5f); hash = history_[t_0].bucket + 17 * history_[t_1].bucket; predicted_period_[i] = prediction_hash_table_[hash % kHashTableSize]; if (predicted_period_[i] == 0.0f) { predicted_period_[i] = last_period; } } break; default: { // Periodicity detector. size_t candidate_period = i - PREDICTOR_PERIOD_1 + 1; size_t t = current_pulse_ + 1 + kHistorySize - candidate_period; predicted_period_[i] = history_[t % kHistorySize].total_duration; } break; } if (prediction_accuracy_[i] >= prediction_accuracy_[best_predictor]) { best_predictor = Predictor(i); } } Prediction p; p.period = predicted_period_[best_predictor]; p.accuracy = prediction_accuracy_[best_predictor]; return p; } bool RampExtractor::Process( Ratio ratio, bool always_ramp_to_maximum, const GateFlags* gate_flags, float* ramp, size_t size) { bool reset_observed = false; while (size--) { GateFlags flags = *gate_flags++; // We are done with the previous pulse. if (flags & GATE_FLAG_RISING) { Pulse& p = history_[current_pulse_]; const bool record_pulse = p.total_duration < reset_interval_; if (!record_pulse) { // Quite a long pause - the clock has probably been stopped // and restarted. reset_frequency_ = 0.0f; train_phase_ = 0.0f; reset_counter_ = ratio.q; reset_interval_ = 4 * p.total_duration; reset_observed = true; } else { float period = float(p.total_duration); if (period <= audio_rate_period_hysteresis_) { audio_rate_ = true; audio_rate_period_hysteresis_ = audio_rate_period_ * 1.1f; average_pulse_width_ = 0.0f; bool no_glide = f_ratio_ != ratio.to_float(); f_ratio_ = ratio.to_float(); float frequency = 1.0f / period; target_frequency_ = std::min(f_ratio_ * frequency, max_frequency_); float up_tolerance = (1.02f + 2.0f * frequency) * frequency_; float down_tolerance = (0.98f - 2.0f * frequency) * frequency_; no_glide |= target_frequency_ > up_tolerance || target_frequency_ < down_tolerance; lp_coefficient_ = no_glide ? 1.0f : period * 0.00001f; } else { audio_rate_ = false; audio_rate_period_hysteresis_ = audio_rate_period_; // Compute the pulse width of the previous pulse, and check if the // PW has been consistent over the past pulses. p.pulse_width = static_cast(p.on_duration) / period; average_pulse_width_ = ComputeAveragePulseWidth(kPulseWidthTolerance); if (p.on_duration < 32) { average_pulse_width_ = 0.0f; } // Try to predict the next interval between pulses. If the prediction // has been reliable over the past pulses, or if the PW is steady, // we'll be able to make reliable prediction about the time at which // the next pulse will occur Prediction prediction = PredictNextPeriod(); frequency_ = 1.0f / prediction.period; --reset_counter_; if (!reset_counter_) { next_f_ratio_ = ratio.to_float() * kMaxRampValue; next_max_train_phase_ = static_cast(ratio.q); if (always_ramp_to_maximum && train_phase_ < max_train_phase_) { reset_frequency_ = \ (0.01f + max_train_phase_ - train_phase_) * 0.0625f; } else { reset_frequency_ = 0.0f; train_phase_ = 0.0f; f_ratio_ = next_f_ratio_; max_train_phase_ = next_max_train_phase_; } reset_counter_ = ratio.q; } else { float expected = max_train_phase_ - static_cast(reset_counter_); float warp = expected - train_phase_ + 1.0f; frequency_ *= max(warp, 0.01f); } } reset_interval_ = static_cast( std::max(4.0f / target_frequency_, 32000 * 3.0f)); current_pulse_ = (current_pulse_ + 1) % kHistorySize; } history_[current_pulse_].on_duration = 0; history_[current_pulse_].total_duration = 0; history_[current_pulse_].bucket = 0; next_bucket_ = 48.0f; } // Update history buffer with total duration and on duration. ++history_[current_pulse_].total_duration; if (flags & GATE_FLAG_HIGH) { ++history_[current_pulse_].on_duration; } if (float(history_[current_pulse_].total_duration) >= next_bucket_) { ++history_[current_pulse_].bucket; next_bucket_ *= kLogOneFourth; } // If the pulse width is constant, and if a clock falling edge is // detected, estimate the period using the on time and the pulse width, // and correct the phase increment accordingly. if ((flags & GATE_FLAG_FALLING) && average_pulse_width_ > 0.0f) { float t_on = static_cast(history_[current_pulse_].on_duration); float next = max_train_phase_ - static_cast(reset_counter_) + 1.0f; float pw = average_pulse_width_; frequency_ = max((next - train_phase_), 0.0f) * pw / ((1.0f - pw) * t_on); } if (audio_rate_) { ONE_POLE(frequency_, target_frequency_, lp_coefficient_); train_phase_ += frequency_; if (train_phase_ >= 1.0f) { train_phase_ -= 1.0f; } *ramp++ = train_phase_; } else { if (reset_frequency_) { train_phase_ += reset_frequency_; if (train_phase_ >= max_train_phase_) { train_phase_ = 0.0f; reset_frequency_ = 0.0f; f_ratio_ = next_f_ratio_; max_train_phase_ = next_max_train_phase_; } } else { train_phase_ += frequency_; if (train_phase_ >= max_train_phase_) { if (frequency_ == max_frequency_) { train_phase_ -= max_train_phase_; } else { train_phase_ = max_train_phase_; } } } float output_phase = train_phase_ * f_ratio_; output_phase -= static_cast(static_cast(output_phase)); *ramp++ = output_phase; } } return reset_observed; } } // namespace marbles ================================================ FILE: lib/marbles/ramp/ramp_extractor.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Recovers a ramp from a clock input by guessing at what time the next edge // will occur. Prediction strategies: // - Moving average of previous intervals. // - Trigram model on quantized intervals. // - Periodic rhythmic pattern. // - Assume that the pulse width is constant, deduct the period from the on time // and the pulse width. // // All prediction strategies are concurrently tested, and the output from the // best performing one is selected (à la early Scheirer/Goto beat trackers). #ifndef MARBLES_RAMP_RAMP_EXTRACTOR_H_ #define MARBLES_RAMP_RAMP_EXTRACTOR_H_ #include "stmlib/stmlib.h" #include "stmlib/utils/gate_flags.h" #include "marbles/ramp/ramp_divider.h" namespace marbles { class RampExtractor { public: RampExtractor() { } ~RampExtractor() { } void Init(float max_frequency); bool Process( Ratio r, bool always_ramp_to_maximum, const stmlib::GateFlags* gate_flags, float* ramp, size_t size); void Reset(); private: struct Pulse { uint32_t on_duration; uint32_t total_duration; uint32_t bucket; // 4xlog2(total_duration). float pulse_width; }; struct Prediction { float period; float accuracy; }; enum Predictor { PREDICTOR_SLOW_MOVING_AVERAGE, PREDICTOR_FAST_MOVING_AVERAGE, PREDICTOR_HASH, PREDICTOR_PERIOD_1, PREDICTOR_PERIOD_2, PREDICTOR_PERIOD_3, PREDICTOR_PERIOD_4, PREDICTOR_PERIOD_5, PREDICTOR_PERIOD_6, PREDICTOR_PERIOD_7, PREDICTOR_PERIOD_8, PREDICTOR_PERIOD_9, PREDICTOR_PERIOD_10, PREDICTOR_LAST }; static const size_t kHistorySize = 16; static const size_t kHashTableSize = 256; float ComputeAveragePulseWidth(float tolerance) const; Prediction PredictNextPeriod(); size_t current_pulse_; Pulse history_[kHistorySize]; float next_bucket_; float prediction_hash_table_[kHashTableSize]; float predicted_period_[PREDICTOR_LAST]; float prediction_accuracy_[PREDICTOR_LAST]; float average_pulse_width_; float train_phase_; float frequency_; float max_output_phase_; float max_train_phase_; float reset_frequency_; float target_frequency_; float lp_coefficient_; float f_ratio_; float next_f_ratio_; float next_max_train_phase_; int reset_counter_; uint32_t reset_interval_; bool audio_rate_; float max_frequency_; float audio_rate_period_; float audio_rate_period_hysteresis_; DISALLOW_COPY_AND_ASSIGN(RampExtractor); }; } // namespace marbles #endif // MARBLES_RAMP_RAMP_EXTRACTOR_H_ ================================================ FILE: lib/marbles/ramp/ramp_generator.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Simple ramp generator. #ifndef MARBLES_RAMP_RAMP_GENERATOR_H_ #define MARBLES_RAMP_RAMP_GENERATOR_H_ #include "stmlib/stmlib.h" namespace marbles { class RampGenerator { public: RampGenerator() { } ~RampGenerator() { } void Init() { phase_ = 0.0f; } void Render(float frequency, float* out, size_t size) { while (size--) { phase_ += frequency; if (phase_ >= 1.0f) { phase_ -= 1.0f; } *out++ = phase_; } } private: float phase_; DISALLOW_COPY_AND_ASSIGN(RampGenerator); }; } // namespace marbles #endif // MARBLES_RAMP_RAMP_GENERATOR_H_ ================================================ FILE: lib/marbles/ramp/slave_ramp.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // A ramp that follows a mater ramp through division/multiplication. #ifndef MARBLES_RAMP_SLAVE_RAMP_H_ #define MARBLES_RAMP_SLAVE_RAMP_H_ #include "stmlib/stmlib.h" #include "marbles/ramp/ramp.h" namespace marbles { class SlaveRamp { public: SlaveRamp() { } ~SlaveRamp() { } inline void Init() { phase_ = 0.0f; max_phase_ = kMaxRampValue; ratio_ = 1.0f; pulse_width_ = 0.0f; target_ = 1.0f; pulse_length_ = 0; bernoulli_ = false; must_complete_ = false; } // Initialize with a multiplied/divided rate compared to the master. inline void Init(int pattern_length, Ratio ratio, float pulse_width) { bernoulli_ = false; phase_ = 0.0f; max_phase_ = static_cast(pattern_length) * kMaxRampValue; ratio_ = ratio.to_float(); pulse_width_ = pulse_width; target_ = 1.0f; pulse_length_ = 0; } // Initialize with an adaptive slope: divide the frequency by 2 every time // we know we won't have to reach 1.0 at the next tick. inline void Init( bool must_complete, float pulse_width, float expected_value) { bernoulli_ = true; if (must_complete_) { phase_ = 0.0f; pulse_width_ = pulse_width; ratio_ = 1.0f; pulse_length_ = 0; } if (!must_complete) { ratio_ = (1.0f - phase_) * expected_value; } else { ratio_ = 1.0f - phase_; } must_complete_ = must_complete; } inline void Process(float frequency, float* phase, bool* gate) { float output_phase; if (bernoulli_) { phase_ += frequency * ratio_; output_phase = phase_; if (output_phase >= 1.0f) { output_phase = 1.0f; } } else { phase_ += frequency; if (phase_ >= max_phase_) { phase_ = max_phase_; } output_phase = phase_ * ratio_; if (output_phase > target_) { pulse_length_ = 0; target_ += 1.0f; } output_phase -= static_cast(static_cast(output_phase)); } *phase = output_phase; *gate = pulse_width_ == 0.0f ? pulse_length_ < 32 && output_phase <= 0.5f : output_phase < pulse_width_; ++pulse_length_; } private: float phase_; float max_phase_; float ratio_; float pulse_width_; float target_; int pulse_length_; bool bernoulli_; bool must_complete_; DISALLOW_COPY_AND_ASSIGN(SlaveRamp); }; } // namespace marbles #endif // MARBLES_RAMP_SLAVE_RAMP_H_ ================================================ FILE: lib/marbles/random/discrete_distribution_quantizer.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Quantize voltages by sampling from a discrete distribution. #include "marbles/random/discrete_distribution_quantizer.h" #include "stmlib/dsp/dsp.h" #include #include namespace marbles { using namespace stmlib; using namespace std; void DiscreteDistributionQuantizer::Init(const Scale& scale) { int n = scale.num_degrees; // We don't want garbage scale data here... if (!n || n > kMaxDegrees || scale.base_interval == 0.0f) { return; } base_interval_ = scale.base_interval; base_interval_reciprocal_ = 1.0f / scale.base_interval; num_cells_ = n + 1; for (int i = 0; i <= n; ++i) { float previous_voltage = scale.cell_voltage(i == 0 ? 0 : i - 1); float next_voltage = scale.cell_voltage(i == n ? n : i + 1); cells_[i].center = scale.cell_voltage(i); cells_[i].width = 0.5f * (next_voltage - previous_voltage); cells_[i].weight = static_cast(scale.degree[i % n].weight) / 256.0f; } } float DiscreteDistributionQuantizer::Process(float value, float amount) { if (amount < 0.0f) { return value; } float raw_value = value; // Assuming 1V/Octave and a scale repeating every octave, note_integral // will store the octave number, and note_fractional the fractional // pitch class. const float note = value * base_interval_reciprocal_; MAKE_INTEGRAL_FRACTIONAL(note); if (value < 0.0f) { note_integral -= 1; note_fractional += 1.0f; } // For amount ranging between 0 and 0.25, do not remove notes from the scale // just crossfade from the unquantized output to the quantized output. const float scaled_amount = amount < 0.25f ? 0.0f : (amount - 0.25f) * 1.333f; distribution_.Init(); for (int i = 0; i < num_cells_ - 1; ++i) { distribution_.AddToken(i, cells_[i].scaled_width(scaled_amount)); } distribution_.NoMoreTokens(); Distribution::Result r = distribution_.Sample(note_fractional); float quantized_value = cells_[r.token_id].center; float offset = static_cast(note_integral) * base_interval_; quantized_value += offset; r.start *= base_interval_; r.start += offset; if (amount < 0.25f) { amount *= 4.0f; float x; if (r.token_id == 0) { x = r.fraction - 1.0f; } else if (r.token_id == num_cells_ - 1) { x = -r.fraction; } else { x = 2.0f * (fabs(r.fraction - 0.5f) - 0.5f); } const float slope = amount / (1.01f - amount); const float y = max(x * slope + 1.0f, 0.0f); quantized_value -= y * (quantized_value - raw_value); } return quantized_value; } } // namespace marbles ================================================ FILE: lib/marbles/random/discrete_distribution_quantizer.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Quantize voltages by sampling from a discrete distribution. #ifndef MARBLES_RANDOM_DISCRETE_DISTRIBUTION_QUANTIZER_H_ #define MARBLES_RANDOM_DISCRETE_DISTRIBUTION_QUANTIZER_H_ #include "stmlib/stmlib.h" #include "marbles/random/distributions.h" #include "marbles/random/quantizer.h" namespace marbles { class DiscreteDistributionQuantizer { public: typedef DiscreteDistribution Distribution; struct Cell { float center; float width; float weight; inline float scaled_width(float amount) { float w = 8.0f * (weight - amount) + 0.5f; CONSTRAIN(w, 0.0f, 1.0f); return w * width; } }; DiscreteDistributionQuantizer() { } ~DiscreteDistributionQuantizer() { } void Init(const Scale& scale); float Process(float value, float amount); private: float base_interval_; float base_interval_reciprocal_; int num_cells_; Cell cells_[kMaxDegrees + 1]; Distribution distribution_; DISALLOW_COPY_AND_ASSIGN(DiscreteDistributionQuantizer); }; } // namespace marbles #endif // MARBLES_RANDOM_DISCRETE_DISTRIBUTION_QUANTIZER_H_ ================================================ FILE: lib/marbles/random/distributions.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Generates samples from various kinds of random distributions. #ifndef MARBLES_RANDOM_DISTRIBUTIONS_H_ #define MARBLES_RANDOM_DISTRIBUTIONS_H_ #include "stmlib/stmlib.h" #include #include "stmlib/dsp/dsp.h" #include "marbles/resources.h" namespace marbles { const size_t kNumBiasValues = 5; const size_t kNumRangeValues = 9; const float kIcdfTableSize = 128.0f; // Generates samples from beta distribution, from uniformly distributed samples. // For higher throughput, uses pre-computed tables of inverse cdfs. inline float BetaDistributionSample(float uniform, float spread, float bias) { // Tables are pre-computed only for bias <= 0.5. For values above 0.5, // symmetry is used. bool flip_result = bias > 0.5f; if (flip_result) { uniform = 1.0f - uniform; bias = 1.0f - bias; } bias *= (static_cast(kNumBiasValues) - 1.0f) * 2.0f; spread *= (static_cast(kNumRangeValues) - 1.0f); MAKE_INTEGRAL_FRACTIONAL(bias); MAKE_INTEGRAL_FRACTIONAL(spread); size_t cell = bias_integral * (kNumRangeValues + 1) + spread_integral; // Lower 5% and 95% percentiles use a different table with higher resolution. size_t offset = 0; if (uniform <= 0.05f) { offset = kIcdfTableSize + 1; uniform *= 20.0f; } else if (uniform >= 0.95f) { offset = 2 * (kIcdfTableSize + 1); uniform = (uniform - 0.95f) * 20.0f; } float x1y1 = stmlib::Interpolate( distributions_table[cell] + offset, uniform, kIcdfTableSize); float x2y1 = stmlib::Interpolate( distributions_table[cell + 1] + offset, uniform, kIcdfTableSize); float x1y2 = stmlib::Interpolate( distributions_table[cell + kNumRangeValues + 1] + offset, uniform, kIcdfTableSize); float x2y2 = stmlib::Interpolate( distributions_table[cell + kNumRangeValues + 2] + offset, uniform, kIcdfTableSize); float y1 = x1y1 + (x2y1 - x1y1) * spread_fractional; float y2 = x1y2 + (x2y2 - x1y2) * spread_fractional; float y = y1 + (y2 - y1) * bias_fractional; if (flip_result) { y = 1.0f - y; } return y; } // Pre-computed beta(3, 3) with a fatter tail. inline float FastBetaDistributionSample(float uniform) { return stmlib::Interpolate(dist_icdf_4_3, uniform, kIcdfTableSize); } // Draws samples from a discrete distribution. Used for the quantizer. // Example: // * 1 with probability 0.2 // * 20 with probability 0.7 // * 666 with probability 0.1 // // DiscreteDistribution d; // d.Init(); // d.AddToken(1, 0.2); // d.AddToken(20, 0.7); // d.AddToken(666, 0.1); // d.NoMoreTokens(); // Result r = d.Sample(u); // cout << r.token_id; // // Weights do not have to add to 1.0f - the class handles normalization. // template class DiscreteDistribution { public: DiscreteDistribution() { } ~DiscreteDistribution() { } void Init() { sum_ = 0.0f; num_tokens_ = 1; cdf_[0] = 0.0f; token_ids_[0] = 0; } void AddToken(int token_id, float weight) { if (weight <= 0.0f) { return; } sum_ += weight; token_ids_[num_tokens_] = token_id; cdf_[num_tokens_] = sum_; ++num_tokens_; } void NoMoreTokens() { token_ids_[num_tokens_] = token_ids_[num_tokens_ - 1]; cdf_[num_tokens_] = sum_ + 1.0f; } struct Result { int token_id; float fraction; float start; float width; }; inline Result Sample(float u) const { Result r; u *= sum_; int n = std::upper_bound(&cdf_[1], &cdf_[num_tokens_ + 1], u) - &cdf_[0]; float norm = 1.0f / sum_; r.token_id = token_ids_[n]; r.width = (cdf_[n] - cdf_[n - 1]) * norm; r.start = (cdf_[n - 1]) * norm; r.fraction = (u - cdf_[n - 1]) / (cdf_[n] - cdf_[n - 1]); return r; } float sum_; float cdf_[size + 2]; int token_ids_[size + 2]; int num_tokens_; DISALLOW_COPY_AND_ASSIGN(DiscreteDistribution); }; } // namespace marbles #endif // MARBLES_RANDOM_DISTRIBUTIONS_H_ ================================================ FILE: lib/marbles/random/lag_processor.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Lag processor for the STEPS control. #include "marbles/random/lag_processor.h" #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/units.h" #include "marbles/resources.h" namespace marbles { using namespace stmlib; void LagProcessor::Init() { ramp_start_ = 0.0f; ramp_value_ = 0.0f; lp_state_ = 0.0f; previous_phase_ = 0.0f; } float LagProcessor::Process(float value, float smoothness, float phase) { float frequency = phase - previous_phase_; if (frequency < 0.0f) { frequency += 1.0f; } previous_phase_ = phase; // The frequency of the portamento/glide LP filter follows an exponential // scale, with a minimum frequency corresponding to half the clock pulse // frequency (giving a roughly linear glide), and a maximum value 7 octaves // above. // // When smoothness approaches 0, the response curve is tweaked to give // immediate voltage changes, without any lag. frequency *= 0.25f; frequency *= SemitonesToRatio(84.0f * (1.0f - smoothness)); if (frequency >= 1.0f) { frequency = 1.0f; } if (smoothness <= 0.05f) { frequency += 20.f * (0.05f - smoothness) * (1.0f - frequency); } ONE_POLE(lp_state_, value, frequency); // The final output is a crossfade between a variable shape interpolation and // the low-pass glide/lag. float interp_amount = (smoothness - 0.6f) * 5.0f; CONSTRAIN(interp_amount, 0.0f, 1.0f); float interp_linearity = (1.0f - smoothness) * 5.0f; CONSTRAIN(interp_linearity, 0.0f, 1.0f); float warped_phase = Interpolate(lut_raised_cosine, phase, 256.0f); float interp_phase = Crossfade(warped_phase, phase, interp_linearity); float interp = Crossfade(ramp_start_, value, interp_phase); ramp_value_ = interp; return Crossfade(lp_state_, interp, interp_amount); } } // namespace marbles ================================================ FILE: lib/marbles/random/lag_processor.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Lag processor for the STEPS control. #ifndef MARBLES_RANDOM_LAG_PROCESSOR_H_ #define MARBLES_RANDOM_LAG_PROCESSOR_H_ #include "stmlib/stmlib.h" #include namespace marbles { class LagProcessor { public: LagProcessor() { } ~LagProcessor() { } void Init(); inline void ResetRamp() { ramp_start_ = ramp_value_; } float Process(float value, float smoothness, float phase); private: float ramp_start_; float ramp_value_; float lp_state_; float previous_phase_; DISALLOW_COPY_AND_ASSIGN(LagProcessor); }; } // namespace marbles #endif // MARBLES_RANDOM_LAG_PROCESSOR_H_ ================================================ FILE: lib/marbles/random/output_channel.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Random generation channel. #include "marbles/random/output_channel.h" #include "marbles/random/distributions.h" #include "marbles/random/random_sequence.h" #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/utils/random.h" namespace marbles { using namespace stmlib; const size_t kNumReacquisitions = 20; // 6.4 samples per millisecond void OutputChannel::Init() { spread_ = 0.5f; bias_ = 0.5f; steps_ = 0.5f; scale_index_ = 0; register_mode_ = false; register_value_ = 0.0f; register_transposition_ = 0.0f; previous_steps_ = 0.0f; previous_phase_ = 0.0f; reacquisition_counter_ = 0; previous_voltage_ = 0.0f; voltage_ = 0.0f; quantized_voltage_ = 0.0f; scale_offset_ = ScaleOffset(10.0f, -5.0f); lag_processor_.Init(); Scale scale; scale.Init(); for (int i = 0; i < 6; ++i) { quantizer_[i].Init(scale); } } float OutputChannel::GenerateNewVoltage(RandomSequence* random_sequence) { float u = random_sequence->NextValue(register_mode_, register_value_); if (register_mode_) { return 10.0f * (u - 0.5f) + register_transposition_; } else { float degenerate_amount = 1.25f - spread_ * 25.0f; float bernoulli_amount = spread_ * 25.0f - 23.75f; CONSTRAIN(degenerate_amount, 0.0f, 1.0f); CONSTRAIN(bernoulli_amount, 0.0f, 1.0f); float value = BetaDistributionSample(u, spread_, bias_); float bernoulli_value = u >= (1.0f - bias_) ? 0.999999f : 0.0f; value += degenerate_amount * (bias_ - value); value += bernoulli_amount * (bernoulli_value - value); return scale_offset_(value); } } void OutputChannel::Process( RandomSequence* random_sequence, const float* phase, float* output, size_t size, size_t stride) { ParameterInterpolator steps_modulation( &previous_steps_, steps_, size); // This is a horrible hack that wouldn't be here if all the sequencers // and MIDI/CV interfaces in this world didn't have *horrible* slew on // their CV output (I'm looking at you KORG). // Without this hack, the shift register gets its value as soon as the // rising edge is observed on the GATE input. Problem: the CV input is // probably still slewing up, so we acquire the wrong value in the shift // register. What to do then? Over the next 2ms, we'll just track the CV // input until it reaches its final value - which means that Marbles // output will be slewed too. Another option would have been to wait 2ms // between the rising edge and the actual acquisition, but we don't want // to penalize people who use tighter sequencers. if (reacquisition_counter_) { --reacquisition_counter_; float u = random_sequence->RewriteValue(register_value_); voltage_ = 10.0f * (u - 0.5f) + register_transposition_; quantized_voltage_ = Quantize(voltage_, 2.0f * steps_ - 1.0f); } while (size--) { const float steps = steps_modulation.Next(); if (*phase < previous_phase_) { previous_voltage_ = voltage_; voltage_ = GenerateNewVoltage(random_sequence); lag_processor_.ResetRamp(); quantized_voltage_ = Quantize(voltage_, 2.0f * steps - 1.0f); if (register_mode_) { reacquisition_counter_ = kNumReacquisitions; } } if (steps >= 0.5f) { *output = quantized_voltage_; } else { const float smoothness = 1.0f - 2.0f * steps; *output = lag_processor_.Process(voltage_, smoothness, *phase); } output += stride; previous_phase_ = *phase++; } } } // namespace marbles ================================================ FILE: lib/marbles/random/output_channel.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Random generation channel. #ifndef MARBLES_RANDOM_OUTPUT_CHANNEL_H_ #define MARBLES_RANDOM_OUTPUT_CHANNEL_H_ #include "stmlib/stmlib.h" #include "marbles/random/lag_processor.h" #include "marbles/random/quantizer.h" namespace marbles { class RandomSequence; struct ScaleOffset { ScaleOffset(float s, float o) { scale = s; offset = o; } ScaleOffset() { scale = 1.0f; offset = 0.0f; } float scale; float offset; inline float operator()(float x) { return x * scale + offset; } }; class OutputChannel { public: OutputChannel() { } ~OutputChannel() { } void Init(); void LoadScale(int i, const Scale& scale) { quantizer_[i].Init(scale); } void Process( RandomSequence* random_sequence, const float* phase, float* output, size_t size, size_t stride); inline void set_spread(float spread) { spread_ = spread; } inline void set_bias(float bias) { bias_ = bias; } inline void set_scale_index(int i) { scale_index_ = i; } inline void set_steps(float steps) { steps_ = steps; } inline void set_register_mode(bool register_mode) { register_mode_ = register_mode; } inline void set_register_value(float register_value) { register_value_ = register_value; } inline void set_register_transposition(float register_transposition) { register_transposition_ = register_transposition; } inline void set_scale_offset(const ScaleOffset& scale_offset) { scale_offset_ = scale_offset; } inline float Quantize(float voltage, float amount) { return quantizer_[scale_index_].Process(voltage, amount, false); } private: float GenerateNewVoltage(RandomSequence* random_sequence); float spread_; float bias_; float steps_; int scale_index_; bool register_mode_; float register_value_; float register_transposition_; float previous_steps_; float previous_phase_; uint32_t reacquisition_counter_; float previous_voltage_; float voltage_; float quantized_voltage_; ScaleOffset scale_offset_; LagProcessor lag_processor_; Quantizer quantizer_[6]; DISALLOW_COPY_AND_ASSIGN(OutputChannel); }; } // namespace marbles #endif // MARBLES_RANDOM_OUTPUT_CHANNEL_H_ ================================================ FILE: lib/marbles/random/quantizer.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Variable resolution quantizer. #include "marbles/random/quantizer.h" #include "stmlib/dsp/dsp.h" #include #include namespace marbles { using namespace std; void Quantizer::Init(const Scale& scale) { int n = scale.num_degrees; // We don't want garbage scale data here... if (!n || n > kMaxDegrees || scale.base_interval == 0.0f) { return; } num_degrees_ = n; base_interval_ = scale.base_interval; base_interval_reciprocal_ = 1.0f / scale.base_interval; uint8_t second_largest_threshold = 0; for (int i = 0; i < n; ++i) { voltage_[i] = scale.degree[i].voltage; if (scale.degree[i].weight != 255 && \ scale.degree[i].weight >= second_largest_threshold) { second_largest_threshold = scale.degree[i].weight; } } uint8_t thresholds_[kNumThresholds] = { 0, 16, 32, 64, 128, 192, 255 }; if (second_largest_threshold > 192) { // Be more selective to only include the notes at rank 1 and 2 at // the last but one position. thresholds_[kNumThresholds - 2] = second_largest_threshold; } for (int t = 0; t < kNumThresholds; ++t) { uint16_t bitmask = 0; uint8_t first = 0xff; uint8_t last = 0; for (int i = 0; i < n; ++i) { if (scale.degree[i].weight >= thresholds_[t]) { bitmask |= 1 << i; if (first == 0xff) first = i; last = i; } } level_[t].bitmask = bitmask; level_[t].first = first; level_[t].last = last; } level_quantizer_.Init(); fill(&feedback_[0], &feedback_[kNumThresholds], 0.0f); } float Quantizer::Process(float value, float amount, bool hysteresis) { int level = level_quantizer_.Process(amount, kNumThresholds + 1); float quantized_voltage = value; if (level > 0) { level -= 1; float raw_value = value; if (hysteresis) { value += feedback_[level]; } const float note = value * base_interval_reciprocal_; MAKE_INTEGRAL_FRACTIONAL(note); if (value < 0.0f) { note_integral -= 1; note_fractional += 1.0f; } note_fractional *= base_interval_; // Search for the tightest upper/lower bound in the set of available // voltages. stl::upper_bound / stl::lower_bound wouldn't work here // because some entries are masked. Level l = level_[level]; float a = voltage_[l.last] - base_interval_; float b = voltage_[l.first] + base_interval_; uint16_t bitmask = l.bitmask; for (int i = 0; i < num_degrees_; ++i) { if (bitmask & 1) { float v = voltage_[i]; if (note_fractional > v) { a = v; } else { b = v; break; } } bitmask >>= 1; } quantized_voltage = note_fractional < (a + b) * 0.5f ? a : b; quantized_voltage += static_cast(note_integral) * base_interval_; feedback_[level] = (quantized_voltage - raw_value) * 0.25f; } return quantized_voltage; } } // namespace marbles ================================================ FILE: lib/marbles/random/quantizer.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Variable resolution quantizer. #ifndef MARBLES_RANDOM_QUANTIZER_H_ #define MARBLES_RANDOM_QUANTIZER_H_ #include "stmlib/stmlib.h" #include "stmlib/dsp/hysteresis_quantizer.h" #include "marbles/random/distributions.h" #include "marbles/random/quantizer.h" namespace marbles { const int kMaxDegrees = 16; const int kNumThresholds = 7; struct Degree { float voltage; uint8_t weight; }; struct Scale { float base_interval; int num_degrees; Degree degree[kMaxDegrees]; inline float cell_voltage(int i) const { float transposition = static_cast(i / num_degrees) * base_interval; return degree[i % num_degrees].voltage + transposition; } void Init() { base_interval = 1.0f; num_degrees = 1; degree[0].voltage = 0.0f; degree[0].weight = 0.0f; } void InitMajor() { const uint8_t major_scale_weights[] = { 255, 16, 128, 16, 192, 64, 8, 224, 16, 96, 32, 160, }; base_interval = 1.0f; num_degrees = 12; for (size_t i = 0; i < 12; ++i) { degree[i].voltage = static_cast(i) * 0.0833333333f; degree[i].weight = major_scale_weights[i]; } } void InitTenth() { const uint8_t major_scale_weights[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 25 }; base_interval = 1.0f; num_degrees = 10; for (size_t i = 0; i < 10; ++i) { degree[i].voltage = static_cast(i) * 0.1f; degree[i].weight = major_scale_weights[i]; } } }; class Quantizer { public: Quantizer() { } ~Quantizer() { } void Init(const Scale& scale); float Process(float value, float amount, bool hysteresis); private: struct Level { uint16_t bitmask; // bitmask of active degrees. uint8_t first; // index of the first active degree. uint8_t last; // index of the last active degree. }; float voltage_[kMaxDegrees]; Level level_[kNumThresholds]; float feedback_[kNumThresholds]; float base_interval_; float base_interval_reciprocal_; int num_degrees_; stmlib::HysteresisQuantizer level_quantizer_; DISALLOW_COPY_AND_ASSIGN(Quantizer); }; } // namespace marbles #endif // MARBLES_RANDOM_QUANTIZER_H_ ================================================ FILE: lib/marbles/random/random_generator.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Pseudo-random generator used as a fallback when we need more random values // than available in the hardware RNG buffer. #ifndef MARBLES_RANDOM_RANDOM_GENERATOR_H_ #define MARBLES_RANDOM_RANDOM_GENERATOR_H_ #include "stmlib/stmlib.h" #include "stmlib/utils/ring_buffer.h" namespace marbles { class RandomGenerator { public: RandomGenerator() { } ~RandomGenerator() { } inline void Init(uint32_t seed) { state_ = seed; } inline void Mix(uint32_t word) { // state_ ^= word; } inline uint32_t GetWord() { state_ = state_ * 1664525L + 1013904223L; return state_; } private: uint32_t state_; DISALLOW_COPY_AND_ASSIGN(RandomGenerator); }; } // namespace marbles #endif // MARBLES_RANDOM_RANDOM_GENERATOR_H_ ================================================ FILE: lib/marbles/random/random_sequence.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Sequence of random values. #ifndef MARBLES_RANDOM_RANDOM_SEQUENCE_H_ #define MARBLES_RANDOM_RANDOM_SEQUENCE_H_ #include "stmlib/stmlib.h" #include "marbles/random/random_stream.h" #include namespace marbles { const int kDejaVuBufferSize = 16; const int kHistoryBufferSize = 16; const float kMaxUint32 = 4294967296.0f; class RandomSequence { public: RandomSequence() { } ~RandomSequence() { } inline void Init(RandomStream* random_stream) { random_stream_ = random_stream; for (int i = 0; i < kDejaVuBufferSize; ++i) { loop_[i] = random_stream_->GetFloat(); } std::fill(&history_[0], &history_[kHistoryBufferSize], 0.0f); loop_write_head_ = 0; length_ = 8; step_ = 0; record_head_ = 0; replay_head_ = -1; replay_start_ = 0; deja_vu_ = 0.0f; replay_hash_ = replay_shift_ = 0; redo_read_ptr_ = &loop_[0]; redo_write_ptr_ = NULL; redo_write_history_ptr_ = NULL; } inline void Clone(const RandomSequence& source) { random_stream_ = source.random_stream_; std::copy( &source.loop_[0], &source.loop_[kDejaVuBufferSize], &loop_[0]); std::copy( &source.history_[0], &source.history_[kHistoryBufferSize], &history_[0]); loop_write_head_ = source.loop_write_head_; length_ = source.length_; step_ = source.step_; record_head_ = source.record_head_; replay_head_ = source.replay_head_; replay_start_ = source.replay_start_; replay_hash_ = source.replay_hash_; replay_shift_ = source.replay_shift_; deja_vu_ = source.deja_vu_; redo_read_ptr_ = source.redo_read_ptr_ ? &loop_[source.redo_read_ptr_ - &source.loop_[0]] : NULL; redo_write_ptr_ = source.redo_write_ptr_ ? &loop_[source.redo_write_ptr_ - &source.loop_[0]] : NULL; redo_write_history_ptr_ = source.redo_write_history_ptr_ ? &history_[source.redo_write_history_ptr_ - &source.history_[0]] : NULL; } inline void Record() { replay_start_ = record_head_; replay_head_ = -1; } inline void ReplayPseudoRandom(uint32_t hash) { replay_head_ = replay_start_; replay_hash_ = hash; replay_shift_ = 0; } inline void ReplayShifted(uint32_t shift) { replay_head_ = replay_start_; replay_hash_ = 0; replay_shift_ = shift; } inline float GetReplayValue() const { uint32_t h = (replay_head_ - 1 - replay_shift_ + \ 2 * kHistoryBufferSize) % kHistoryBufferSize; if (!replay_hash_) { return history_[h]; } else { uint32_t word = static_cast(history_[h] * kMaxUint32); word = (word ^ replay_hash_) * 1664525L + 1013904223L; return static_cast(word) / kMaxUint32; } } inline float RewriteValue(float value) { // RewriteValue(x) returns what the most recent call to NextValue would have // returned if its second argument were x instead. This is used to "rewrite // history" when the module acquires data from an external source (ASR, // randomizer or quantizer mode). if (replay_head_ >= 0) { return GetReplayValue(); } if (redo_write_ptr_) { *redo_write_ptr_ = 1.0f + value; } float result = *redo_read_ptr_; if (result >= 1.0f) { result -= 1.0f; } else { result = 0.5f; } if (redo_write_history_ptr_) { *redo_write_history_ptr_ = result; } return result; } inline float NextValue(bool deterministic, float value) { if (replay_head_ >= 0) { replay_head_ = (replay_head_ + 1) % kHistoryBufferSize; return GetReplayValue(); } const float p_sqrt = 2.0f * deja_vu_ - 1.0f; const float p = p_sqrt * p_sqrt; float rho = random_stream_->GetFloat(); if (rho < p && deja_vu_ <= 0.5f) { // Generate a new value and put it at the end of the loop. redo_write_ptr_ = &loop_[loop_write_head_]; *redo_write_ptr_ = deterministic ? 1.0f + value : random_stream_->GetFloat(); loop_write_head_ = (loop_write_head_ + 1) % kDejaVuBufferSize; step_ = length_ - 1; } else { // Do not generate a new value, just replay the loop or jump randomly. // through it. redo_write_ptr_ = NULL; if (rho < p) { step_ = static_cast( random_stream_->GetFloat() * static_cast(length_)); } else { step_ = step_ + 1; if (step_ >= length_) { step_ = 0; } } } uint32_t i = loop_write_head_ + kDejaVuBufferSize - length_ + step_; redo_read_ptr_ = &loop_[i % kDejaVuBufferSize]; float result = *redo_read_ptr_; if (result >= 1.0f) { result -= 1.0f; } else if (deterministic) { // We ask for a deterministic value (shift register), but the loop // contain random values. return 0.5f in this case! result = 0.5f; } redo_write_history_ptr_ = &history_[record_head_]; *redo_write_history_ptr_ = result; record_head_ = (record_head_ + 1) % kHistoryBufferSize; return result; } inline void NextVector(float* destination, size_t size) { float seed = NextValue(false, 0.0f); uint32_t word = static_cast(seed * kMaxUint32); while (size--) { *destination++ = static_cast(word) / kMaxUint32; word = word * 1664525L + 1013904223L; } } inline void set_deja_vu(float deja_vu) { deja_vu_ = deja_vu; } inline void set_length(int length) { if (length < 1 || length > kDejaVuBufferSize) { return; } length_ = length; step_ = step_ % length; } inline float deja_vu() const { return deja_vu_; } inline int length() const { return length_; } private: RandomStream* random_stream_; float loop_[kDejaVuBufferSize]; float history_[kHistoryBufferSize]; int loop_write_head_; int length_; int step_; // Allows to go back in the past and get the same results again from NextValue // calls. Allows the 3 X channels to be locked to the same random loop. int record_head_; int replay_head_; int replay_start_; uint32_t replay_hash_; uint32_t replay_shift_; float deja_vu_; float* redo_read_ptr_; float* redo_write_ptr_; float* redo_write_history_ptr_; DISALLOW_COPY_AND_ASSIGN(RandomSequence); }; } // namespace marbles #endif // MARBLES_RANDOM_RANDOM_SEQUENCE_H_ ================================================ FILE: lib/marbles/random/random_stream.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Stream of random values, filled from a hardware RNG, with a fallback // mechanism. #ifndef MARBLES_RANDOM_RANDOM_STREAM_H_ #define MARBLES_RANDOM_RANDOM_STREAM_H_ #include "stmlib/stmlib.h" #include "stmlib/utils/ring_buffer.h" #include "marbles/random/random_generator.h" namespace marbles { class RandomStream { public: RandomStream() { } ~RandomStream() { } inline void Init(RandomGenerator* fallback_generator) { fallback_generator_ = fallback_generator; buffer_.Init(); } inline void Write(uint32_t value) { // buffer_.Swallow(1); // buffer_.Overwrite(value); if (buffer_.writable()) { buffer_.Overwrite(value); } fallback_generator_->Mix(value); } inline uint32_t GetWord() { if (buffer_.readable()) { return buffer_.ImmediateRead(); } else { return fallback_generator_->GetWord(); } } inline float GetFloat() { uint32_t word = GetWord(); return static_cast(word) / 4294967296.0f; } private: stmlib::RingBuffer buffer_; RandomGenerator* fallback_generator_; DISALLOW_COPY_AND_ASSIGN(RandomStream); }; } // namespace marbles #endif // MARBLES_RANDOM_RANDOM_STREAM_H_ ================================================ FILE: lib/marbles/random/t_generator.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Generator for the T outputs. #include "marbles/random/t_generator.h" #include #include "stmlib/dsp/units.h" #include "marbles/resources.h" namespace marbles { using namespace std; using namespace stmlib; /* static */ DividerPattern TGenerator::divider_patterns[kNumDividerPatterns] = { { { { 1, 1 }, { 1, 1 } }, 1 }, { { { 1, 1 }, { 2, 1 } }, 1 }, { { { 1, 2 }, { 1, 1 } }, 2 }, { { { 1, 1 }, { 4, 1 } }, 1 }, { { { 1, 2 }, { 2, 1 } }, 2 }, { { { 1, 1 }, { 3, 2 } }, 2 }, { { { 1, 4 }, { 4, 1 } }, 4 }, { { { 1, 4 }, { 2, 1 } }, 4 }, { { { 1, 2 }, { 3, 2 } }, 2 }, { { { 1, 1 }, { 8, 1 } }, 1 }, { { { 1, 1 }, { 3, 1 } }, 1 }, { { { 1, 3 }, { 1, 1 } }, 3 }, { { { 1, 1 }, { 5, 4 } }, 4 }, { { { 1, 2 }, { 5, 4 } }, 4 }, { { { 1, 1 }, { 6, 1 } }, 1 }, { { { 1, 3 }, { 2, 1 } }, 3 }, { { { 1, 1 }, { 16, 1 } }, 1 }, }; /* static */ DividerPattern TGenerator::fixed_divider_patterns[kNumDividerPatterns] = { { { { 8, 1 }, { 1, 8 } }, 8 }, { { { 6, 1 }, { 1, 6 } }, 6 }, { { { 4, 1 }, { 1, 4 } }, 4 }, { { { 3, 1 }, { 1, 3 } }, 3 }, { { { 2, 1 }, { 1, 2 } }, 2 }, { { { 3, 2 }, { 2, 3 } }, 6 }, { { { 4, 3 }, { 3, 4 } }, 12 }, { { { 5, 4 }, { 4, 5 } }, 20 }, { { { 1, 1 }, { 1, 1 } }, 1 }, { { { 4, 5 }, { 5, 4 } }, 20 }, { { { 3, 4 }, { 4, 3 } }, 12 }, { { { 2, 2 }, { 3, 2 } }, 6 }, { { { 1, 2 }, { 2, 1 } }, 2 }, { { { 1, 3 }, { 3, 1 } }, 3 }, { { { 1, 4 }, { 4, 1 } }, 4 }, { { { 1, 6 }, { 6, 1 } }, 6 }, { { { 1, 8 }, { 8, 1 } }, 8 }, }; /* static */ Ratio TGenerator::input_divider_ratios[kNumInputDividerRatios] = { { 1, 4 }, { 1, 3 }, { 1, 2 }, { 2, 3 }, { 1, 1 }, { 3, 2 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, }; /* static */ uint8_t TGenerator::drum_patterns[kNumDrumPatterns][kDrumPatternSize] = { { 1, 0, 0, 0, 2, 0, 0, 0 }, { 0, 0, 1, 0, 2, 0, 0, 0 }, { 1, 0, 1, 0, 2, 0, 0, 0 }, { 0, 0, 1, 0, 2, 0, 0, 2 }, { 1, 0, 1, 0, 2, 0, 1, 0 }, { 0, 2, 1, 0, 2, 0, 0, 2 }, { 1, 0, 0, 0, 2, 0, 1, 0 }, { 0, 2, 1, 0, 2, 0, 1, 2 }, { 1, 0, 0, 1, 2, 0, 0, 0 }, { 0, 2, 1, 1, 2, 0, 1, 2 }, { 1, 0, 0, 1, 2, 0, 1, 0 }, { 0, 2, 1, 1, 2, 2, 1, 2 }, { 1, 0, 0, 1, 2, 0, 1, 2 }, { 0, 2, 0, 1, 2, 0, 1, 2 }, { 1, 0, 1, 1, 2, 0, 1, 2 }, { 2, 0, 1, 2, 0, 1, 2, 0 }, { 1, 2, 1, 1, 2, 0, 1, 2 }, { 2, 0, 1, 2, 0, 1, 2, 2 } }; void TGenerator::Init(RandomStream* random_stream, float sr) { one_hertz_ = 1.0f / static_cast(sr); model_ = T_GENERATOR_MODEL_COMPLEMENTARY_BERNOULLI; range_ = T_GENERATOR_RANGE_1X; rate_ = 0.0f; bias_ = 0.5f; jitter_ = 0.0f; pulse_width_mean_ = 0.0f; pulse_width_std_ = 0.0f; master_phase_ = 0.0f; jitter_multiplier_ = 1.0f; phase_difference_ = 0.0f; previous_external_ramp_value_ = 0.0f; divider_pattern_length_ = 0; fill(&streak_counter_[0], &streak_counter_[kMarkovHistorySize], 0); fill(&markov_history_[0], &markov_history_[kMarkovHistorySize], 0); markov_history_ptr_ = 0; drum_pattern_step_ = 0; drum_pattern_index_ = 0; sequence_.Init(random_stream); ramp_divider_.Init(); ramp_extractor_.Init(1000.0f / sr); ramp_generator_.Init(); for (size_t i = 0; i < kNumTChannels; ++i) { slave_ramp_[i].Init(); } bias_quantizer_.Init(); rate_quantizer_.Init(); use_external_clock_ = false; } int TGenerator::GenerateComplementaryBernoulli(const RandomVector& x) { int bitmask = 0; for (size_t i = 0; i < kNumTChannels; ++i) { if ((x.variables.u[i >> 1] > bias_) ^ (i & 1)) { bitmask |= 1 << i; } } return bitmask; } int TGenerator::GenerateIndependentBernoulli(const RandomVector& x) { int bitmask = 0; for (size_t i = 0; i < kNumTChannels; ++i) { if ((x.variables.u[i] > bias_) ^ (i & 1)) { bitmask |= 1 << i; } } return bitmask; } int TGenerator::GenerateThreeStates(const RandomVector& x) { int bitmask = 0; float p_none = 0.75f - fabs(bias_ - 0.5f); float threshold = p_none + (1.0f - p_none) * (0.25f + (bias_ * 0.5f)); for (size_t i = 0; i < kNumTChannels; ++i) { float u = x.variables.u[i >> 1]; if (u > p_none && ((u > threshold) ^ (i & 1))) { bitmask |= 1 << i; } } return bitmask; } int TGenerator::GenerateDrums(const RandomVector& x) { ++drum_pattern_step_; if (drum_pattern_step_ >= kDrumPatternSize) { drum_pattern_step_ = 0; float u = x.variables.u[0] * 2.0f * fabs(bias_ - 0.5f); drum_pattern_index_ = static_cast(kNumDrumPatterns * u); if (bias_ <= 0.5f) { drum_pattern_index_ -= drum_pattern_index_ % 2; } } return drum_patterns[drum_pattern_index_][drum_pattern_step_]; } int TGenerator::GenerateMarkov(const RandomVector& x) { int bitmask = 0; float b = 1.5f * bias_ - 0.5f; markov_history_[markov_history_ptr_] = 0; const int32_t p = markov_history_ptr_; for (size_t i = 0; i < kNumTChannels; ++i) { int32_t mask = 1 << i; // 4 rules: // * We favor repeating what we played 8 ticks ago. // * We do not favor pulses appearing on both channels. // * We favor sparse patterns (no consecutive hits). // * We favor patterns in which one channel "echoes" what the other // channel played 4 ticks before. bool periodic = markov_history_[(p + 8) % kMarkovHistorySize] & mask; bool simultaneous = markov_history_[(p + 8) % kMarkovHistorySize] & ~mask; bool dense = markov_history_[(p + 1) % kMarkovHistorySize] & mask; bool alternate = markov_history_[(p + 4) % kMarkovHistorySize] & ~mask; float logit = -1.5f; logit += streak_counter_[i] > 24 ? 10.0f : 0.0f; logit += 8.0f * fabs(b) * (periodic ? b : -b); logit -= 2.0f * (simultaneous ? b : -b); logit -= 1.0f * (dense ? b : 0.0f); logit += 1.0f * (alternate ? b : 0.0f); CONSTRAIN(logit, -10.0f, 10.0f); float probability = lut_logit[static_cast(logit * 12.8f + 128.0f)]; bool state = x.variables.u[i] < probability; if (sequence_.deja_vu() >= x.variables.p) { state = markov_history_[(p + sequence_.length()) % kMarkovHistorySize] & mask; } if (state) { bitmask |= mask; streak_counter_[i] = 0; } else { ++streak_counter_[i]; } } markov_history_[p] |= bitmask; markov_history_ptr_ = (p + kMarkovHistorySize - 1) % kMarkovHistorySize; return bitmask; } void TGenerator::ScheduleOutputPulses(const RandomVector& x, int bitmask) { for (size_t i = 0; i < kNumTChannels; ++i) { slave_ramp_[i].Init( bitmask & 1, RandomPulseWidth(i, x.variables.pulse_width[i]), 0.5f); bitmask >>= 1; } } void TGenerator::ConfigureSlaveRamps(const RandomVector& x) { switch (model_) { // Generate a bitmask that will describe which outputs are active // at this clock tick. Use this bitmask to actually schedule pulses on the // outputs. case T_GENERATOR_MODEL_COMPLEMENTARY_BERNOULLI: ScheduleOutputPulses(x, GenerateComplementaryBernoulli(x)); break; case T_GENERATOR_MODEL_INDEPENDENT_BERNOULLI: ScheduleOutputPulses(x, GenerateIndependentBernoulli(x)); break; case T_GENERATOR_MODEL_THREE_STATES: ScheduleOutputPulses(x, GenerateThreeStates(x)); break; case T_GENERATOR_MODEL_DRUMS: ScheduleOutputPulses(x, GenerateDrums(x)); break; case T_GENERATOR_MODEL_MARKOV: ScheduleOutputPulses(x, GenerateMarkov(x)); break; case T_GENERATOR_MODEL_CLUSTERS: case T_GENERATOR_MODEL_DIVIDER: --divider_pattern_length_; if (divider_pattern_length_ <= 0) { DividerPattern pattern; if (model_ == T_GENERATOR_MODEL_DIVIDER) { pattern = bias_quantizer_.Lookup( fixed_divider_patterns, bias_, kNumDividerPatterns); } else { float strength = fabs(bias_ - 0.5f) * 2.0f; float u = x.variables.u[0]; u *= (u + strength * strength * (1.0f - u)); u *= strength; pattern = divider_patterns[static_cast( u * kNumDividerPatterns)]; if (bias_ < 0.5f) { for (size_t i = 0; i < kNumTChannels / 2; ++i) { swap(pattern.ratios[i], pattern.ratios[kNumTChannels - 1 - i]); } } } for (size_t i = 0; i < kNumTChannels; ++i) { slave_ramp_[i].Init( pattern.length, pattern.ratios[i], RandomPulseWidth(i, x.variables.pulse_width[i])); } divider_pattern_length_ = pattern.length; } break; } } void TGenerator::Process( bool use_external_clock, const GateFlags* external_clock, Ramps ramps, bool* gate, size_t size) { float internal_frequency; if (use_external_clock) { if (!use_external_clock_) { ramp_extractor_.Reset(); } Ratio ratio = rate_quantizer_.Lookup( input_divider_ratios, 1.05f * rate_ / 96.0f + 0.5f, kNumInputDividerRatios); if (range_ == T_GENERATOR_RANGE_0_25X) { ratio.q *= 4; } else if (range_ == T_GENERATOR_RANGE_4X) { ratio.p *= 4; } ratio.Simplify<2>(); bool reset_observed = ramp_extractor_.Process( ratio, true, external_clock, ramps.external, size); if (reset_observed) { if (model_ == T_GENERATOR_MODEL_DRUMS) { drum_pattern_step_ = kDrumPatternSize; RandomVector random_vector; sequence_.NextVector( random_vector.x, sizeof(random_vector.x) / sizeof(float)); ConfigureSlaveRamps(random_vector); } else if (model_ == T_GENERATOR_MODEL_CLUSTERS || model_ == T_GENERATOR_MODEL_DIVIDER) { divider_pattern_length_ = 0; } } internal_frequency = 0.0f; } else { float rate = 2.0f; if (range_ == T_GENERATOR_RANGE_4X) { rate = 8.0f; } else if (range_ == T_GENERATOR_RANGE_0_25X) { rate = 0.5f; } internal_frequency = rate * one_hertz_ * SemitonesToRatio(rate_); } use_external_clock_ = use_external_clock; while (size--) { float frequency = use_external_clock ? *ramps.external - previous_external_ramp_value_ : internal_frequency; frequency += frequency < 0.0f ? 1.0f : 0.0f; float jittery_frequency = frequency * jitter_multiplier_; master_phase_ += jittery_frequency; phase_difference_ += frequency - jittery_frequency; if (master_phase_ > 1.0f) { master_phase_ -= 1.0f; RandomVector random_vector; sequence_.NextVector( random_vector.x, sizeof(random_vector.x) / sizeof(float)); float jitter_amount = jitter_ * jitter_ * jitter_ * jitter_ * 36.0f; float x = FastBetaDistributionSample(random_vector.variables.jitter); float multiplier = SemitonesToRatio((x * 2.0f - 1.0f) * jitter_amount); // This step is crucial in making sure that the jittered clock does not // deviate too much from the master clock. The larger the phase difference // difference between the two, the more likely the jittery clock will // speed up or down to catch up with the straight clock. multiplier *= phase_difference_ > 0.0f ? 1.0f + phase_difference_ : 1.0f / (1.0f - phase_difference_); jitter_multiplier_ = multiplier; ConfigureSlaveRamps(random_vector); } if (internal_frequency) { *ramps.external = master_phase_; } previous_external_ramp_value_ = *ramps.external; ramps.external++; *ramps.master++ = master_phase_; for (size_t j = 0; j < kNumTChannels; ++j) { slave_ramp_[j].Process( frequency * jitter_multiplier_, ramps.slave[j], gate); ramps.slave[j]++; gate++; } } } } // namespace marbles ================================================ FILE: lib/marbles/random/t_generator.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Generator for the T outputs. #ifndef MARBLES_RANDOM_T_GENERATOR_H_ #define MARBLES_RANDOM_T_GENERATOR_H_ #include "stmlib/stmlib.h" #include "marbles/ramp/ramp_divider.h" #include "marbles/ramp/ramp_extractor.h" #include "marbles/ramp/ramp_generator.h" #include "marbles/ramp/slave_ramp.h" #include "marbles/random/distributions.h" #include "marbles/random/random_sequence.h" #include "stmlib/dsp/hysteresis_quantizer.h" namespace marbles { enum TGeneratorModel { T_GENERATOR_MODEL_COMPLEMENTARY_BERNOULLI, T_GENERATOR_MODEL_CLUSTERS, T_GENERATOR_MODEL_DRUMS, T_GENERATOR_MODEL_INDEPENDENT_BERNOULLI, T_GENERATOR_MODEL_DIVIDER, T_GENERATOR_MODEL_THREE_STATES, T_GENERATOR_MODEL_MARKOV, }; enum TGeneratorRange { T_GENERATOR_RANGE_0_25X, T_GENERATOR_RANGE_1X, T_GENERATOR_RANGE_4X, }; const size_t kNumTChannels = 2; const size_t kMarkovHistorySize = 16; const size_t kNumDrumPatterns = 18; const size_t kDrumPatternSize = 8; struct DividerPattern { Ratio ratios[kNumTChannels]; int32_t length; }; struct Ramps { float* external; float* master; float* slave[kNumTChannels]; }; const size_t kNumDividerPatterns = 17; const size_t kNumInputDividerRatios = 9; class TGenerator { public: TGenerator() { } ~TGenerator() { } void Init(RandomStream* random_stream, float sr); void Process( bool use_external_clock, const stmlib::GateFlags* external_clock, Ramps ramps, bool* gate, size_t size); inline void set_model(TGeneratorModel model) { model_ = model; } inline void set_range(TGeneratorRange range) { range_ = range; } inline void set_rate(float rate) { rate_ = rate; } inline void set_bias(float bias) { bias_ = bias; } inline void set_jitter(float jitter) { jitter_ = jitter; } inline void set_deja_vu(float deja_vu) { sequence_.set_deja_vu(deja_vu); } inline void set_length(int length) { sequence_.set_length(length); } inline void set_pulse_width_mean(float pulse_width_mean) { pulse_width_mean_ = pulse_width_mean; } inline void set_pulse_width_std(float pulse_width_std) { pulse_width_std_ = pulse_width_std; } private: union RandomVector { struct { float pulse_width[kNumTChannels]; float u[kNumTChannels]; float p; float jitter; } variables; float x[2 * kNumTChannels + 2]; }; void ConfigureSlaveRamps(const RandomVector& v); int GenerateComplementaryBernoulli(const RandomVector& v); int GenerateIndependentBernoulli(const RandomVector& v); int GenerateThreeStates(const RandomVector& v); int GenerateDrums(const RandomVector& v); int GenerateMarkov(const RandomVector& v); void ScheduleOutputPulses(const RandomVector& v, int bitmask); float RandomPulseWidth(int i, float u) { if (pulse_width_std_ == 0.0f) { return 0.05f + 0.9f * pulse_width_mean_; } else { return 0.05f + 0.9f * BetaDistributionSample( u, pulse_width_std_, pulse_width_mean_); // Jon Brooks // i & 1 ? 1.0f - pulse_width_mean_); } } float one_hertz_; TGeneratorModel model_; TGeneratorRange range_; float rate_; float bias_; float jitter_; float pulse_width_mean_; float pulse_width_std_; float master_phase_; float jitter_multiplier_; float phase_difference_; float previous_external_ramp_value_; bool use_external_clock_; int32_t divider_pattern_length_; int32_t streak_counter_[kMarkovHistorySize]; int32_t markov_history_[kMarkovHistorySize]; int32_t markov_history_ptr_; size_t drum_pattern_step_; size_t drum_pattern_index_; RandomSequence sequence_; RampDivider ramp_divider_; RampExtractor ramp_extractor_; RampGenerator ramp_generator_; SlaveRamp slave_ramp_[kNumTChannels]; stmlib::HysteresisQuantizer bias_quantizer_; stmlib::HysteresisQuantizer rate_quantizer_; static DividerPattern divider_patterns[kNumDividerPatterns]; static DividerPattern fixed_divider_patterns[kNumDividerPatterns]; static Ratio input_divider_ratios[kNumInputDividerRatios]; static uint8_t drum_patterns[kNumDrumPatterns][kDrumPatternSize]; DISALLOW_COPY_AND_ASSIGN(TGenerator); }; } // namespace marbles #endif // MARBLES_RANDOM_T_GENERATOR_H_ ================================================ FILE: lib/marbles/random/x_y_generator.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Generator for the X/Y outputs. #include "marbles/random/x_y_generator.h" #include #include "stmlib/dsp/dsp.h" namespace marbles { using namespace std; using namespace stmlib; void XYGenerator::Init(RandomStream* random_stream, float sr) { for (size_t i = 0; i < kNumChannels; ++i) { random_sequence_[i].Init(random_stream); output_channel_[i].Init(); } ramp_extractor_.Init(8000.0f / sr); ramp_divider_.Init(); external_clock_stabilization_counter_ = 16; fill( &use_shifted_sequences_[0], &use_shifted_sequences_[kNumChannels], false); } const uint32_t hashes[kNumXChannels] = { 0, 0xbeca55e5, 0xf0cacc1a }; void XYGenerator::Process( ClockSource clock_source, const GroupSettings& x_settings, const GroupSettings& y_settings, const GateFlags* external_clock, const Ramps& ramps, float* output, size_t size) { float* channel_ramp[kNumChannels]; if (clock_source != CLOCK_SOURCE_EXTERNAL) { // For a couple of upcoming blocks, we'll still be receiving garbage from // the normalization pin that we need to ignore. external_clock_stabilization_counter_ = 16; } else { if (external_clock_stabilization_counter_) { --external_clock_stabilization_counter_; if (external_clock_stabilization_counter_ == 0) { ramp_extractor_.Reset(); } } } switch (clock_source) { case CLOCK_SOURCE_EXTERNAL: { Ratio r = { 1, 1 }; ramp_extractor_.Process(r, false, external_clock, ramps.slave[0], size); if (external_clock_stabilization_counter_) { fill(&ramps.slave[0][0], &ramps.slave[0][size], 0.0f); } } channel_ramp[0] = ramps.slave[0]; channel_ramp[1] = ramps.slave[0]; channel_ramp[2] = ramps.slave[0]; break; case CLOCK_SOURCE_INTERNAL_T1: channel_ramp[0] = ramps.slave[0]; channel_ramp[1] = ramps.slave[0]; channel_ramp[2] = ramps.slave[0]; break; case CLOCK_SOURCE_INTERNAL_T2: channel_ramp[0] = ramps.master; channel_ramp[1] = ramps.master; channel_ramp[2] = ramps.master; break; case CLOCK_SOURCE_INTERNAL_T3: channel_ramp[0] = ramps.slave[1]; channel_ramp[1] = ramps.slave[1]; channel_ramp[2] = ramps.slave[1]; break; default: channel_ramp[0] = ramps.slave[0]; channel_ramp[1] = ramps.master; channel_ramp[2] = ramps.slave[1]; break; } ramp_divider_.Process(y_settings.ratio, channel_ramp[1], ramps.external, size); channel_ramp[kNumChannels - 1] = ramps.external; for (size_t i = 0; i < kNumChannels; ++i) { OutputChannel& channel = output_channel_[i]; const GroupSettings& settings = i < kNumXChannels ? x_settings : y_settings; switch (settings.voltage_range) { case VOLTAGE_RANGE_NARROW: channel.set_scale_offset(ScaleOffset(2.0f, 0.0f)); break; case VOLTAGE_RANGE_POSITIVE: channel.set_scale_offset(ScaleOffset(5.0f, 0.0f)); break; case VOLTAGE_RANGE_FULL: channel.set_scale_offset(ScaleOffset(10.0f, -5.0f)); break; default: break; } float amount = 1.0f; if (settings.control_mode == CONTROL_MODE_BUMP) { amount = i == kNumXChannels / 2 ? 1.0f : -1.0f; } else if (settings.control_mode == CONTROL_MODE_TILT) { amount = 2.0f * static_cast(i) / float(kNumXChannels - 1) - 1.0f; } channel.set_spread(0.5f + (settings.spread - 0.5f) * amount); channel.set_bias(0.5f + (settings.bias - 0.5f) * amount); channel.set_steps(0.5f + (settings.steps - 0.5f) * \ (settings.register_mode ? 1.0f : amount)); channel.set_scale_index(settings.scale_index); channel.set_register_mode(settings.register_mode); channel.set_register_value(settings.register_value); channel.set_register_transposition( 4.0f * settings.spread * (settings.bias - 0.5f) * amount); RandomSequence* sequence = &random_sequence_[i]; sequence->Record(); sequence->set_length(settings.length); sequence->set_deja_vu(settings.deja_vu); bool use_shifted_sequences = false; // When all channels follow the same clock, the deja-vu random looping will // follow the same pattern and the constant-mode input will be shifted! if (clock_source != CLOCK_SOURCE_INTERNAL_T1_T2_T3 && i > 0 && i < kNumXChannels) { sequence = &random_sequence_[0]; if (settings.register_mode) { use_shifted_sequences = true; if (settings.control_mode == CONTROL_MODE_IDENTICAL) { sequence->ReplayShifted(i); } else if (settings.control_mode == CONTROL_MODE_BUMP) { sequence->ReplayShifted(i == 2 ? 1 : 0); } else { sequence->ReplayShifted(0); } } else { sequence->ReplayPseudoRandom(hashes[i]); } } if (!use_shifted_sequences && use_shifted_sequences_[i]) { sequence->Clone(random_sequence_[0]); } use_shifted_sequences_[i] = use_shifted_sequences; channel.Process(sequence, channel_ramp[i], &output[i], size, kNumChannels); } } } // namespace marbles ================================================ FILE: lib/marbles/random/x_y_generator.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Generator for the X/Y outputs. #ifndef MARBLES_RANDOM_X_Y_GENERATOR_H_ #define MARBLES_RANDOM_X_Y_GENERATOR_H_ #include "stmlib/stmlib.h" #include "marbles/ramp/ramp_divider.h" #include "marbles/ramp/ramp_extractor.h" #include "marbles/random/output_channel.h" #include "marbles/random/random_sequence.h" #include "marbles/random/t_generator.h" namespace marbles { enum VoltageRange { VOLTAGE_RANGE_NARROW, // +2V VOLTAGE_RANGE_POSITIVE, // +5V VOLTAGE_RANGE_FULL // +/- 5V }; enum ClockSource { CLOCK_SOURCE_INTERNAL_T1_T2_T3, CLOCK_SOURCE_INTERNAL_T1, CLOCK_SOURCE_INTERNAL_T2, CLOCK_SOURCE_INTERNAL_T3, CLOCK_SOURCE_EXTERNAL }; enum ControlMode { CONTROL_MODE_IDENTICAL, CONTROL_MODE_BUMP, CONTROL_MODE_TILT }; enum OutputGroup { OUTPUT_GROUP_X, OUTPUT_GROUP_Y, OUTPUT_GROUP_LAST }; const size_t kNumXChannels = 3; const size_t kNumYChannels = 1; const size_t kNumChannels = kNumXChannels + kNumYChannels; struct GroupSettings { ControlMode control_mode; VoltageRange voltage_range; bool register_mode; float register_value; float spread; float bias; float steps; float deja_vu; int scale_index; int length; Ratio ratio; }; class XYGenerator { public: XYGenerator() { } ~XYGenerator() { } void Init(RandomStream* random_stream, float sr); void Process( ClockSource clock_source, const GroupSettings& x_settings, const GroupSettings& y_settings, const stmlib::GateFlags* external_clock, const Ramps& ramps, float* output, size_t size); void LoadScale(int channel, int scale_index, const Scale& scale) { output_channel_[channel].LoadScale(scale_index, scale); } void LoadScale(int scale_index, const Scale& scale) { for (size_t i = 0; i < kNumXChannels; ++i) { output_channel_[i].LoadScale(scale_index, scale); } } private: RandomSequence random_sequence_[kNumChannels]; OutputChannel output_channel_[kNumChannels]; RampExtractor ramp_extractor_; RampDivider ramp_divider_; int external_clock_stabilization_counter_; bool use_shifted_sequences_[kNumChannels]; DISALLOW_COPY_AND_ASSIGN(XYGenerator); }; } // namespace marbles #endif // MARBLES_RANDOM_X_Y_GENERATOR_H_ ================================================ FILE: lib/marbles/resources.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resources definitions. // // Automatically generated with: // make resources #include "marbles/resources.h" namespace marbles { const float lut_raised_cosine[] = { 0.000000000e+00, 3.764908043e-05, 1.505906519e-04, 3.388077058e-04, 6.022718974e-04, 9.409435499e-04, 1.354771661e-03, 1.843693909e-03, 2.407636664e-03, 3.046514999e-03, 3.760232701e-03, 4.548682286e-03, 5.411745018e-03, 6.349290921e-03, 7.361178806e-03, 8.447256284e-03, 9.607359798e-03, 1.084131464e-02, 1.214893498e-02, 1.353002390e-02, 1.498437340e-02, 1.651176448e-02, 1.811196710e-02, 1.978474029e-02, 2.152983213e-02, 2.334697982e-02, 2.523590970e-02, 2.719633731e-02, 2.922796741e-02, 3.133049404e-02, 3.350360058e-02, 3.574695976e-02, 3.806023374e-02, 4.044307415e-02, 4.289512215e-02, 4.541600845e-02, 4.800535344e-02, 5.066276715e-02, 5.338784940e-02, 5.618018980e-02, 5.903936783e-02, 6.196495290e-02, 6.495650445e-02, 6.801357194e-02, 7.113569500e-02, 7.432240345e-02, 7.757321738e-02, 8.088764722e-02, 8.426519385e-02, 8.770534861e-02, 9.120759342e-02, 9.477140087e-02, 9.839623426e-02, 1.020815477e-01, 1.058267862e-01, 1.096313857e-01, 1.134947733e-01, 1.174163672e-01, 1.213955767e-01, 1.254318027e-01, 1.295244373e-01, 1.336728642e-01, 1.378764585e-01, 1.421345874e-01, 1.464466094e-01, 1.508118753e-01, 1.552297276e-01, 1.596995011e-01, 1.642205226e-01, 1.687921112e-01, 1.734135785e-01, 1.780842286e-01, 1.828033579e-01, 1.875702559e-01, 1.923842047e-01, 1.972444793e-01, 2.021503478e-01, 2.071010713e-01, 2.120959043e-01, 2.171340946e-01, 2.222148835e-01, 2.273375058e-01, 2.325011901e-01, 2.377051587e-01, 2.429486279e-01, 2.482308081e-01, 2.535509039e-01, 2.589081140e-01, 2.643016316e-01, 2.697306445e-01, 2.751943352e-01, 2.806918807e-01, 2.862224533e-01, 2.917852200e-01, 2.973793430e-01, 3.030039800e-01, 3.086582838e-01, 3.143414030e-01, 3.200524817e-01, 3.257906599e-01, 3.315550733e-01, 3.373448539e-01, 3.431591298e-01, 3.489970253e-01, 3.548576614e-01, 3.607401553e-01, 3.666436213e-01, 3.725671702e-01, 3.785099100e-01, 3.844709459e-01, 3.904493799e-01, 3.964443119e-01, 4.024548390e-01, 4.084800560e-01, 4.145190556e-01, 4.205709283e-01, 4.266347628e-01, 4.327096457e-01, 4.387946624e-01, 4.448888964e-01, 4.509914298e-01, 4.571013438e-01, 4.632177182e-01, 4.693396318e-01, 4.754661628e-01, 4.815963885e-01, 4.877293857e-01, 4.938642309e-01, 5.000000000e-01, 5.061357691e-01, 5.122706143e-01, 5.184036115e-01, 5.245338372e-01, 5.306603682e-01, 5.367822818e-01, 5.428986562e-01, 5.490085702e-01, 5.551111036e-01, 5.612053376e-01, 5.672903543e-01, 5.733652372e-01, 5.794290717e-01, 5.854809444e-01, 5.915199440e-01, 5.975451610e-01, 6.035556881e-01, 6.095506201e-01, 6.155290541e-01, 6.214900900e-01, 6.274328298e-01, 6.333563787e-01, 6.392598447e-01, 6.451423386e-01, 6.510029747e-01, 6.568408702e-01, 6.626551461e-01, 6.684449267e-01, 6.742093401e-01, 6.799475183e-01, 6.856585970e-01, 6.913417162e-01, 6.969960200e-01, 7.026206570e-01, 7.082147800e-01, 7.137775467e-01, 7.193081193e-01, 7.248056648e-01, 7.302693555e-01, 7.356983684e-01, 7.410918860e-01, 7.464490961e-01, 7.517691919e-01, 7.570513721e-01, 7.622948413e-01, 7.674988099e-01, 7.726624942e-01, 7.777851165e-01, 7.828659054e-01, 7.879040957e-01, 7.928989287e-01, 7.978496522e-01, 8.027555207e-01, 8.076157953e-01, 8.124297441e-01, 8.171966421e-01, 8.219157714e-01, 8.265864215e-01, 8.312078888e-01, 8.357794774e-01, 8.403004989e-01, 8.447702724e-01, 8.491881247e-01, 8.535533906e-01, 8.578654126e-01, 8.621235415e-01, 8.663271358e-01, 8.704755627e-01, 8.745681973e-01, 8.786044233e-01, 8.825836328e-01, 8.865052267e-01, 8.903686143e-01, 8.941732138e-01, 8.979184523e-01, 9.016037657e-01, 9.052285991e-01, 9.087924066e-01, 9.122946514e-01, 9.157348062e-01, 9.191123528e-01, 9.224267826e-01, 9.256775966e-01, 9.288643050e-01, 9.319864281e-01, 9.350434956e-01, 9.380350471e-01, 9.409606322e-01, 9.438198102e-01, 9.466121506e-01, 9.493372328e-01, 9.519946466e-01, 9.545839915e-01, 9.571048779e-01, 9.595569258e-01, 9.619397663e-01, 9.642530402e-01, 9.664963994e-01, 9.686695060e-01, 9.707720326e-01, 9.728036627e-01, 9.747640903e-01, 9.766530202e-01, 9.784701679e-01, 9.802152597e-01, 9.818880329e-01, 9.834882355e-01, 9.850156266e-01, 9.864699761e-01, 9.878510650e-01, 9.891586854e-01, 9.903926402e-01, 9.915527437e-01, 9.926388212e-01, 9.936507091e-01, 9.945882550e-01, 9.954513177e-01, 9.962397673e-01, 9.969534850e-01, 9.975923633e-01, 9.981563061e-01, 9.986452283e-01, 9.990590565e-01, 9.993977281e-01, 9.996611923e-01, 9.998494093e-01, 9.999623509e-01, 1.000000000e+00, }; const float lut_sine[] = { 0.000000000e+00, 2.454122852e-02, 4.906767433e-02, 7.356456360e-02, 9.801714033e-02, 1.224106752e-01, 1.467304745e-01, 1.709618888e-01, 1.950903220e-01, 2.191012402e-01, 2.429801799e-01, 2.667127575e-01, 2.902846773e-01, 3.136817404e-01, 3.368898534e-01, 3.598950365e-01, 3.826834324e-01, 4.052413140e-01, 4.275550934e-01, 4.496113297e-01, 4.713967368e-01, 4.928981922e-01, 5.141027442e-01, 5.349976199e-01, 5.555702330e-01, 5.758081914e-01, 5.956993045e-01, 6.152315906e-01, 6.343932842e-01, 6.531728430e-01, 6.715589548e-01, 6.895405447e-01, 7.071067812e-01, 7.242470830e-01, 7.409511254e-01, 7.572088465e-01, 7.730104534e-01, 7.883464276e-01, 8.032075315e-01, 8.175848132e-01, 8.314696123e-01, 8.448535652e-01, 8.577286100e-01, 8.700869911e-01, 8.819212643e-01, 8.932243012e-01, 9.039892931e-01, 9.142097557e-01, 9.238795325e-01, 9.329927988e-01, 9.415440652e-01, 9.495281806e-01, 9.569403357e-01, 9.637760658e-01, 9.700312532e-01, 9.757021300e-01, 9.807852804e-01, 9.852776424e-01, 9.891765100e-01, 9.924795346e-01, 9.951847267e-01, 9.972904567e-01, 9.987954562e-01, 9.996988187e-01, 1.000000000e+00, 9.996988187e-01, 9.987954562e-01, 9.972904567e-01, 9.951847267e-01, 9.924795346e-01, 9.891765100e-01, 9.852776424e-01, 9.807852804e-01, 9.757021300e-01, 9.700312532e-01, 9.637760658e-01, 9.569403357e-01, 9.495281806e-01, 9.415440652e-01, 9.329927988e-01, 9.238795325e-01, 9.142097557e-01, 9.039892931e-01, 8.932243012e-01, 8.819212643e-01, 8.700869911e-01, 8.577286100e-01, 8.448535652e-01, 8.314696123e-01, 8.175848132e-01, 8.032075315e-01, 7.883464276e-01, 7.730104534e-01, 7.572088465e-01, 7.409511254e-01, 7.242470830e-01, 7.071067812e-01, 6.895405447e-01, 6.715589548e-01, 6.531728430e-01, 6.343932842e-01, 6.152315906e-01, 5.956993045e-01, 5.758081914e-01, 5.555702330e-01, 5.349976199e-01, 5.141027442e-01, 4.928981922e-01, 4.713967368e-01, 4.496113297e-01, 4.275550934e-01, 4.052413140e-01, 3.826834324e-01, 3.598950365e-01, 3.368898534e-01, 3.136817404e-01, 2.902846773e-01, 2.667127575e-01, 2.429801799e-01, 2.191012402e-01, 1.950903220e-01, 1.709618888e-01, 1.467304745e-01, 1.224106752e-01, 9.801714033e-02, 7.356456360e-02, 4.906767433e-02, 2.454122852e-02, 1.224646799e-16, -2.454122852e-02, -4.906767433e-02, -7.356456360e-02, -9.801714033e-02, -1.224106752e-01, -1.467304745e-01, -1.709618888e-01, -1.950903220e-01, -2.191012402e-01, -2.429801799e-01, -2.667127575e-01, -2.902846773e-01, -3.136817404e-01, -3.368898534e-01, -3.598950365e-01, -3.826834324e-01, -4.052413140e-01, -4.275550934e-01, -4.496113297e-01, -4.713967368e-01, -4.928981922e-01, -5.141027442e-01, -5.349976199e-01, -5.555702330e-01, -5.758081914e-01, -5.956993045e-01, -6.152315906e-01, -6.343932842e-01, -6.531728430e-01, -6.715589548e-01, -6.895405447e-01, -7.071067812e-01, -7.242470830e-01, -7.409511254e-01, -7.572088465e-01, -7.730104534e-01, -7.883464276e-01, -8.032075315e-01, -8.175848132e-01, -8.314696123e-01, -8.448535652e-01, -8.577286100e-01, -8.700869911e-01, -8.819212643e-01, -8.932243012e-01, -9.039892931e-01, -9.142097557e-01, -9.238795325e-01, -9.329927988e-01, -9.415440652e-01, -9.495281806e-01, -9.569403357e-01, -9.637760658e-01, -9.700312532e-01, -9.757021300e-01, -9.807852804e-01, -9.852776424e-01, -9.891765100e-01, -9.924795346e-01, -9.951847267e-01, -9.972904567e-01, -9.987954562e-01, -9.996988187e-01, -1.000000000e+00, -9.996988187e-01, -9.987954562e-01, -9.972904567e-01, -9.951847267e-01, -9.924795346e-01, -9.891765100e-01, -9.852776424e-01, -9.807852804e-01, -9.757021300e-01, -9.700312532e-01, -9.637760658e-01, -9.569403357e-01, -9.495281806e-01, -9.415440652e-01, -9.329927988e-01, -9.238795325e-01, -9.142097557e-01, -9.039892931e-01, -8.932243012e-01, -8.819212643e-01, -8.700869911e-01, -8.577286100e-01, -8.448535652e-01, -8.314696123e-01, -8.175848132e-01, -8.032075315e-01, -7.883464276e-01, -7.730104534e-01, -7.572088465e-01, -7.409511254e-01, -7.242470830e-01, -7.071067812e-01, -6.895405447e-01, -6.715589548e-01, -6.531728430e-01, -6.343932842e-01, -6.152315906e-01, -5.956993045e-01, -5.758081914e-01, -5.555702330e-01, -5.349976199e-01, -5.141027442e-01, -4.928981922e-01, -4.713967368e-01, -4.496113297e-01, -4.275550934e-01, -4.052413140e-01, -3.826834324e-01, -3.598950365e-01, -3.368898534e-01, -3.136817404e-01, -2.902846773e-01, -2.667127575e-01, -2.429801799e-01, -2.191012402e-01, -1.950903220e-01, -1.709618888e-01, -1.467304745e-01, -1.224106752e-01, -9.801714033e-02, -7.356456360e-02, -4.906767433e-02, -2.454122852e-02, -2.449293598e-16, }; const float lut_logit[] = { 9.756097561e-04, 1.029841827e-03, 1.087085263e-03, 1.147506902e-03, 1.211282784e-03, 1.278598651e-03, 1.349650476e-03, 1.424645024e-03, 1.503800438e-03, 1.587346853e-03, 1.675527056e-03, 1.768597162e-03, 1.866827345e-03, 1.970502590e-03, 2.079923497e-03, 2.195407119e-03, 2.317287851e-03, 2.445918356e-03, 2.581670544e-03, 2.724936605e-03, 2.876130082e-03, 3.035687013e-03, 3.204067123e-03, 3.381755074e-03, 3.569261780e-03, 3.767125791e-03, 3.975914737e-03, 4.196226847e-03, 4.428692539e-03, 4.673976092e-03, 4.932777388e-03, 5.205833741e-03, 5.493921811e-03, 5.797859605e-03, 6.118508566e-03, 6.456775757e-03, 6.813616142e-03, 7.190034962e-03, 7.587090215e-03, 8.005895235e-03, 8.447621377e-03, 8.913500811e-03, 9.404829421e-03, 9.922969810e-03, 1.046935442e-02, 1.104548875e-02, 1.165295471e-02, 1.229341403e-02, 1.296861181e-02, 1.368038021e-02, 1.443064212e-02, 1.522141505e-02, 1.605481500e-02, 1.693306051e-02, 1.785847665e-02, 1.883349920e-02, 1.986067876e-02, 2.094268495e-02, 2.208231056e-02, 2.328247576e-02, 2.454623222e-02, 2.587676715e-02, 2.727740726e-02, 2.875162262e-02, 3.030303030e-02, 3.193539780e-02, 3.365264624e-02, 3.545885323e-02, 3.735825534e-02, 3.935525016e-02, 4.145439785e-02, 4.366042208e-02, 4.597821036e-02, 4.841281356e-02, 5.096944459e-02, 5.365347623e-02, 5.647043776e-02, 5.942601054e-02, 6.252602226e-02, 6.577643982e-02, 6.918336064e-02, 7.275300236e-02, 7.649169073e-02, 8.040584556e-02, 8.450196469e-02, 8.878660570e-02, 9.326636540e-02, 9.794785684e-02, 1.028376839e-01, 1.079424132e-01, 1.132685434e-01, 1.188224717e-01, 1.246104577e-01, 1.306385847e-01, 1.369127177e-01, 1.434384597e-01, 1.502211048e-01, 1.572655893e-01, 1.645764408e-01, 1.721577255e-01, 1.800129939e-01, 1.881452256e-01, 1.965567737e-01, 2.052493091e-01, 2.142237651e-01, 2.234802836e-01, 2.330181631e-01, 2.428358094e-01, 2.529306894e-01, 2.632992903e-01, 2.739370820e-01, 2.848384876e-01, 2.959968589e-01, 3.074044601e-01, 3.190524600e-01, 3.309309323e-01, 3.430288657e-01, 3.553341839e-01, 3.678337753e-01, 3.805135333e-01, 3.933584068e-01, 4.063524602e-01, 4.194789441e-01, 4.327203741e-01, 4.460586192e-01, 4.594749964e-01, 4.729503737e-01, 4.864652765e-01, 5.000000000e-01, 5.135347235e-01, 5.270496263e-01, 5.405250036e-01, 5.539413808e-01, 5.672796259e-01, 5.805210559e-01, 5.936475398e-01, 6.066415932e-01, 6.194864667e-01, 6.321662247e-01, 6.446658161e-01, 6.569711343e-01, 6.690690677e-01, 6.809475400e-01, 6.925955399e-01, 7.040031411e-01, 7.151615124e-01, 7.260629180e-01, 7.367007097e-01, 7.470693106e-01, 7.571641906e-01, 7.669818369e-01, 7.765197164e-01, 7.857762349e-01, 7.947506909e-01, 8.034432263e-01, 8.118547744e-01, 8.199870061e-01, 8.278422745e-01, 8.354235592e-01, 8.427344107e-01, 8.497788952e-01, 8.565615403e-01, 8.630872823e-01, 8.693614153e-01, 8.753895423e-01, 8.811775283e-01, 8.867314566e-01, 8.920575868e-01, 8.971623161e-01, 9.020521432e-01, 9.067336346e-01, 9.112133943e-01, 9.154980353e-01, 9.195941544e-01, 9.235083093e-01, 9.272469976e-01, 9.308166394e-01, 9.342235602e-01, 9.374739777e-01, 9.405739895e-01, 9.435295622e-01, 9.463465238e-01, 9.490305554e-01, 9.515871864e-01, 9.540217896e-01, 9.563395779e-01, 9.585456022e-01, 9.606447498e-01, 9.626417447e-01, 9.645411468e-01, 9.663473538e-01, 9.680646022e-01, 9.696969697e-01, 9.712483774e-01, 9.727225927e-01, 9.741232329e-01, 9.754537678e-01, 9.767175242e-01, 9.779176894e-01, 9.790573151e-01, 9.801393212e-01, 9.811665008e-01, 9.821415234e-01, 9.830669395e-01, 9.839451850e-01, 9.847785850e-01, 9.855693579e-01, 9.863196198e-01, 9.870313882e-01, 9.877065860e-01, 9.883470453e-01, 9.889545112e-01, 9.895306456e-01, 9.900770302e-01, 9.905951706e-01, 9.910864992e-01, 9.915523786e-01, 9.919941048e-01, 9.924129098e-01, 9.928099650e-01, 9.931863839e-01, 9.935432242e-01, 9.938814914e-01, 9.942021404e-01, 9.945060782e-01, 9.947941663e-01, 9.950672226e-01, 9.953260239e-01, 9.955713075e-01, 9.958037732e-01, 9.960240853e-01, 9.962328742e-01, 9.964307382e-01, 9.966182449e-01, 9.967959329e-01, 9.969643130e-01, 9.971238699e-01, 9.972750634e-01, 9.974183295e-01, 9.975540816e-01, 9.976827121e-01, 9.978045929e-01, 9.979200765e-01, 9.980294974e-01, 9.981331727e-01, 9.982314028e-01, 9.983244729e-01, 9.984126531e-01, 9.984961996e-01, 9.985753550e-01, 9.986503495e-01, 9.987214013e-01, 9.987887172e-01, 9.988524931e-01, 9.989129147e-01, 9.989701582e-01, 9.990243902e-01, }; const float* lookup_table_table[] = { lut_raised_cosine, lut_sine, lut_logit, }; const float dist_icdf_0_0[] = { 0.000000000e+00, 4.087982131e-02, 4.305530135e-02, 4.446717099e-02, 4.554461095e-02, 4.643028146e-02, 4.719036259e-02, 4.786130177e-02, 4.846544150e-02, 4.901752808e-02, 4.952783693e-02, 5.000383245e-02, 5.045111894e-02, 5.087401856e-02, 5.127593970e-02, 5.165962113e-02, 5.202729920e-02, 5.238082566e-02, 5.272175258e-02, 5.305139493e-02, 5.337087757e-02, 5.368117102e-02, 5.398311923e-02, 5.427746127e-02, 5.456484856e-02, 5.484585871e-02, 5.512100673e-02, 5.539075414e-02, 5.565551651e-02, 5.591566975e-02, 5.617155528e-02, 5.642348449e-02, 5.667174243e-02, 5.691659100e-02, 5.715827167e-02, 5.739700778e-02, 5.763300665e-02, 5.786646125e-02, 5.809755178e-02, 5.832644702e-02, 5.855330550e-02, 5.877827655e-02, 5.900150124e-02, 5.922311321e-02, 5.944323939e-02, 5.966200071e-02, 5.987951263e-02, 6.009588577e-02, 6.031122633e-02, 6.052563658e-02, 6.073921527e-02, 6.095205800e-02, 6.116425758e-02, 6.137590434e-02, 6.158708647e-02, 6.179789027e-02, 6.200840044e-02, 6.221870034e-02, 6.242887223e-02, 6.263899748e-02, 6.284915686e-02, 6.305943072e-02, 6.326989919e-02, 6.348064244e-02, 6.369174088e-02, 6.390327537e-02, 6.411532743e-02, 6.432797947e-02, 6.454131500e-02, 6.475541891e-02, 6.497037764e-02, 6.518627947e-02, 6.540321479e-02, 6.562127634e-02, 6.584055954e-02, 6.606116275e-02, 6.628318767e-02, 6.650673963e-02, 6.673192802e-02, 6.695886667e-02, 6.718767432e-02, 6.741847510e-02, 6.765139910e-02, 6.788658290e-02, 6.812417027e-02, 6.836431288e-02, 6.860717107e-02, 6.885291476e-02, 6.910172445e-02, 6.935379229e-02, 6.960932336e-02, 6.986853705e-02, 7.013166868e-02, 7.039897125e-02, 7.067071756e-02, 7.094720251e-02, 7.122874586e-02, 7.151569529e-02, 7.180843008e-02, 7.210736531e-02, 7.241295677e-02, 7.272570685e-02, 7.304617137e-02, 7.337496784e-02, 7.371278529e-02, 7.406039621e-02, 7.441867100e-02, 7.478859585e-02, 7.517129474e-02, 7.556805707e-02, 7.598037259e-02, 7.640997608e-02, 7.685890539e-02, 7.732957775e-02, 7.782489202e-02, 7.834836803e-02, 7.890434069e-02, 7.949823715e-02, 8.013698356e-02, 8.082962263e-02, 8.158828889e-02, 8.242982515e-02, 8.337862717e-02, 8.447204952e-02, 8.577178628e-02, 8.739155340e-02, 8.958128632e-02, 9.311481710e-02, 1.000000000e+00, 0.000000000e+00, 3.371122655e-02, 3.513071484e-02, 3.601706803e-02, 3.667393961e-02, 3.720074235e-02, 3.764309658e-02, 3.802590894e-02, 3.836433481e-02, 3.866831217e-02, 3.894472555e-02, 3.919854936e-02, 3.943349984e-02, 3.965242956e-02, 3.985757791e-02, 4.005073651e-02, 4.023336216e-02, 4.040665606e-02, 4.057162083e-02, 4.072910239e-02, 4.087982131e-02, 4.102439664e-02, 4.116336428e-02, 4.129719142e-02, 4.142628787e-02, 4.155101522e-02, 4.167169419e-02, 4.178861061e-02, 4.190202037e-02, 4.201215349e-02, 4.211921756e-02, 4.222340057e-02, 4.232487333e-02, 4.242379152e-02, 4.252029748e-02, 4.261452166e-02, 4.270658395e-02, 4.279659481e-02, 4.288465623e-02, 4.297086257e-02, 4.305530135e-02, 4.313805388e-02, 4.321919583e-02, 4.329879776e-02, 4.337692558e-02, 4.345364096e-02, 4.352900166e-02, 4.360306187e-02, 4.367587254e-02, 4.374748157e-02, 4.381793411e-02, 4.388727274e-02, 4.395553766e-02, 4.402276687e-02, 4.408899637e-02, 4.415426022e-02, 4.421859075e-02, 4.428201864e-02, 4.434457305e-02, 4.440628170e-02, 4.446717099e-02, 4.452726605e-02, 4.458659086e-02, 4.464516829e-02, 4.470302019e-02, 4.476016742e-02, 4.481662995e-02, 4.487242688e-02, 4.492757649e-02, 4.498209632e-02, 4.503600317e-02, 4.508931316e-02, 4.514204178e-02, 4.519420388e-02, 4.524581377e-02, 4.529688518e-02, 4.534743133e-02, 4.539746494e-02, 4.544699828e-02, 4.549604316e-02, 4.554461095e-02, 4.559271264e-02, 4.564035883e-02, 4.568755975e-02, 4.573432527e-02, 4.578066494e-02, 4.582658798e-02, 4.587210333e-02, 4.591721960e-02, 4.596194515e-02, 4.600628806e-02, 4.605025617e-02, 4.609385706e-02, 4.613709808e-02, 4.617998636e-02, 4.622252880e-02, 4.626473212e-02, 4.630660282e-02, 4.634814722e-02, 4.638937145e-02, 4.643028146e-02, 4.647088305e-02, 4.651118184e-02, 4.655118330e-02, 4.659089274e-02, 4.663031535e-02, 4.666945615e-02, 4.670832004e-02, 4.674691178e-02, 4.678523603e-02, 4.682329730e-02, 4.686110000e-02, 4.689864843e-02, 4.693594675e-02, 4.697299906e-02, 4.700980933e-02, 4.704638144e-02, 4.708271917e-02, 4.711882622e-02, 4.715470619e-02, 4.719036259e-02, 4.722579886e-02, 4.726101836e-02, 4.729602435e-02, 4.733082005e-02, 4.736540857e-02, 4.739979298e-02, 4.743397625e-02, 4.746796131e-02, 8.298422555e-02, 8.303237008e-02, 8.308083474e-02, 8.312962441e-02, 8.317874409e-02, 8.322819891e-02, 8.327799409e-02, 8.332813502e-02, 8.337862717e-02, 8.342947618e-02, 8.348068782e-02, 8.353226799e-02, 8.358422277e-02, 8.363655835e-02, 8.368928111e-02, 8.374239758e-02, 8.379591448e-02, 8.384983866e-02, 8.390417721e-02, 8.395893736e-02, 8.401412656e-02, 8.406975246e-02, 8.412582290e-02, 8.418234597e-02, 8.423932997e-02, 8.429678342e-02, 8.435471510e-02, 8.441313404e-02, 8.447204952e-02, 8.453147112e-02, 8.459140868e-02, 8.465187234e-02, 8.471287254e-02, 8.477442006e-02, 8.483652600e-02, 8.489920180e-02, 8.496245927e-02, 8.502631059e-02, 8.509076836e-02, 8.515584555e-02, 8.522155558e-02, 8.528791233e-02, 8.535493012e-02, 8.542262378e-02, 8.549100865e-02, 8.556010060e-02, 8.562991607e-02, 8.570047208e-02, 8.577178628e-02, 8.584387696e-02, 8.591676309e-02, 8.599046436e-02, 8.606500122e-02, 8.614039490e-02, 8.621666745e-02, 8.629384184e-02, 8.637194193e-02, 8.645099256e-02, 8.653101960e-02, 8.661205004e-02, 8.669411197e-02, 8.677723474e-02, 8.686144897e-02, 8.694678665e-02, 8.703328123e-02, 8.712096769e-02, 8.720988265e-02, 8.730006448e-02, 8.739155340e-02, 8.748439160e-02, 8.757862339e-02, 8.767429534e-02, 8.777145642e-02, 8.787015820e-02, 8.797045499e-02, 8.807240410e-02, 8.817606603e-02, 8.828150472e-02, 8.838878779e-02, 8.849798691e-02, 8.860917803e-02, 8.872244181e-02, 8.883786399e-02, 8.895553582e-02, 8.907555456e-02, 8.919802402e-02, 8.932305516e-02, 8.945076680e-02, 8.958128632e-02, 8.971475057e-02, 8.985130683e-02, 8.999111388e-02, 9.013434323e-02, 9.028118059e-02, 9.043182743e-02, 9.058650287e-02, 9.074544579e-02, 9.090891730e-02, 9.107720365e-02, 9.125061953e-02, 9.142951204e-02, 9.161426530e-02, 9.180530596e-02, 9.200310981e-02, 9.220820960e-02, 9.242120466e-02, 9.264277250e-02, 9.287368319e-02, 9.311481710e-02, 9.336718725e-02, 9.363196749e-02, 9.391052881e-02, 9.420448640e-02, 9.451576181e-02, 9.484666624e-02, 9.520001450e-02, 9.557928395e-02, 9.598884202e-02, 9.643428110e-02, 9.692292814e-02, 9.746465204e-02, 9.807320583e-02, 9.876859706e-02, 9.958160960e-02, 1.005633646e-01, 1.018086946e-01, 1.035276807e-01, 1.063778878e-01, 1.000000000e+00, }; const float dist_icdf_0_1[] = { 0.000000000e+00, 5.775967733e-02, 6.707029213e-02, 7.344987461e-02, 7.848926629e-02, 8.273886990e-02, 8.646080382e-02, 8.980231529e-02, 9.285512486e-02, 9.568058999e-02, 9.832196591e-02, 1.008109989e-01, 1.031717446e-01, 1.054229108e-01, 1.075793640e-01, 1.096531351e-01, 1.116541136e-01, 1.135905398e-01, 1.154693614e-01, 1.172964987e-01, 1.190770435e-01, 1.208154125e-01, 1.225154661e-01, 1.241806021e-01, 1.258138303e-01, 1.274178326e-01, 1.289950118e-01, 1.305475317e-01, 1.320773503e-01, 1.335862472e-01, 1.350758471e-01, 1.365476389e-01, 1.380029929e-01, 1.394431744e-01, 1.408693562e-01, 1.422826293e-01, 1.436840117e-01, 1.450744567e-01, 1.464548594e-01, 1.478260638e-01, 1.491888670e-01, 1.505440251e-01, 1.518922568e-01, 1.532342479e-01, 1.545706540e-01, 1.559021043e-01, 1.572292039e-01, 1.585525369e-01, 1.598726685e-01, 1.611901471e-01, 1.625055063e-01, 1.638192671e-01, 1.651319394e-01, 1.664440234e-01, 1.677560117e-01, 1.690683903e-01, 1.703816403e-01, 1.716962389e-01, 1.730126612e-01, 1.743313810e-01, 1.756528725e-01, 1.769776111e-01, 1.783060750e-01, 1.796387462e-01, 1.809761119e-01, 1.823186655e-01, 1.836669085e-01, 1.850213512e-01, 1.863825142e-01, 1.877509303e-01, 1.891271455e-01, 1.905117208e-01, 1.919052339e-01, 1.933082808e-01, 1.947214781e-01, 1.961454644e-01, 1.975809033e-01, 1.990284850e-01, 2.004889293e-01, 2.019629884e-01, 2.034514498e-01, 2.049551394e-01, 2.064749256e-01, 2.080117230e-01, 2.095664970e-01, 2.111402686e-01, 2.127341198e-01, 2.143491997e-01, 2.159867314e-01, 2.176480193e-01, 2.193344581e-01, 2.210475417e-01, 2.227888751e-01, 2.245601857e-01, 2.263633384e-01, 2.282003509e-01, 2.300734130e-01, 2.319849075e-01, 2.339374356e-01, 2.359338454e-01, 2.379772658e-01, 2.400711471e-01, 2.422193075e-01, 2.444259898e-01, 2.466959290e-01, 2.490344340e-01, 2.514474865e-01, 2.539418634e-01, 2.565252874e-01, 2.592066160e-01, 2.619960800e-01, 2.649055891e-01, 2.679491277e-01, 2.711432755e-01, 2.745079047e-01, 2.780671283e-01, 2.818506217e-01, 2.858955058e-01, 2.902491089e-01, 2.949731546e-01, 3.001503663e-01, 3.058953959e-01, 3.123740231e-01, 3.198395630e-01, 3.287093170e-01, 3.397499388e-01, 3.546388029e-01, 3.785312373e-01, 1.000000000e+00, 0.000000000e+00, 3.192269535e-02, 3.641890780e-02, 3.938557046e-02, 4.166204844e-02, 4.353517362e-02, 4.514034051e-02, 4.655306902e-02, 4.782011687e-02, 4.897259663e-02, 5.003233599e-02, 5.101528342e-02, 5.193347290e-02, 5.279622538e-02, 5.361091873e-02, 5.438350047e-02, 5.511884060e-02, 5.582098098e-02, 5.649331595e-02, 5.713872582e-02, 5.775967733e-02, 5.835830054e-02, 5.893644842e-02, 5.949574372e-02, 6.003761626e-02, 6.056333286e-02, 6.107402166e-02, 6.157069199e-02, 6.205425076e-02, 6.252551616e-02, 6.298522905e-02, 6.343406259e-02, 6.387263038e-02, 6.430149343e-02, 6.472116613e-02, 6.513212133e-02, 6.553479482e-02, 6.592958916e-02, 6.631687705e-02, 6.669700423e-02, 6.707029213e-02, 6.743704010e-02, 6.779752742e-02, 6.815201513e-02, 6.850074756e-02, 6.884395383e-02, 6.918184901e-02, 6.951463538e-02, 6.984250336e-02, 7.016563246e-02, 7.048419215e-02, 7.079834256e-02, 7.110823521e-02, 7.141401358e-02, 7.171581373e-02, 7.201376479e-02, 7.230798943e-02, 7.259860431e-02, 7.288572045e-02, 7.316944361e-02, 7.344987461e-02, 7.372710968e-02, 7.400124068e-02, 7.427235541e-02, 7.454053784e-02, 7.480586833e-02, 7.506842384e-02, 7.532827811e-02, 7.558550188e-02, 7.584016300e-02, 7.609232665e-02, 7.634205541e-02, 7.658940947e-02, 7.683444670e-02, 7.707722280e-02, 7.731779138e-02, 7.755620413e-02, 7.779251082e-02, 7.802675946e-02, 7.825899638e-02, 7.848926629e-02, 7.871761235e-02, 7.894407627e-02, 7.916869835e-02, 7.939151757e-02, 7.961257162e-02, 7.983189698e-02, 8.004952894e-02, 8.026550172e-02, 8.047984843e-02, 8.069260117e-02, 8.090379106e-02, 8.111344828e-02, 8.132160211e-02, 8.152828097e-02, 8.173351242e-02, 8.193732327e-02, 8.213973951e-02, 8.234078643e-02, 8.254048860e-02, 8.273886990e-02, 8.293595357e-02, 8.313176219e-02, 8.332631777e-02, 8.351964170e-02, 8.371175482e-02, 8.390267741e-02, 8.409242924e-02, 8.428102958e-02, 8.446849717e-02, 8.465485032e-02, 8.484010687e-02, 8.502428420e-02, 8.520739928e-02, 8.538946867e-02, 8.557050852e-02, 8.575053461e-02, 8.592956232e-02, 8.610760670e-02, 8.628468242e-02, 8.646080382e-02, 8.663598494e-02, 8.681023946e-02, 8.698358077e-02, 8.715602196e-02, 8.732757584e-02, 8.749825492e-02, 8.766807144e-02, 8.783703740e-02, 3.096809047e-01, 3.100096523e-01, 3.103405866e-01, 3.106737407e-01, 3.110091485e-01, 3.113468447e-01, 3.116868649e-01, 3.120292452e-01, 3.123740231e-01, 3.127212367e-01, 3.130709250e-01, 3.134231281e-01, 3.137778869e-01, 3.141352437e-01, 3.144952415e-01, 3.148579246e-01, 3.152233383e-01, 3.155915293e-01, 3.159625452e-01, 3.163364353e-01, 3.167132498e-01, 3.170930404e-01, 3.174758604e-01, 3.178617642e-01, 3.182508082e-01, 3.186430498e-01, 3.190385485e-01, 3.194373653e-01, 3.198395630e-01, 3.202452062e-01, 3.206543615e-01, 3.210670973e-01, 3.214834842e-01, 3.219035950e-01, 3.223275046e-01, 3.227552903e-01, 3.231870319e-01, 3.236228115e-01, 3.240627140e-01, 3.245068272e-01, 3.249552415e-01, 3.254080504e-01, 3.258653506e-01, 3.263272421e-01, 3.267938283e-01, 3.272652161e-01, 3.277415163e-01, 3.282228437e-01, 3.287093170e-01, 3.292010595e-01, 3.296981990e-01, 3.302008679e-01, 3.307092039e-01, 3.312233499e-01, 3.317434543e-01, 3.322696715e-01, 3.328021619e-01, 3.333410928e-01, 3.338866379e-01, 3.344389785e-01, 3.349983036e-01, 3.355648102e-01, 3.361387039e-01, 3.367201996e-01, 3.373095218e-01, 3.379069052e-01, 3.385125955e-01, 3.391268502e-01, 3.397499388e-01, 3.403821443e-01, 3.410237635e-01, 3.416751086e-01, 3.423365075e-01, 3.430083056e-01, 3.436908663e-01, 3.443845734e-01, 3.450898313e-01, 3.458070679e-01, 3.465367352e-01, 3.472793121e-01, 3.480353061e-01, 3.488052560e-01, 3.495897342e-01, 3.503893496e-01, 3.512047511e-01, 3.520366310e-01, 3.528857290e-01, 3.537528368e-01, 3.546388029e-01, 3.555445384e-01, 3.564710233e-01, 3.574193139e-01, 3.583905504e-01, 3.593859671e-01, 3.604069020e-01, 3.614548098e-01, 3.625312755e-01, 3.636380306e-01, 3.647769723e-01, 3.659501849e-01, 3.671599661e-01, 3.684088570e-01, 3.696996782e-01, 3.710355728e-01, 3.724200577e-01, 3.738570865e-01, 3.753511249e-01, 3.769072442e-01, 3.785312373e-01, 3.802297637e-01, 3.820105327e-01, 3.838825389e-01, 3.858563674e-01, 3.879445963e-01, 3.901623353e-01, 3.925279618e-01, 3.950641455e-01, 3.977993140e-01, 4.007698049e-01, 4.040231355e-01, 4.076231722e-01, 4.116587047e-01, 4.162585474e-01, 4.216202624e-01, 4.280706728e-01, 4.362131524e-01, 4.473757968e-01, 4.656744235e-01, 1.000000000e+00, }; const float dist_icdf_0_2[] = { 0.000000000e+00, 2.174355841e-02, 3.092888348e-02, 3.812320475e-02, 4.429997329e-02, 4.983386356e-02, 5.491617951e-02, 5.966017291e-02, 6.413942945e-02, 6.840494830e-02, 7.249379666e-02, 7.643392067e-02, 8.024701264e-02, 8.395031560e-02, 8.755781005e-02, 9.108102307e-02, 9.452959714e-02, 9.791170021e-02, 1.012343283e-01, 1.045035331e-01, 1.077245956e-01, 1.109021616e-01, 1.140403481e-01, 1.171428276e-01, 1.202128970e-01, 1.232535328e-01, 1.262674371e-01, 1.292570750e-01, 1.322247065e-01, 1.351724129e-01, 1.381021195e-01, 1.410156146e-01, 1.439145658e-01, 1.468005346e-01, 1.496749883e-01, 1.525393111e-01, 1.553948128e-01, 1.582427381e-01, 1.610842730e-01, 1.639205517e-01, 1.667526626e-01, 1.695816530e-01, 1.724085344e-01, 1.752342864e-01, 1.780598607e-01, 1.808861847e-01, 1.837141649e-01, 1.865446897e-01, 1.893786323e-01, 1.922168535e-01, 1.950602044e-01, 1.979095281e-01, 2.007656627e-01, 2.036294431e-01, 2.065017033e-01, 2.093832783e-01, 2.122750063e-01, 2.151777305e-01, 2.180923013e-01, 2.210195783e-01, 2.239604320e-01, 2.269157461e-01, 2.298864198e-01, 2.328733692e-01, 2.358775304e-01, 2.388998611e-01, 2.419413432e-01, 2.450029856e-01, 2.480858261e-01, 2.511909351e-01, 2.543194176e-01, 2.574724169e-01, 2.606511180e-01, 2.638567508e-01, 2.670905940e-01, 2.703539795e-01, 2.736482967e-01, 2.769749974e-01, 2.803356010e-01, 2.837317004e-01, 2.871649681e-01, 2.906371632e-01, 2.941501391e-01, 2.977058516e-01, 3.013063682e-01, 3.049538782e-01, 3.086507044e-01, 3.123993150e-01, 3.162023386e-01, 3.200625789e-01, 3.239830333e-01, 3.279669124e-01, 3.320176622e-01, 3.361389905e-01, 3.403348952e-01, 3.446096976e-01, 3.489680809e-01, 3.534151336e-01, 3.579564004e-01, 3.625979410e-01, 3.673463990e-01, 3.722090826e-01, 3.771940600e-01, 3.823102724e-01, 3.875676695e-01, 3.929773722e-01, 3.985518702e-01, 4.043052633e-01, 4.102535592e-01, 4.164150442e-01, 4.228107498e-01, 4.294650475e-01, 4.364064145e-01, 4.436684375e-01, 4.512911461e-01, 4.593228202e-01, 4.678224871e-01, 4.768634586e-01, 4.865384784e-01, 4.969674609e-01, 5.083095845e-01, 5.207830984e-01, 5.346997151e-01, 5.505289609e-01, 5.690311803e-01, 5.915738191e-01, 6.210652108e-01, 6.660635133e-01, 1.000000000e+00, 0.000000000e+00, 4.922842828e-03, 6.920535491e-03, 8.451337086e-03, 9.741940876e-03, 1.087967776e-02, 1.190917253e-02, 1.285685991e-02, 1.373992404e-02, 1.457027778e-02, 1.535658012e-02, 1.610535802e-02, 1.682167545e-02, 1.750955456e-02, 1.817225278e-02, 1.881245191e-02, 1.943239104e-02, 2.003396240e-02, 2.061878220e-02, 2.118824379e-02, 2.174355841e-02, 2.228578684e-02, 2.281586425e-02, 2.333462012e-02, 2.384279417e-02, 2.434104942e-02, 2.482998282e-02, 2.531013415e-02, 2.578199335e-02, 2.624600676e-02, 2.670258234e-02, 2.715209412e-02, 2.759488605e-02, 2.803127525e-02, 2.846155484e-02, 2.888599644e-02, 2.930485227e-02, 2.971835708e-02, 3.012672973e-02, 3.053017474e-02, 3.092888348e-02, 3.132303539e-02, 3.171279895e-02, 3.209833264e-02, 3.247978569e-02, 3.285729888e-02, 3.323100513e-02, 3.360103017e-02, 3.396749301e-02, 3.433050647e-02, 3.469017759e-02, 3.504660808e-02, 3.539989464e-02, 3.575012931e-02, 3.609739981e-02, 3.644178975e-02, 3.678337898e-02, 3.712224374e-02, 3.745845695e-02, 3.779208835e-02, 3.812320475e-02, 3.845187016e-02, 3.877814595e-02, 3.910209103e-02, 3.942376194e-02, 3.974321304e-02, 4.006049656e-02, 4.037566277e-02, 4.068876005e-02, 4.099983500e-02, 4.130893253e-02, 4.161609594e-02, 4.192136699e-02, 4.222478600e-02, 4.252639189e-02, 4.282622229e-02, 4.312431354e-02, 4.342070080e-02, 4.371541807e-02, 4.400849828e-02, 4.429997329e-02, 4.458987398e-02, 4.487823025e-02, 4.516507111e-02, 4.545042469e-02, 4.573431827e-02, 4.601677832e-02, 4.629783056e-02, 4.657749995e-02, 4.685581073e-02, 4.713278649e-02, 4.740845013e-02, 4.768282394e-02, 4.795592959e-02, 4.822778816e-02, 4.849842018e-02, 4.876784563e-02, 4.903608398e-02, 4.930315419e-02, 4.956907471e-02, 4.983386356e-02, 5.009753829e-02, 5.036011602e-02, 5.062161343e-02, 5.088204682e-02, 5.114143208e-02, 5.139978472e-02, 5.165711990e-02, 5.191345239e-02, 5.216879666e-02, 5.242316682e-02, 5.267657665e-02, 5.292903964e-02, 5.318056897e-02, 5.343117753e-02, 5.368087791e-02, 5.392968245e-02, 5.417760320e-02, 5.442465197e-02, 5.467084031e-02, 5.491617951e-02, 5.516068067e-02, 5.540435461e-02, 5.564721195e-02, 5.588926309e-02, 5.613051823e-02, 5.637098734e-02, 5.661068023e-02, 5.684960647e-02, 5.289344619e-01, 5.296397483e-01, 5.303493000e-01, 5.310631783e-01, 5.317814459e-01, 5.325041669e-01, 5.332314071e-01, 5.339632336e-01, 5.346997151e-01, 5.354409218e-01, 5.361869258e-01, 5.369378008e-01, 5.376936222e-01, 5.384544674e-01, 5.392204156e-01, 5.399915479e-01, 5.407679475e-01, 5.415496997e-01, 5.423368920e-01, 5.431296139e-01, 5.439279575e-01, 5.447320172e-01, 5.455418899e-01, 5.463576751e-01, 5.471794748e-01, 5.480073939e-01, 5.488415403e-01, 5.496820247e-01, 5.505289609e-01, 5.513824659e-01, 5.522426601e-01, 5.531096675e-01, 5.539836153e-01, 5.548646348e-01, 5.557528611e-01, 5.566484333e-01, 5.575514947e-01, 5.584621931e-01, 5.593806809e-01, 5.603071150e-01, 5.612416577e-01, 5.621844761e-01, 5.631357429e-01, 5.640956366e-01, 5.650643414e-01, 5.660420478e-01, 5.670289528e-01, 5.680252600e-01, 5.690311803e-01, 5.700469320e-01, 5.710727412e-01, 5.721088422e-01, 5.731554777e-01, 5.742128997e-01, 5.752813695e-01, 5.763611585e-01, 5.774525485e-01, 5.785558324e-01, 5.796713147e-01, 5.807993124e-01, 5.819401553e-01, 5.830941868e-01, 5.842617651e-01, 5.854432635e-01, 5.866390716e-01, 5.878495963e-01, 5.890752627e-01, 5.903165153e-01, 5.915738191e-01, 5.928476613e-01, 5.941385522e-01, 5.954470271e-01, 5.967736481e-01, 5.981190053e-01, 5.994837195e-01, 6.008684439e-01, 6.022738668e-01, 6.037007139e-01, 6.051497510e-01, 6.066217877e-01, 6.081176803e-01, 6.096383355e-01, 6.111847150e-01, 6.127578396e-01, 6.143587946e-01, 6.159887352e-01, 6.176488931e-01, 6.193405830e-01, 6.210652108e-01, 6.228242823e-01, 6.246194131e-01, 6.264523396e-01, 6.283249317e-01, 6.302392072e-01, 6.321973478e-01, 6.342017182e-01, 6.362548870e-01, 6.383596517e-01, 6.405190673e-01, 6.427364790e-01, 6.450155616e-01, 6.473603646e-01, 6.497753664e-01, 6.522655378e-01, 6.548364188e-01, 6.574942108e-01, 6.602458881e-01, 6.630993347e-01, 6.660635133e-01, 6.691486755e-01, 6.723666263e-01, 6.757310625e-01, 6.792580075e-01, 6.829663828e-01, 6.868787669e-01, 6.910224254e-01, 6.954307351e-01, 7.001452035e-01, 7.052184107e-01, 7.107184362e-01, 7.167357856e-01, 7.233947496e-01, 7.308731533e-01, 7.394393664e-01, 7.495289276e-01, 7.619271224e-01, 7.783093378e-01, 8.036267830e-01, 1.000000000e+00, }; const float dist_icdf_0_3[] = { 0.000000000e+00, 1.136630499e-02, 1.812428419e-02, 2.386615269e-02, 2.905355219e-02, 3.387634622e-02, 3.843584130e-02, 4.279405263e-02, 4.699238532e-02, 5.106020347e-02, 5.501928171e-02, 5.888633262e-02, 6.267454085e-02, 6.639454450e-02, 7.005508997e-02, 7.366348437e-02, 7.722591737e-02, 8.074769597e-02, 8.423341938e-02, 8.768711188e-02, 9.111232529e-02, 9.451221931e-02, 9.788962525e-02, 1.012470972e-01, 1.045869537e-01, 1.079113115e-01, 1.112221142e-01, 1.145211554e-01, 1.178100986e-01, 1.210904941e-01, 1.243637928e-01, 1.276313590e-01, 1.308944806e-01, 1.341543787e-01, 1.374122149e-01, 1.406690993e-01, 1.439260960e-01, 1.471842290e-01, 1.504444869e-01, 1.537078276e-01, 1.569751824e-01, 1.602474592e-01, 1.635255461e-01, 1.668103148e-01, 1.701026226e-01, 1.734033160e-01, 1.767132325e-01, 1.800332031e-01, 1.833640546e-01, 1.867066116e-01, 1.900616986e-01, 1.934301421e-01, 1.968127721e-01, 2.002104243e-01, 2.036239420e-01, 2.070541778e-01, 2.105019953e-01, 2.139682714e-01, 2.174538979e-01, 2.209597834e-01, 2.244868553e-01, 2.280360619e-01, 2.316083747e-01, 2.352047901e-01, 2.388263321e-01, 2.424740547e-01, 2.461490442e-01, 2.498524219e-01, 2.535853474e-01, 2.573490208e-01, 2.611446868e-01, 2.649736376e-01, 2.688372166e-01, 2.727368228e-01, 2.766739147e-01, 2.806500151e-01, 2.846667162e-01, 2.887256850e-01, 2.928286693e-01, 2.969775040e-01, 3.011741187e-01, 3.054205449e-01, 3.097189252e-01, 3.140715222e-01, 3.184807293e-01, 3.229490820e-01, 3.274792709e-01, 3.320741560e-01, 3.367367823e-01, 3.414703980e-01, 3.462784741e-01, 3.511647272e-01, 3.561331444e-01, 3.611880128e-01, 3.663339513e-01, 3.715759482e-01, 3.769194042e-01, 3.823701809e-01, 3.879346574e-01, 3.936197967e-01, 3.994332214e-01, 4.053833037e-01, 4.114792714e-01, 4.177313327e-01, 4.241508257e-01, 4.307503978e-01, 4.375442228e-01, 4.445482653e-01, 4.517806065e-01, 4.592618485e-01, 4.670156219e-01, 4.750692297e-01, 4.834544764e-01, 4.922087481e-01, 5.013764448e-01, 5.110109121e-01, 5.211771014e-01, 5.319553204e-01, 5.434466648e-01, 5.557811429e-01, 5.691302991e-01, 5.837277572e-01, 5.999046350e-01, 6.181552614e-01, 6.392716828e-01, 6.646597189e-01, 6.972576369e-01, 7.454848184e-01, 1.000000000e+00, 0.000000000e+00, 1.550327841e-03, 2.453948846e-03, 3.211115815e-03, 3.886829909e-03, 4.507973099e-03, 5.088952189e-03, 5.638618270e-03, 6.162898283e-03, 6.666005288e-03, 7.151068748e-03, 7.620493191e-03, 8.076176397e-03, 8.519649257e-03, 8.952169276e-03, 9.374785302e-03, 9.788383651e-03, 1.019372180e-02, 1.059145355e-02, 1.098214814e-02, 1.136630499e-02, 1.174436539e-02, 1.211672159e-02, 1.248372429e-02, 1.284568861e-02, 1.320289901e-02, 1.355561341e-02, 1.390406656e-02, 1.424847289e-02, 1.458902894e-02, 1.492591540e-02, 1.525929890e-02, 1.558933348e-02, 1.591616194e-02, 1.623991693e-02, 1.656072200e-02, 1.687869240e-02, 1.719393593e-02, 1.750655353e-02, 1.781663993e-02, 1.812428419e-02, 1.842957012e-02, 1.873257677e-02, 1.903337876e-02, 1.933204664e-02, 1.962864722e-02, 1.992324381e-02, 2.021589651e-02, 2.050666239e-02, 2.079559577e-02, 2.108274834e-02, 2.136816938e-02, 2.165190589e-02, 2.193400276e-02, 2.221450288e-02, 2.249344728e-02, 2.277087525e-02, 2.304682442e-02, 2.332133086e-02, 2.359442921e-02, 2.386615269e-02, 2.413653326e-02, 2.440560163e-02, 2.467338733e-02, 2.493991881e-02, 2.520522348e-02, 2.546932774e-02, 2.573225705e-02, 2.599403601e-02, 2.625468832e-02, 2.651423690e-02, 2.677270391e-02, 2.703011075e-02, 2.728647814e-02, 2.754182612e-02, 2.779617410e-02, 2.804954088e-02, 2.830194469e-02, 2.855340317e-02, 2.880393347e-02, 2.905355219e-02, 2.930227547e-02, 2.955011897e-02, 2.979709789e-02, 3.004322703e-02, 3.028852074e-02, 3.053299299e-02, 3.077665736e-02, 3.101952709e-02, 3.126161502e-02, 3.150293368e-02, 3.174349528e-02, 3.198331168e-02, 3.222239447e-02, 3.246075493e-02, 3.269840406e-02, 3.293535259e-02, 3.317161098e-02, 3.340718945e-02, 3.364209795e-02, 3.387634622e-02, 3.410994375e-02, 3.434289983e-02, 3.457522351e-02, 3.480692365e-02, 3.503800891e-02, 3.526848775e-02, 3.549836843e-02, 3.572765906e-02, 3.595636754e-02, 3.618450162e-02, 3.641206888e-02, 3.663907672e-02, 3.686553242e-02, 3.709144308e-02, 3.731681566e-02, 3.754165698e-02, 3.776597372e-02, 3.798977244e-02, 3.821305953e-02, 3.843584130e-02, 3.865812391e-02, 3.887991340e-02, 3.910121570e-02, 3.932203663e-02, 3.954238188e-02, 3.976225706e-02, 3.998166765e-02, 4.020061906e-02, 5.932174711e-01, 5.940366506e-01, 5.948604733e-01, 5.956890038e-01, 5.965223081e-01, 5.973604536e-01, 5.982035093e-01, 5.990515458e-01, 5.999046350e-01, 6.007628509e-01, 6.016262690e-01, 6.024949664e-01, 6.033690223e-01, 6.042485176e-01, 6.051335352e-01, 6.060241600e-01, 6.069204789e-01, 6.078225812e-01, 6.087305580e-01, 6.096445030e-01, 6.105645121e-01, 6.114906839e-01, 6.124231191e-01, 6.133619215e-01, 6.143071973e-01, 6.152590556e-01, 6.162176085e-01, 6.171829710e-01, 6.181552614e-01, 6.191346010e-01, 6.201211148e-01, 6.211149311e-01, 6.221161819e-01, 6.231250030e-01, 6.241415342e-01, 6.251659192e-01, 6.261983063e-01, 6.272388479e-01, 6.282877012e-01, 6.293450282e-01, 6.304109959e-01, 6.314857766e-01, 6.325695479e-01, 6.336624933e-01, 6.347648022e-01, 6.358766700e-01, 6.369982990e-01, 6.381298979e-01, 6.392716828e-01, 6.404238772e-01, 6.415867123e-01, 6.427604276e-01, 6.439452710e-01, 6.451414997e-01, 6.463493802e-01, 6.475691889e-01, 6.488012127e-01, 6.500457496e-01, 6.513031090e-01, 6.525736128e-01, 6.538575955e-01, 6.551554053e-01, 6.564674048e-01, 6.577939717e-01, 6.591354999e-01, 6.604924002e-01, 6.618651014e-01, 6.632540516e-01, 6.646597189e-01, 6.660825933e-01, 6.675231876e-01, 6.689820392e-01, 6.704597112e-01, 6.719567951e-01, 6.734739116e-01, 6.750117137e-01, 6.765708882e-01, 6.781521585e-01, 6.797562873e-01, 6.813840798e-01, 6.830363863e-01, 6.847141064e-01, 6.864181928e-01, 6.881496555e-01, 6.899095667e-01, 6.916990663e-01, 6.935193676e-01, 6.953717641e-01, 6.972576369e-01, 6.991784628e-01, 7.011358238e-01, 7.031314177e-01, 7.051670694e-01, 7.072447450e-01, 7.093665667e-01, 7.115348302e-01, 7.137520248e-01, 7.160208562e-01, 7.183442733e-01, 7.207254987e-01, 7.231680647e-01, 7.256758556e-01, 7.282531568e-01, 7.309047141e-01, 7.336358034e-01, 7.364523154e-01, 7.393608574e-01, 7.423688776e-01, 7.454848184e-01, 7.487183066e-01, 7.520803922e-01, 7.555838521e-01, 7.592435801e-01, 7.630770961e-01, 7.671052216e-01, 7.713529908e-01, 7.758509060e-01, 7.806367088e-01, 7.857579461e-01, 7.912758108e-01, 7.972711136e-01, 8.038540068e-01, 8.111807607e-01, 8.194849205e-01, 8.291411365e-01, 8.408153119e-01, 8.559016189e-01, 8.784043144e-01, 1.000000000e+00, }; const float dist_icdf_0_4[] = { 0.000000000e+00, 4.318552295e-03, 8.136040937e-03, 1.180014022e-02, 1.537593950e-02, 1.889308061e-02, 2.236853835e-02, 2.581330409e-02, 2.923507613e-02, 3.263955250e-02, 3.603112869e-02, 3.941330696e-02, 4.278895200e-02, 4.616045870e-02, 4.952986670e-02, 5.289894125e-02, 5.626923179e-02, 5.964211556e-02, 6.301883064e-02, 6.640050140e-02, 6.978815852e-02, 7.318275496e-02, 7.658517870e-02, 7.999626330e-02, 8.341679646e-02, 8.684752728e-02, 9.028917230e-02, 9.374242061e-02, 9.720793831e-02, 1.006863723e-01, 1.041783536e-01, 1.076845002e-01, 1.112054199e-01, 1.147417123e-01, 1.182939709e-01, 1.218627855e-01, 1.254487433e-01, 1.290524307e-01, 1.326744350e-01, 1.363153456e-01, 1.399757555e-01, 1.436562621e-01, 1.473574693e-01, 1.510799879e-01, 1.548244369e-01, 1.585914450e-01, 1.623816515e-01, 1.661957074e-01, 1.700342766e-01, 1.738980372e-01, 1.777876823e-01, 1.817039217e-01, 1.856474827e-01, 1.896191116e-01, 1.936195750e-01, 1.976496612e-01, 2.017101816e-01, 2.058019722e-01, 2.099258949e-01, 2.140828399e-01, 2.182737267e-01, 2.224995062e-01, 2.267611629e-01, 2.310597166e-01, 2.353962250e-01, 2.397717858e-01, 2.441875393e-01, 2.486446712e-01, 2.531444154e-01, 2.576880572e-01, 2.622769366e-01, 2.669124519e-01, 2.715960638e-01, 2.763292995e-01, 2.811137571e-01, 2.859511110e-01, 2.908431167e-01, 2.957916174e-01, 3.007985499e-01, 3.058659516e-01, 3.109959686e-01, 3.161908637e-01, 3.214530258e-01, 3.267849801e-01, 3.321893994e-01, 3.376691163e-01, 3.432271373e-01, 3.488666579e-01, 3.545910799e-01, 3.604040301e-01, 3.663093820e-01, 3.723112797e-01, 3.784141650e-01, 3.846228077e-01, 3.909423406e-01, 3.973782989e-01, 4.039366650e-01, 4.106239205e-01, 4.174471056e-01, 4.244138880e-01, 4.315326429e-01, 4.388125467e-01, 4.462636868e-01, 4.538971911e-01, 4.617253825e-01, 4.697619638e-01, 4.780222397e-01, 4.865233873e-01, 4.952847879e-01, 5.043284360e-01, 5.136794521e-01, 5.233667293e-01, 5.334237613e-01, 5.438897175e-01, 5.548108582e-01, 5.662424343e-01, 5.782512864e-01, 5.909194836e-01, 6.043495569e-01, 6.186722632e-01, 6.340585441e-01, 6.507387983e-01, 6.690357417e-01, 6.894246183e-01, 7.126546234e-01, 7.400290923e-01, 7.742009798e-01, 8.224738122e-01, 1.000000000e+00, 0.000000000e+00, 2.827441263e-04, 5.309614341e-04, 7.676889192e-04, 9.972822069e-04, 1.221734232e-03, 1.442189052e-03, 1.659387712e-03, 1.873848346e-03, 2.085952989e-03, 2.295994583e-03, 2.504204628e-03, 2.710770500e-03, 2.915846842e-03, 3.119563366e-03, 3.322030365e-03, 3.523342719e-03, 3.723582879e-03, 3.922823127e-03, 4.121127328e-03, 4.318552295e-03, 4.515148887e-03, 4.710962881e-03, 4.906035691e-03, 5.100404952e-03, 5.294105008e-03, 5.487167322e-03, 5.679620815e-03, 5.871492159e-03, 6.062806029e-03, 6.253585311e-03, 6.443851288e-03, 6.633623805e-03, 6.822921401e-03, 7.011761435e-03, 7.200160194e-03, 7.388132989e-03, 7.575694233e-03, 7.762857525e-03, 7.949635709e-03, 8.136040937e-03, 8.322084723e-03, 8.507777990e-03, 8.693131115e-03, 8.878153968e-03, 9.062855945e-03, 9.247246005e-03, 9.431332697e-03, 9.615124187e-03, 9.798628284e-03, 9.981852461e-03, 1.016480388e-02, 1.034748939e-02, 1.052991560e-02, 1.071208882e-02, 1.089401513e-02, 1.107570038e-02, 1.125715019e-02, 1.143836999e-02, 1.161936499e-02, 1.180014022e-02, 1.198070056e-02, 1.216105069e-02, 1.234119514e-02, 1.252113830e-02, 1.270088440e-02, 1.288043754e-02, 1.305980169e-02, 1.323898070e-02, 1.341797829e-02, 1.359679808e-02, 1.377544357e-02, 1.395391815e-02, 1.413222514e-02, 1.431036773e-02, 1.448834904e-02, 1.466617210e-02, 1.484383985e-02, 1.502135515e-02, 1.519872080e-02, 1.537593950e-02, 1.555301389e-02, 1.572994655e-02, 1.590673998e-02, 1.608339663e-02, 1.625991888e-02, 1.643630905e-02, 1.661256940e-02, 1.678870216e-02, 1.696470947e-02, 1.714059345e-02, 1.731635616e-02, 1.749199960e-02, 1.766752575e-02, 1.784293652e-02, 1.801823379e-02, 1.819341940e-02, 1.836849515e-02, 1.854346279e-02, 1.871832405e-02, 1.889308061e-02, 1.906773411e-02, 1.924228618e-02, 1.941673839e-02, 1.959109229e-02, 1.976534941e-02, 1.993951122e-02, 2.011357919e-02, 2.028755475e-02, 2.046143931e-02, 2.063523422e-02, 2.080894086e-02, 2.098256053e-02, 2.115609454e-02, 2.132954416e-02, 2.150291065e-02, 2.167619524e-02, 2.184939913e-02, 2.202252350e-02, 2.219556953e-02, 2.236853835e-02, 2.254143110e-02, 2.271424887e-02, 2.288699276e-02, 2.305966382e-02, 2.323226311e-02, 2.340479167e-02, 2.357725051e-02, 2.374964062e-02, 6.614969627e-01, 6.624223679e-01, 6.633524863e-01, 6.642873798e-01, 6.652271120e-01, 6.661717474e-01, 6.671213522e-01, 6.680759940e-01, 6.690357417e-01, 6.700006659e-01, 6.709708389e-01, 6.719463343e-01, 6.729272276e-01, 6.739135960e-01, 6.749055184e-01, 6.759030757e-01, 6.769063506e-01, 6.779154277e-01, 6.789303938e-01, 6.799513376e-01, 6.809783501e-01, 6.820115246e-01, 6.830509566e-01, 6.840967440e-01, 6.851489872e-01, 6.862077892e-01, 6.872732556e-01, 6.883454949e-01, 6.894246183e-01, 6.905107401e-01, 6.916039775e-01, 6.927044510e-01, 6.938122844e-01, 6.949276049e-01, 6.960505433e-01, 6.971812341e-01, 6.983198156e-01, 6.994664302e-01, 7.006212244e-01, 7.017843491e-01, 7.029559595e-01, 7.041362158e-01, 7.053252829e-01, 7.065233309e-01, 7.077305352e-01, 7.089470768e-01, 7.101731424e-01, 7.114089249e-01, 7.126546234e-01, 7.139104438e-01, 7.151765989e-01, 7.164533086e-01, 7.177408006e-01, 7.190393106e-01, 7.203490826e-01, 7.216703692e-01, 7.230034327e-01, 7.243485446e-01, 7.257059869e-01, 7.270760523e-01, 7.284590447e-01, 7.298552800e-01, 7.312650868e-01, 7.326888066e-01, 7.341267954e-01, 7.355794237e-01, 7.370470777e-01, 7.385301604e-01, 7.400290923e-01, 7.415443126e-01, 7.430762805e-01, 7.446254761e-01, 7.461924021e-01, 7.477775853e-01, 7.493815778e-01, 7.510049592e-01, 7.526483383e-01, 7.543123551e-01, 7.559976831e-01, 7.577050318e-01, 7.594351494e-01, 7.611888259e-01, 7.629668959e-01, 7.647702428e-01, 7.665998025e-01, 7.684565674e-01, 7.703415920e-01, 7.722559979e-01, 7.742009798e-01, 7.761778124e-01, 7.781878579e-01, 7.802325744e-01, 7.823135256e-01, 7.844323916e-01, 7.865909811e-01, 7.887912453e-01, 7.910352942e-01, 7.933254144e-01, 7.956640905e-01, 7.980540294e-01, 8.004981888e-01, 8.029998100e-01, 8.055624571e-01, 8.081900628e-01, 8.108869830e-01, 8.136580625e-01, 8.165087134e-01, 8.194450113e-01, 8.224738122e-01, 8.256028983e-01, 8.288411587e-01, 8.321988194e-01, 8.356877362e-01, 8.393217759e-01, 8.431173179e-01, 8.470939272e-01, 8.512752763e-01, 8.556904349e-01, 8.603757250e-01, 8.653774745e-01, 8.707562571e-01, 8.765937281e-01, 8.830042789e-01, 8.901563967e-01, 8.983157447e-01, 9.079445898e-01, 9.199841476e-01, 9.370265573e-01, 1.000000000e+00, }; const float dist_icdf_0_5[] = { 0.000000000e+00, 1.018114730e-03, 2.447577757e-03, 4.090490249e-03, 5.890934762e-03, 7.819702758e-03, 9.858497479e-03, 1.199468311e-02, 1.421897836e-02, 1.652426967e-02, 1.890493304e-02, 2.135641640e-02, 2.387496739e-02, 2.645744780e-02, 2.910120255e-02, 3.180396430e-02, 3.456378239e-02, 3.737896864e-02, 4.024805539e-02, 4.316976240e-02, 4.614297046e-02, 4.916670001e-02, 5.224009373e-02, 5.536240216e-02, 5.853297174e-02, 6.175123485e-02, 6.501670131e-02, 6.832895130e-02, 7.168762928e-02, 7.509243873e-02, 7.854313775e-02, 8.203953521e-02, 8.558148741e-02, 8.916889531e-02, 9.280170199e-02, 9.647989060e-02, 1.002034825e-01, 1.039725357e-01, 1.077871436e-01, 1.116474338e-01, 1.155535673e-01, 1.195057376e-01, 1.235041700e-01, 1.275491216e-01, 1.316408803e-01, 1.357797652e-01, 1.399661263e-01, 1.442003443e-01, 1.484828310e-01, 1.528140295e-01, 1.571944143e-01, 1.616244922e-01, 1.661048023e-01, 1.706359169e-01, 1.752184425e-01, 1.798530199e-01, 1.845403259e-01, 1.892810740e-01, 1.940760156e-01, 1.989259413e-01, 2.038316821e-01, 2.087941115e-01, 2.138141466e-01, 2.188927501e-01, 2.240309325e-01, 2.292297540e-01, 2.344903268e-01, 2.398138180e-01, 2.452014519e-01, 2.506545133e-01, 2.561743506e-01, 2.617623790e-01, 2.674200851e-01, 2.731490300e-01, 2.789508547e-01, 2.848272843e-01, 2.907801337e-01, 2.968113131e-01, 3.029228345e-01, 3.091168186e-01, 3.153955022e-01, 3.217612466e-01, 3.282165467e-01, 3.347640407e-01, 3.414065214e-01, 3.481469485e-01, 3.549884613e-01, 3.619343947e-01, 3.689882947e-01, 3.761539374e-01, 3.834353497e-01, 3.908368320e-01, 3.983629845e-01, 4.060187359e-01, 4.138093769e-01, 4.217405974e-01, 4.298185290e-01, 4.380497936e-01, 4.464415593e-01, 4.550016046e-01, 4.637383928e-01, 4.726611579e-01, 4.817800062e-01, 4.911060348e-01, 5.006514717e-01, 5.104298430e-01, 5.204561730e-01, 5.307472260e-01, 5.413218004e-01, 5.522010904e-01, 5.634091346e-01, 5.749733794e-01, 5.869253929e-01, 5.993017859e-01, 6.121454129e-01, 6.255069703e-01, 6.394471608e-01, 6.540396919e-01, 6.693755400e-01, 6.855691975e-01, 7.027681651e-01, 7.211680193e-01, 7.410376703e-01, 7.627647521e-01, 7.869450991e-01, 8.145835948e-01, 8.476444412e-01, 8.912175164e-01, 1.000000000e+00, 0.000000000e+00, 2.305193561e-05, 5.537266463e-05, 9.245485435e-05, 1.330132332e-04, 1.763701639e-04, 2.220967632e-04, 2.698934464e-04, 3.195373823e-04, 3.708554146e-04, 4.237085659e-04, 4.779824786e-04, 5.335811724e-04, 5.904227827e-04, 6.484365446e-04, 7.075605930e-04, 7.677403191e-04, 8.289271148e-04, 8.910773963e-04, 9.541518332e-04, 1.018114730e-03, 1.082933522e-03, 1.148578370e-03, 1.215021812e-03, 1.282238481e-03, 1.350204864e-03, 1.418899101e-03, 1.488300802e-03, 1.558390906e-03, 1.629151545e-03, 1.700565930e-03, 1.772618256e-03, 1.845293613e-03, 1.918577907e-03, 1.992457794e-03, 2.066920620e-03, 2.141954364e-03, 2.217547593e-03, 2.293689415e-03, 2.370369443e-03, 2.447577757e-03, 2.525304872e-03, 2.603541711e-03, 2.682279576e-03, 2.761510126e-03, 2.841225351e-03, 2.921417557e-03, 3.002079341e-03, 3.083203580e-03, 3.164783411e-03, 3.246812217e-03, 3.329283615e-03, 3.412191444e-03, 3.495529747e-03, 3.579292771e-03, 3.663474947e-03, 3.748070885e-03, 3.833075366e-03, 3.918483332e-03, 4.004289878e-03, 4.090490249e-03, 4.177079825e-03, 4.264054125e-03, 4.351408791e-03, 4.439139591e-03, 4.527242409e-03, 4.615713239e-03, 4.704548185e-03, 4.793743453e-03, 4.883295347e-03, 4.973200267e-03, 5.063454704e-03, 5.154055237e-03, 5.244998528e-03, 5.336281320e-03, 5.427900437e-03, 5.519852774e-03, 5.612135302e-03, 5.704745061e-03, 5.797679157e-03, 5.890934762e-03, 5.984509112e-03, 6.078399503e-03, 6.172603289e-03, 6.267117881e-03, 6.361940745e-03, 6.457069402e-03, 6.552501422e-03, 6.648234424e-03, 6.744266079e-03, 6.840594102e-03, 6.937216254e-03, 7.034130340e-03, 7.131334207e-03, 7.228825745e-03, 7.326602883e-03, 7.424663588e-03, 7.523005868e-03, 7.621627764e-03, 7.720527356e-03, 7.819702758e-03, 7.919152117e-03, 8.018873612e-03, 8.118865458e-03, 8.219125896e-03, 8.319653201e-03, 8.420445677e-03, 8.521501656e-03, 8.622819498e-03, 8.724397591e-03, 8.826234350e-03, 8.928328214e-03, 9.030677649e-03, 9.133281146e-03, 9.236137220e-03, 9.339244408e-03, 9.442601272e-03, 9.546206395e-03, 9.650058383e-03, 9.754155861e-03, 9.858497479e-03, 9.963081904e-03, 1.006790782e-02, 1.017297395e-02, 1.027827900e-02, 1.038382173e-02, 1.048960090e-02, 1.059561528e-02, 1.070186369e-02, 7.328920314e-01, 7.338950798e-01, 7.349023549e-01, 7.359139073e-01, 7.369297885e-01, 7.379500512e-01, 7.389747491e-01, 7.400039368e-01, 7.410376703e-01, 7.420760067e-01, 7.431190043e-01, 7.441667225e-01, 7.452192224e-01, 7.462765658e-01, 7.473388164e-01, 7.484060390e-01, 7.494782999e-01, 7.505556671e-01, 7.516382097e-01, 7.527259988e-01, 7.538191070e-01, 7.549176085e-01, 7.560215793e-01, 7.571310973e-01, 7.582462421e-01, 7.593670954e-01, 7.604937406e-01, 7.616262636e-01, 7.627647521e-01, 7.639092961e-01, 7.650599878e-01, 7.662169221e-01, 7.673801958e-01, 7.685499089e-01, 7.697261634e-01, 7.709090645e-01, 7.720987200e-01, 7.732952407e-01, 7.744987406e-01, 7.757093368e-01, 7.769271495e-01, 7.781523027e-01, 7.793849237e-01, 7.806251437e-01, 7.818730977e-01, 7.831289247e-01, 7.843927681e-01, 7.856647754e-01, 7.869450991e-01, 7.882338960e-01, 7.895313284e-01, 7.908375635e-01, 7.921527739e-01, 7.934771383e-01, 7.948108411e-01, 7.961540731e-01, 7.975070315e-01, 7.988699205e-01, 8.002429518e-01, 8.016263443e-01, 8.030203251e-01, 8.044251298e-01, 8.058410026e-01, 8.072681971e-01, 8.087069770e-01, 8.101576160e-01, 8.116203991e-01, 8.130956224e-01, 8.145835948e-01, 8.160846378e-01, 8.175990867e-01, 8.191272914e-01, 8.206696173e-01, 8.222264463e-01, 8.237981776e-01, 8.253852292e-01, 8.269880389e-01, 8.286070659e-01, 8.302427919e-01, 8.318957231e-01, 8.335663915e-01, 8.352553572e-01, 8.369632105e-01, 8.386905739e-01, 8.404381048e-01, 8.422064985e-01, 8.439964910e-01, 8.458088625e-01, 8.476444412e-01, 8.495041079e-01, 8.513888001e-01, 8.532995179e-01, 8.552373296e-01, 8.572033784e-01, 8.591988902e-01, 8.612251822e-01, 8.632836724e-01, 8.653758910e-01, 8.675034929e-01, 8.696682731e-01, 8.718721829e-01, 8.741173506e-01, 8.764061039e-01, 8.787409977e-01, 8.811248460e-01, 8.835607606e-01, 8.860521966e-01, 8.886030082e-01, 8.912175164e-01, 8.939005915e-01, 8.966577567e-01, 8.994953173e-01, 9.024205244e-01, 9.054417870e-01, 9.085689472e-01, 9.118136479e-01, 9.151898297e-01, 9.187144200e-01, 9.224083122e-01, 9.262978018e-01, 9.304167668e-01, 9.348101309e-01, 9.395396669e-01, 9.446944290e-01, 9.504113165e-01, 9.569212379e-01, 9.646755908e-01, 9.748442279e-01, 1.000000000e+00, }; const float dist_icdf_0_6[] = { 0.000000000e+00, 1.172340652e-04, 4.021646897e-04, 8.271706545e-04, 1.379870657e-03, 2.052359069e-03, 2.838935565e-03, 3.735208528e-03, 4.737649774e-03, 5.843341990e-03, 7.049822176e-03, 8.354978198e-03, 9.756977052e-03, 1.125421317e-02, 1.284527004e-02, 1.452889094e-02, 1.630395620e-02, 1.816946515e-02, 2.012452166e-02, 2.216832231e-02, 2.430014665e-02, 2.651934910e-02, 2.882535217e-02, 3.121764067e-02, 3.369575685e-02, 3.625929617e-02, 3.890790372e-02, 4.164127112e-02, 4.445913378e-02, 4.736126860e-02, 5.034749195e-02, 5.341765787e-02, 5.657165654e-02, 5.980941299e-02, 6.313088592e-02, 6.653606673e-02, 7.002497867e-02, 7.359767614e-02, 7.725424408e-02, 8.099479753e-02, 8.481948121e-02, 8.872846927e-02, 9.272196506e-02, 9.680020106e-02, 1.009634388e-01, 1.052119690e-01, 1.095461116e-01, 1.139662159e-01, 1.184726610e-01, 1.230658561e-01, 1.277462407e-01, 1.325142854e-01, 1.373704923e-01, 1.423153954e-01, 1.473495619e-01, 1.524735922e-01, 1.576881214e-01, 1.629938202e-01, 1.683913954e-01, 1.738815916e-01, 1.794651922e-01, 1.851430207e-01, 1.909159423e-01, 1.967848651e-01, 2.027507423e-01, 2.088145736e-01, 2.149774072e-01, 2.212403422e-01, 2.276045306e-01, 2.340711797e-01, 2.406415551e-01, 2.473169831e-01, 2.540988542e-01, 2.609886263e-01, 2.679878281e-01, 2.750980633e-01, 2.823210147e-01, 2.896584487e-01, 2.971122208e-01, 3.046842801e-01, 3.123766762e-01, 3.201915649e-01, 3.281312158e-01, 3.361980196e-01, 3.443944968e-01, 3.527233069e-01, 3.611872585e-01, 3.697893208e-01, 3.785326358e-01, 3.874205322e-01, 3.964565406e-01, 4.056444108e-01, 4.149881302e-01, 4.244919458e-01, 4.341603875e-01, 4.439982951e-01, 4.540108486e-01, 4.642036030e-01, 4.745825269e-01, 4.851540477e-01, 4.959251028e-01, 5.069031989e-01, 5.180964806e-01, 5.295138106e-01, 5.411648636e-01, 5.530602362e-01, 5.652115788e-01, 5.776317520e-01, 5.903350160e-01, 6.033372597e-01, 6.166562829e-01, 6.303121455e-01, 6.443276052e-01, 6.587286739e-01, 6.735453343e-01, 6.888124785e-01, 7.045711594e-01, 7.208702962e-01, 7.377690553e-01, 7.553402709e-01, 7.736755330e-01, 7.928930756e-01, 8.131506561e-01, 8.346680215e-01, 8.577696864e-01, 8.829770436e-01, 9.112476744e-01, 9.448477179e-01, 1.000000000e+00, 0.000000000e+00, 5.694358136e-07, 1.953261497e-06, 4.016983988e-06, 6.700024794e-06, 9.963453256e-06, 1.377896926e-05, 1.812455522e-05, 2.298231823e-05, 2.833726704e-05, 3.417655444e-05, 4.048897702e-05, 4.726462846e-05, 5.449464977e-05, 6.217104388e-05, 7.028653437e-05, 7.883445544e-05, 8.780866481e-05, 9.720347348e-05, 1.070135884e-04, 1.172340652e-04, 1.278602684e-04, 1.388878385e-04, 1.503126630e-04, 1.621308526e-04, 1.743387201e-04, 1.869327617e-04, 1.999096416e-04, 2.132661780e-04, 2.269993301e-04, 2.411061878e-04, 2.555839617e-04, 2.704299740e-04, 2.856416513e-04, 3.012165168e-04, 3.171521844e-04, 3.334463528e-04, 3.500968001e-04, 3.671013791e-04, 3.844580125e-04, 4.021646897e-04, 4.202194622e-04, 4.386204407e-04, 4.573657920e-04, 4.764537355e-04, 4.958825413e-04, 5.156505272e-04, 5.357560563e-04, 5.561975354e-04, 5.769734122e-04, 5.980821741e-04, 6.195223462e-04, 6.412924893e-04, 6.633911989e-04, 6.858171036e-04, 7.085688635e-04, 7.316451690e-04, 7.550447398e-04, 7.787663236e-04, 8.028086949e-04, 8.271706545e-04, 8.518510276e-04, 8.768486639e-04, 9.021624361e-04, 9.277912394e-04, 9.537339902e-04, 9.799896263e-04, 1.006557105e-03, 1.033435404e-03, 1.060623519e-03, 1.088120464e-03, 1.115925272e-03, 1.144036990e-03, 1.172454685e-03, 1.201177438e-03, 1.230204347e-03, 1.259534523e-03, 1.289167094e-03, 1.319101201e-03, 1.349335999e-03, 1.379870657e-03, 1.410704356e-03, 1.441836291e-03, 1.473265668e-03, 1.504991707e-03, 1.537013637e-03, 1.569330702e-03, 1.601942153e-03, 1.634847256e-03, 1.668045285e-03, 1.701535524e-03, 1.735317268e-03, 1.769389823e-03, 1.803752503e-03, 1.838404631e-03, 1.873345540e-03, 1.908574572e-03, 1.944091078e-03, 1.979894417e-03, 2.015983955e-03, 2.052359069e-03, 2.089019141e-03, 2.125963564e-03, 2.163191736e-03, 2.200703063e-03, 2.238496959e-03, 2.276572844e-03, 2.314930147e-03, 2.353568301e-03, 2.392486749e-03, 2.431684938e-03, 2.471162322e-03, 2.510918362e-03, 2.550952525e-03, 2.591264284e-03, 2.631853117e-03, 2.672718510e-03, 2.713859952e-03, 2.755276940e-03, 2.796968976e-03, 2.838935565e-03, 2.881176221e-03, 2.923690462e-03, 2.966477808e-03, 3.009537789e-03, 3.052869937e-03, 3.096473790e-03, 3.140348888e-03, 3.184494781e-03, 8.049105078e-01, 8.059301109e-01, 8.069526314e-01, 8.079780978e-01, 8.090065392e-01, 8.100379853e-01, 8.110724662e-01, 8.121100127e-01, 8.131506561e-01, 8.141944284e-01, 8.152413620e-01, 8.162914902e-01, 8.173448468e-01, 8.184014662e-01, 8.194613836e-01, 8.205246349e-01, 8.215912567e-01, 8.226612862e-01, 8.237347617e-01, 8.248117219e-01, 8.258922067e-01, 8.269762565e-01, 8.280639127e-01, 8.291552178e-01, 8.302502149e-01, 8.313489481e-01, 8.324514627e-01, 8.335578047e-01, 8.346680215e-01, 8.357821612e-01, 8.369002734e-01, 8.380224085e-01, 8.391486183e-01, 8.402789558e-01, 8.414134752e-01, 8.425522321e-01, 8.436952834e-01, 8.448426874e-01, 8.459945041e-01, 8.471507947e-01, 8.483116222e-01, 8.494770510e-01, 8.506471474e-01, 8.518219795e-01, 8.530016170e-01, 8.541861317e-01, 8.553755973e-01, 8.565700896e-01, 8.577696864e-01, 8.589744680e-01, 8.601845168e-01, 8.613999175e-01, 8.626207578e-01, 8.638471275e-01, 8.650791195e-01, 8.663168294e-01, 8.675603558e-01, 8.688098006e-01, 8.700652688e-01, 8.713268689e-01, 8.725947131e-01, 8.738689172e-01, 8.751496011e-01, 8.764368888e-01, 8.777309086e-01, 8.790317936e-01, 8.803396816e-01, 8.816547155e-01, 8.829770436e-01, 8.843068198e-01, 8.856442042e-01, 8.869893628e-01, 8.883424688e-01, 8.897037022e-01, 8.910732504e-01, 8.924513091e-01, 8.938380822e-01, 8.952337828e-01, 8.966386333e-01, 8.980528667e-01, 8.994767266e-01, 9.009104685e-01, 9.023543601e-01, 9.038086828e-01, 9.052737321e-01, 9.067498191e-01, 9.082372715e-01, 9.097364349e-01, 9.112476744e-01, 9.127713758e-01, 9.143079480e-01, 9.158578245e-01, 9.174214658e-01, 9.189993618e-01, 9.205920347e-01, 9.222000421e-01, 9.238239805e-01, 9.254644892e-01, 9.271222552e-01, 9.287980184e-01, 9.304925774e-01, 9.322067966e-01, 9.339416143e-01, 9.356980523e-01, 9.374772266e-01, 9.392803607e-01, 9.411088012e-01, 9.429640363e-01, 9.448477179e-01, 9.467616896e-01, 9.487080196e-01, 9.506890424e-01, 9.527074116e-01, 9.547661657e-01, 9.568688141e-01, 9.590194500e-01, 9.612229003e-01, 9.634849308e-01, 9.658125334e-01, 9.682143389e-01, 9.707012325e-01, 9.732873098e-01, 9.759914408e-01, 9.788400043e-01, 9.818721051e-01, 9.851508371e-01, 9.887926216e-01, 9.930744994e-01, 1.000000000e+00, }; const float dist_icdf_0_7[] = { 0.000000000e+00, 4.586558125e-06, 2.646347167e-05, 7.377292896e-05, 1.526888560e-04, 2.684396949e-04, 4.256561038e-04, 6.285447692e-04, 8.809908037e-04, 1.186624293e-03, 1.548866513e-03, 1.970963608e-03, 2.456012062e-03, 3.006978519e-03, 3.626715580e-03, 4.317974644e-03, 5.083416509e-03, 5.925620257e-03, 6.847090789e-03, 7.850265279e-03, 8.937518763e-03, 1.011116901e-02, 1.137348080e-02, 1.272666973e-02, 1.417290556e-02, 1.571431527e-02, 1.735298574e-02, 1.909096624e-02, 2.093027063e-02, 2.287287942e-02, 2.492074165e-02, 2.707577653e-02, 2.933987510e-02, 3.171490163e-02, 3.420269500e-02, 3.680506996e-02, 3.952381827e-02, 4.236070985e-02, 4.531749375e-02, 4.839589916e-02, 5.159763631e-02, 5.492439731e-02, 5.837785700e-02, 6.195967369e-02, 6.567148991e-02, 6.951493309e-02, 7.349161627e-02, 7.760313868e-02, 8.185108643e-02, 8.623703301e-02, 9.076253994e-02, 9.542915726e-02, 1.002384241e-01, 1.051918691e-01, 1.102910112e-01, 1.155373597e-01, 1.209324150e-01, 1.264776690e-01, 1.321746058e-01, 1.380247017e-01, 1.440294259e-01, 1.501902410e-01, 1.565086032e-01, 1.629859632e-01, 1.696237661e-01, 1.764234520e-01, 1.833864566e-01, 1.905142116e-01, 1.978081451e-01, 2.052696818e-01, 2.129002440e-01, 2.207012515e-01, 2.286741225e-01, 2.368202738e-01, 2.451411216e-01, 2.536380817e-01, 2.623125702e-01, 2.711660042e-01, 2.801998019e-01, 2.894153839e-01, 2.988141733e-01, 3.083975965e-01, 3.181670841e-01, 3.281240715e-01, 3.382699996e-01, 3.486063158e-01, 3.591344750e-01, 3.698559403e-01, 3.807721844e-01, 3.918846903e-01, 4.031949531e-01, 4.147044806e-01, 4.264147957e-01, 4.383274371e-01, 4.504439617e-01, 4.627659460e-01, 4.752949890e-01, 4.880327136e-01, 5.009807703e-01, 5.141408395e-01, 5.275146350e-01, 5.411039080e-01, 5.549104513e-01, 5.689361044e-01, 5.831827591e-01, 5.976523660e-01, 6.123469423e-01, 6.272685811e-01, 6.424194615e-01, 6.578018618e-01, 6.734181744e-01, 6.892709246e-01, 7.053627930e-01, 7.216966442e-01, 7.382755619e-01, 7.551028944e-01, 7.721823141e-01, 7.895178952e-01, 8.071142202e-01, 8.249765284e-01, 8.431109289e-01, 8.615247198e-01, 8.802268893e-01, 8.992289526e-01, 9.185464667e-01, 9.382021046e-01, 9.582330668e-01, 9.787153834e-01, 1.000000000e+00, 0.000000000e+00, 2.354013782e-09, 1.358215835e-08, 3.786332271e-08, 7.836616211e-08, 1.377740100e-07, 2.184633114e-07, 3.225928083e-07, 4.521560734e-07, 6.090156427e-07, 7.949267127e-07, 1.011554405e-06, 1.260486813e-06, 1.543245157e-06, 1.861291862e-06, 2.216037130e-06, 2.608844355e-06, 3.041034659e-06, 3.513890735e-06, 4.028660139e-06, 4.586558125e-06, 5.188770128e-06, 5.836453932e-06, 6.530741593e-06, 7.272741140e-06, 8.063538102e-06, 8.904196874e-06, 9.795761953e-06, 1.073925905e-05, 1.173569612e-05, 1.278606426e-05, 1.389133859e-05, 1.505247901e-05, 1.627043094e-05, 1.754612596e-05, 1.888048240e-05, 2.027440599e-05, 2.172879030e-05, 2.324451729e-05, 2.482245773e-05, 2.646347167e-05, 2.816840880e-05, 2.993810888e-05, 3.177340205e-05, 3.367510918e-05, 3.564404219e-05, 3.768100434e-05, 3.978679053e-05, 4.196218754e-05, 4.420797430e-05, 4.652492213e-05, 4.891379495e-05, 5.137534953e-05, 5.391033566e-05, 5.651949637e-05, 5.920356811e-05, 6.196328091e-05, 6.479935860e-05, 6.771251891e-05, 7.070347367e-05, 7.377292896e-05, 7.692158522e-05, 8.015013742e-05, 8.345927518e-05, 8.684968289e-05, 9.032203983e-05, 9.387702031e-05, 9.751529377e-05, 1.012375249e-04, 1.050443736e-04, 1.089364954e-04, 1.129145413e-04, 1.169791579e-04, 1.211309875e-04, 1.253706683e-04, 1.296988343e-04, 1.341161155e-04, 1.386231380e-04, 1.432205239e-04, 1.479088917e-04, 1.526888560e-04, 1.575610279e-04, 1.625260147e-04, 1.675844204e-04, 1.727368454e-04, 1.779838867e-04, 1.833261381e-04, 1.887641899e-04, 1.942986293e-04, 1.999300404e-04, 2.056590040e-04, 2.114860979e-04, 2.174118971e-04, 2.234369732e-04, 2.295618953e-04, 2.357872294e-04, 2.421135386e-04, 2.485413834e-04, 2.550713215e-04, 2.617039079e-04, 2.684396949e-04, 2.752792321e-04, 2.822230667e-04, 2.892717432e-04, 2.964258037e-04, 3.036857878e-04, 3.110522326e-04, 3.185256728e-04, 3.261066408e-04, 3.337956666e-04, 3.415932780e-04, 3.495000003e-04, 3.575163568e-04, 3.656428685e-04, 3.738800540e-04, 3.822284302e-04, 3.906885114e-04, 3.992608101e-04, 4.079458365e-04, 4.167440990e-04, 4.256561038e-04, 4.346823552e-04, 4.438233554e-04, 4.530796047e-04, 4.624516015e-04, 4.719398424e-04, 4.815448219e-04, 4.912670327e-04, 5.011069658e-04, 8.727107489e-01, 8.736476726e-01, 8.745853344e-01, 8.755237357e-01, 8.764628781e-01, 8.774027631e-01, 8.783433923e-01, 8.792847671e-01, 8.802268893e-01, 8.811697604e-01, 8.821133821e-01, 8.830577560e-01, 8.840028839e-01, 8.849487674e-01, 8.858954083e-01, 8.868428083e-01, 8.877909694e-01, 8.887398932e-01, 8.896895816e-01, 8.906400366e-01, 8.915912600e-01, 8.925432539e-01, 8.934960201e-01, 8.944495607e-01, 8.954038777e-01, 8.963589733e-01, 8.973148495e-01, 8.982715086e-01, 8.992289526e-01, 9.001871839e-01, 9.011462047e-01, 9.021060174e-01, 9.030666242e-01, 9.040280277e-01, 9.049902302e-01, 9.059532343e-01, 9.069170426e-01, 9.078816575e-01, 9.088470819e-01, 9.098133183e-01, 9.107803696e-01, 9.117482386e-01, 9.127169282e-01, 9.136864412e-01, 9.146567808e-01, 9.156279499e-01, 9.165999518e-01, 9.175727896e-01, 9.185464667e-01, 9.195209864e-01, 9.204963521e-01, 9.214725674e-01, 9.224496359e-01, 9.234275613e-01, 9.244063473e-01, 9.253859980e-01, 9.263665172e-01, 9.273479090e-01, 9.283301777e-01, 9.293133276e-01, 9.302973631e-01, 9.312822888e-01, 9.322681093e-01, 9.332548295e-01, 9.342424543e-01, 9.352309889e-01, 9.362204385e-01, 9.372108085e-01, 9.382021046e-01, 9.391943325e-01, 9.401874981e-01, 9.411816076e-01, 9.421766675e-01, 9.431726841e-01, 9.441696645e-01, 9.451676156e-01, 9.461665447e-01, 9.471664595e-01, 9.481673677e-01, 9.491692776e-01, 9.501721977e-01, 9.511761367e-01, 9.521811039e-01, 9.531871089e-01, 9.541941617e-01, 9.552022727e-01, 9.562114528e-01, 9.572217135e-01, 9.582330668e-01, 9.592455251e-01, 9.602591016e-01, 9.612738103e-01, 9.622896657e-01, 9.633066832e-01, 9.643248790e-01, 9.653442703e-01, 9.663648754e-01, 9.673867136e-01, 9.684098054e-01, 9.694341727e-01, 9.704598389e-01, 9.714868291e-01, 9.725151702e-01, 9.735448912e-01, 9.745760231e-01, 9.756085999e-01, 9.766426582e-01, 9.776782381e-01, 9.787153834e-01, 9.797541424e-01, 9.807945682e-01, 9.818367200e-01, 9.828806638e-01, 9.839264741e-01, 9.849742351e-01, 9.860240431e-01, 9.870760092e-01, 9.881302632e-01, 9.891869585e-01, 9.902462796e-01, 9.913084522e-01, 9.923737588e-01, 9.934425643e-01, 9.945153569e-01, 9.955928249e-01, 9.966760129e-01, 9.977667007e-01, 9.988686588e-01, 1.000000000e+00, }; const float dist_icdf_0_8[] = { 0.000000000e+00, 2.499558898e-16, 5.522325275e-14, 1.298450393e-12, 1.220058326e-11, 6.935268843e-11, 2.868692324e-10, 9.528604901e-10, 2.695499165e-09, 6.745083776e-09, 1.532222751e-08, 3.218590475e-08, 6.337858886e-08, 1.182091278e-07, 2.105173420e-07, 3.602675959e-07, 5.955218045e-07, 9.548454854e-07, 1.490203567e-06, 2.270405709e-06, 3.385163899e-06, 4.949828024e-06, 7.110868034e-06, 1.005217413e-05, 1.400224922e-05, 1.924237054e-05, 2.611580003e-05, 3.503812543e-05, 4.650881662e-05, 6.112408374e-05, 7.959112573e-05, 1.027438597e-04, 1.315602227e-04, 1.671811392e-04, 2.109312467e-04, 2.643414733e-04, 3.291735600e-04, 4.074466168e-04, 5.014658015e-04, 6.138532050e-04, 7.475810194e-04, 9.060070596e-04, 1.092912699e-03, 1.312543263e-03, 1.569650919e-03, 1.869540068e-03, 2.218115222e-03, 2.621931346e-03, 3.088246559e-03, 3.625077110e-03, 4.241254441e-03, 4.946484128e-03, 5.751406407e-03, 6.667657933e-03, 7.707934304e-03, 8.886052824e-03, 1.021701481e-02, 1.171706669e-02, 1.340375891e-02, 1.529600160e-02, 1.741411574e-02, 1.977987824e-02, 2.241655952e-02, 2.534895137e-02, 2.860338336e-02, 3.220772502e-02, 3.619137160e-02, 4.058521024e-02, 4.542156369e-02, 5.073410821e-02, 5.655776215e-02, 6.292854176e-02, 6.988338039e-02, 7.745990758e-02, 8.569618437e-02, 9.463039168e-02, 1.043004687e-01, 1.147436990e-01, 1.259962430e-01, 1.380926158e-01, 1.510651111e-01, 1.649431741e-01, 1.797527258e-01, 1.955154463e-01, 2.122480231e-01, 2.299613772e-01, 2.486598786e-01, 2.683405666e-01, 2.889923945e-01, 3.105955182e-01, 3.331206517e-01, 3.565285139e-01, 3.807693922e-01, 4.057828473e-01, 4.314975858e-01, 4.578315218e-01, 4.846920480e-01, 5.119765315e-01, 5.395730457e-01, 5.673613399e-01, 5.952140449e-01, 6.229981014e-01, 6.505763917e-01, 6.778095468e-01, 7.045578915e-01, 7.306834868e-01, 7.560522194e-01, 7.805358885e-01, 8.040142364e-01, 8.263768698e-01, 8.475250246e-01, 8.673731289e-01, 8.858501289e-01, 9.029005494e-01, 9.184852738e-01, 9.325820367e-01, 9.451856350e-01, 9.563078781e-01, 9.659773035e-01, 9.742387033e-01, 9.811525136e-01, 9.867941361e-01, 9.912532814e-01, 9.946334519e-01, 9.970517424e-01, 9.986392589e-01, 9.995427675e-01, 9.999291847e-01, 1.000000000e+00, 0.000000000e+00, 1.845636753e-26, 4.077602051e-24, 9.587562705e-23, 9.008727455e-22, 5.120898362e-21, 2.118199331e-20, 7.035778765e-20, 1.990316106e-19, 4.980468584e-19, 1.131370278e-18, 2.376558914e-18, 4.679779986e-18, 8.728385052e-18, 1.554428621e-17, 2.660162358e-17, 4.397245029e-17, 7.050439418e-17, 1.100344848e-16, 1.676435599e-16, 2.499558898e-16, 3.654888753e-16, 5.250578960e-16, 7.422415969e-16, 1.033913117e-15, 1.420842969e-15, 1.928379500e-15, 2.587213046e-15, 3.434230123e-15, 4.513464189e-15, 5.877149700e-15, 7.586886413e-15, 9.714921055e-15, 1.234555368e-14, 1.557667628e-14, 1.952145128e-14, 2.431013795e-14, 3.009207471e-14, 3.703782571e-14, 4.534150010e-14, 5.522325275e-14, 6.693197511e-14, 8.074818544e-14, 9.698712749e-14, 1.160020871e-13, 1.381879364e-13, 1.639849149e-13, 1.938826584e-13, 2.284244849e-13, 2.682119478e-13, 3.139096681e-13, 3.662504549e-13, 4.260407252e-13, 4.941662353e-13, 5.715981332e-13, 6.593993446e-13, 7.587313037e-13, 8.708610405e-13, 9.971686360e-13, 1.139155059e-12, 1.298450393e-12, 1.476822473e-12, 1.676185932e-12, 1.898611688e-12, 2.146336865e-12, 2.421775176e-12, 2.727527773e-12, 3.066394581e-12, 3.441386127e-12, 3.855735883e-12, 4.312913128e-12, 4.816636353e-12, 5.370887215e-12, 5.979925059e-12, 6.648302023e-12, 7.380878736e-12, 8.182840630e-12, 9.059714874e-12, 1.001738796e-11, 1.106212392e-11, 1.220058326e-11, 1.343984253e-11, 1.478741462e-11, 1.625126981e-11, 1.783985749e-11, 1.956212869e-11, 2.142755932e-11, 2.344617426e-11, 2.562857223e-11, 2.798595144e-11, 3.053013611e-11, 3.327360388e-11, 3.622951398e-11, 3.941173642e-11, 4.283488203e-11, 4.651433334e-11, 5.046627656e-11, 5.470773443e-11, 5.925660002e-11, 6.413167158e-11, 6.935268843e-11, 7.494036778e-11, 8.091644273e-11, 8.730370125e-11, 9.412602628e-11, 1.014084370e-10, 1.091771310e-10, 1.174595280e-10, 1.262843144e-10, 1.356814893e-10, 1.456824110e-10, 1.563198462e-10, 1.676280186e-10, 1.796426607e-10, 1.924010648e-10, 2.059421374e-10, 2.203064535e-10, 2.355363127e-10, 2.516757968e-10, 2.687708286e-10, 2.868692324e-10, 3.060207954e-10, 3.262773313e-10, 3.476927447e-10, 3.703230975e-10, 3.942266766e-10, 4.194640630e-10, 4.460982029e-10, 4.741944800e-10, 9.896052010e-01, 9.898208991e-01, 9.900338024e-01, 9.902439243e-01, 9.904512781e-01, 9.906558772e-01, 9.908577350e-01, 9.910568652e-01, 9.912532814e-01, 9.914469974e-01, 9.916380269e-01, 9.918263840e-01, 9.920120825e-01, 9.921951366e-01, 9.923755605e-01, 9.925533683e-01, 9.927285745e-01, 9.929011934e-01, 9.930712396e-01, 9.932387276e-01, 9.934036721e-01, 9.935660879e-01, 9.937259899e-01, 9.938833928e-01, 9.940383119e-01, 9.941907621e-01, 9.943407586e-01, 9.944883168e-01, 9.946334519e-01, 9.947761795e-01, 9.949165150e-01, 9.950544741e-01, 9.951900724e-01, 9.953233258e-01, 9.954542502e-01, 9.955828614e-01, 9.957091756e-01, 9.958332089e-01, 9.959549775e-01, 9.960744978e-01, 9.961917862e-01, 9.963068591e-01, 9.964197331e-01, 9.965304250e-01, 9.966389515e-01, 9.967453295e-01, 9.968495760e-01, 9.969517079e-01, 9.970517424e-01, 9.971496968e-01, 9.972455885e-01, 9.973394348e-01, 9.974312532e-01, 9.975210615e-01, 9.976088773e-01, 9.976947184e-01, 9.977786029e-01, 9.978605486e-01, 9.979405738e-01, 9.980186967e-01, 9.980949355e-01, 9.981693088e-01, 9.982418352e-01, 9.983125332e-01, 9.983814216e-01, 9.984485193e-01, 9.985138454e-01, 9.985774188e-01, 9.986392589e-01, 9.986993850e-01, 9.987578165e-01, 9.988145730e-01, 9.988696742e-01, 9.989231400e-01, 9.989749903e-01, 9.990252451e-01, 9.990739248e-01, 9.991210496e-01, 9.991666401e-01, 9.992107169e-01, 9.992533007e-01, 9.992944124e-01, 9.993340733e-01, 9.993723043e-01, 9.994091270e-01, 9.994445629e-01, 9.994786337e-01, 9.995113612e-01, 9.995427675e-01, 9.995728748e-01, 9.996017055e-01, 9.996292823e-01, 9.996556279e-01, 9.996807652e-01, 9.997047176e-01, 9.997275084e-01, 9.997491612e-01, 9.997696999e-01, 9.997891487e-01, 9.998075318e-01, 9.998248740e-01, 9.998412000e-01, 9.998565351e-01, 9.998709047e-01, 9.998843347e-01, 9.998968510e-01, 9.999084802e-01, 9.999192490e-01, 9.999291847e-01, 9.999383149e-01, 9.999466675e-01, 9.999542712e-01, 9.999611549e-01, 9.999673481e-01, 9.999728809e-01, 9.999777842e-01, 9.999820893e-01, 9.999858284e-01, 9.999890345e-01, 9.999917418e-01, 9.999939851e-01, 9.999958008e-01, 9.999972267e-01, 9.999983021e-01, 9.999990686e-01, 9.999995706e-01, 9.999998558e-01, 9.999999777e-01, 1.000000000e+00, }; const float dist_icdf_1_0[] = { 0.000000000e+00, 1.100527359e-01, 1.135849643e-01, 1.158490613e-01, 1.175626723e-01, 1.189624288e-01, 1.201575147e-01, 1.212078128e-01, 1.221499076e-01, 1.230078763e-01, 1.237984539e-01, 1.245337702e-01, 1.252229140e-01, 1.258728819e-01, 1.264891816e-01, 1.270762321e-01, 1.276376359e-01, 1.281763718e-01, 1.286949333e-01, 1.291954299e-01, 1.296796639e-01, 1.301491883e-01, 1.306053521e-01, 1.310493348e-01, 1.314821751e-01, 1.319047927e-01, 1.323180067e-01, 1.327225501e-01, 1.331190822e-01, 1.335081984e-01, 1.338904389e-01, 1.342662957e-01, 1.346362186e-01, 1.350006200e-01, 1.353598799e-01, 1.357143489e-01, 1.360643520e-01, 1.364101914e-01, 1.367521485e-01, 1.370904864e-01, 1.374254520e-01, 1.377572771e-01, 1.380861802e-01, 1.384123682e-01, 1.387360366e-01, 1.390573717e-01, 1.393765506e-01, 1.396937426e-01, 1.400091099e-01, 1.403228081e-01, 1.406349872e-01, 1.409457916e-01, 1.412553615e-01, 1.415638327e-01, 1.418713372e-01, 1.421780039e-01, 1.424839590e-01, 1.427893260e-01, 1.430942265e-01, 1.433987802e-01, 1.437031058e-01, 1.440073206e-01, 1.443115413e-01, 1.446158843e-01, 1.449204659e-01, 1.452254024e-01, 1.455308111e-01, 1.458368096e-01, 1.461435172e-01, 1.464510544e-01, 1.467595435e-01, 1.470691093e-01, 1.473798788e-01, 1.476919822e-01, 1.480055529e-01, 1.483207281e-01, 1.486376491e-01, 1.489564623e-01, 1.492773187e-01, 1.496003756e-01, 1.499257965e-01, 1.502537519e-01, 1.505844201e-01, 1.509179880e-01, 1.512546519e-01, 1.515946186e-01, 1.519381062e-01, 1.522853455e-01, 1.526365815e-01, 1.529920742e-01, 1.533521010e-01, 1.537169582e-01, 1.540869633e-01, 1.544624570e-01, 1.548438064e-01, 1.552314079e-01, 1.556256908e-01, 1.560271215e-01, 1.564362082e-01, 1.568535065e-01, 1.572796262e-01, 1.577152386e-01, 1.581610858e-01, 1.586179916e-01, 1.590868744e-01, 1.595687633e-01, 1.600648166e-01, 1.605763456e-01, 1.611048438e-01, 1.616520232e-01, 1.622198601e-01, 1.628106539e-01, 1.634271036e-01, 1.640724077e-01, 1.647503988e-01, 1.654657259e-01, 1.662241093e-01, 1.670327028e-01, 1.679006264e-01, 1.688397728e-01, 1.698660805e-01, 1.710016410e-01, 1.722784021e-01, 1.737451946e-01, 1.754824989e-01, 1.776382869e-01, 1.805367416e-01, 1.851768742e-01, 1.000000000e+00, 0.000000000e+00, 9.798423805e-02, 1.004320032e-01, 1.019449101e-01, 1.030587399e-01, 1.039476089e-01, 1.046910248e-01, 1.053322308e-01, 1.058974588e-01, 1.064038644e-01, 1.068633053e-01, 1.072843317e-01, 1.076733195e-01, 1.080351549e-01, 1.083736678e-01, 1.086919180e-01, 1.089923902e-01, 1.092771307e-01, 1.095478457e-01, 1.098059729e-01, 1.100527359e-01, 1.102891848e-01, 1.105162280e-01, 1.107346564e-01, 1.109451635e-01, 1.111483606e-01, 1.113447894e-01, 1.115349324e-01, 1.117192212e-01, 1.118980437e-01, 1.120717494e-01, 1.122406548e-01, 1.124050474e-01, 1.125651888e-01, 1.127213183e-01, 1.128736549e-01, 1.130224000e-01, 1.131677387e-01, 1.133098421e-01, 1.134488685e-01, 1.135849643e-01, 1.137182656e-01, 1.138488993e-01, 1.139769832e-01, 1.141026276e-01, 1.142259355e-01, 1.143470034e-01, 1.144659219e-01, 1.145827759e-01, 1.146976455e-01, 1.148106058e-01, 1.149217279e-01, 1.150310788e-01, 1.151387218e-01, 1.152447168e-01, 1.153491206e-01, 1.154519870e-01, 1.155533669e-01, 1.156533089e-01, 1.157518591e-01, 1.158490613e-01, 1.159449574e-01, 1.160395870e-01, 1.161329883e-01, 1.162251974e-01, 1.163162491e-01, 1.164061763e-01, 1.164950108e-01, 1.165827830e-01, 1.166695218e-01, 1.167552551e-01, 1.168400096e-01, 1.169238110e-01, 1.170066838e-01, 1.170886518e-01, 1.171697376e-01, 1.172499632e-01, 1.173293496e-01, 1.174079170e-01, 1.174856849e-01, 1.175626723e-01, 1.176388971e-01, 1.177143771e-01, 1.177891289e-01, 1.178631690e-01, 1.179365131e-01, 1.180091764e-01, 1.180811737e-01, 1.181525191e-01, 1.182232265e-01, 1.182933092e-01, 1.183627801e-01, 1.184316517e-01, 1.184999361e-01, 1.185676451e-01, 1.186347900e-01, 1.187013818e-01, 1.187674314e-01, 1.188329491e-01, 1.188979450e-01, 1.189624288e-01, 1.190264102e-01, 1.190898983e-01, 1.191529022e-01, 1.192154306e-01, 1.192774921e-01, 1.193390948e-01, 1.194002468e-01, 1.194609560e-01, 1.195212300e-01, 1.195810762e-01, 1.196405019e-01, 1.196995141e-01, 1.197581196e-01, 1.198163252e-01, 1.198741374e-01, 1.199315626e-01, 1.199886069e-01, 1.200452765e-01, 1.201015771e-01, 1.201575147e-01, 1.202130948e-01, 1.202683230e-01, 1.203232045e-01, 1.203777446e-01, 1.204319486e-01, 1.204858213e-01, 1.205393676e-01, 1.205925924e-01, 1.717481254e-01, 1.718128906e-01, 1.718780767e-01, 1.719436901e-01, 1.720097375e-01, 1.720762254e-01, 1.721431608e-01, 1.722105506e-01, 1.722784021e-01, 1.723467225e-01, 1.724155194e-01, 1.724848006e-01, 1.725545739e-01, 1.726248475e-01, 1.726956296e-01, 1.727669288e-01, 1.728387539e-01, 1.729111139e-01, 1.729840178e-01, 1.730574753e-01, 1.731314960e-01, 1.732060899e-01, 1.732812673e-01, 1.733570386e-01, 1.734334147e-01, 1.735104068e-01, 1.735880262e-01, 1.736662848e-01, 1.737451946e-01, 1.738247681e-01, 1.739050182e-01, 1.739859581e-01, 1.740676014e-01, 1.741499620e-01, 1.742330546e-01, 1.743168940e-01, 1.744014955e-01, 1.744868750e-01, 1.745730490e-01, 1.746600343e-01, 1.747478484e-01, 1.748365094e-01, 1.749260359e-01, 1.750164471e-01, 1.751077631e-01, 1.752000046e-01, 1.752931928e-01, 1.753873499e-01, 1.754824989e-01, 1.755786636e-01, 1.756758686e-01, 1.757741395e-01, 1.758735029e-01, 1.759739863e-01, 1.760756185e-01, 1.761784293e-01, 1.762824496e-01, 1.763877118e-01, 1.764942494e-01, 1.766020974e-01, 1.767112923e-01, 1.768218722e-01, 1.769338769e-01, 1.770473478e-01, 1.771623284e-01, 1.772788639e-01, 1.773970020e-01, 1.775167923e-01, 1.776382869e-01, 1.777615407e-01, 1.778866109e-01, 1.780135579e-01, 1.781424451e-01, 1.782733394e-01, 1.784063110e-01, 1.785414342e-01, 1.786787872e-01, 1.788184528e-01, 1.789605185e-01, 1.791050769e-01, 1.792522264e-01, 1.794020711e-01, 1.795547219e-01, 1.797102967e-01, 1.798689213e-01, 1.800307296e-01, 1.801958650e-01, 1.803644808e-01, 1.805367416e-01, 1.807128238e-01, 1.808929175e-01, 1.810772274e-01, 1.812659748e-01, 1.814593989e-01, 1.816577594e-01, 1.818613385e-01, 1.820704438e-01, 1.822854116e-01, 1.825066102e-01, 1.827344445e-01, 1.829693608e-01, 1.832118530e-01, 1.834624695e-01, 1.837218213e-01, 1.839905927e-01, 1.842695530e-01, 1.845595714e-01, 1.848616356e-01, 1.851768742e-01, 1.855065851e-01, 1.858522715e-01, 1.862156885e-01, 1.865989021e-01, 1.870043692e-01, 1.874350429e-01, 1.878945173e-01, 1.883872296e-01, 1.889187485e-01, 1.894961988e-01, 1.901289070e-01, 1.908294234e-01, 1.916152190e-01, 1.925116803e-01, 1.935578145e-01, 1.948182966e-01, 1.964128743e-01, 1.986061731e-01, 2.022235068e-01, 1.000000000e+00, }; const float dist_icdf_1_1[] = { 0.000000000e+00, 1.149786663e-01, 1.284674249e-01, 1.374687029e-01, 1.444580818e-01, 1.502765114e-01, 1.553196690e-01, 1.598078010e-01, 1.638770833e-01, 1.676180425e-01, 1.710941509e-01, 1.743517684e-01, 1.774258719e-01, 1.803435550e-01, 1.831262690e-01, 1.857913146e-01, 1.883528673e-01, 1.908227023e-01, 1.932107187e-01, 1.955253276e-01, 1.977737430e-01, 1.999622058e-01, 2.020961558e-01, 2.041803684e-01, 2.062190622e-01, 2.082159865e-01, 2.101744909e-01, 2.120975841e-01, 2.139879804e-01, 2.158481403e-01, 2.176803032e-01, 2.194865152e-01, 2.212686533e-01, 2.230284454e-01, 2.247674877e-01, 2.264872595e-01, 2.281891366e-01, 2.298744020e-01, 2.315442563e-01, 2.331998261e-01, 2.348421719e-01, 2.364722943e-01, 2.380911407e-01, 2.396996104e-01, 2.412985591e-01, 2.428888038e-01, 2.444711263e-01, 2.460462770e-01, 2.476149778e-01, 2.491779255e-01, 2.507357941e-01, 2.522892374e-01, 2.538388918e-01, 2.553853777e-01, 2.569293019e-01, 2.584712598e-01, 2.600118365e-01, 2.615516094e-01, 2.630911489e-01, 2.646310207e-01, 2.661717873e-01, 2.677140089e-01, 2.692582456e-01, 2.708050586e-01, 2.723550116e-01, 2.739086721e-01, 2.754666135e-01, 2.770294160e-01, 2.785976685e-01, 2.801719700e-01, 2.817529315e-01, 2.833411775e-01, 2.849373479e-01, 2.865421003e-01, 2.881561111e-01, 2.897800789e-01, 2.914147257e-01, 2.930608002e-01, 2.947190800e-01, 2.963903747e-01, 2.980755292e-01, 2.997754269e-01, 3.014909935e-01, 3.032232014e-01, 3.049730740e-01, 3.067416910e-01, 3.085301934e-01, 3.103397908e-01, 3.121717672e-01, 3.140274895e-01, 3.159084159e-01, 3.178161059e-01, 3.197522315e-01, 3.217185894e-01, 3.237171159e-01, 3.257499030e-01, 3.278192175e-01, 3.299275228e-01, 3.320775038e-01, 3.342720969e-01, 3.365145237e-01, 3.388083322e-01, 3.411574440e-01, 3.435662117e-01, 3.460394873e-01, 3.485827043e-01, 3.512019780e-01, 3.539042288e-01, 3.566973339e-01, 3.595903177e-01, 3.625935917e-01, 3.657192617e-01, 3.689815250e-01, 3.723971930e-01, 3.759863895e-01, 3.797735003e-01, 3.837884939e-01, 3.880688020e-01, 3.926620738e-01, 3.976303452e-01, 4.030566040e-01, 4.090556351e-01, 4.157930345e-01, 4.235211869e-01, 4.326546209e-01, 4.439521594e-01, 4.590664150e-01, 4.830426172e-01, 1.000000000e+00, 0.000000000e+00, 7.443910396e-02, 8.193164811e-02, 8.675320917e-02, 9.039464369e-02, 9.335579335e-02, 9.586964562e-02, 9.806491533e-02, 1.000206775e-01, 1.017892043e-01, 1.034069600e-01, 1.049004544e-01, 1.062896004e-01, 1.075897593e-01, 1.088130449e-01, 1.099691892e-01, 1.110661357e-01, 1.121104578e-01, 1.131076605e-01, 1.140624032e-01, 1.149786663e-01, 1.158598791e-01, 1.167090181e-01, 1.175286848e-01, 1.183211666e-01, 1.190884864e-01, 1.198324423e-01, 1.205546403e-01, 1.212565209e-01, 1.219393818e-01, 1.226043958e-01, 1.232526274e-01, 1.238850452e-01, 1.245025336e-01, 1.251059026e-01, 1.256958955e-01, 1.262731966e-01, 1.268384373e-01, 1.273922014e-01, 1.279350298e-01, 1.284674249e-01, 1.289898540e-01, 1.295027526e-01, 1.300065272e-01, 1.305015583e-01, 1.309882017e-01, 1.314667917e-01, 1.319376421e-01, 1.324010480e-01, 1.328572874e-01, 1.333066225e-01, 1.337493009e-01, 1.341855566e-01, 1.346156111e-01, 1.350396741e-01, 1.354579446e-01, 1.358706114e-01, 1.362778541e-01, 1.366798432e-01, 1.370767412e-01, 1.374687029e-01, 1.378558758e-01, 1.382384007e-01, 1.386164121e-01, 1.389900384e-01, 1.393594027e-01, 1.397246225e-01, 1.400858104e-01, 1.404430745e-01, 1.407965182e-01, 1.411462409e-01, 1.414923379e-01, 1.418349009e-01, 1.421740179e-01, 1.425097737e-01, 1.428422497e-01, 1.431715244e-01, 1.434976734e-01, 1.438207695e-01, 1.441408831e-01, 1.444580818e-01, 1.447724310e-01, 1.450839939e-01, 1.453928315e-01, 1.456990026e-01, 1.460025644e-01, 1.463035718e-01, 1.466020783e-01, 1.468981354e-01, 1.471917930e-01, 1.474830997e-01, 1.477721022e-01, 1.480588462e-01, 1.483433755e-01, 1.486257331e-01, 1.489059603e-01, 1.491840975e-01, 1.494601838e-01, 1.497342571e-01, 1.500063544e-01, 1.502765114e-01, 1.505447631e-01, 1.508111434e-01, 1.510756851e-01, 1.513384203e-01, 1.515993804e-01, 1.518585956e-01, 1.521160955e-01, 1.523719090e-01, 1.526260641e-01, 1.528785881e-01, 1.531295077e-01, 1.533788489e-01, 1.536266370e-01, 1.538728967e-01, 1.541176522e-01, 1.543609268e-01, 1.546027437e-01, 1.548431252e-01, 1.550820932e-01, 1.553196690e-01, 1.555558735e-01, 1.557907271e-01, 1.560242498e-01, 1.562564608e-01, 1.564873795e-01, 1.567170242e-01, 1.569454132e-01, 1.571725643e-01, 4.129958695e-01, 4.133375854e-01, 4.136814990e-01, 4.140276433e-01, 4.143760520e-01, 4.147267596e-01, 4.150798017e-01, 4.154352142e-01, 4.157930345e-01, 4.161533003e-01, 4.165160505e-01, 4.168813252e-01, 4.172491650e-01, 4.176196118e-01, 4.179927085e-01, 4.183684992e-01, 4.187470289e-01, 4.191283440e-01, 4.195124919e-01, 4.198995215e-01, 4.202894827e-01, 4.206824270e-01, 4.210784072e-01, 4.214774775e-01, 4.218796936e-01, 4.222851128e-01, 4.226937941e-01, 4.231057981e-01, 4.235211869e-01, 4.239400248e-01, 4.243623778e-01, 4.247883139e-01, 4.252179030e-01, 4.256512172e-01, 4.260883310e-01, 4.265293208e-01, 4.269742657e-01, 4.274232473e-01, 4.278763495e-01, 4.283336593e-01, 4.287952663e-01, 4.292612630e-01, 4.297317453e-01, 4.302068120e-01, 4.306865654e-01, 4.311711115e-01, 4.316605598e-01, 4.321550238e-01, 4.326546209e-01, 4.331594731e-01, 4.336697065e-01, 4.341854523e-01, 4.347068462e-01, 4.352340296e-01, 4.357671489e-01, 4.363063567e-01, 4.368518113e-01, 4.374036777e-01, 4.379621276e-01, 4.385273396e-01, 4.390995002e-01, 4.396788036e-01, 4.402654526e-01, 4.408596590e-01, 4.414616439e-01, 4.420716386e-01, 4.426898852e-01, 4.433166369e-01, 4.439521594e-01, 4.445967309e-01, 4.452506436e-01, 4.459142045e-01, 4.465877360e-01, 4.472715776e-01, 4.479660868e-01, 4.486716402e-01, 4.493886353e-01, 4.501174922e-01, 4.508586545e-01, 4.516125923e-01, 4.523798035e-01, 4.531608164e-01, 4.539561920e-01, 4.547665273e-01, 4.555924581e-01, 4.564346622e-01, 4.572938640e-01, 4.581708382e-01, 4.590664150e-01, 4.599814854e-01, 4.609170075e-01, 4.618740134e-01, 4.628536171e-01, 4.638570235e-01, 4.648855387e-01, 4.659405818e-01, 4.670236985e-01, 4.681365765e-01, 4.692810640e-01, 4.704591909e-01, 4.716731934e-01, 4.729255435e-01, 4.742189836e-01, 4.755565681e-01, 4.769417126e-01, 4.783782545e-01, 4.798705257e-01, 4.814234426e-01, 4.830426172e-01, 4.847344967e-01, 4.865065392e-01, 4.883674397e-01, 4.903274228e-01, 4.923986277e-01, 4.945956242e-01, 4.969361164e-01, 4.994419216e-01, 5.021403692e-01, 5.050663525e-01, 5.082654433e-01, 5.117988091e-01, 5.157513583e-01, 5.202460657e-01, 5.254711723e-01, 5.317373780e-01, 5.396167222e-01, 5.503639038e-01, 5.678471904e-01, 1.000000000e+00, }; const float dist_icdf_1_2[] = { 0.000000000e+00, 4.772006582e-02, 6.296615905e-02, 7.427407753e-02, 8.365153308e-02, 9.184022598e-02, 9.920878639e-02, 1.059710445e-01, 1.122636706e-01, 1.181800824e-01, 1.237873671e-01, 1.291355676e-01, 1.342631566e-01, 1.392004468e-01, 1.439718144e-01, 1.485972037e-01, 1.530931756e-01, 1.574736603e-01, 1.617505076e-01, 1.659338993e-01, 1.700326625e-01, 1.740545113e-01, 1.780062374e-01, 1.818938596e-01, 1.857227450e-01, 1.894977068e-01, 1.932230840e-01, 1.969028077e-01, 2.005404557e-01, 2.041392989e-01, 2.077023394e-01, 2.112323442e-01, 2.147318727e-01, 2.182033009e-01, 2.216488427e-01, 2.250705673e-01, 2.284704155e-01, 2.318502134e-01, 2.352116842e-01, 2.385564595e-01, 2.418860883e-01, 2.452020459e-01, 2.485057413e-01, 2.517985242e-01, 2.550816910e-01, 2.583564905e-01, 2.616241292e-01, 2.648857755e-01, 2.681425644e-01, 2.713956014e-01, 2.746459660e-01, 2.778947155e-01, 2.811428878e-01, 2.843915047e-01, 2.876415747e-01, 2.908940958e-01, 2.941500581e-01, 2.974104465e-01, 3.006762431e-01, 3.039484293e-01, 3.072279889e-01, 3.105159099e-01, 3.138131873e-01, 3.171208251e-01, 3.204398389e-01, 3.237712585e-01, 3.271161303e-01, 3.304755200e-01, 3.338505150e-01, 3.372422278e-01, 3.406517982e-01, 3.440803970e-01, 3.475292292e-01, 3.509995371e-01, 3.544926045e-01, 3.580097602e-01, 3.615523827e-01, 3.651219045e-01, 3.687198171e-01, 3.723476766e-01, 3.760071092e-01, 3.796998181e-01, 3.834275898e-01, 3.871923026e-01, 3.909959344e-01, 3.948405726e-01, 3.987284239e-01, 4.026618262e-01, 4.066432616e-01, 4.106753701e-01, 4.147609664e-01, 4.189030573e-01, 4.231048628e-01, 4.273698387e-01, 4.317017032e-01, 4.361044665e-01, 4.405824657e-01, 4.451404038e-01, 4.497833955e-01, 4.545170203e-01, 4.593473841e-01, 4.642811920e-01, 4.693258332e-01, 4.744894827e-01, 4.797812222e-01, 4.852111858e-01, 4.907907357e-01, 4.965326778e-01, 5.024515263e-01, 5.085638336e-01, 5.148886044e-01, 5.214478227e-01, 5.282671298e-01, 5.353767113e-01, 5.428124739e-01, 5.506176367e-01, 5.588449272e-01, 5.675596847e-01, 5.768443667e-01, 5.868053100e-01, 5.975832673e-01, 6.093706188e-01, 6.224411640e-01, 6.372056689e-01, 6.543262046e-01, 6.749867043e-01, 7.016867178e-01, 7.417019543e-01, 1.000000000e+00, 0.000000000e+00, 1.499541236e-02, 1.952937653e-02, 2.281015992e-02, 2.547740008e-02, 2.776662006e-02, 2.979460053e-02, 3.162895214e-02, 3.331281609e-02, 3.487563487e-02, 3.633852094e-02, 3.771719963e-02, 3.902374190e-02, 4.026764332e-02, 4.145652677e-02, 4.259661749e-02, 4.369307429e-02, 4.475022666e-02, 4.577174851e-02, 4.676078792e-02, 4.772006582e-02, 4.865195222e-02, 4.955852581e-02, 5.044162130e-02, 5.130286730e-02, 5.214371703e-02, 5.296547339e-02, 5.376930967e-02, 5.455628670e-02, 5.532736725e-02, 5.608342813e-02, 5.682527046e-02, 5.755362840e-02, 5.826917666e-02, 5.897253699e-02, 5.966428369e-02, 6.034494854e-02, 6.101502500e-02, 6.167497195e-02, 6.232521694e-02, 6.296615905e-02, 6.359817150e-02, 6.422160388e-02, 6.483678414e-02, 6.544402048e-02, 6.604360288e-02, 6.663580458e-02, 6.722088343e-02, 6.779908299e-02, 6.837063367e-02, 6.893575365e-02, 6.949464977e-02, 7.004751833e-02, 7.059454584e-02, 7.113590964e-02, 7.167177856e-02, 7.220231343e-02, 7.272766762e-02, 7.324798752e-02, 7.376341294e-02, 7.427407753e-02, 7.478010916e-02, 7.528163025e-02, 7.577875806e-02, 7.627160506e-02, 7.676027909e-02, 7.724488373e-02, 7.772551843e-02, 7.820227881e-02, 7.867525684e-02, 7.914454098e-02, 7.961021646e-02, 8.007236533e-02, 8.053106672e-02, 8.098639692e-02, 8.143842953e-02, 8.188723562e-02, 8.233288381e-02, 8.277544041e-02, 8.321496951e-02, 8.365153308e-02, 8.408519111e-02, 8.451600162e-02, 8.494402082e-02, 8.536930314e-02, 8.579190134e-02, 8.621186654e-02, 8.662924833e-02, 8.704409482e-02, 8.745645268e-02, 8.786636724e-02, 8.827388250e-02, 8.867904120e-02, 8.908188489e-02, 8.948245393e-02, 8.988078759e-02, 9.027692404e-02, 9.067090043e-02, 9.106275291e-02, 9.145251667e-02, 9.184022598e-02, 9.222591419e-02, 9.260961384e-02, 9.299135659e-02, 9.337117332e-02, 9.374909416e-02, 9.412514845e-02, 9.449936484e-02, 9.487177128e-02, 9.524239502e-02, 9.561126270e-02, 9.597840030e-02, 9.634383320e-02, 9.670758619e-02, 9.706968348e-02, 9.743014875e-02, 9.778900512e-02, 9.814627521e-02, 9.850198111e-02, 9.885614446e-02, 9.920878639e-02, 9.955992759e-02, 9.990958831e-02, 1.002577884e-01, 1.006045471e-01, 1.009498836e-01, 1.012938164e-01, 1.016363636e-01, 1.019775432e-01, 6.170366727e-01, 6.176986034e-01, 6.183643182e-01, 6.190338707e-01, 6.197073159e-01, 6.203847098e-01, 6.210661097e-01, 6.217515745e-01, 6.224411640e-01, 6.231349398e-01, 6.238329646e-01, 6.245353029e-01, 6.252420205e-01, 6.259531849e-01, 6.266688652e-01, 6.273891322e-01, 6.281140585e-01, 6.288437184e-01, 6.295781881e-01, 6.303175458e-01, 6.310618716e-01, 6.318112478e-01, 6.325657587e-01, 6.333254909e-01, 6.340905334e-01, 6.348609774e-01, 6.356369166e-01, 6.364184475e-01, 6.372056689e-01, 6.379986826e-01, 6.387975932e-01, 6.396025084e-01, 6.404135388e-01, 6.412307983e-01, 6.420544043e-01, 6.428844774e-01, 6.437211420e-01, 6.445645263e-01, 6.454147624e-01, 6.462719864e-01, 6.471363389e-01, 6.480079647e-01, 6.488870134e-01, 6.497736395e-01, 6.506680025e-01, 6.515702672e-01, 6.524806039e-01, 6.533991890e-01, 6.543262046e-01, 6.552618393e-01, 6.562062886e-01, 6.571597547e-01, 6.581224473e-01, 6.590945838e-01, 6.600763897e-01, 6.610680990e-01, 6.620699547e-01, 6.630822093e-01, 6.641051252e-01, 6.651389751e-01, 6.661840432e-01, 6.672406251e-01, 6.683090287e-01, 6.693895751e-01, 6.704825993e-01, 6.715884509e-01, 6.727074949e-01, 6.738401130e-01, 6.749867043e-01, 6.761476867e-01, 6.773234978e-01, 6.785145965e-01, 6.797214640e-01, 6.809446060e-01, 6.821845537e-01, 6.834418659e-01, 6.847171313e-01, 6.860109699e-01, 6.873240363e-01, 6.886570216e-01, 6.900106564e-01, 6.913857144e-01, 6.927830153e-01, 6.942034290e-01, 6.956478797e-01, 6.971173506e-01, 6.986128893e-01, 7.001356135e-01, 7.016867178e-01, 7.032674807e-01, 7.048792730e-01, 7.065235673e-01, 7.082019481e-01, 7.099161243e-01, 7.116679421e-01, 7.134594013e-01, 7.152926725e-01, 7.171701179e-01, 7.190943149e-01, 7.210680840e-01, 7.230945206e-01, 7.251770328e-01, 7.273193864e-01, 7.295257577e-01, 7.318007963e-01, 7.341497020e-01, 7.365783167e-01, 7.390932372e-01, 7.417019543e-01, 7.444130262e-01, 7.472362960e-01, 7.501831692e-01, 7.532669707e-01, 7.565034130e-01, 7.599112167e-01, 7.635129523e-01, 7.673362015e-01, 7.714152009e-01, 7.757932332e-01, 7.805262173e-01, 7.856883133e-01, 7.913810931e-01, 7.977494403e-01, 8.050112561e-01, 8.135187408e-01, 8.239037798e-01, 8.375058344e-01, 8.582456226e-01, 1.000000000e+00, }; const float dist_icdf_1_3[] = { 0.000000000e+00, 2.816362283e-02, 4.073114933e-02, 5.066862151e-02, 5.924514514e-02, 6.695453594e-02, 7.405075716e-02, 8.068497887e-02, 8.695585717e-02, 9.293201726e-02, 9.866349293e-02, 1.041881077e-01, 1.095352894e-01, 1.147284777e-01, 1.197867108e-01, 1.247257102e-01, 1.295586440e-01, 1.342966793e-01, 1.389493894e-01, 1.435250613e-01, 1.480309305e-01, 1.524733645e-01, 1.568580063e-01, 1.611898902e-01, 1.654735339e-01, 1.697130145e-01, 1.739120306e-01, 1.780739538e-01, 1.822018718e-01, 1.862986244e-01, 1.903668348e-01, 1.944089349e-01, 1.984271885e-01, 2.024237105e-01, 2.064004834e-01, 2.103593722e-01, 2.143021371e-01, 2.182304449e-01, 2.221458788e-01, 2.260499475e-01, 2.299440928e-01, 2.338296971e-01, 2.377080891e-01, 2.415805505e-01, 2.454483204e-01, 2.493126005e-01, 2.531745593e-01, 2.570353363e-01, 2.608960459e-01, 2.647577802e-01, 2.686216132e-01, 2.724886030e-01, 2.763597954e-01, 2.802362262e-01, 2.841189242e-01, 2.880089133e-01, 2.919072155e-01, 2.958148532e-01, 2.997328513e-01, 3.036622398e-01, 3.076040561e-01, 3.115593475e-01, 3.155291733e-01, 3.195146076e-01, 3.235167413e-01, 3.275366851e-01, 3.315755718e-01, 3.356345592e-01, 3.397148327e-01, 3.438176086e-01, 3.479441371e-01, 3.520957054e-01, 3.562736416e-01, 3.604793180e-01, 3.647141556e-01, 3.689796277e-01, 3.732772653e-01, 3.776086615e-01, 3.819754772e-01, 3.863794467e-01, 3.908223843e-01, 3.953061912e-01, 3.998328630e-01, 4.044044982e-01, 4.090233075e-01, 4.136916236e-01, 4.184119129e-01, 4.231867877e-01, 4.280190203e-01, 4.329115582e-01, 4.378675421e-01, 4.428903247e-01, 4.479834934e-01, 4.531508949e-01, 4.583966634e-01, 4.637252530e-01, 4.691414745e-01, 4.746505375e-01, 4.802580996e-01, 4.859703224e-01, 4.917939378e-01, 4.977363245e-01, 5.038055991e-01, 5.100107227e-01, 5.163616292e-01, 5.228693780e-01, 5.295463393e-01, 5.364064191e-01, 5.434653363e-01, 5.507409658e-01, 5.582537683e-01, 5.660273358e-01, 5.740890907e-01, 5.824711971e-01, 5.912117649e-01, 6.003564717e-01, 6.099607911e-01, 6.200931256e-01, 6.308393340e-01, 6.423094832e-01, 6.546483062e-01, 6.680521651e-01, 6.827981811e-01, 6.992980564e-01, 7.182076801e-01, 7.406831072e-01, 7.691188047e-01, 8.102844589e-01, 1.000000000e+00, 0.000000000e+00, 5.892691047e-03, 8.442042046e-03, 1.042264322e-02, 1.210689516e-02, 1.360095758e-02, 1.495949798e-02, 1.621509210e-02, 1.738901806e-02, 1.849608684e-02, 1.954710177e-02, 2.055023152e-02, 2.151183130e-02, 2.243696153e-02, 2.332972995e-02, 2.419352551e-02, 2.503118323e-02, 2.584510333e-02, 2.663733938e-02, 2.740966461e-02, 2.816362283e-02, 2.890056795e-02, 2.962169525e-02, 3.032806620e-02, 3.102062864e-02, 3.170023306e-02, 3.236764610e-02, 3.302356168e-02, 3.366861035e-02, 3.430336707e-02, 3.492835788e-02, 3.554406552e-02, 3.615093428e-02, 3.674937415e-02, 3.733976444e-02, 3.792245688e-02, 3.849777836e-02, 3.906603332e-02, 3.962750587e-02, 4.018246162e-02, 4.073114933e-02, 4.127380238e-02, 4.181064007e-02, 4.234186876e-02, 4.286768296e-02, 4.338826621e-02, 4.390379197e-02, 4.441442436e-02, 4.492031886e-02, 4.542162290e-02, 4.591847648e-02, 4.641101266e-02, 4.689935805e-02, 4.738363319e-02, 4.786395302e-02, 4.834042719e-02, 4.881316040e-02, 4.928225274e-02, 4.974779992e-02, 5.020989359e-02, 5.066862151e-02, 5.112406783e-02, 5.157631331e-02, 5.202543542e-02, 5.247150863e-02, 5.291460450e-02, 5.335479187e-02, 5.379213698e-02, 5.422670362e-02, 5.465855327e-02, 5.508774518e-02, 5.551433650e-02, 5.593838240e-02, 5.635993612e-02, 5.677904912e-02, 5.719577111e-02, 5.761015018e-02, 5.802223282e-02, 5.843206404e-02, 5.883968741e-02, 5.924514514e-02, 5.964847812e-02, 6.004972599e-02, 6.044892719e-02, 6.084611901e-02, 6.124133764e-02, 6.163461821e-02, 6.202599483e-02, 6.241550065e-02, 6.280316787e-02, 6.318902780e-02, 6.357311088e-02, 6.395544673e-02, 6.433606416e-02, 6.471499121e-02, 6.509225518e-02, 6.546788267e-02, 6.584189957e-02, 6.621433112e-02, 6.658520192e-02, 6.695453594e-02, 6.732235658e-02, 6.768868663e-02, 6.805354835e-02, 6.841696347e-02, 6.877895316e-02, 6.913953814e-02, 6.949873861e-02, 6.985657430e-02, 7.021306452e-02, 7.056822810e-02, 7.092208347e-02, 7.127464863e-02, 7.162594120e-02, 7.197597839e-02, 7.232477705e-02, 7.267235366e-02, 7.301872436e-02, 7.336390493e-02, 7.370791082e-02, 7.405075716e-02, 7.439245877e-02, 7.473303017e-02, 7.507248556e-02, 7.541083889e-02, 7.574810380e-02, 7.608429367e-02, 7.641942162e-02, 7.675350051e-02, 6.767162794e-01, 6.774623576e-01, 6.782123708e-01, 6.789663729e-01, 6.797244187e-01, 6.804865644e-01, 6.812528674e-01, 6.820233863e-01, 6.827981811e-01, 6.835773132e-01, 6.843608452e-01, 6.851488414e-01, 6.859413675e-01, 6.867384906e-01, 6.875402796e-01, 6.883468050e-01, 6.891581389e-01, 6.899743551e-01, 6.907955295e-01, 6.916217396e-01, 6.924530650e-01, 6.932895872e-01, 6.941313897e-01, 6.949785585e-01, 6.958311813e-01, 6.966893486e-01, 6.975531530e-01, 6.984226897e-01, 6.992980564e-01, 7.001793534e-01, 7.010666838e-01, 7.019601538e-01, 7.028598723e-01, 7.037659513e-01, 7.046785062e-01, 7.055976556e-01, 7.065235216e-01, 7.074562299e-01, 7.083959099e-01, 7.093426953e-01, 7.102967233e-01, 7.112581358e-01, 7.122270790e-01, 7.132037037e-01, 7.141881656e-01, 7.151806254e-01, 7.161812491e-01, 7.171902082e-01, 7.182076801e-01, 7.192338481e-01, 7.202689018e-01, 7.213130375e-01, 7.223664586e-01, 7.234293756e-01, 7.245020067e-01, 7.255845781e-01, 7.266773246e-01, 7.277804898e-01, 7.288943267e-01, 7.300190982e-01, 7.311550775e-01, 7.323025487e-01, 7.334618078e-01, 7.346331628e-01, 7.358169346e-01, 7.370134580e-01, 7.382230821e-01, 7.394461715e-01, 7.406831072e-01, 7.419342874e-01, 7.432001288e-01, 7.444810678e-01, 7.457775616e-01, 7.470900899e-01, 7.484191561e-01, 7.497652892e-01, 7.511290454e-01, 7.525110102e-01, 7.539118007e-01, 7.553320674e-01, 7.567724975e-01, 7.582338171e-01, 7.597167949e-01, 7.612222451e-01, 7.627510317e-01, 7.643040723e-01, 7.658823432e-01, 7.674868841e-01, 7.691188047e-01, 7.707792903e-01, 7.724696099e-01, 7.741911241e-01, 7.759452944e-01, 7.777336939e-01, 7.795580188e-01, 7.814201029e-01, 7.833219325e-01, 7.852656646e-01, 7.872536476e-01, 7.892884457e-01, 7.913728661e-01, 7.935099927e-01, 7.957032240e-01, 7.979563194e-01, 8.002734531e-01, 8.026592799e-01, 8.051190140e-01, 8.076585257e-01, 8.102844589e-01, 8.130043790e-01, 8.158269562e-01, 8.187621991e-01, 8.218217550e-01, 8.250192998e-01, 8.283710555e-01, 8.318964859e-01, 8.356192544e-01, 8.395685713e-01, 8.437811417e-01, 8.483040732e-01, 8.531993845e-01, 8.585513239e-01, 8.644789519e-01, 8.711594158e-01, 8.788754109e-01, 8.881261959e-01, 8.999483706e-01, 9.172824028e-01, 1.000000000e+00, }; const float dist_icdf_1_4[] = { 0.000000000e+00, 1.304208331e-02, 2.155380799e-02, 2.896488608e-02, 3.575988175e-02, 4.214276896e-02, 4.822411052e-02, 5.407241163e-02, 5.973386382e-02, 6.524149950e-02, 7.061999023e-02, 7.588839187e-02, 8.106182201e-02, 8.615253946e-02, 9.117066841e-02, 9.612470122e-02, 1.010218577e-01, 1.058683484e-01, 1.106695710e-01, 1.154302611e-01, 1.201546074e-01, 1.248463440e-01, 1.295088222e-01, 1.341450696e-01, 1.387578376e-01, 1.433496404e-01, 1.479227875e-01, 1.524794111e-01, 1.570214887e-01, 1.615508624e-01, 1.660692558e-01, 1.705782880e-01, 1.750794860e-01, 1.795742953e-01, 1.840640892e-01, 1.885501775e-01, 1.930338132e-01, 1.975161990e-01, 2.019984935e-01, 2.064818161e-01, 2.109672515e-01, 2.154558543e-01, 2.199486526e-01, 2.244466514e-01, 2.289508364e-01, 2.334621764e-01, 2.379816266e-01, 2.425101306e-01, 2.470486238e-01, 2.515980349e-01, 2.561592886e-01, 2.607333076e-01, 2.653210148e-01, 2.699233352e-01, 2.745411980e-01, 2.791755386e-01, 2.838273004e-01, 2.884974366e-01, 2.931869128e-01, 2.978967082e-01, 3.026278181e-01, 3.073812557e-01, 3.121580544e-01, 3.169592699e-01, 3.217859822e-01, 3.266392985e-01, 3.315203551e-01, 3.364303204e-01, 3.413703972e-01, 3.463418260e-01, 3.513458877e-01, 3.563839073e-01, 3.614572568e-01, 3.665673593e-01, 3.717156929e-01, 3.769037950e-01, 3.821332669e-01, 3.874057788e-01, 3.927230754e-01, 3.980869817e-01, 4.034994092e-01, 4.089623637e-01, 4.144779520e-01, 4.200483913e-01, 4.256760179e-01, 4.313632977e-01, 4.371128377e-01, 4.429273984e-01, 4.488099080e-01, 4.547634777e-01, 4.607914199e-01, 4.668972667e-01, 4.730847930e-01, 4.793580409e-01, 4.857213476e-01, 4.921793781e-01, 4.987371609e-01, 5.054001306e-01, 5.121741754e-01, 5.190656928e-01, 5.260816543e-01, 5.332296801e-01, 5.405181277e-01, 5.479561958e-01, 5.555540473e-01, 5.633229575e-01, 5.712754907e-01, 5.794257161e-01, 5.877894704e-01, 5.963846830e-01, 6.052317810e-01, 6.143542001e-01, 6.237790370e-01, 6.335378936e-01, 6.436679874e-01, 6.542136360e-01, 6.652282839e-01, 6.767773310e-01, 6.889421867e-01, 7.018262641e-01, 7.155641757e-01, 7.303364892e-01, 7.463947649e-01, 7.641071782e-01, 7.840499281e-01, 8.072165153e-01, 8.356059142e-01, 8.746271312e-01, 1.000000000e+00, 0.000000000e+00, 1.512966588e-03, 2.487670283e-03, 3.328144398e-03, 4.092040395e-03, 4.803753636e-03, 5.476563085e-03, 6.118725039e-03, 6.735822405e-03, 7.331856681e-03, 7.909821634e-03, 8.472032216e-03, 9.020325964e-03, 9.556192872e-03, 1.008086266e-02, 1.059536550e-02, 1.110057546e-02, 1.159724237e-02, 1.208601572e-02, 1.256746291e-02, 1.304208331e-02, 1.351031945e-02, 1.397256584e-02, 1.442917612e-02, 1.488046889e-02, 1.532673246e-02, 1.576822884e-02, 1.620519705e-02, 1.663785591e-02, 1.706640639e-02, 1.749103364e-02, 1.791190872e-02, 1.832919008e-02, 1.874302485e-02, 1.915354999e-02, 1.956089323e-02, 1.996517397e-02, 2.036650401e-02, 2.076498827e-02, 2.116072533e-02, 2.155380799e-02, 2.194432375e-02, 2.233235522e-02, 2.271798050e-02, 2.310127354e-02, 2.348230445e-02, 2.386113977e-02, 2.423784271e-02, 2.461247341e-02, 2.498508915e-02, 2.535574452e-02, 2.572449160e-02, 2.609138016e-02, 2.645645775e-02, 2.681976986e-02, 2.718136007e-02, 2.754127013e-02, 2.789954008e-02, 2.825620835e-02, 2.861131186e-02, 2.896488608e-02, 2.931696514e-02, 2.966758188e-02, 3.001676790e-02, 3.036455369e-02, 3.071096863e-02, 3.105604105e-02, 3.139979831e-02, 3.174226682e-02, 3.208347212e-02, 3.242343888e-02, 3.276219097e-02, 3.309975148e-02, 3.343614278e-02, 3.377138652e-02, 3.410550367e-02, 3.443851459e-02, 3.477043900e-02, 3.510129604e-02, 3.543110428e-02, 3.575988175e-02, 3.608764598e-02, 3.641441397e-02, 3.674020228e-02, 3.706502699e-02, 3.738890373e-02, 3.771184774e-02, 3.803387383e-02, 3.835499641e-02, 3.867522955e-02, 3.899458691e-02, 3.931308183e-02, 3.963072732e-02, 3.994753604e-02, 4.026352035e-02, 4.057869231e-02, 4.089306369e-02, 4.120664596e-02, 4.151945034e-02, 4.183148778e-02, 4.214276896e-02, 4.245330435e-02, 4.276310414e-02, 4.307217832e-02, 4.338053664e-02, 4.368818865e-02, 4.399514368e-02, 4.430141085e-02, 4.460699910e-02, 4.491191717e-02, 4.521617363e-02, 4.551977684e-02, 4.582273502e-02, 4.612505621e-02, 4.642674827e-02, 4.672781892e-02, 4.702827573e-02, 4.732812609e-02, 4.762737729e-02, 4.792603644e-02, 4.822411052e-02, 4.852160639e-02, 4.881853077e-02, 4.911489026e-02, 4.941069131e-02, 4.970594030e-02, 5.000064344e-02, 5.029480687e-02, 5.058843658e-02, 7.397969437e-01, 7.406082489e-01, 7.414232903e-01, 7.422421162e-01, 7.430647755e-01, 7.438913184e-01, 7.447217958e-01, 7.455562602e-01, 7.463947649e-01, 7.472373644e-01, 7.480841145e-01, 7.489350721e-01, 7.497902955e-01, 7.506498443e-01, 7.515137793e-01, 7.523821629e-01, 7.532550589e-01, 7.541325325e-01, 7.550146505e-01, 7.559014813e-01, 7.567930950e-01, 7.576895632e-01, 7.585909595e-01, 7.594973591e-01, 7.604088392e-01, 7.613254790e-01, 7.622473596e-01, 7.631745642e-01, 7.641071782e-01, 7.650452892e-01, 7.659889871e-01, 7.669383643e-01, 7.678935156e-01, 7.688545384e-01, 7.698215329e-01, 7.707946019e-01, 7.717738512e-01, 7.727593897e-01, 7.737513293e-01, 7.747497851e-01, 7.757548759e-01, 7.767667237e-01, 7.777854544e-01, 7.788111975e-01, 7.798440868e-01, 7.808842600e-01, 7.819318594e-01, 7.829870316e-01, 7.840499281e-01, 7.851207054e-01, 7.861995250e-01, 7.872865540e-01, 7.883819652e-01, 7.894859373e-01, 7.905986553e-01, 7.917203106e-01, 7.928511016e-01, 7.939912341e-01, 7.951409211e-01, 7.963003840e-01, 7.974698524e-01, 7.986495647e-01, 7.998397689e-01, 8.010407225e-01, 8.022526938e-01, 8.034759617e-01, 8.047108171e-01, 8.059575629e-01, 8.072165153e-01, 8.084880042e-01, 8.097723742e-01, 8.110699854e-01, 8.123812148e-01, 8.137064568e-01, 8.150461247e-01, 8.164006519e-01, 8.177704936e-01, 8.191561274e-01, 8.205580562e-01, 8.219768087e-01, 8.234129425e-01, 8.248670454e-01, 8.263397384e-01, 8.278316776e-01, 8.293435579e-01, 8.308761154e-01, 8.324301316e-01, 8.340064367e-01, 8.356059142e-01, 8.372295061e-01, 8.388782178e-01, 8.405531242e-01, 8.422553773e-01, 8.439862129e-01, 8.457469602e-01, 8.475390516e-01, 8.493640337e-01, 8.512235810e-01, 8.531195104e-01, 8.550537988e-01, 8.570286033e-01, 8.590462846e-01, 8.611094345e-01, 8.632209089e-01, 8.653838656e-01, 8.676018115e-01, 8.698786572e-01, 8.722187850e-01, 8.746271312e-01, 8.771092876e-01, 8.796716289e-01, 8.823214723e-01, 8.850672824e-01, 8.879189356e-01, 8.908880683e-01, 8.939885425e-01, 8.972370812e-01, 9.006541560e-01, 9.042652589e-01, 9.081027837e-01, 9.122089120e-01, 9.166402468e-01, 9.214756757e-01, 9.268307039e-01, 9.328861828e-01, 9.399541098e-01, 9.486626553e-01, 9.607131225e-01, 1.000000000e+00, }; const float dist_icdf_1_5[] = { 0.000000000e+00, 4.203160627e-03, 8.440297374e-03, 1.269985348e-02, 1.697952692e-02, 2.127832878e-02, 2.559575951e-02, 2.993155884e-02, 3.428560274e-02, 3.865785302e-02, 4.304832972e-02, 4.745709482e-02, 5.188424191e-02, 5.632988943e-02, 6.079417606e-02, 6.527725748e-02, 6.977930401e-02, 7.430049894e-02, 7.884103729e-02, 8.340112485e-02, 8.798097750e-02, 9.258082071e-02, 9.720088917e-02, 1.018414265e-01, 1.065026852e-01, 1.111849263e-01, 1.158884195e-01, 1.206134434e-01, 1.253602849e-01, 1.301292401e-01, 1.349206137e-01, 1.397347197e-01, 1.445718811e-01, 1.494324308e-01, 1.543167110e-01, 1.592250739e-01, 1.641578823e-01, 1.691155091e-01, 1.740983383e-01, 1.791067652e-01, 1.841411966e-01, 1.892020513e-01, 1.942897607e-01, 1.994047690e-01, 2.045475337e-01, 2.097185264e-01, 2.149182330e-01, 2.201471546e-01, 2.254058076e-01, 2.306947252e-01, 2.360144571e-01, 2.413655711e-01, 2.467486532e-01, 2.521643088e-01, 2.576131637e-01, 2.630958644e-01, 2.686130798e-01, 2.741655019e-01, 2.797538469e-01, 2.853788565e-01, 2.910412990e-01, 2.967419710e-01, 3.024816982e-01, 3.082613378e-01, 3.140817794e-01, 3.199439470e-01, 3.258488011e-01, 3.317973404e-01, 3.377906043e-01, 3.438296749e-01, 3.499156797e-01, 3.560497942e-01, 3.622332451e-01, 3.684673131e-01, 3.747533362e-01, 3.810927142e-01, 3.874869115e-01, 3.939374626e-01, 4.004459760e-01, 4.070141398e-01, 4.136437271e-01, 4.203366023e-01, 4.270947278e-01, 4.339201712e-01, 4.408151137e-01, 4.477818590e-01, 4.548228429e-01, 4.619406446e-01, 4.691379987e-01, 4.764178087e-01, 4.837831619e-01, 4.912373465e-01, 4.987838702e-01, 5.064264815e-01, 5.141691939e-01, 5.220163124e-01, 5.299724647e-01, 5.380426363e-01, 5.462322105e-01, 5.545470145e-01, 5.629933729e-01, 5.715781698e-01, 5.803089204e-01, 5.891938562e-01, 5.982420248e-01, 6.074634084e-01, 6.168690662e-01, 6.264713045e-01, 6.362838856e-01, 6.463222811e-01, 6.566039879e-01, 6.671489221e-01, 6.779799179e-01, 6.891233682e-01, 7.006100586e-01, 7.124762717e-01, 7.247652786e-01, 7.375293966e-01, 7.508329017e-01, 7.647562778e-01, 7.794026379e-01, 7.949078601e-01, 8.114574692e-01, 8.293167523e-01, 8.488896155e-01, 8.708493268e-01, 8.964919166e-01, 9.291001401e-01, 1.000000000e+00, 0.000000000e+00, 2.077662927e-04, 4.165101518e-04, 6.256472745e-04, 8.350530399e-04, 1.044668217e-03, 1.254457910e-03, 1.464399060e-03, 1.674475281e-03, 1.884674324e-03, 2.094986687e-03, 2.305404783e-03, 2.515922413e-03, 2.726534422e-03, 2.937236452e-03, 3.148024773e-03, 3.358896158e-03, 3.569847785e-03, 3.780877171e-03, 3.991982108e-03, 4.203160627e-03, 4.414410956e-03, 4.625731497e-03, 4.837120796e-03, 5.048577531e-03, 5.260100492e-03, 5.471688565e-03, 5.683340728e-03, 5.895056032e-03, 6.106833602e-03, 6.318672621e-03, 6.530572332e-03, 6.742532026e-03, 6.954551041e-03, 7.166628755e-03, 7.378764586e-03, 7.590957986e-03, 7.803208438e-03, 8.015515456e-03, 8.227878580e-03, 8.440297374e-03, 8.652771426e-03, 8.865300345e-03, 9.077883761e-03, 9.290521320e-03, 9.503212687e-03, 9.715957543e-03, 9.928755583e-03, 1.014160652e-02, 1.035451007e-02, 1.056746597e-02, 1.078047397e-02, 1.099353382e-02, 1.120664530e-02, 1.141980818e-02, 1.163302224e-02, 1.184628729e-02, 1.205960312e-02, 1.227296955e-02, 1.248638640e-02, 1.269985348e-02, 1.291337064e-02, 1.312693772e-02, 1.334055455e-02, 1.355422098e-02, 1.376793688e-02, 1.398170210e-02, 1.419551651e-02, 1.440937999e-02, 1.462329239e-02, 1.483725362e-02, 1.505126354e-02, 1.526532204e-02, 1.547942903e-02, 1.569358439e-02, 1.590778801e-02, 1.612203982e-02, 1.633633970e-02, 1.655068757e-02, 1.676508334e-02, 1.697952692e-02, 1.719401823e-02, 1.740855719e-02, 1.762314372e-02, 1.783777775e-02, 1.805245920e-02, 1.826718801e-02, 1.848196410e-02, 1.869678741e-02, 1.891165788e-02, 1.912657543e-02, 1.934154003e-02, 1.955655159e-02, 1.977161007e-02, 1.998671542e-02, 2.020186758e-02, 2.041706649e-02, 2.063231212e-02, 2.084760440e-02, 2.106294330e-02, 2.127832878e-02, 2.149376077e-02, 2.170923925e-02, 2.192476417e-02, 2.214033550e-02, 2.235595319e-02, 2.257161720e-02, 2.278732751e-02, 2.300308407e-02, 2.321888685e-02, 2.343473582e-02, 2.365063096e-02, 2.386657221e-02, 2.408255957e-02, 2.429859299e-02, 2.451467246e-02, 2.473079794e-02, 2.494696941e-02, 2.516318684e-02, 2.537945022e-02, 2.559575951e-02, 2.581211469e-02, 2.602851575e-02, 2.624496266e-02, 2.646145540e-02, 2.667799395e-02, 2.689457830e-02, 2.711120843e-02, 2.732788431e-02, 8.046976007e-01, 8.055318708e-01, 8.063691310e-01, 8.072094159e-01, 8.080527607e-01, 8.088992014e-01, 8.097487747e-01, 8.106015179e-01, 8.114574692e-01, 8.123166675e-01, 8.131791527e-01, 8.140449652e-01, 8.149141465e-01, 8.157867389e-01, 8.166627856e-01, 8.175423308e-01, 8.184254196e-01, 8.193120980e-01, 8.202024132e-01, 8.210964134e-01, 8.219941477e-01, 8.228956667e-01, 8.238010217e-01, 8.247102656e-01, 8.256234523e-01, 8.265406371e-01, 8.274618765e-01, 8.283872284e-01, 8.293167523e-01, 8.302505088e-01, 8.311885602e-01, 8.321309706e-01, 8.330778053e-01, 8.340291315e-01, 8.349850181e-01, 8.359455358e-01, 8.369107573e-01, 8.378807570e-01, 8.388556115e-01, 8.398353994e-01, 8.408202015e-01, 8.418101008e-01, 8.428051829e-01, 8.438055355e-01, 8.448112490e-01, 8.458224165e-01, 8.468391338e-01, 8.478614995e-01, 8.488896155e-01, 8.499235864e-01, 8.509635203e-01, 8.520095287e-01, 8.530617267e-01, 8.541202330e-01, 8.551851704e-01, 8.562566655e-01, 8.573348494e-01, 8.584198576e-01, 8.595118304e-01, 8.606109127e-01, 8.617172551e-01, 8.628310132e-01, 8.639523485e-01, 8.650814285e-01, 8.662184271e-01, 8.673635248e-01, 8.685169093e-01, 8.696787757e-01, 8.708493268e-01, 8.720287739e-01, 8.732173371e-01, 8.744152460e-01, 8.756227397e-01, 8.768400684e-01, 8.780674929e-01, 8.793052865e-01, 8.805537347e-01, 8.818131369e-01, 8.830838067e-01, 8.843660734e-01, 8.856602827e-01, 8.869667982e-01, 8.882860024e-01, 8.896182985e-01, 8.909641117e-01, 8.923238911e-01, 8.936981115e-01, 8.950872757e-01, 8.964919166e-01, 8.979126001e-01, 8.993499281e-01, 9.008045413e-01, 9.022771233e-01, 9.037684047e-01, 9.052791675e-01, 9.068102508e-01, 9.083625562e-01, 9.099370554e-01, 9.115347972e-01, 9.131569172e-01, 9.148046478e-01, 9.164793302e-01, 9.181824289e-01, 9.199155477e-01, 9.216804495e-01, 9.234790793e-01, 9.253135919e-01, 9.271863850e-01, 9.291001401e-01, 9.310578717e-01, 9.330629889e-01, 9.351193720e-01, 9.372314700e-01, 9.394044253e-01, 9.416442360e-01, 9.439579713e-01, 9.463540622e-01, 9.488427019e-01, 9.514364139e-01, 9.541508797e-01, 9.570061896e-01, 9.600288182e-01, 9.632549133e-01, 9.667361640e-01, 9.705512686e-01, 9.748314094e-01, 9.798291121e-01, 9.861840124e-01, 1.000000000e+00, }; const float dist_icdf_1_6[] = { 0.000000000e+00, 7.877882007e-04, 2.100042262e-03, 3.727177925e-03, 5.600284917e-03, 7.680990070e-03, 9.944108992e-03, 1.237157422e-02, 1.494966865e-02, 1.766755982e-02, 2.051644175e-02, 2.348899513e-02, 2.657902868e-02, 2.978123067e-02, 3.309099055e-02, 3.650426737e-02, 4.001749025e-02, 4.362748166e-02, 4.733139714e-02, 5.112667734e-02, 5.501100918e-02, 5.898229420e-02, 6.303862234e-02, 6.717825014e-02, 7.139958240e-02, 7.570115664e-02, 8.008162979e-02, 8.453976693e-02, 8.907443134e-02, 9.368457610e-02, 9.836923661e-02, 1.031275241e-01, 1.079586200e-01, 1.128617708e-01, 1.178362838e-01, 1.228815229e-01, 1.279969054e-01, 1.331818987e-01, 1.384360177e-01, 1.437588223e-01, 1.491499151e-01, 1.546089394e-01, 1.601355779e-01, 1.657295507e-01, 1.713906139e-01, 1.771185589e-01, 1.829132107e-01, 1.887744275e-01, 1.947020997e-01, 2.006961490e-01, 2.067565281e-01, 2.128832202e-01, 2.190762386e-01, 2.253356261e-01, 2.316614555e-01, 2.380538287e-01, 2.445128772e-01, 2.510387619e-01, 2.576316735e-01, 2.642918324e-01, 2.710194891e-01, 2.778149248e-01, 2.846784516e-01, 2.916104133e-01, 2.986111857e-01, 3.056811775e-01, 3.128208316e-01, 3.200306251e-01, 3.273110712e-01, 3.346627198e-01, 3.420861591e-01, 3.495820169e-01, 3.571509622e-01, 3.647937065e-01, 3.725110065e-01, 3.803036651e-01, 3.881725346e-01, 3.961185181e-01, 4.041425733e-01, 4.122457143e-01, 4.204290155e-01, 4.286936148e-01, 4.370407174e-01, 4.454716000e-01, 4.539876153e-01, 4.625901972e-01, 4.712808662e-01, 4.800612357e-01, 4.889330184e-01, 4.978980342e-01, 5.069582184e-01, 5.161156307e-01, 5.253724659e-01, 5.347310652e-01, 5.441939291e-01, 5.537637322e-01, 5.634433396e-01, 5.732358252e-01, 5.831444931e-01, 5.931729017e-01, 6.033248915e-01, 6.136046164e-01, 6.240165812e-01, 6.345656840e-01, 6.452572659e-01, 6.560971707e-01, 6.670918135e-01, 6.782482646e-01, 6.895743487e-01, 7.010787659e-01, 7.127712393e-01, 7.246626979e-01, 7.367655043e-01, 7.490937432e-01, 7.616635920e-01, 7.744938030e-01, 7.876063442e-01, 8.010272681e-01, 8.147879167e-01, 8.289266439e-01, 8.434913592e-01, 8.585434418e-01, 8.741640790e-01, 8.904652148e-01, 9.076101613e-01, 9.258573700e-01, 9.456721333e-01, 9.681232008e-01, 1.000000000e+00, 0.000000000e+00, 1.138721031e-05, 3.034865559e-05, 5.384828237e-05, 8.088424301e-05, 1.108964430e-04, 1.435156424e-04, 1.784756212e-04, 2.155731485e-04, 2.546467676e-04, 2.955643711e-04, 3.382153826e-04, 3.825055600e-04, 4.283533932e-04, 4.756875174e-04, 5.244448030e-04, 5.745689109e-04, 6.260091769e-04, 6.787197355e-04, 7.326588207e-04, 7.877882007e-04, 8.440727150e-04, 9.014798922e-04, 9.599796298e-04, 1.019543926e-03, 1.080146649e-03, 1.141763344e-03, 1.204371066e-03, 1.267948227e-03, 1.332474479e-03, 1.397930596e-03, 1.464298380e-03, 1.531560570e-03, 1.599700772e-03, 1.668703387e-03, 1.738553548e-03, 1.809237072e-03, 1.880740404e-03, 1.953050575e-03, 2.026155165e-03, 2.100042262e-03, 2.174700430e-03, 2.250118681e-03, 2.326286445e-03, 2.403193546e-03, 2.480830178e-03, 2.559186884e-03, 2.638254535e-03, 2.718024315e-03, 2.798487700e-03, 2.879636446e-03, 2.961462573e-03, 3.043958350e-03, 3.127116286e-03, 3.210929116e-03, 3.295389790e-03, 3.380491462e-03, 3.466227486e-03, 3.552591397e-03, 3.639576915e-03, 3.727177925e-03, 3.815388478e-03, 3.904202783e-03, 3.993615194e-03, 4.083620214e-03, 4.174212479e-03, 4.265386762e-03, 4.357137959e-03, 4.449461090e-03, 4.542351292e-03, 4.635803816e-03, 4.729814022e-03, 4.824377373e-03, 4.919489435e-03, 5.015145870e-03, 5.111342437e-03, 5.208074982e-03, 5.305339441e-03, 5.403131835e-03, 5.501448266e-03, 5.600284917e-03, 5.699638044e-03, 5.799503982e-03, 5.899879135e-03, 6.000759976e-03, 6.102143049e-03, 6.204024959e-03, 6.306402379e-03, 6.409272040e-03, 6.512630735e-03, 6.616475313e-03, 6.720802682e-03, 6.825609802e-03, 6.930893687e-03, 7.036651406e-03, 7.142880073e-03, 7.249576854e-03, 7.356738962e-03, 7.464363658e-03, 7.572448244e-03, 7.680990070e-03, 7.789986527e-03, 7.899435048e-03, 8.009333107e-03, 8.119678216e-03, 8.230467927e-03, 8.341699830e-03, 8.453371551e-03, 8.565480752e-03, 8.678025130e-03, 8.791002417e-03, 8.904410376e-03, 9.018246805e-03, 9.132509533e-03, 9.247196421e-03, 9.362305357e-03, 9.477834264e-03, 9.593781089e-03, 9.710143811e-03, 9.826920434e-03, 9.944108992e-03, 1.006170754e-02, 1.017971417e-02, 1.029812699e-02, 1.041694414e-02, 1.053616376e-02, 1.065578406e-02, 1.077580323e-02, 1.089621951e-02, 8.678412984e-01, 8.686259991e-01, 8.694122835e-01, 8.702001660e-01, 8.709896616e-01, 8.717807851e-01, 8.725735521e-01, 8.733679781e-01, 8.741640790e-01, 8.749618711e-01, 8.757613707e-01, 8.765625948e-01, 8.773655604e-01, 8.781702850e-01, 8.789767864e-01, 8.797850827e-01, 8.805951924e-01, 8.814071343e-01, 8.822209278e-01, 8.830365923e-01, 8.838541479e-01, 8.846736150e-01, 8.854950145e-01, 8.863183677e-01, 8.871436962e-01, 8.879710222e-01, 8.888003685e-01, 8.896317581e-01, 8.904652148e-01, 8.913007627e-01, 8.921384266e-01, 8.929782317e-01, 8.938202039e-01, 8.946643696e-01, 8.955107560e-01, 8.963593907e-01, 8.972103022e-01, 8.980635194e-01, 8.989190721e-01, 8.997769909e-01, 9.006373070e-01, 9.015000523e-01, 9.023652599e-01, 9.032329633e-01, 9.041031972e-01, 9.049759970e-01, 9.058513992e-01, 9.067294411e-01, 9.076101613e-01, 9.084935993e-01, 9.093797956e-01, 9.102687921e-01, 9.111606316e-01, 9.120553585e-01, 9.129530182e-01, 9.138536578e-01, 9.147573253e-01, 9.156640708e-01, 9.165739455e-01, 9.174870024e-01, 9.184032963e-01, 9.193228835e-01, 9.202458225e-01, 9.211721736e-01, 9.221019990e-01, 9.230353633e-01, 9.239723334e-01, 9.249129784e-01, 9.258573700e-01, 9.268055825e-01, 9.277576931e-01, 9.287137820e-01, 9.296739322e-01, 9.306382304e-01, 9.316067665e-01, 9.325796343e-01, 9.335569314e-01, 9.345387596e-01, 9.355252251e-01, 9.365164389e-01, 9.375125170e-01, 9.385135807e-01, 9.395197571e-01, 9.405311796e-01, 9.415479877e-01, 9.425703286e-01, 9.435983566e-01, 9.446322343e-01, 9.456721333e-01, 9.467182345e-01, 9.477707294e-01, 9.488298203e-01, 9.498957220e-01, 9.509686626e-01, 9.520488844e-01, 9.531366459e-01, 9.542322228e-01, 9.553359102e-01, 9.564480242e-01, 9.575689045e-01, 9.586989169e-01, 9.598384564e-01, 9.609879504e-01, 9.621478632e-01, 9.633187003e-01, 9.645010146e-01, 9.656954124e-01, 9.669025614e-01, 9.681232008e-01, 9.693581520e-01, 9.706083335e-01, 9.718747777e-01, 9.731586532e-01, 9.744612921e-01, 9.757842260e-01, 9.771292318e-01, 9.784983938e-01, 9.798941871e-01, 9.813195940e-01, 9.827782702e-01, 9.842747909e-01, 9.858150298e-01, 9.874067737e-01, 9.890607861e-01, 9.907928124e-01, 9.926278457e-01, 9.946110324e-01, 9.968464800e-01, 1.000000000e+00, }; const float dist_icdf_1_7[] = { 0.000000000e+00, 6.592502467e-05, 2.648932647e-04, 5.975786147e-04, 1.064331402e-03, 1.665386233e-03, 2.400913347e-03, 3.271040413e-03, 4.275863916e-03, 5.415455870e-03, 6.689868120e-03, 8.099135249e-03, 9.643276637e-03, 1.132229797e-02, 1.313619238e-02, 1.508494129e-02, 1.716851510e-02, 1.938687374e-02, 2.173996707e-02, 2.422773521e-02, 2.685010885e-02, 2.960700941e-02, 3.249834927e-02, 3.552403188e-02, 3.868395185e-02, 4.197799505e-02, 4.540603865e-02, 4.896795119e-02, 5.266359254e-02, 5.649281393e-02, 6.045545794e-02, 6.455135847e-02, 6.878034070e-02, 7.314222102e-02, 7.763680698e-02, 8.226389721e-02, 8.702328137e-02, 9.191473998e-02, 9.693804439e-02, 1.020929566e-01, 1.073792292e-01, 1.127966052e-01, 1.183448178e-01, 1.240235905e-01, 1.298326365e-01, 1.357716589e-01, 1.418403505e-01, 1.480383932e-01, 1.543654584e-01, 1.608212061e-01, 1.674052852e-01, 1.741173331e-01, 1.809569751e-01, 1.879238246e-01, 1.950174827e-01, 2.022375375e-01, 2.095835643e-01, 2.170551248e-01, 2.246517670e-01, 2.323730249e-01, 2.402184175e-01, 2.481874492e-01, 2.562796087e-01, 2.644943688e-01, 2.728311856e-01, 2.812894984e-01, 2.898687288e-01, 2.985682800e-01, 3.073875364e-01, 3.163258628e-01, 3.253826036e-01, 3.345570820e-01, 3.438485993e-01, 3.532564337e-01, 3.627798397e-01, 3.724180470e-01, 3.821702590e-01, 3.920356523e-01, 4.020133747e-01, 4.121025445e-01, 4.223022486e-01, 4.326115411e-01, 4.430294416e-01, 4.535549333e-01, 4.641869611e-01, 4.749244295e-01, 4.857661999e-01, 4.967110886e-01, 5.077578638e-01, 5.189052422e-01, 5.301518864e-01, 5.414964006e-01, 5.529373271e-01, 5.644731413e-01, 5.761022476e-01, 5.878229732e-01, 5.996335626e-01, 6.115321704e-01, 6.235168542e-01, 6.355855659e-01, 6.477361418e-01, 6.599662925e-01, 6.722735894e-01, 6.846554517e-01, 6.971091290e-01, 7.096316833e-01, 7.222199662e-01, 7.348705940e-01, 7.475799165e-01, 7.603439812e-01, 7.731584903e-01, 7.860187472e-01, 7.989195932e-01, 8.118553275e-01, 8.248196073e-01, 8.378053207e-01, 8.508044226e-01, 8.638077174e-01, 8.768045663e-01, 8.897824816e-01, 9.027265479e-01, 9.156185622e-01, 9.284356976e-01, 9.411482986e-01, 9.537159421e-01, 9.660795857e-01, 9.781430613e-01, 9.897144251e-01, 1.000000000e+00, 0.000000000e+00, 1.616208035e-07, 6.494156025e-07, 1.465058436e-06, 2.609444952e-06, 4.083202062e-06, 5.886813922e-06, 8.020675440e-06, 1.048512026e-05, 1.328043733e-05, 1.640688145e-05, 1.986468059e-05, 2.365404091e-05, 2.777515067e-05, 3.222818300e-05, 3.701329820e-05, 4.213064548e-05, 4.758036439e-05, 5.336258599e-05, 5.947743382e-05, 6.592502467e-05, 7.270546935e-05, 7.981887318e-05, 8.726533655e-05, 9.504495534e-05, 1.031578213e-04, 1.116040223e-04, 1.203836430e-04, 1.294967643e-04, 1.389434647e-04, 1.487238193e-04, 1.588379011e-04, 1.692857804e-04, 1.800675251e-04, 1.911832013e-04, 2.026328726e-04, 2.144166012e-04, 2.265344470e-04, 2.389864686e-04, 2.517727228e-04, 2.648932647e-04, 2.783481482e-04, 2.921374257e-04, 3.062611482e-04, 3.207193656e-04, 3.355121265e-04, 3.506394782e-04, 3.661014671e-04, 3.818981385e-04, 3.980295365e-04, 4.144957045e-04, 4.312966847e-04, 4.484325186e-04, 4.659032466e-04, 4.837089085e-04, 5.018495432e-04, 5.203251887e-04, 5.391358823e-04, 5.582816607e-04, 5.777625597e-04, 5.975786147e-04, 6.177298600e-04, 6.382163296e-04, 6.590380569e-04, 6.801950744e-04, 7.016874143e-04, 7.235151081e-04, 7.456781867e-04, 7.681766807e-04, 7.910106198e-04, 8.141800335e-04, 8.376849507e-04, 8.615253998e-04, 8.857014088e-04, 9.102130052e-04, 9.350602159e-04, 9.602430676e-04, 9.857615865e-04, 1.011615798e-03, 1.037805729e-03, 1.064331402e-03, 1.091192843e-03, 1.118390077e-03, 1.145923126e-03, 1.173792014e-03, 1.201996765e-03, 1.230537402e-03, 1.259413946e-03, 1.288626419e-03, 1.318174844e-03, 1.348059242e-03, 1.378279634e-03, 1.408836041e-03, 1.439728483e-03, 1.470956981e-03, 1.502521555e-03, 1.534422223e-03, 1.566659006e-03, 1.599231923e-03, 1.632140992e-03, 1.665386233e-03, 1.698967662e-03, 1.732885299e-03, 1.767139161e-03, 1.801729266e-03, 1.836655631e-03, 1.871918272e-03, 1.907517208e-03, 1.943452454e-03, 1.979724026e-03, 2.016331942e-03, 2.053276216e-03, 2.090556865e-03, 2.128173903e-03, 2.166127347e-03, 2.204417211e-03, 2.243043510e-03, 2.282006259e-03, 2.321305472e-03, 2.360941163e-03, 2.400913347e-03, 2.441222037e-03, 2.481867246e-03, 2.522848990e-03, 2.564167279e-03, 2.605822129e-03, 2.647813551e-03, 2.690141559e-03, 2.732806164e-03, 9.233195393e-01, 9.239598954e-01, 9.246000204e-01, 9.252399104e-01, 9.258795615e-01, 9.265189699e-01, 9.271581314e-01, 9.277970420e-01, 9.284356976e-01, 9.290740941e-01, 9.297122271e-01, 9.303500923e-01, 9.309876854e-01, 9.316250019e-01, 9.322620373e-01, 9.328987870e-01, 9.335352462e-01, 9.341714104e-01, 9.348072746e-01, 9.354428339e-01, 9.360780834e-01, 9.367130181e-01, 9.373476326e-01, 9.379819219e-01, 9.386158805e-01, 9.392495030e-01, 9.398827840e-01, 9.405157178e-01, 9.411482986e-01, 9.417805206e-01, 9.424123780e-01, 9.430438646e-01, 9.436749744e-01, 9.443057009e-01, 9.449360378e-01, 9.455659787e-01, 9.461955168e-01, 9.468246453e-01, 9.474533574e-01, 9.480816459e-01, 9.487095037e-01, 9.493369234e-01, 9.499638974e-01, 9.505904182e-01, 9.512164778e-01, 9.518420683e-01, 9.524671815e-01, 9.530918089e-01, 9.537159421e-01, 9.543395722e-01, 9.549626903e-01, 9.555852873e-01, 9.562073536e-01, 9.568288798e-01, 9.574498558e-01, 9.580702717e-01, 9.586901170e-01, 9.593093812e-01, 9.599280532e-01, 9.605461220e-01, 9.611635759e-01, 9.617804033e-01, 9.623965920e-01, 9.630121294e-01, 9.636270027e-01, 9.642411989e-01, 9.648547041e-01, 9.654675045e-01, 9.660795857e-01, 9.666909326e-01, 9.673015301e-01, 9.679113623e-01, 9.685204127e-01, 9.691286646e-01, 9.697361004e-01, 9.703427021e-01, 9.709484509e-01, 9.715533276e-01, 9.721573120e-01, 9.727603832e-01, 9.733625197e-01, 9.739636989e-01, 9.745638976e-01, 9.751630914e-01, 9.757612549e-01, 9.763583619e-01, 9.769543846e-01, 9.775492945e-01, 9.781430613e-01, 9.787356535e-01, 9.793270382e-01, 9.799171807e-01, 9.805060447e-01, 9.810935917e-01, 9.816797815e-01, 9.822645715e-01, 9.828479167e-01, 9.834297694e-01, 9.840100790e-01, 9.845887920e-01, 9.851658510e-01, 9.857411951e-01, 9.863147588e-01, 9.868864723e-01, 9.874562602e-01, 9.880240412e-01, 9.885897274e-01, 9.891532234e-01, 9.897144251e-01, 9.902732188e-01, 9.908294791e-01, 9.913830678e-01, 9.919338312e-01, 9.924815972e-01, 9.930261723e-01, 9.935673366e-01, 9.941048383e-01, 9.946383856e-01, 9.951676364e-01, 9.956921838e-01, 9.962115347e-01, 9.967250788e-01, 9.972320395e-01, 9.977313927e-01, 9.982217215e-01, 9.987009239e-01, 9.991655225e-01, 9.996084633e-01, 1.000000000e+00, }; const float dist_icdf_1_8[] = { 0.000000000e+00, 1.968089292e-12, 1.236989249e-10, 1.394171973e-09, 7.774761039e-09, 2.948608673e-08, 8.762690108e-08, 2.200748477e-07, 4.886614248e-07, 9.876149446e-07, 1.853266231e-06, 3.275012418e-06, 5.507534599e-06, 8.884265230e-06, 1.383210117e-05, 2.088735797e-05, 3.071296036e-05, 4.411686327e-05, 6.207169617e-05, 8.573562193e-05, 1.164743992e-04, 1.558846343e-04, 2.058182045e-04, 2.684078312e-04, 3.460937739e-04, 4.416516108e-04, 5.582210628e-04, 6.993358069e-04, 8.689542163e-04, 1.071490946e-03, 1.311849274e-03, 1.595454079e-03, 1.928285331e-03, 2.316911929e-03, 2.768525705e-03, 3.290975380e-03, 3.892800228e-03, 4.583263149e-03, 5.372382848e-03, 6.270964713e-03, 7.290630009e-03, 8.443842882e-03, 9.743934655e-03, 1.120512483e-02, 1.284253811e-02, 1.467221678e-02, 1.671112759e-02, 1.897716234e-02, 2.148913118e-02, 2.426674779e-02, 2.733060511e-02, 3.070214091e-02, 3.440359170e-02, 3.845793405e-02, 4.288881201e-02, 4.772044954e-02, 5.297754673e-02, 5.868515878e-02, 6.486855676e-02, 7.155306916e-02, 7.876390376e-02, 8.652594909e-02, 9.486355550e-02, 1.038002958e-01, 1.133587062e-01, 1.235600078e-01, 1.344238113e-01, 1.459678056e-01, 1.582074332e-01, 1.711555565e-01, 1.848221170e-01, 1.992137934e-01, 2.143336633e-01, 2.301808735e-01, 2.467503259e-01, 2.640323862e-01, 2.820126204e-01, 3.006715698e-01, 3.199845684e-01, 3.399216129e-01, 3.604472903e-01, 3.815207706e-01, 4.030958703e-01, 4.251211902e-01, 4.475403321e-01, 4.702921954e-01, 4.933113546e-01, 5.165285144e-01, 5.398710412e-01, 5.632635634e-01, 5.866286341e-01, 6.098874469e-01, 6.329605937e-01, 6.557688520e-01, 6.782339897e-01, 7.002795709e-01, 7.218317505e-01, 7.428200421e-01, 7.631780456e-01, 7.828441210e-01, 8.017619977e-01, 8.198813079e-01, 8.371580374e-01, 8.535548853e-01, 8.690415322e-01, 8.835948111e-01, 8.971987850e-01, 9.098447323e-01, 9.215310444e-01, 9.322630430e-01, 9.420527240e-01, 9.509184378e-01, 9.588845144e-01, 9.659808462e-01, 9.722424361e-01, 9.777089240e-01, 9.824240998e-01, 9.864354148e-01, 9.897934981e-01, 9.925516881e-01, 9.947655846e-01, 9.964926289e-01, 9.977917162e-01, 9.987228439e-01, 9.993467991e-01, 9.997248862e-01, 9.999186918e-01, 9.999898822e-01, 1.000000000e+00, 0.000000000e+00, 3.325295141e-20, 2.090024246e-18, 2.355601095e-17, 1.313628163e-16, 4.981986486e-16, 1.480549303e-15, 3.718397924e-15, 8.256454226e-15, 1.668680910e-14, 3.131292745e-14, 5.533490434e-14, 9.305591864e-14, 1.501098257e-13, 2.337098359e-13, 3.529182322e-13, 5.189370804e-13, 7.454198943e-13, 1.048804215e-12, 1.448665073e-12, 1.968089292e-12, 2.634070617e-12, 3.477925623e-12, 4.535730381e-12, 5.848777867e-12, 7.464056061e-12, 9.434746749e-12, 1.182074497e-11, 1.468919909e-11, 1.811507156e-11, 2.218172014e-11, 2.698149987e-11, 3.261638544e-11, 3.919861419e-11, 4.685134962e-11, 5.570936541e-11, 6.591974986e-11, 7.764263094e-11, 9.105192165e-11, 1.063360859e-10, 1.236989249e-10, 1.433603836e-10, 1.655573783e-10, 1.905446435e-10, 2.185956003e-10, 2.500032445e-10, 2.850810550e-10, 3.241639228e-10, 3.676091003e-10, 4.157971709e-10, 4.691330386e-10, 5.280469386e-10, 5.929954671e-10, 6.644626325e-10, 7.429609261e-10, 8.290324133e-10, 9.232498452e-10, 1.026217790e-09, 1.138573785e-09, 1.260989509e-09, 1.394171973e-09, 1.538864737e-09, 1.695849135e-09, 1.865945536e-09, 2.050014613e-09, 2.248958635e-09, 2.463722782e-09, 2.695296480e-09, 2.944714751e-09, 3.213059588e-09, 3.501461352e-09, 3.811100181e-09, 4.143207425e-09, 4.499067104e-09, 4.880017378e-09, 5.287452042e-09, 5.722822042e-09, 6.187637007e-09, 6.683466806e-09, 7.211943120e-09, 7.774761039e-09, 8.373680675e-09, 9.010528794e-09, 9.687200478e-09, 1.040566079e-08, 1.116794648e-08, 1.197616769e-08, 1.283250968e-08, 1.373923462e-08, 1.469868332e-08, 1.571327705e-08, 1.678551933e-08, 1.791799783e-08, 1.911338611e-08, 2.037444563e-08, 2.170402752e-08, 2.310507459e-08, 2.458062320e-08, 2.613380524e-08, 2.776785012e-08, 2.948608673e-08, 3.129194547e-08, 3.318896030e-08, 3.518077077e-08, 3.727112408e-08, 3.946387724e-08, 4.176299911e-08, 4.417257255e-08, 4.669679661e-08, 4.933998867e-08, 5.210658665e-08, 5.500115118e-08, 5.802836792e-08, 6.119304970e-08, 6.450013891e-08, 6.795470968e-08, 7.156197029e-08, 7.532726543e-08, 7.925607858e-08, 8.335403440e-08, 8.762690108e-08, 9.208059279e-08, 9.672117209e-08, 1.015548524e-07, 1.065880004e-07, 1.118271386e-07, 1.172789479e-07, 1.229502699e-07, 1.288481098e-07, 9.973196172e-01, 9.973819818e-01, 9.974433736e-01, 9.975038000e-01, 9.975632687e-01, 9.976217871e-01, 9.976793628e-01, 9.977360033e-01, 9.977917162e-01, 9.978465090e-01, 9.979003894e-01, 9.979533648e-01, 9.980054428e-01, 9.980566311e-01, 9.981069371e-01, 9.981563685e-01, 9.982049329e-01, 9.982526378e-01, 9.982994909e-01, 9.983454997e-01, 9.983906719e-01, 9.984350150e-01, 9.984785367e-01, 9.985212447e-01, 9.985631464e-01, 9.986042495e-01, 9.986445617e-01, 9.986840906e-01, 9.987228439e-01, 9.987608291e-01, 9.987980539e-01, 9.988345259e-01, 9.988702528e-01, 9.989052423e-01, 9.989395020e-01, 9.989730395e-01, 9.990058625e-01, 9.990379787e-01, 9.990693957e-01, 9.991001212e-01, 9.991301629e-01, 9.991595284e-01, 9.991882255e-01, 9.992162617e-01, 9.992436447e-01, 9.992703823e-01, 9.992964821e-01, 9.993219518e-01, 9.993467991e-01, 9.993710317e-01, 9.993946572e-01, 9.994176834e-01, 9.994401179e-01, 9.994619685e-01, 9.994832428e-01, 9.995039485e-01, 9.995240933e-01, 9.995436850e-01, 9.995627311e-01, 9.995812395e-01, 9.995992179e-01, 9.996166738e-01, 9.996336151e-01, 9.996500494e-01, 9.996659844e-01, 9.996814279e-01, 9.996963876e-01, 9.997108711e-01, 9.997248862e-01, 9.997384406e-01, 9.997515419e-01, 9.997641980e-01, 9.997764164e-01, 9.997882050e-01, 9.997995715e-01, 9.998105234e-01, 9.998210686e-01, 9.998312148e-01, 9.998409697e-01, 9.998503409e-01, 9.998593363e-01, 9.998679634e-01, 9.998762301e-01, 9.998841440e-01, 9.998917128e-01, 9.998989443e-01, 9.999058462e-01, 9.999124261e-01, 9.999186918e-01, 9.999246510e-01, 9.999303114e-01, 9.999356806e-01, 9.999407665e-01, 9.999455767e-01, 9.999501189e-01, 9.999544008e-01, 9.999584301e-01, 9.999622146e-01, 9.999657619e-01, 9.999690796e-01, 9.999721756e-01, 9.999750575e-01, 9.999777330e-01, 9.999802098e-01, 9.999824956e-01, 9.999845980e-01, 9.999865248e-01, 9.999882836e-01, 9.999898822e-01, 9.999913282e-01, 9.999926292e-01, 9.999937930e-01, 9.999948273e-01, 9.999957396e-01, 9.999965377e-01, 9.999972292e-01, 9.999978219e-01, 9.999983232e-01, 9.999987410e-01, 9.999990828e-01, 9.999993563e-01, 9.999995692e-01, 9.999997290e-01, 9.999998433e-01, 9.999999199e-01, 9.999999663e-01, 9.999999900e-01, 9.999999988e-01, 1.000000000e+00, }; const float dist_icdf_2_0[] = { 0.000000000e+00, 2.237672937e-01, 2.285440040e-01, 2.315843188e-01, 2.338746000e-01, 2.357386352e-01, 2.373253744e-01, 2.387163221e-01, 2.399611778e-01, 2.410925969e-01, 2.421332450e-01, 2.430995295e-01, 2.440037306e-01, 2.448552915e-01, 2.456616389e-01, 2.464287258e-01, 2.471614013e-01, 2.478636718e-01, 2.485388879e-01, 2.491898826e-01, 2.498190743e-01, 2.504285456e-01, 2.510201037e-01, 2.515953283e-01, 2.521556093e-01, 2.527021764e-01, 2.532361239e-01, 2.537584308e-01, 2.542699767e-01, 2.547715555e-01, 2.552638870e-01, 2.557476261e-01, 2.562233710e-01, 2.566916700e-01, 2.571530275e-01, 2.576079089e-01, 2.580567449e-01, 2.584999356e-01, 2.589378533e-01, 2.593708457e-01, 2.597992386e-01, 2.602233376e-01, 2.606434306e-01, 2.610597894e-01, 2.614726711e-01, 2.618823197e-01, 2.622889672e-01, 2.626928352e-01, 2.630941351e-01, 2.634930699e-01, 2.638898346e-01, 2.642846170e-01, 2.646775986e-01, 2.650689550e-01, 2.654588569e-01, 2.658474705e-01, 2.662349577e-01, 2.666214772e-01, 2.670071847e-01, 2.673922333e-01, 2.677767740e-01, 2.681609563e-01, 2.685449282e-01, 2.689288371e-01, 2.693128298e-01, 2.696970532e-01, 2.700816545e-01, 2.704667816e-01, 2.708525836e-01, 2.712392111e-01, 2.716268168e-01, 2.720155558e-01, 2.724055857e-01, 2.727970680e-01, 2.731901676e-01, 2.735850538e-01, 2.739819008e-01, 2.743808884e-01, 2.747822024e-01, 2.751860354e-01, 2.755925874e-01, 2.760020669e-01, 2.764146914e-01, 2.768306888e-01, 2.772502979e-01, 2.776737700e-01, 2.781013700e-01, 2.785333778e-01, 2.789700899e-01, 2.794118213e-01, 2.798589071e-01, 2.803117054e-01, 2.807705990e-01, 2.812359989e-01, 2.817083474e-01, 2.821881216e-01, 2.826758380e-01, 2.831720572e-01, 2.836773897e-01, 2.841925025e-01, 2.847181272e-01, 2.852550686e-01, 2.858042160e-01, 2.863665561e-01, 2.869431883e-01, 2.875353432e-01, 2.881444058e-01, 2.887719433e-01, 2.894197393e-01, 2.900898371e-01, 2.907845943e-01, 2.915067526e-01, 2.922595280e-01, 2.930467297e-01, 2.938729188e-01, 2.947436250e-01, 2.956656471e-01, 2.966474820e-01, 2.976999534e-01, 2.988371642e-01, 3.000779982e-01, 3.014486035e-01, 3.029867529e-01, 3.047501085e-01, 3.068335679e-01, 3.094113041e-01, 3.128640397e-01, 3.183611310e-01, 1.000000000e+00, 0.000000000e+00, 2.071142520e-01, 2.105359226e-01, 2.126391547e-01, 2.141820491e-01, 2.154100048e-01, 2.164347847e-01, 2.173170522e-01, 2.180935449e-01, 2.187882558e-01, 2.194177473e-01, 2.199939495e-01, 2.205257498e-01, 2.210199526e-01, 2.214818874e-01, 2.219158087e-01, 2.223251688e-01, 2.227128090e-01, 2.230810969e-01, 2.234320265e-01, 2.237672937e-01, 2.240883533e-01, 2.243964629e-01, 2.246927174e-01, 2.249780760e-01, 2.252533839e-01, 2.255193899e-01, 2.257767607e-01, 2.260260924e-01, 2.262679202e-01, 2.265027267e-01, 2.267309484e-01, 2.269529818e-01, 2.271691877e-01, 2.273798958e-01, 2.275854078e-01, 2.277860010e-01, 2.279819305e-01, 2.281734317e-01, 2.283607223e-01, 2.285440040e-01, 2.287234639e-01, 2.288992763e-01, 2.290716035e-01, 2.292405968e-01, 2.294063978e-01, 2.295691392e-01, 2.297289453e-01, 2.298859327e-01, 2.300402112e-01, 2.301918842e-01, 2.303410491e-01, 2.304877977e-01, 2.306322171e-01, 2.307743892e-01, 2.309143920e-01, 2.310522991e-01, 2.311881805e-01, 2.313221026e-01, 2.314541287e-01, 2.315843188e-01, 2.317127300e-01, 2.318394170e-01, 2.319644317e-01, 2.320878237e-01, 2.322096405e-01, 2.323299273e-01, 2.324487276e-01, 2.325660827e-01, 2.326820325e-01, 2.327966149e-01, 2.329098666e-01, 2.330218225e-01, 2.331325163e-01, 2.332419804e-01, 2.333502458e-01, 2.334573424e-01, 2.335632989e-01, 2.336681431e-01, 2.337719016e-01, 2.338746000e-01, 2.339762633e-01, 2.340769152e-01, 2.341765788e-01, 2.342752764e-01, 2.343730295e-01, 2.344698589e-01, 2.345657846e-01, 2.346608261e-01, 2.347550022e-01, 2.348483310e-01, 2.349408301e-01, 2.350325167e-01, 2.351234072e-01, 2.352135175e-01, 2.353028633e-01, 2.353914596e-01, 2.354793210e-01, 2.355664616e-01, 2.356528952e-01, 2.357386352e-01, 2.358236945e-01, 2.359080858e-01, 2.359918212e-01, 2.360749127e-01, 2.361573718e-01, 2.362392099e-01, 2.363204379e-01, 2.364010664e-01, 2.364811059e-01, 2.365605663e-01, 2.366394577e-01, 2.367177895e-01, 2.367955712e-01, 2.368728117e-01, 2.369495201e-01, 2.370257049e-01, 2.371013746e-01, 2.371765374e-01, 2.372512014e-01, 2.373253744e-01, 2.373990641e-01, 2.374722779e-01, 2.375450231e-01, 2.376173069e-01, 2.376891362e-01, 2.377605178e-01, 2.378314584e-01, 2.379019644e-01, 3.023482827e-01, 3.024262900e-01, 3.025047965e-01, 3.025838097e-01, 3.026633373e-01, 3.027433873e-01, 3.028239676e-01, 3.029050867e-01, 3.029867529e-01, 3.030689749e-01, 3.031517616e-01, 3.032351222e-01, 3.033190660e-01, 3.034036025e-01, 3.034887416e-01, 3.035744933e-01, 3.036608679e-01, 3.037478761e-01, 3.038355287e-01, 3.039238368e-01, 3.040128120e-01, 3.041024660e-01, 3.041928108e-01, 3.042838590e-01, 3.043756232e-01, 3.044681165e-01, 3.045613525e-01, 3.046553451e-01, 3.047501085e-01, 3.048456573e-01, 3.049420068e-01, 3.050391725e-01, 3.051371705e-01, 3.052360172e-01, 3.053357297e-01, 3.054363256e-01, 3.055378230e-01, 3.056402406e-01, 3.057435976e-01, 3.058479140e-01, 3.059532104e-01, 3.060595080e-01, 3.061668287e-01, 3.062751953e-01, 3.063846313e-01, 3.064951609e-01, 3.066068094e-01, 3.067196027e-01, 3.068335679e-01, 3.069487330e-01, 3.070651270e-01, 3.071827799e-01, 3.073017230e-01, 3.074219888e-01, 3.075436110e-01, 3.076666246e-01, 3.077910660e-01, 3.079169733e-01, 3.080443858e-01, 3.081733448e-01, 3.083038931e-01, 3.084360754e-01, 3.085699385e-01, 3.087055310e-01, 3.088429040e-01, 3.089821107e-01, 3.091232069e-01, 3.092662509e-01, 3.094113041e-01, 3.095584305e-01, 3.097076976e-01, 3.098591762e-01, 3.100129406e-01, 3.101690693e-01, 3.103276447e-01, 3.104887538e-01, 3.106524885e-01, 3.108189457e-01, 3.109882280e-01, 3.111604442e-01, 3.113357092e-01, 3.115141453e-01, 3.116958823e-01, 3.118810583e-01, 3.120698206e-01, 3.122623261e-01, 3.124587426e-01, 3.126592496e-01, 3.128640397e-01, 3.130733194e-01, 3.132873109e-01, 3.135062539e-01, 3.137304068e-01, 3.139600497e-01, 3.141954860e-01, 3.144370455e-01, 3.146850877e-01, 3.149400053e-01, 3.152022285e-01, 3.154722301e-01, 3.157505311e-01, 3.160377080e-01, 3.163344003e-01, 3.166413211e-01, 3.169592681e-01, 3.172891382e-01, 3.176319443e-01, 3.179888371e-01, 3.183611310e-01, 3.187503370e-01, 3.191582048e-01, 3.195867759e-01, 3.200384532e-01, 3.205160924e-01, 3.210231247e-01, 3.215637244e-01, 3.221430419e-01, 3.227675378e-01, 3.234454730e-01, 3.241876547e-01, 3.250086151e-01, 3.259285692e-01, 3.269768652e-01, 3.281985533e-01, 3.296682426e-01, 3.315238816e-01, 3.340697709e-01, 3.382524533e-01, 1.000000000e+00, }; const float dist_icdf_2_1[] = { 0.000000000e+00, 1.859542478e-01, 2.030266017e-01, 2.142287108e-01, 2.228310438e-01, 2.299321245e-01, 2.360449678e-01, 2.414535080e-01, 2.463324831e-01, 2.507975981e-01, 2.549297009e-01, 2.587876628e-01, 2.624157784e-01, 2.658482727e-01, 2.691121802e-01, 2.722292574e-01, 2.752172943e-01, 2.780910396e-01, 2.808628693e-01, 2.835432798e-01, 2.861412585e-01, 2.886645665e-01, 2.911199576e-01, 2.935133508e-01, 2.958499662e-01, 2.981344353e-01, 3.003708891e-01, 3.025630316e-01, 3.047141989e-01, 3.068274093e-01, 3.089054052e-01, 3.109506877e-01, 3.129655464e-01, 3.149520851e-01, 3.169122428e-01, 3.188478132e-01, 3.207604601e-01, 3.226517321e-01, 3.245230743e-01, 3.263758395e-01, 3.282112975e-01, 3.300306436e-01, 3.318350056e-01, 3.336254511e-01, 3.354029929e-01, 3.371685947e-01, 3.389231755e-01, 3.406676141e-01, 3.424027533e-01, 3.441294032e-01, 3.458483443e-01, 3.475603310e-01, 3.492660941e-01, 3.509663435e-01, 3.526617703e-01, 3.543530494e-01, 3.560408418e-01, 3.577257958e-01, 3.594085497e-01, 3.610897335e-01, 3.627699702e-01, 3.644498781e-01, 3.661300719e-01, 3.678111648e-01, 3.694937701e-01, 3.711785023e-01, 3.728659792e-01, 3.745568236e-01, 3.762516646e-01, 3.779511393e-01, 3.796558950e-01, 3.813665906e-01, 3.830838985e-01, 3.848085068e-01, 3.865411212e-01, 3.882824675e-01, 3.900332933e-01, 3.917943714e-01, 3.935665017e-01, 3.953505146e-01, 3.971472742e-01, 3.989576812e-01, 4.007826772e-01, 4.026232487e-01, 4.044804314e-01, 4.063553153e-01, 4.082490504e-01, 4.101628522e-01, 4.120980096e-01, 4.140558913e-01, 4.160379553e-01, 4.180457579e-01, 4.200809652e-01, 4.221453648e-01, 4.242408801e-01, 4.263695867e-01, 4.285337302e-01, 4.307357480e-01, 4.329782934e-01, 4.352642647e-01, 4.375968381e-01, 4.399795076e-01, 4.424161310e-01, 4.449109856e-01, 4.474688341e-01, 4.500950050e-01, 4.527954890e-01, 4.555770586e-01, 4.584474150e-01, 4.614153718e-01, 4.644910869e-01, 4.676863584e-01, 4.710150084e-01, 4.744933855e-01, 4.781410371e-01, 4.819816218e-01, 4.860441784e-01, 4.903649284e-01, 4.949899151e-01, 4.999789916e-01, 5.054120924e-01, 5.113995761e-01, 5.181003269e-01, 5.257559352e-01, 5.347621208e-01, 5.458408909e-01, 5.605580193e-01, 5.836638935e-01, 1.000000000e+00, 0.000000000e+00, 1.320233851e-01, 1.423504406e-01, 1.488981756e-01, 1.537964510e-01, 1.577515107e-01, 1.610901466e-01, 1.639918877e-01, 1.665665248e-01, 1.688863544e-01, 1.710016416e-01, 1.729488204e-01, 1.747551863e-01, 1.764417447e-01, 1.780250238e-01, 1.795182751e-01, 1.809322945e-01, 1.822759999e-01, 1.835568476e-01, 1.847811385e-01, 1.859542478e-01, 1.870807998e-01, 1.881648030e-01, 1.892097564e-01, 1.902187329e-01, 1.911944471e-01, 1.921393091e-01, 1.930554691e-01, 1.939448542e-01, 1.948091983e-01, 1.956500674e-01, 1.964688812e-01, 1.972669306e-01, 1.980453932e-01, 1.988053464e-01, 1.995477787e-01, 2.002735989e-01, 2.009836451e-01, 2.016786915e-01, 2.023594553e-01, 2.030266017e-01, 2.036807492e-01, 2.043224739e-01, 2.049523133e-01, 2.055707697e-01, 2.061783132e-01, 2.067753847e-01, 2.073623979e-01, 2.079397419e-01, 2.085077828e-01, 2.090668659e-01, 2.096173167e-01, 2.101594431e-01, 2.106935361e-01, 2.112198714e-01, 2.117387101e-01, 2.122503001e-01, 2.127548768e-01, 2.132526639e-01, 2.137438743e-01, 2.142287108e-01, 2.147073665e-01, 2.151800258e-01, 2.156468644e-01, 2.161080506e-01, 2.165637448e-01, 2.170141009e-01, 2.174592658e-01, 2.178993806e-01, 2.183345803e-01, 2.187649946e-01, 2.191907477e-01, 2.196119591e-01, 2.200287436e-01, 2.204412114e-01, 2.208494687e-01, 2.212536177e-01, 2.216537566e-01, 2.220499803e-01, 2.224423800e-01, 2.228310438e-01, 2.232160568e-01, 2.235975008e-01, 2.239754551e-01, 2.243499962e-01, 2.247211981e-01, 2.250891322e-01, 2.254538676e-01, 2.258154713e-01, 2.261740081e-01, 2.265295406e-01, 2.268821296e-01, 2.272318340e-01, 2.275787108e-01, 2.279228154e-01, 2.282642015e-01, 2.286029211e-01, 2.289390248e-01, 2.292725617e-01, 2.296035795e-01, 2.299321245e-01, 2.302582416e-01, 2.305819748e-01, 2.309033664e-01, 2.312224580e-01, 2.315392898e-01, 2.318539009e-01, 2.321663295e-01, 2.324766128e-01, 2.327847869e-01, 2.330908871e-01, 2.333949477e-01, 2.336970022e-01, 2.339970831e-01, 2.342952224e-01, 2.345914510e-01, 2.348857992e-01, 2.351782964e-01, 2.354689717e-01, 2.357578530e-01, 2.360449678e-01, 2.363303430e-01, 2.366140048e-01, 2.368959787e-01, 2.371762897e-01, 2.374549623e-01, 2.377320204e-01, 2.380074874e-01, 2.382813860e-01, 5.153214020e-01, 5.156611194e-01, 5.160029569e-01, 5.163469462e-01, 5.166931196e-01, 5.170415101e-01, 5.173921516e-01, 5.177450787e-01, 5.181003269e-01, 5.184579325e-01, 5.188179326e-01, 5.191803655e-01, 5.195452700e-01, 5.199126863e-01, 5.202826553e-01, 5.206552191e-01, 5.210304208e-01, 5.214083046e-01, 5.217889160e-01, 5.221723014e-01, 5.225585087e-01, 5.229475870e-01, 5.233395866e-01, 5.237345594e-01, 5.241325585e-01, 5.245336387e-01, 5.249378560e-01, 5.253452684e-01, 5.257559352e-01, 5.261699176e-01, 5.265872786e-01, 5.270080830e-01, 5.274323975e-01, 5.278602907e-01, 5.282918337e-01, 5.287270992e-01, 5.291661627e-01, 5.296091018e-01, 5.300559965e-01, 5.305069295e-01, 5.309619862e-01, 5.314212547e-01, 5.318848262e-01, 5.323527947e-01, 5.328252576e-01, 5.333023156e-01, 5.337840729e-01, 5.342706374e-01, 5.347621208e-01, 5.352586390e-01, 5.357603118e-01, 5.362672639e-01, 5.367796243e-01, 5.372975271e-01, 5.378211115e-01, 5.383505222e-01, 5.388859097e-01, 5.394274304e-01, 5.399752472e-01, 5.405295297e-01, 5.410904546e-01, 5.416582061e-01, 5.422329765e-01, 5.428149665e-01, 5.434043856e-01, 5.440014529e-01, 5.446063978e-01, 5.452194600e-01, 5.458408909e-01, 5.464709541e-01, 5.471099260e-01, 5.477580968e-01, 5.484157717e-01, 5.490832715e-01, 5.497609341e-01, 5.504491156e-01, 5.511481915e-01, 5.518585583e-01, 5.525806353e-01, 5.533148659e-01, 5.540617201e-01, 5.548216962e-01, 5.555953236e-01, 5.563831648e-01, 5.571858192e-01, 5.580039255e-01, 5.588381660e-01, 5.596892701e-01, 5.605580193e-01, 5.614452520e-01, 5.623518694e-01, 5.632788419e-01, 5.642272167e-01, 5.651981257e-01, 5.661927957e-01, 5.672125589e-01, 5.682588658e-01, 5.693332996e-01, 5.704375930e-01, 5.715736485e-01, 5.727435607e-01, 5.739496441e-01, 5.751944653e-01, 5.764808808e-01, 5.778120840e-01, 5.791916600e-01, 5.806236539e-01, 5.821126537e-01, 5.836638935e-01, 5.852833820e-01, 5.869780657e-01, 5.887560374e-01, 5.906268058e-01, 5.926016517e-01, 5.946941033e-01, 5.969205837e-01, 5.993013129e-01, 6.018615930e-01, 6.046336933e-01, 6.076597081e-01, 6.109960624e-01, 6.147209672e-01, 6.189475113e-01, 6.238484787e-01, 6.297084304e-01, 6.370498843e-01, 6.470149727e-01, 6.631069916e-01, 1.000000000e+00, }; const float dist_icdf_2_2[] = { 0.000000000e+00, 8.118337049e-02, 1.023138483e-01, 1.174621933e-01, 1.297526043e-01, 1.403112116e-01, 1.496887316e-01, 1.582007333e-01, 1.660469292e-01, 1.733626958e-01, 1.802445542e-01, 1.867640456e-01, 1.929758544e-01, 1.989228414e-01, 2.046393065e-01, 2.101531860e-01, 2.154875781e-01, 2.206618321e-01, 2.256923431e-01, 2.305931449e-01, 2.353763584e-01, 2.400525381e-01, 2.446309418e-01, 2.491197450e-01, 2.535262109e-01, 2.578568297e-01, 2.621174303e-01, 2.663132738e-01, 2.704491303e-01, 2.745293430e-01, 2.785578826e-01, 2.825383932e-01, 2.864742311e-01, 2.903684984e-01, 2.942240718e-01, 2.980436275e-01, 3.018296630e-01, 3.055845160e-01, 3.093103809e-01, 3.130093237e-01, 3.166832948e-01, 3.203341406e-01, 3.239636136e-01, 3.275733819e-01, 3.311650372e-01, 3.347401025e-01, 3.383000385e-01, 3.418462503e-01, 3.453800924e-01, 3.489028742e-01, 3.524158648e-01, 3.559202971e-01, 3.594173722e-01, 3.629082628e-01, 3.663941172e-01, 3.698760623e-01, 3.733552070e-01, 3.768326452e-01, 3.803094588e-01, 3.837867203e-01, 3.872654956e-01, 3.907468468e-01, 3.942318348e-01, 3.977215218e-01, 4.012169739e-01, 4.047192640e-01, 4.082294738e-01, 4.117486971e-01, 4.152780423e-01, 4.188186351e-01, 4.223716215e-01, 4.259381708e-01, 4.295194789e-01, 4.331167715e-01, 4.367313075e-01, 4.403643831e-01, 4.440173352e-01, 4.476915465e-01, 4.513884492e-01, 4.551095305e-01, 4.588563379e-01, 4.626304849e-01, 4.664336572e-01, 4.702676202e-01, 4.741342259e-01, 4.780354221e-01, 4.819732610e-01, 4.859499100e-01, 4.899676628e-01, 4.940289525e-01, 4.981363656e-01, 5.022926583e-01, 5.065007745e-01, 5.107638665e-01, 5.150853179e-01, 5.194687702e-01, 5.239181535e-01, 5.284377209e-01, 5.330320886e-01, 5.377062831e-01, 5.424657950e-01, 5.473166429e-01, 5.522654479e-01, 5.573195231e-01, 5.624869788e-01, 5.677768502e-01, 5.731992509e-01, 5.787655604e-01, 5.844886555e-01, 5.903831966e-01, 5.964659877e-01, 6.027564333e-01, 6.092771266e-01, 6.160546161e-01, 6.231204220e-01, 6.305124087e-01, 6.382766741e-01, 6.464702150e-01, 6.551647906e-01, 6.644527026e-01, 6.744557835e-01, 6.853400369e-01, 6.973408986e-01, 7.108101706e-01, 7.263122279e-01, 7.448505278e-01, 7.685278469e-01, 8.033973195e-01, 1.000000000e+00, 0.000000000e+00, 3.106621173e-02, 3.865437620e-02, 4.396047104e-02, 4.818156417e-02, 5.174682664e-02, 5.486532158e-02, 5.765646720e-02, 6.019563397e-02, 6.253378827e-02, 6.470718680e-02, 6.674264590e-02, 6.866062137e-02, 7.047711355e-02, 7.220490096e-02, 7.385436959e-02, 7.543408836e-02, 7.695121930e-02, 7.841181665e-02, 7.982104951e-02, 8.118337049e-02, 8.250264551e-02, 8.378225504e-02, 8.502517414e-02, 8.623403642e-02, 8.741118568e-02, 8.855871805e-02, 8.967851653e-02, 9.077227977e-02, 9.184154592e-02, 9.288771284e-02, 9.391205503e-02, 9.491573821e-02, 9.589983160e-02, 9.686531862e-02, 9.781310607e-02, 9.874403212e-02, 9.965887320e-02, 1.005583502e-01, 1.014431335e-01, 1.023138483e-01, 1.031710779e-01, 1.040153682e-01, 1.048472305e-01, 1.056671445e-01, 1.064755612e-01, 1.072729046e-01, 1.080595746e-01, 1.088359484e-01, 1.096023824e-01, 1.103592135e-01, 1.111067610e-01, 1.118453273e-01, 1.125751995e-01, 1.132966503e-01, 1.140099390e-01, 1.147153123e-01, 1.154130054e-01, 1.161032423e-01, 1.167862369e-01, 1.174621933e-01, 1.181313069e-01, 1.187937641e-01, 1.194497437e-01, 1.200994169e-01, 1.207429477e-01, 1.213804934e-01, 1.220122049e-01, 1.226382274e-01, 1.232587001e-01, 1.238737570e-01, 1.244835270e-01, 1.250881342e-01, 1.256876979e-01, 1.262823335e-01, 1.268721518e-01, 1.274572599e-01, 1.280377611e-01, 1.286137553e-01, 1.291853386e-01, 1.297526043e-01, 1.303156423e-01, 1.308745398e-01, 1.314293809e-01, 1.319802472e-01, 1.325272176e-01, 1.330703687e-01, 1.336097745e-01, 1.341455069e-01, 1.346776357e-01, 1.352062283e-01, 1.357313505e-01, 1.362530658e-01, 1.367714363e-01, 1.372865218e-01, 1.377983809e-01, 1.383070703e-01, 1.388126451e-01, 1.393151590e-01, 1.398146642e-01, 1.403112116e-01, 1.408048505e-01, 1.412956292e-01, 1.417835945e-01, 1.422687921e-01, 1.427512666e-01, 1.432310613e-01, 1.437082185e-01, 1.441827795e-01, 1.446547846e-01, 1.451242729e-01, 1.455912828e-01, 1.460558516e-01, 1.465180159e-01, 1.469778114e-01, 1.474352727e-01, 1.478904340e-01, 1.483433284e-01, 1.487939885e-01, 1.492424459e-01, 1.496887316e-01, 1.501328762e-01, 1.505749091e-01, 1.510148594e-01, 1.514527556e-01, 1.518886254e-01, 1.523224961e-01, 1.527543942e-01, 1.531843458e-01, 6.923874374e-01, 6.929947893e-01, 6.936054269e-01, 6.942193962e-01, 6.948367441e-01, 6.954575186e-01, 6.960817689e-01, 6.967095451e-01, 6.973408986e-01, 6.979758819e-01, 6.986145488e-01, 6.992569543e-01, 6.999031546e-01, 7.005532074e-01, 7.012071718e-01, 7.018651083e-01, 7.025270786e-01, 7.031931464e-01, 7.038633767e-01, 7.045378361e-01, 7.052165930e-01, 7.058997175e-01, 7.065872817e-01, 7.072793592e-01, 7.079760258e-01, 7.086773593e-01, 7.093834396e-01, 7.100943486e-01, 7.108101706e-01, 7.115309922e-01, 7.122569024e-01, 7.129879928e-01, 7.137243574e-01, 7.144660931e-01, 7.152132995e-01, 7.159660793e-01, 7.167245381e-01, 7.174887847e-01, 7.182589312e-01, 7.190350932e-01, 7.198173899e-01, 7.206059441e-01, 7.214008828e-01, 7.222023368e-01, 7.230104413e-01, 7.238253359e-01, 7.246471650e-01, 7.254760775e-01, 7.263122279e-01, 7.271557756e-01, 7.280068860e-01, 7.288657300e-01, 7.297324848e-01, 7.306073341e-01, 7.314904684e-01, 7.323820852e-01, 7.332823897e-01, 7.341915948e-01, 7.351099217e-01, 7.360376006e-01, 7.369748708e-01, 7.379219813e-01, 7.388791914e-01, 7.398467716e-01, 7.408250034e-01, 7.418141811e-01, 7.428146114e-01, 7.438266152e-01, 7.448505278e-01, 7.458866999e-01, 7.469354989e-01, 7.479973096e-01, 7.490725358e-01, 7.501616011e-01, 7.512649506e-01, 7.523830523e-01, 7.535163988e-01, 7.546655088e-01, 7.558309295e-01, 7.570132385e-01, 7.582130461e-01, 7.594309982e-01, 7.606677786e-01, 7.619241127e-01, 7.632007707e-01, 7.644985716e-01, 7.658183875e-01, 7.671611482e-01, 7.685278469e-01, 7.699195457e-01, 7.713373831e-01, 7.727825808e-01, 7.742564529e-01, 7.757604152e-01, 7.772959967e-01, 7.788648518e-01, 7.804687753e-01, 7.821097187e-01, 7.837898095e-01, 7.855113740e-01, 7.872769630e-01, 7.890893826e-01, 7.909517305e-01, 7.928674385e-01, 7.948403240e-01, 7.968746515e-01, 7.989752069e-01, 8.011473886e-01, 8.033973195e-01, 8.057319861e-01, 8.081594140e-01, 8.106888897e-01, 8.133312474e-01, 8.160992432e-01, 8.190080511e-01, 8.220759342e-01, 8.253251700e-01, 8.287833569e-01, 8.324853107e-01, 8.364759073e-01, 8.408145094e-01, 8.455821903e-01, 8.508942228e-01, 8.569233339e-01, 8.639474923e-01, 8.724627474e-01, 8.835133158e-01, 9.001240145e-01, 1.000000000e+00, }; const float dist_icdf_2_3[] = { 0.000000000e+00, 5.156460241e-02, 7.025365981e-02, 8.438877451e-02, 9.624538510e-02, 1.066801039e-01, 1.161239739e-01, 1.248293697e-01, 1.329588097e-01, 1.406240760e-01, 1.479058747e-01, 1.548646901e-01, 1.615472133e-01, 1.679903684e-01, 1.742239464e-01, 1.802723945e-01, 1.861560676e-01, 1.918921289e-01, 1.974952111e-01, 2.029779120e-01, 2.083511730e-01, 2.136245718e-01, 2.188065524e-01, 2.239046078e-01, 2.289254267e-01, 2.338750129e-01, 2.387587830e-01, 2.435816472e-01, 2.483480763e-01, 2.530621582e-01, 2.577276455e-01, 2.623479963e-01, 2.669264082e-01, 2.714658487e-01, 2.759690802e-01, 2.804386829e-01, 2.848770741e-01, 2.892865251e-01, 2.936691765e-01, 2.980270511e-01, 3.023620661e-01, 3.066760434e-01, 3.109707190e-01, 3.152477514e-01, 3.195087295e-01, 3.237551791e-01, 3.279885693e-01, 3.322103186e-01, 3.364217994e-01, 3.406243437e-01, 3.448192468e-01, 3.490077719e-01, 3.531911539e-01, 3.573706028e-01, 3.615473075e-01, 3.657224388e-01, 3.698971524e-01, 3.740725922e-01, 3.782498930e-01, 3.824301830e-01, 3.866145869e-01, 3.908042285e-01, 3.950002331e-01, 3.992037304e-01, 4.034158570e-01, 4.076377588e-01, 4.118705944e-01, 4.161155369e-01, 4.203737774e-01, 4.246465277e-01, 4.289350232e-01, 4.332405262e-01, 4.375643291e-01, 4.419077580e-01, 4.462721760e-01, 4.506589878e-01, 4.550696432e-01, 4.595056417e-01, 4.639685378e-01, 4.684599455e-01, 4.729815444e-01, 4.775350856e-01, 4.821223984e-01, 4.867453976e-01, 4.914060916e-01, 4.961065907e-01, 5.008491176e-01, 5.056360175e-01, 5.104697703e-01, 5.153530039e-01, 5.202885089e-01, 5.252792555e-01, 5.303284123e-01, 5.354393669e-01, 5.406157509e-01, 5.458614661e-01, 5.511807167e-01, 5.565780441e-01, 5.620583690e-01, 5.676270382e-01, 5.732898805e-01, 5.790532715e-01, 5.849242090e-01, 5.909104038e-01, 5.970203857e-01, 6.032636325e-01, 6.096507236e-01, 6.161935286e-01, 6.229054372e-01, 6.298016449e-01, 6.368995094e-01, 6.442190028e-01, 6.517832895e-01, 6.596194785e-01, 6.677596156e-01, 6.762420160e-01, 6.851130922e-01, 6.944299174e-01, 7.042639193e-01, 7.147063735e-01, 7.258768861e-01, 7.379371035e-01, 7.511141635e-01, 7.657438307e-01, 7.823578790e-01, 8.018868686e-01, 8.262401558e-01, 8.607404527e-01, 1.000000000e+00, 0.000000000e+00, 1.398057981e-02, 1.885775773e-02, 2.247762213e-02, 2.546760705e-02, 2.806364241e-02, 3.038435232e-02, 3.249914629e-02, 3.445269526e-02, 3.627570700e-02, 3.799033927e-02, 3.961318702e-02, 4.115705152e-02, 4.263204764e-02, 4.404632838e-02, 4.540657670e-02, 4.671834982e-02, 4.798632654e-02, 4.921448906e-02, 5.040625923e-02, 5.156460241e-02, 5.269210797e-02, 5.379105240e-02, 5.486344947e-02, 5.591109060e-02, 5.693557753e-02, 5.793834915e-02, 5.892070362e-02, 5.988381679e-02, 6.082875765e-02, 6.175650138e-02, 6.266794040e-02, 6.356389381e-02, 6.444511551e-02, 6.531230118e-02, 6.616609438e-02, 6.700709179e-02, 6.783584783e-02, 6.865287871e-02, 6.945866602e-02, 7.025365981e-02, 7.103828147e-02, 7.181292613e-02, 7.257796493e-02, 7.333374698e-02, 7.408060113e-02, 7.481883757e-02, 7.554874930e-02, 7.627061336e-02, 7.698469208e-02, 7.769123412e-02, 7.839047540e-02, 7.908264007e-02, 7.976794123e-02, 8.044658173e-02, 8.111875481e-02, 8.178464473e-02, 8.244442735e-02, 8.309827063e-02, 8.374633515e-02, 8.438877451e-02, 8.502573577e-02, 8.565735985e-02, 8.628378182e-02, 8.690513130e-02, 8.752153271e-02, 8.813310559e-02, 8.873996484e-02, 8.934222097e-02, 8.993998036e-02, 9.053334540e-02, 9.112241477e-02, 9.170728360e-02, 9.228804363e-02, 9.286478336e-02, 9.343758828e-02, 9.400654092e-02, 9.457172106e-02, 9.513320582e-02, 9.569106977e-02, 9.624538510e-02, 9.679622166e-02, 9.734364711e-02, 9.788772701e-02, 9.842852486e-02, 9.896610226e-02, 9.950051894e-02, 1.000318329e-01, 1.005601003e-01, 1.010853758e-01, 1.016077124e-01, 1.021271618e-01, 1.026437739e-01, 1.031575974e-01, 1.036686798e-01, 1.041770670e-01, 1.046828039e-01, 1.051859341e-01, 1.056865001e-01, 1.061845433e-01, 1.066801039e-01, 1.071732212e-01, 1.076639335e-01, 1.081522780e-01, 1.086382913e-01, 1.091220086e-01, 1.096034647e-01, 1.100826934e-01, 1.105597275e-01, 1.110345994e-01, 1.115073404e-01, 1.119779812e-01, 1.124465519e-01, 1.129130817e-01, 1.133775993e-01, 1.138401327e-01, 1.143007093e-01, 1.147593557e-01, 1.152160984e-01, 1.156709627e-01, 1.161239739e-01, 1.165751564e-01, 1.170245343e-01, 1.174721310e-01, 1.179179696e-01, 1.183620727e-01, 1.188044622e-01, 1.192451599e-01, 1.196841870e-01, 7.456909806e-01, 7.463571329e-01, 7.470265510e-01, 7.476992788e-01, 7.483753609e-01, 7.490548432e-01, 7.497377723e-01, 7.504241961e-01, 7.511141635e-01, 7.518077242e-01, 7.525049294e-01, 7.532058313e-01, 7.539104833e-01, 7.546189402e-01, 7.553312577e-01, 7.560474932e-01, 7.567677052e-01, 7.574919539e-01, 7.582203006e-01, 7.589528084e-01, 7.596895418e-01, 7.604305669e-01, 7.611759515e-01, 7.619257652e-01, 7.626800792e-01, 7.634389667e-01, 7.642025028e-01, 7.649707644e-01, 7.657438307e-01, 7.665217828e-01, 7.673047042e-01, 7.680926807e-01, 7.688858002e-01, 7.696841533e-01, 7.704878332e-01, 7.712969356e-01, 7.721115591e-01, 7.729318051e-01, 7.737577780e-01, 7.745895855e-01, 7.754273384e-01, 7.762711507e-01, 7.771211403e-01, 7.779774286e-01, 7.788401409e-01, 7.797094063e-01, 7.805853585e-01, 7.814681353e-01, 7.823578790e-01, 7.832547370e-01, 7.841588615e-01, 7.850704101e-01, 7.859895456e-01, 7.869164370e-01, 7.878512591e-01, 7.887941932e-01, 7.897454271e-01, 7.907051558e-01, 7.916735817e-01, 7.926509150e-01, 7.936373739e-01, 7.946331856e-01, 7.956385861e-01, 7.966538213e-01, 7.976791471e-01, 7.987148305e-01, 7.997611495e-01, 8.008183944e-01, 8.018868686e-01, 8.029668886e-01, 8.040587859e-01, 8.051629071e-01, 8.062796153e-01, 8.074092912e-01, 8.085523340e-01, 8.097091631e-01, 8.108802190e-01, 8.120659654e-01, 8.132668904e-01, 8.144835083e-01, 8.157163620e-01, 8.169660251e-01, 8.182331038e-01, 8.195182403e-01, 8.208221152e-01, 8.221454510e-01, 8.234890157e-01, 8.248536268e-01, 8.262401558e-01, 8.276495330e-01, 8.290827536e-01, 8.305408836e-01, 8.320250672e-01, 8.335365346e-01, 8.350766114e-01, 8.366467291e-01, 8.382484368e-01, 8.398834151e-01, 8.415534919e-01, 8.432606605e-01, 8.450071012e-01, 8.467952062e-01, 8.486276087e-01, 8.505072177e-01, 8.524372594e-01, 8.544213264e-01, 8.564634377e-01, 8.585681112e-01, 8.607404527e-01, 8.629862668e-01, 8.653121948e-01, 8.677258898e-01, 8.702362415e-01, 8.728536674e-01, 8.755904988e-01, 8.784614987e-01, 8.814845727e-01, 8.846817666e-01, 8.880807064e-01, 8.917167395e-01, 8.956362464e-01, 8.999019968e-01, 9.046023235e-01, 9.098680170e-01, 9.159065992e-01, 9.230819916e-01, 9.321428628e-01, 9.451837998e-01, 1.000000000e+00, }; const float dist_icdf_2_4[] = { 0.000000000e+00, 2.695397666e-02, 4.110739181e-02, 5.271023992e-02, 6.294554102e-02, 7.228895093e-02, 8.099050278e-02, 8.920152585e-02, 9.702212136e-02, 1.045227143e-01, 1.117551555e-01, 1.187589803e-01, 1.255651847e-01, 1.321986273e-01, 1.386796250e-01, 1.450250504e-01, 1.512491094e-01, 1.573639064e-01, 1.633798640e-01, 1.693060405e-01, 1.751503742e-01, 1.809198748e-01, 1.866207738e-01, 1.922586462e-01, 1.978385079e-01, 2.033648961e-01, 2.088419351e-01, 2.142733916e-01, 2.196627203e-01, 2.250131029e-01, 2.303274813e-01, 2.356085856e-01, 2.408589583e-01, 2.460809752e-01, 2.512768640e-01, 2.564487197e-01, 2.615985188e-01, 2.667281314e-01, 2.718393326e-01, 2.769338112e-01, 2.820131792e-01, 2.870789793e-01, 2.921326916e-01, 2.971757400e-01, 3.022094980e-01, 3.072352941e-01, 3.122544161e-01, 3.172681156e-01, 3.222776124e-01, 3.272840979e-01, 3.322887385e-01, 3.372926793e-01, 3.422970469e-01, 3.473029522e-01, 3.523114934e-01, 3.573237587e-01, 3.623408286e-01, 3.673637785e-01, 3.723936814e-01, 3.774316097e-01, 3.824786379e-01, 3.875358450e-01, 3.926043164e-01, 3.976851468e-01, 4.027794421e-01, 4.078883217e-01, 4.130129215e-01, 4.181543958e-01, 4.233139204e-01, 4.284926949e-01, 4.336919457e-01, 4.389129288e-01, 4.441569331e-01, 4.494252836e-01, 4.547193448e-01, 4.600405246e-01, 4.653902779e-01, 4.707701111e-01, 4.761815870e-01, 4.816263290e-01, 4.871060271e-01, 4.926224433e-01, 4.981774184e-01, 5.037728783e-01, 5.094108423e-01, 5.150934308e-01, 5.208228750e-01, 5.266015268e-01, 5.324318701e-01, 5.383165335e-01, 5.442583041e-01, 5.502601433e-01, 5.563252043e-01, 5.624568518e-01, 5.686586846e-01, 5.749345607e-01, 5.812886264e-01, 5.877253491e-01, 5.942495554e-01, 6.008664749e-01, 6.075817905e-01, 6.144016976e-01, 6.213329733e-01, 6.283830574e-01, 6.355601490e-01, 6.428733212e-01, 6.503326593e-01, 6.579494274e-01, 6.657362730e-01, 6.737074776e-01, 6.818792696e-01, 6.902702175e-01, 6.989017310e-01, 7.077987082e-01, 7.169903835e-01, 7.265114597e-01, 7.364036473e-01, 7.467178077e-01, 7.575170125e-01, 7.688810512e-01, 7.809133174e-01, 7.937518080e-01, 8.075876893e-01, 8.226989287e-01, 8.395172100e-01, 8.587798418e-01, 8.819520410e-01, 9.129255057e-01, 1.000000000e+00, 0.000000000e+00, 4.436153319e-03, 6.724776836e-03, 8.579782530e-03, 1.020018075e-02, 1.166622129e-02, 1.302018774e-02, 1.428772259e-02, 1.548581635e-02, 1.662643929e-02, 1.771841462e-02, 1.876847575e-02, 1.978190484e-02, 2.076293954e-02, 2.171504335e-02, 2.264109181e-02, 2.354350451e-02, 2.442434118e-02, 2.528537304e-02, 2.612813687e-02, 2.695397666e-02, 2.776407614e-02, 2.855948457e-02, 2.934113737e-02, 3.010987288e-02, 3.086644598e-02, 3.161153943e-02, 3.234577324e-02, 3.306971250e-02, 3.378387404e-02, 3.448873210e-02, 3.518472306e-02, 3.587224962e-02, 3.655168439e-02, 3.722337291e-02, 3.788763640e-02, 3.854477410e-02, 3.919506535e-02, 3.983877138e-02, 4.047613696e-02, 4.110739181e-02, 4.173275189e-02, 4.235242053e-02, 4.296658945e-02, 4.357543968e-02, 4.417914239e-02, 4.477785961e-02, 4.537174492e-02, 4.596094408e-02, 4.654559553e-02, 4.712583097e-02, 4.770177574e-02, 4.827354931e-02, 4.884126561e-02, 4.940503342e-02, 4.996495668e-02, 5.052113480e-02, 5.107366292e-02, 5.162263217e-02, 5.216812991e-02, 5.271023992e-02, 5.324904267e-02, 5.378461543e-02, 5.431703246e-02, 5.484636523e-02, 5.537268250e-02, 5.589605048e-02, 5.641653298e-02, 5.693419153e-02, 5.744908547e-02, 5.796127208e-02, 5.847080666e-02, 5.897774265e-02, 5.948213171e-02, 5.998402377e-02, 6.048346718e-02, 6.098050871e-02, 6.147519364e-02, 6.196756587e-02, 6.245766792e-02, 6.294554102e-02, 6.343122517e-02, 6.391475917e-02, 6.439618068e-02, 6.487552629e-02, 6.535283151e-02, 6.582813087e-02, 6.630145792e-02, 6.677284528e-02, 6.724232470e-02, 6.770992704e-02, 6.817568236e-02, 6.863961991e-02, 6.910176818e-02, 6.956215492e-02, 7.002080718e-02, 7.047775130e-02, 7.093301298e-02, 7.138661729e-02, 7.183858866e-02, 7.228895093e-02, 7.273772739e-02, 7.318494074e-02, 7.363061317e-02, 7.407476635e-02, 7.451742143e-02, 7.495859908e-02, 7.539831952e-02, 7.583660250e-02, 7.627346732e-02, 7.670893287e-02, 7.714301762e-02, 7.757573964e-02, 7.800711661e-02, 7.843716584e-02, 7.886590425e-02, 7.929334845e-02, 7.971951465e-02, 8.014441878e-02, 8.056807640e-02, 8.099050278e-02, 8.141171289e-02, 8.183172137e-02, 8.225054261e-02, 8.266819069e-02, 8.308467942e-02, 8.350002236e-02, 8.391423279e-02, 8.432732375e-02, 8.019183596e-01, 8.026166567e-01, 8.033178420e-01, 8.040219518e-01, 8.047290229e-01, 8.054390933e-01, 8.061522014e-01, 8.068683867e-01, 8.075876893e-01, 8.083101502e-01, 8.090358116e-01, 8.097647162e-01, 8.104969079e-01, 8.112324314e-01, 8.119713326e-01, 8.127136583e-01, 8.134594563e-01, 8.142087757e-01, 8.149616666e-01, 8.157181803e-01, 8.164783694e-01, 8.172422875e-01, 8.180099898e-01, 8.187815326e-01, 8.195569738e-01, 8.203363725e-01, 8.211197895e-01, 8.219072870e-01, 8.226989287e-01, 8.234947802e-01, 8.242949085e-01, 8.250993827e-01, 8.259082735e-01, 8.267216535e-01, 8.275395973e-01, 8.283621817e-01, 8.291894854e-01, 8.300215893e-01, 8.308585769e-01, 8.317005337e-01, 8.325475479e-01, 8.333997102e-01, 8.342571142e-01, 8.351198559e-01, 8.359880345e-01, 8.368617522e-01, 8.377411143e-01, 8.386262295e-01, 8.395172100e-01, 8.404141714e-01, 8.413172332e-01, 8.422265189e-01, 8.431421561e-01, 8.440642767e-01, 8.449930171e-01, 8.459285186e-01, 8.468709272e-01, 8.478203945e-01, 8.487770774e-01, 8.497411386e-01, 8.507127467e-01, 8.516920771e-01, 8.526793117e-01, 8.536746395e-01, 8.546782569e-01, 8.556903686e-01, 8.567111873e-01, 8.577409347e-01, 8.587798418e-01, 8.598281498e-01, 8.608861101e-01, 8.619539854e-01, 8.630320505e-01, 8.641205926e-01, 8.652199125e-01, 8.663303254e-01, 8.674521617e-01, 8.685857685e-01, 8.697315103e-01, 8.708897703e-01, 8.720609522e-01, 8.732454813e-01, 8.744438061e-01, 8.756564006e-01, 8.768837659e-01, 8.781264326e-01, 8.793849630e-01, 8.806599542e-01, 8.819520410e-01, 8.832618993e-01, 8.845902496e-01, 8.859378618e-01, 8.873055594e-01, 8.886942252e-01, 8.901048075e-01, 8.915383267e-01, 8.929958833e-01, 8.944786672e-01, 8.959879676e-01, 8.975251852e-01, 8.990918462e-01, 9.006896182e-01, 9.023203291e-01, 9.039859898e-01, 9.056888200e-01, 9.074312801e-01, 9.092161090e-01, 9.110463698e-01, 9.129255057e-01, 9.148574089e-01, 9.168465065e-01, 9.188978685e-01, 9.210173448e-01, 9.232117431e-01, 9.254890618e-01, 9.278588003e-01, 9.303323819e-01, 9.329237415e-01, 9.356501662e-01, 9.385335328e-01, 9.416021983e-01, 9.448940215e-01, 9.484614628e-01, 9.523808247e-01, 9.567706423e-01, 9.618334432e-01, 9.679718812e-01, 9.762561128e-01, 1.000000000e+00, }; const float dist_icdf_2_5[] = { 0.000000000e+00, 1.053468150e-02, 1.893424839e-02, 2.670341150e-02, 3.410025603e-02, 4.123932205e-02, 4.818498632e-02, 5.497827400e-02, 6.164749562e-02, 6.821330149e-02, 7.469138542e-02, 8.109405867e-02, 8.743122657e-02, 9.371102570e-02, 9.994025655e-02, 1.061246874e-01, 1.122692738e-01, 1.183783207e-01, 1.244556048e-01, 1.305044690e-01, 1.365278954e-01, 1.425285640e-01, 1.485088988e-01, 1.544711060e-01, 1.604172048e-01, 1.663490530e-01, 1.722683685e-01, 1.781767471e-01, 1.840756778e-01, 1.899665557e-01, 1.958506934e-01, 2.017293303e-01, 2.076036411e-01, 2.134747431e-01, 2.193437025e-01, 2.252115402e-01, 2.310792371e-01, 2.369477377e-01, 2.428179552e-01, 2.486907742e-01, 2.545670547e-01, 2.604476345e-01, 2.663333323e-01, 2.722249500e-01, 2.781232753e-01, 2.840290833e-01, 2.899431390e-01, 2.958661990e-01, 3.017990133e-01, 3.077423268e-01, 3.136968814e-01, 3.196634169e-01, 3.256426728e-01, 3.316353900e-01, 3.376423118e-01, 3.436641855e-01, 3.497017638e-01, 3.557558059e-01, 3.618270793e-01, 3.679163611e-01, 3.740244391e-01, 3.801521133e-01, 3.863001978e-01, 3.924695218e-01, 3.986609314e-01, 4.048752910e-01, 4.111134853e-01, 4.173764208e-01, 4.236650276e-01, 4.299802616e-01, 4.363231062e-01, 4.426945749e-01, 4.490957131e-01, 4.555276009e-01, 4.619913555e-01, 4.684881343e-01, 4.750191374e-01, 4.815856116e-01, 4.881888530e-01, 4.948302116e-01, 5.015110950e-01, 5.082329728e-01, 5.149973816e-01, 5.218059306e-01, 5.286603068e-01, 5.355622819e-01, 5.425137191e-01, 5.495165810e-01, 5.565729380e-01, 5.636849781e-01, 5.708550169e-01, 5.780855103e-01, 5.853790668e-01, 5.927384627e-01, 6.001666588e-01, 6.076668193e-01, 6.152423327e-01, 6.228968364e-01, 6.306342446e-01, 6.384587797e-01, 6.463750090e-01, 6.543878876e-01, 6.625028072e-01, 6.707256544e-01, 6.790628786e-01, 6.875215726e-01, 6.961095689e-01, 7.048355554e-01, 7.137092154e-01, 7.227413990e-01, 7.319443343e-01, 7.413318912e-01, 7.509199142e-01, 7.607266476e-01, 7.707732885e-01, 7.810847149e-01, 7.916904656e-01, 8.026260868e-01, 8.139350287e-01, 8.256713978e-01, 8.379040937e-01, 8.507232981e-01, 8.642512048e-01, 8.786610083e-01, 8.942136605e-01, 9.113385802e-01, 9.308485605e-01, 9.547510451e-01, 1.000000000e+00, 0.000000000e+00, 8.424954622e-04, 1.510777833e-03, 2.126155588e-03, 2.709575813e-03, 3.270370962e-03, 3.813802212e-03, 4.343230316e-03, 4.860978581e-03, 5.368743714e-03, 5.867815971e-03, 6.359207543e-03, 6.843732341e-03, 7.322058131e-03, 7.794741990e-03, 8.262255245e-03, 8.725001497e-03, 9.183329973e-03, 9.637545607e-03, 1.008791680e-02, 1.053468150e-02, 1.097805198e-02, 1.141821870e-02, 1.185535346e-02, 1.228961191e-02, 1.272113573e-02, 1.315005435e-02, 1.357648646e-02, 1.400054125e-02, 1.442231949e-02, 1.484191445e-02, 1.525941267e-02, 1.567489467e-02, 1.608843554e-02, 1.650010543e-02, 1.690997004e-02, 1.731809103e-02, 1.772452633e-02, 1.812933049e-02, 1.853255498e-02, 1.893424839e-02, 1.933445669e-02, 1.973322342e-02, 2.013058989e-02, 2.052659533e-02, 2.092127702e-02, 2.131467048e-02, 2.170680952e-02, 2.209772644e-02, 2.248745204e-02, 2.287601578e-02, 2.326344584e-02, 2.364976921e-02, 2.403501176e-02, 2.441919828e-02, 2.480235258e-02, 2.518449755e-02, 2.556565516e-02, 2.594584657e-02, 2.632509215e-02, 2.670341150e-02, 2.708082354e-02, 2.745734650e-02, 2.783299797e-02, 2.820779496e-02, 2.858175387e-02, 2.895489058e-02, 2.932722044e-02, 2.969875830e-02, 3.006951854e-02, 3.043951509e-02, 3.080876143e-02, 3.117727067e-02, 3.154505548e-02, 3.191212818e-02, 3.227850073e-02, 3.264418472e-02, 3.300919144e-02, 3.337353184e-02, 3.373721659e-02, 3.410025603e-02, 3.446266025e-02, 3.482443907e-02, 3.518560202e-02, 3.554615842e-02, 3.590611733e-02, 3.626548757e-02, 3.662427775e-02, 3.698249628e-02, 3.734015132e-02, 3.769725088e-02, 3.805380273e-02, 3.840981451e-02, 3.876529362e-02, 3.912024733e-02, 3.947468272e-02, 3.982860673e-02, 4.018202612e-02, 4.053494752e-02, 4.088737738e-02, 4.123932205e-02, 4.159078772e-02, 4.194178045e-02, 4.229230616e-02, 4.264237067e-02, 4.299197965e-02, 4.334113869e-02, 4.368985322e-02, 4.403812861e-02, 4.438597007e-02, 4.473338274e-02, 4.508037166e-02, 4.542694175e-02, 4.577309785e-02, 4.611884471e-02, 4.646418698e-02, 4.680912922e-02, 4.715367592e-02, 4.749783147e-02, 4.784160019e-02, 4.818498632e-02, 4.852799402e-02, 4.887062737e-02, 4.921289040e-02, 4.955478703e-02, 4.989632116e-02, 5.023749658e-02, 5.057831703e-02, 5.091878620e-02, 8.587453655e-01, 8.594263632e-01, 8.601093810e-01, 8.607944415e-01, 8.614815677e-01, 8.621707830e-01, 8.628621113e-01, 8.635555770e-01, 8.642512048e-01, 8.649490202e-01, 8.656490489e-01, 8.663513174e-01, 8.670558526e-01, 8.677626819e-01, 8.684718333e-01, 8.691833356e-01, 8.698972179e-01, 8.706135101e-01, 8.713322427e-01, 8.720534469e-01, 8.727771546e-01, 8.735033983e-01, 8.742322113e-01, 8.749636277e-01, 8.756976824e-01, 8.764344108e-01, 8.771738496e-01, 8.779160360e-01, 8.786610083e-01, 8.794088055e-01, 8.801594677e-01, 8.809130361e-01, 8.816695526e-01, 8.824290603e-01, 8.831916036e-01, 8.839572277e-01, 8.847259792e-01, 8.854979056e-01, 8.862730562e-01, 8.870514810e-01, 8.878332318e-01, 8.886183616e-01, 8.894069249e-01, 8.901989777e-01, 8.909945777e-01, 8.917937841e-01, 8.925966579e-01, 8.934032618e-01, 8.942136605e-01, 8.950279204e-01, 8.958461103e-01, 8.966683007e-01, 8.974945645e-01, 8.983249770e-01, 8.991596157e-01, 8.999985607e-01, 9.008418949e-01, 9.016897036e-01, 9.025420753e-01, 9.033991014e-01, 9.042608765e-01, 9.051274985e-01, 9.059990690e-01, 9.068756930e-01, 9.077574796e-01, 9.086445418e-01, 9.095369973e-01, 9.104349678e-01, 9.113385802e-01, 9.122479663e-01, 9.131632634e-01, 9.140846143e-01, 9.150121680e-01, 9.159460798e-01, 9.168865118e-01, 9.178336333e-01, 9.187876212e-01, 9.197486607e-01, 9.207169457e-01, 9.216926794e-01, 9.226760749e-01, 9.236673561e-01, 9.246667582e-01, 9.256745288e-01, 9.266909287e-01, 9.277162330e-01, 9.287507320e-01, 9.297947328e-01, 9.308485605e-01, 9.319125596e-01, 9.329870961e-01, 9.340725589e-01, 9.351693623e-01, 9.362779484e-01, 9.373987896e-01, 9.385323917e-01, 9.396792975e-01, 9.408400906e-01, 9.420154000e-01, 9.432059051e-01, 9.444123418e-01, 9.456355094e-01, 9.468762787e-01, 9.481356010e-01, 9.494145196e-01, 9.507141826e-01, 9.520358589e-01, 9.533809563e-01, 9.547510451e-01, 9.561478852e-01, 9.575734606e-01, 9.590300224e-01, 9.605201424e-01, 9.620467824e-01, 9.636133836e-01, 9.652239848e-01, 9.668833810e-01, 9.685973419e-01, 9.703729186e-01, 9.722188896e-01, 9.741464305e-01, 9.761701640e-01, 9.783098958e-01, 9.805936863e-01, 9.830637927e-01, 9.857897143e-01, 9.889029123e-01, 9.927278148e-01, 1.000000000e+00, }; const float dist_icdf_2_6[] = { 0.000000000e+00, 2.669205160e-03, 6.088322551e-03, 9.863908821e-03, 1.389246828e-02, 1.812115190e-02, 2.251727391e-02, 2.705842519e-02, 3.172820346e-02, 3.651404450e-02, 4.140599601e-02, 4.639596910e-02, 5.147725407e-02, 5.664419245e-02, 6.189194680e-02, 6.721633389e-02, 7.261370088e-02, 7.808083136e-02, 8.361487268e-02, 8.921327881e-02, 9.487376485e-02, 1.005942703e-01, 1.063729289e-01, 1.122080441e-01, 1.180980684e-01, 1.240415859e-01, 1.300372978e-01, 1.360840101e-01, 1.421806228e-01, 1.483261204e-01, 1.545195648e-01, 1.607600875e-01, 1.670468840e-01, 1.733792086e-01, 1.797563692e-01, 1.861777239e-01, 1.926426767e-01, 1.991506748e-01, 2.057012051e-01, 2.122937922e-01, 2.189279958e-01, 2.256034087e-01, 2.323196548e-01, 2.390763876e-01, 2.458732888e-01, 2.527100668e-01, 2.595864553e-01, 2.665022128e-01, 2.734571211e-01, 2.804509845e-01, 2.874836295e-01, 2.945549035e-01, 3.016646747e-01, 3.088128311e-01, 3.159992806e-01, 3.232239502e-01, 3.304867859e-01, 3.377877523e-01, 3.451268323e-01, 3.525040275e-01, 3.599193573e-01, 3.673728596e-01, 3.748645903e-01, 3.823946237e-01, 3.899630524e-01, 3.975699876e-01, 4.052155592e-01, 4.128999164e-01, 4.206232276e-01, 4.283856810e-01, 4.361874853e-01, 4.440288697e-01, 4.519100851e-01, 4.598314042e-01, 4.677931227e-01, 4.757955598e-01, 4.838390594e-01, 4.919239909e-01, 5.000507504e-01, 5.082197619e-01, 5.164314786e-01, 5.246863847e-01, 5.329849966e-01, 5.413278651e-01, 5.497155771e-01, 5.581487580e-01, 5.666280741e-01, 5.751542350e-01, 5.837279971e-01, 5.923501663e-01, 6.010216021e-01, 6.097432215e-01, 6.185160033e-01, 6.273409935e-01, 6.362193109e-01, 6.451521531e-01, 6.541408043e-01, 6.631866428e-01, 6.722911505e-01, 6.814559234e-01, 6.906826835e-01, 6.999732925e-01, 7.093297678e-01, 7.187543009e-01, 7.282492787e-01, 7.378173088e-01, 7.474612494e-01, 7.571842443e-01, 7.669897653e-01, 7.768816635e-01, 7.868642309e-01, 7.969422779e-01, 8.071212275e-01, 8.174072362e-01, 8.278073465e-01, 8.383296863e-01, 8.489837309e-01, 8.597806565e-01, 8.707338286e-01, 8.818594933e-01, 8.931777918e-01, 9.047143078e-01, 9.165025492e-01, 9.285881864e-01, 9.410369298e-01, 9.539509923e-01, 9.675102450e-01, 9.821140101e-01, 1.000000000e+00, 0.000000000e+00, 7.569904464e-05, 1.726160003e-04, 2.795722377e-04, 3.936192764e-04, 5.132475999e-04, 6.375209993e-04, 7.657956763e-04, 8.975988670e-04, 1.032567160e-03, 1.170411605e-03, 1.310896404e-03, 1.453825114e-03, 1.599031306e-03, 1.746371990e-03, 1.895722862e-03, 2.046974768e-03, 2.200031014e-03, 2.354805292e-03, 2.511220044e-03, 2.669205160e-03, 2.828696920e-03, 2.989637138e-03, 3.151972448e-03, 3.315653711e-03, 3.480635518e-03, 3.646875770e-03, 3.814335317e-03, 3.982977649e-03, 4.152768628e-03, 4.323676264e-03, 4.495670505e-03, 4.668723064e-03, 4.842807265e-03, 5.017897900e-03, 5.193971114e-03, 5.371004290e-03, 5.548975956e-03, 5.727865696e-03, 5.907654072e-03, 6.088322551e-03, 6.269853446e-03, 6.452229854e-03, 6.635435603e-03, 6.819455209e-03, 7.004273826e-03, 7.189877208e-03, 7.376251674e-03, 7.563384072e-03, 7.751261751e-03, 7.939872526e-03, 8.129204659e-03, 8.319246830e-03, 8.509988114e-03, 8.701417963e-03, 8.893526185e-03, 9.086302923e-03, 9.279738642e-03, 9.473824113e-03, 9.668550394e-03, 9.863908821e-03, 1.005989099e-02, 1.025648876e-02, 1.045369420e-02, 1.065149965e-02, 1.084989763e-02, 1.104888089e-02, 1.124844238e-02, 1.144857524e-02, 1.164927278e-02, 1.185052850e-02, 1.205233607e-02, 1.225468932e-02, 1.245758224e-02, 1.266100896e-02, 1.286496376e-02, 1.306944107e-02, 1.327443543e-02, 1.347994152e-02, 1.368595417e-02, 1.389246828e-02, 1.409947890e-02, 1.430698120e-02, 1.451497042e-02, 1.472344193e-02, 1.493239121e-02, 1.514181381e-02, 1.535170540e-02, 1.556206172e-02, 1.577287861e-02, 1.598415199e-02, 1.619587787e-02, 1.640805233e-02, 1.662067154e-02, 1.683373174e-02, 1.704722923e-02, 1.726116040e-02, 1.747552170e-02, 1.769030966e-02, 1.790552084e-02, 1.812115190e-02, 1.833719955e-02, 1.855366056e-02, 1.877053174e-02, 1.898780998e-02, 1.920549222e-02, 1.942357544e-02, 1.964205669e-02, 1.986093306e-02, 2.008020169e-02, 2.029985976e-02, 2.051990453e-02, 2.074033326e-02, 2.096114329e-02, 2.118233198e-02, 2.140389674e-02, 2.162583503e-02, 2.184814434e-02, 2.207082221e-02, 2.229386620e-02, 2.251727391e-02, 2.274104301e-02, 2.296517116e-02, 2.318965608e-02, 2.341449552e-02, 2.363968726e-02, 2.386522912e-02, 2.409111894e-02, 2.431735460e-02, 9.117544630e-01, 9.123454960e-01, 9.129372249e-01, 9.135296555e-01, 9.141227938e-01, 9.147166461e-01, 9.153112185e-01, 9.159065173e-01, 9.165025492e-01, 9.170993205e-01, 9.176968381e-01, 9.182951087e-01, 9.188941393e-01, 9.194939369e-01, 9.200945088e-01, 9.206958623e-01, 9.212980048e-01, 9.219009439e-01, 9.225046875e-01, 9.231092434e-01, 9.237146197e-01, 9.243208246e-01, 9.249278665e-01, 9.255357539e-01, 9.261444957e-01, 9.267541006e-01, 9.273645778e-01, 9.279759366e-01, 9.285881864e-01, 9.292013369e-01, 9.298153980e-01, 9.304303798e-01, 9.310462927e-01, 9.316631472e-01, 9.322809540e-01, 9.328997242e-01, 9.335194692e-01, 9.341402003e-01, 9.347619296e-01, 9.353846690e-01, 9.360084310e-01, 9.366332282e-01, 9.372590737e-01, 9.378859807e-01, 9.385139630e-01, 9.391430345e-01, 9.397732096e-01, 9.404045030e-01, 9.410369298e-01, 9.416705057e-01, 9.423052464e-01, 9.429411685e-01, 9.435782887e-01, 9.442166244e-01, 9.448561933e-01, 9.454970138e-01, 9.461391047e-01, 9.467824854e-01, 9.474271759e-01, 9.480731968e-01, 9.487205694e-01, 9.493693155e-01, 9.500194578e-01, 9.506710195e-01, 9.513240247e-01, 9.519784985e-01, 9.526344664e-01, 9.532919551e-01, 9.539509923e-01, 9.546116063e-01, 9.552738268e-01, 9.559376845e-01, 9.566032111e-01, 9.572704397e-01, 9.579394046e-01, 9.586101414e-01, 9.592826872e-01, 9.599570806e-01, 9.606333619e-01, 9.613115729e-01, 9.619917576e-01, 9.626739615e-01, 9.633582326e-01, 9.640446207e-01, 9.647331784e-01, 9.654239605e-01, 9.661170247e-01, 9.668124316e-01, 9.675102450e-01, 9.682105320e-01, 9.689133635e-01, 9.696188143e-01, 9.703269635e-01, 9.710378950e-01, 9.717516978e-01, 9.724684664e-01, 9.731883015e-01, 9.739113106e-01, 9.746376085e-01, 9.753673182e-01, 9.761005718e-01, 9.768375115e-01, 9.775782907e-01, 9.783230757e-01, 9.790720467e-01, 9.798254001e-01, 9.805833507e-01, 9.813461342e-01, 9.821140101e-01, 9.828872661e-01, 9.836662221e-01, 9.844512362e-01, 9.852427119e-01, 9.860411067e-01, 9.868469435e-01, 9.876608258e-01, 9.884834569e-01, 9.893156663e-01, 9.901584463e-01, 9.910130034e-01, 9.918808341e-01, 9.927638409e-01, 9.936645176e-01, 9.945862671e-01, 9.955339916e-01, 9.965153278e-01, 9.975437379e-01, 9.986491696e-01, 1.000000000e+00, }; const float dist_icdf_2_7[] = { 0.000000000e+00, 3.568661949e-04, 1.146997717e-03, 2.270594482e-03, 3.685819090e-03, 5.366609188e-03, 7.294389619e-03, 9.454901165e-03, 1.183666135e-02, 1.443010733e-02, 1.722707285e-02, 2.022044723e-02, 2.340394177e-02, 2.677192315e-02, 3.031929086e-02, 3.404138463e-02, 3.793391292e-02, 4.199289664e-02, 4.621462413e-02, 5.059561463e-02, 5.513258823e-02, 5.982244100e-02, 6.466222396e-02, 6.964912543e-02, 7.478045583e-02, 8.005363467e-02, 8.546617930e-02, 9.101569501e-02, 9.669986644e-02, 1.025164499e-01, 1.084632668e-01, 1.145381973e-01, 1.207391754e-01, 1.270641836e-01, 1.335112489e-01, 1.400784385e-01, 1.467638567e-01, 1.535656411e-01, 1.604819596e-01, 1.675110082e-01, 1.746510076e-01, 1.819002013e-01, 1.892568535e-01, 1.967192466e-01, 2.042856794e-01, 2.119544654e-01, 2.197239312e-01, 2.275924142e-01, 2.355582618e-01, 2.436198295e-01, 2.517754795e-01, 2.600235794e-01, 2.683625008e-01, 2.767906180e-01, 2.853063069e-01, 2.939079434e-01, 3.025939027e-01, 3.113625577e-01, 3.202122779e-01, 3.291414284e-01, 3.381483684e-01, 3.472314504e-01, 3.563890189e-01, 3.656194090e-01, 3.749209454e-01, 3.842919413e-01, 3.937306967e-01, 4.032354976e-01, 4.128046145e-01, 4.224363011e-01, 4.321287927e-01, 4.418803050e-01, 4.516890324e-01, 4.615531468e-01, 4.714707955e-01, 4.814400996e-01, 4.914591526e-01, 5.015260178e-01, 5.116387268e-01, 5.217952774e-01, 5.319936310e-01, 5.422317102e-01, 5.525073967e-01, 5.628185280e-01, 5.731628947e-01, 5.835382374e-01, 5.939422431e-01, 6.043725415e-01, 6.148267010e-01, 6.253022247e-01, 6.357965450e-01, 6.463070191e-01, 6.568309227e-01, 6.673654444e-01, 6.779076781e-01, 6.884546163e-01, 6.990031408e-01, 7.095500141e-01, 7.200918685e-01, 7.306251946e-01, 7.411463279e-01, 7.516514342e-01, 7.621364928e-01, 7.725972768e-01, 7.830293314e-01, 7.934279484e-01, 8.037881364e-01, 8.141045870e-01, 8.243716335e-01, 8.345832036e-01, 8.447327618e-01, 8.548132406e-01, 8.648169561e-01, 8.747355048e-01, 8.845596343e-01, 8.942790802e-01, 9.038823556e-01, 9.133564761e-01, 9.226865916e-01, 9.318554804e-01, 9.408428333e-01, 9.496242042e-01, 9.581693968e-01, 9.664398430e-01, 9.743839996e-01, 9.819283633e-01, 9.889568756e-01, 9.952482425e-01, 1.000000000e+00, 0.000000000e+00, 2.295573376e-06, 7.378816787e-06, 1.460892969e-05, 2.371819989e-05, 3.454057630e-05, 4.695832678e-05, 6.088161928e-05, 7.623860715e-05, 9.296990542e-05, 1.110252184e-04, 1.303611399e-04, 1.509396455e-04, 1.727270166e-04, 1.956930488e-04, 2.198104531e-04, 2.450543943e-04, 2.714021260e-04, 2.988326999e-04, 3.273267294e-04, 3.568661949e-04, 3.874342829e-04, 4.190152502e-04, 4.515943093e-04, 4.851575309e-04, 5.196917591e-04, 5.551845393e-04, 5.916240546e-04, 6.289990700e-04, 6.672988843e-04, 7.065132861e-04, 7.466325163e-04, 7.876472332e-04, 8.295484826e-04, 8.723276696e-04, 9.159765344e-04, 9.604871296e-04, 1.005851800e-03, 1.052063165e-03, 1.099114098e-03, 1.146997717e-03, 1.195707367e-03, 1.245236605e-03, 1.295579192e-03, 1.346729082e-03, 1.398680407e-03, 1.451427472e-03, 1.504964748e-03, 1.559286856e-03, 1.614388569e-03, 1.670264798e-03, 1.726910588e-03, 1.784321113e-03, 1.842491668e-03, 1.901417664e-03, 1.961094627e-03, 2.021518184e-03, 2.082684071e-03, 2.144588117e-03, 2.207226249e-03, 2.270594482e-03, 2.334688918e-03, 2.399505746e-03, 2.465041231e-03, 2.531291720e-03, 2.598253630e-03, 2.665923455e-03, 2.734297755e-03, 2.803373158e-03, 2.873146357e-03, 2.943614108e-03, 3.014773228e-03, 3.086620590e-03, 3.159153127e-03, 3.232367824e-03, 3.306261721e-03, 3.380831908e-03, 3.456075527e-03, 3.531989765e-03, 3.608571859e-03, 3.685819090e-03, 3.763728785e-03, 3.842298310e-03, 3.921525078e-03, 4.001406538e-03, 4.081940181e-03, 4.163123535e-03, 4.244954166e-03, 4.327429677e-03, 4.410547704e-03, 4.494305920e-03, 4.578702031e-03, 4.663733773e-03, 4.749398918e-03, 4.835695265e-03, 4.922620647e-03, 5.010172924e-03, 5.098349985e-03, 5.187149748e-03, 5.276570159e-03, 5.366609188e-03, 5.457264834e-03, 5.548535121e-03, 5.640418097e-03, 5.732911836e-03, 5.826014433e-03, 5.919724009e-03, 6.014038708e-03, 6.108956694e-03, 6.204476155e-03, 6.300595299e-03, 6.397312356e-03, 6.494625576e-03, 6.592533228e-03, 6.691033603e-03, 6.790125009e-03, 6.889805774e-03, 6.990074245e-03, 7.090928785e-03, 7.192367776e-03, 7.294389619e-03, 7.396992729e-03, 7.500175541e-03, 7.603936502e-03, 7.708274080e-03, 7.813186756e-03, 7.918673027e-03, 8.024731404e-03, 8.131360416e-03, 9.547819011e-01, 9.552076413e-01, 9.556327336e-01, 9.560571730e-01, 9.564809544e-01, 9.569040727e-01, 9.573265227e-01, 9.577482992e-01, 9.581693968e-01, 9.585898102e-01, 9.590095337e-01, 9.594285620e-01, 9.598468893e-01, 9.602645099e-01, 9.606814180e-01, 9.610976076e-01, 9.615130729e-01, 9.619278078e-01, 9.623418059e-01, 9.627550612e-01, 9.631675672e-01, 9.635793175e-01, 9.639903054e-01, 9.644005244e-01, 9.648099676e-01, 9.652186281e-01, 9.656264990e-01, 9.660335730e-01, 9.664398430e-01, 9.668453016e-01, 9.672499413e-01, 9.676537544e-01, 9.680567332e-01, 9.684588698e-01, 9.688601560e-01, 9.692605839e-01, 9.696601449e-01, 9.700588306e-01, 9.704566323e-01, 9.708535412e-01, 9.712495483e-01, 9.716446445e-01, 9.720388203e-01, 9.724320662e-01, 9.728243725e-01, 9.732157292e-01, 9.736061262e-01, 9.739955532e-01, 9.743839996e-01, 9.747714544e-01, 9.751579068e-01, 9.755433455e-01, 9.759277588e-01, 9.763111350e-01, 9.766934619e-01, 9.770747273e-01, 9.774549185e-01, 9.778340226e-01, 9.782120261e-01, 9.785889157e-01, 9.789646772e-01, 9.793392964e-01, 9.797127587e-01, 9.800850489e-01, 9.804561516e-01, 9.808260510e-01, 9.811947306e-01, 9.815621738e-01, 9.819283633e-01, 9.822932813e-01, 9.826569095e-01, 9.830192291e-01, 9.833802207e-01, 9.837398643e-01, 9.840981392e-01, 9.844550242e-01, 9.848104971e-01, 9.851645353e-01, 9.855171152e-01, 9.858682125e-01, 9.862178019e-01, 9.865658573e-01, 9.869123515e-01, 9.872572564e-01, 9.876005428e-01, 9.879421802e-01, 9.882821371e-01, 9.886203803e-01, 9.889568756e-01, 9.892915870e-01, 9.896244771e-01, 9.899555065e-01, 9.902846343e-01, 9.906118173e-01, 9.909370102e-01, 9.912601654e-01, 9.915812327e-01, 9.919001594e-01, 9.922168894e-01, 9.925313636e-01, 9.928435193e-01, 9.931532896e-01, 9.934606036e-01, 9.937653853e-01, 9.940675535e-01, 9.943670211e-01, 9.946636941e-01, 9.949574712e-01, 9.952482425e-01, 9.955358883e-01, 9.958202779e-01, 9.961012679e-01, 9.963786999e-01, 9.966523979e-01, 9.969221654e-01, 9.971877811e-01, 9.974489936e-01, 9.977055145e-01, 9.979570091e-01, 9.982030838e-01, 9.984432676e-01, 9.986769856e-01, 9.989035176e-01, 9.991219315e-01, 9.993309647e-01, 9.995287935e-01, 9.997125019e-01, 9.998764622e-01, 1.000000000e+00, }; const float dist_icdf_2_8[] = { 0.000000000e+00, 4.578949286e-10, 1.356106336e-08, 9.841977600e-08, 4.016257606e-07, 1.195494376e-06, 2.914805441e-06, 6.192491155e-06, 1.189451001e-05, 2.115405295e-05, 3.540517636e-05, 5.641592304e-05, 8.632096728e-05, 1.276537998e-04, 1.833784496e-04, 2.569207220e-04, 3.521989139e-04, 4.736539483e-04, 6.262788489e-04, 8.156474560e-04, 1.047942259e-03, 1.329981196e-03, 1.669243245e-03, 2.073892598e-03, 2.552801189e-03, 3.115569287e-03, 3.772543877e-03, 4.534834454e-03, 5.414325880e-03, 6.423687867e-03, 7.576380639e-03, 8.886656276e-03, 1.036955520e-02, 1.204089727e-02, 1.391726682e-02, 1.601599106e-02, 1.835511126e-02, 2.095334583e-02, 2.383004492e-02, 2.700513559e-02, 3.049905709e-02, 3.433268555e-02, 3.852724747e-02, 4.310422155e-02, 4.808522839e-02, 5.349190772e-02, 5.934578297e-02, 6.566811315e-02, 7.247973212e-02, 7.980087556e-02, 8.765099631e-02, 9.604856875e-02, 1.050108833e-01, 1.145538328e-01, 1.246916913e-01, 1.354368894e-01, 1.467997859e-01, 1.587884401e-01, 1.714083878e-01, 1.846624227e-01, 1.985503884e-01, 2.130689837e-01, 2.282115851e-01, 2.439680909e-01, 2.603247906e-01, 2.772642626e-01, 2.947653056e-01, 3.128029055e-01, 3.313482420e-01, 3.503687358e-01, 3.698281405e-01, 3.896866792e-01, 4.099012258e-01, 4.304255324e-01, 4.512104996e-01, 4.722044903e-01, 4.933536807e-01, 5.146024474e-01, 5.358937858e-01, 5.571697520e-01, 5.783719256e-01, 5.994418841e-01, 6.203216841e-01, 6.409543406e-01, 6.612842984e-01, 6.812578880e-01, 7.008237600e-01, 7.199332902e-01, 7.385409519e-01, 7.566046490e-01, 7.740860056e-01, 7.909506098e-01, 8.071682092e-01, 8.227128563e-01, 8.375630034e-01, 8.517015483e-01, 8.651158320e-01, 8.777975896e-01, 8.897428590e-01, 9.009518493e-01, 9.114287744e-01, 9.211816541e-01, 9.302220900e-01, 9.385650177e-01, 9.462284425e-01, 9.532331621e-01, 9.596024801e-01, 9.653619153e-01, 9.705389107e-01, 9.751625441e-01, 9.792632446e-01, 9.828725175e-01, 9.860226782e-01, 9.887465981e-01, 9.910774629e-01, 9.930485441e-01, 9.946929823e-01, 9.960435848e-01, 9.971326329e-01, 9.979916998e-01, 9.986514750e-01, 9.991415929e-01, 9.994904595e-01, 9.997250706e-01, 9.998708097e-01, 9.999512082e-01, 9.999876318e-01, 9.999988160e-01, 1.000000000e+00, 0.000000000e+00, 1.999530332e-16, 5.921829667e-15, 4.297783758e-14, 1.753815185e-13, 5.220474806e-13, 1.272836073e-12, 2.704139742e-12, 5.194117152e-12, 9.237641924e-12, 1.546101206e-11, 2.463645365e-11, 3.769644449e-11, 5.574787770e-11, 8.008608167e-11, 1.122087095e-10, 1.538295096e-10, 2.068919857e-10, 2.735829565e-10, 3.563460198e-10, 4.578949286e-10, 5.812268847e-10, 7.296357535e-10, 9.067252057e-10, 1.116421789e-09, 1.362987935e-09, 1.651034897e-09, 1.985535640e-09, 2.371837656e-09, 2.815675743e-09, 3.323184715e-09, 3.900912073e-09, 4.555830619e-09, 5.295351029e-09, 6.127334378e-09, 7.060104621e-09, 8.102461035e-09, 9.263690615e-09, 1.055358043e-08, 1.198242996e-08, 1.356106336e-08, 1.530084170e-08, 1.721367523e-08, 1.931203549e-08, 2.160896751e-08, 2.411810187e-08, 2.685366686e-08, 2.983050043e-08, 3.306406231e-08, 3.657044593e-08, 4.036639041e-08, 4.446929253e-08, 4.889721855e-08, 5.366891620e-08, 5.880382645e-08, 6.432209539e-08, 7.024458600e-08, 7.659288998e-08, 8.338933945e-08, 9.065701872e-08, 9.841977600e-08, 1.067022351e-07, 1.155298070e-07, 1.249287016e-07, 1.349259395e-07, 1.455493630e-07, 1.568276486e-07, 1.687903177e-07, 1.814677486e-07, 1.948911880e-07, 2.090927623e-07, 2.241054894e-07, 2.399632896e-07, 2.567009979e-07, 2.743543747e-07, 2.929601174e-07, 3.125558720e-07, 3.331802442e-07, 3.548728111e-07, 3.776741321e-07, 4.016257606e-07, 4.267702552e-07, 4.531511908e-07, 4.808131702e-07, 5.098018352e-07, 5.401638777e-07, 5.719470512e-07, 6.052001820e-07, 6.399731802e-07, 6.763170509e-07, 7.142839057e-07, 7.539269734e-07, 7.953006114e-07, 8.384603170e-07, 8.834627381e-07, 9.303656846e-07, 9.792281395e-07, 1.030110270e-06, 1.083073438e-06, 1.138180211e-06, 1.195494376e-06, 1.255080947e-06, 1.317006176e-06, 1.381337568e-06, 1.448143886e-06, 1.517495167e-06, 1.589462733e-06, 1.664119197e-06, 1.741538479e-06, 1.821795813e-06, 1.904967764e-06, 1.991132231e-06, 2.080368462e-06, 2.172757067e-06, 2.268380026e-06, 2.367320697e-06, 2.469663836e-06, 2.575495596e-06, 2.684903548e-06, 2.797976686e-06, 2.914805441e-06, 3.035481688e-06, 3.160098761e-06, 3.288751462e-06, 3.421536069e-06, 3.558550353e-06, 3.699893583e-06, 3.845666539e-06, 3.995971523e-06, 9.993661015e-01, 9.993827027e-01, 9.993989954e-01, 9.994149830e-01, 9.994306687e-01, 9.994460559e-01, 9.994611479e-01, 9.994759480e-01, 9.994904595e-01, 9.995046858e-01, 9.995186300e-01, 9.995322954e-01, 9.995456853e-01, 9.995588030e-01, 9.995716516e-01, 9.995842345e-01, 9.995965547e-01, 9.996086155e-01, 9.996204202e-01, 9.996319718e-01, 9.996432736e-01, 9.996543287e-01, 9.996651403e-01, 9.996757115e-01, 9.996860454e-01, 9.996961452e-01, 9.997060139e-01, 9.997156547e-01, 9.997250706e-01, 9.997342647e-01, 9.997432401e-01, 9.997519997e-01, 9.997605468e-01, 9.997688842e-01, 9.997770150e-01, 9.997849421e-01, 9.997926687e-01, 9.998001976e-01, 9.998075318e-01, 9.998146743e-01, 9.998216280e-01, 9.998283958e-01, 9.998349807e-01, 9.998413855e-01, 9.998476132e-01, 9.998536666e-01, 9.998595486e-01, 9.998652620e-01, 9.998708097e-01, 9.998761944e-01, 9.998814191e-01, 9.998864865e-01, 9.998913994e-01, 9.998961605e-01, 9.999007726e-01, 9.999052385e-01, 9.999095609e-01, 9.999137425e-01, 9.999177859e-01, 9.999216940e-01, 9.999254693e-01, 9.999291145e-01, 9.999326322e-01, 9.999360252e-01, 9.999392959e-01, 9.999424469e-01, 9.999454810e-01, 9.999484005e-01, 9.999512082e-01, 9.999539064e-01, 9.999564977e-01, 9.999589847e-01, 9.999613697e-01, 9.999636554e-01, 9.999658440e-01, 9.999679381e-01, 9.999699401e-01, 9.999718523e-01, 9.999736771e-01, 9.999754170e-01, 9.999770742e-01, 9.999786511e-01, 9.999801500e-01, 9.999815731e-01, 9.999829228e-01, 9.999842013e-01, 9.999854109e-01, 9.999865536e-01, 9.999876318e-01, 9.999886476e-01, 9.999896031e-01, 9.999905005e-01, 9.999913419e-01, 9.999921293e-01, 9.999928649e-01, 9.999935507e-01, 9.999941886e-01, 9.999947808e-01, 9.999953291e-01, 9.999958354e-01, 9.999963019e-01, 9.999967302e-01, 9.999971223e-01, 9.999974801e-01, 9.999978053e-01, 9.999980997e-01, 9.999983652e-01, 9.999986034e-01, 9.999988160e-01, 9.999990047e-01, 9.999991712e-01, 9.999993170e-01, 9.999994437e-01, 9.999995529e-01, 9.999996460e-01, 9.999997245e-01, 9.999997899e-01, 9.999998435e-01, 9.999998867e-01, 9.999999207e-01, 9.999999467e-01, 9.999999661e-01, 9.999999799e-01, 9.999999891e-01, 9.999999949e-01, 9.999999981e-01, 9.999999995e-01, 1.000000000e+00, 1.000000000e+00, }; const float dist_icdf_3_0[] = { 0.000000000e+00, 3.357396159e-01, 3.411985141e-01, 3.446595422e-01, 3.472599302e-01, 3.493720818e-01, 3.511670309e-01, 3.527382471e-01, 3.541426668e-01, 3.554176670e-01, 3.565891702e-01, 3.576759287e-01, 3.586919685e-01, 3.596480692e-01, 3.605527042e-01, 3.614126617e-01, 3.622334688e-01, 3.630196899e-01, 3.637751406e-01, 3.645030456e-01, 3.652061569e-01, 3.658868431e-01, 3.665471590e-01, 3.671888999e-01, 3.678136448e-01, 3.684227901e-01, 3.690175783e-01, 3.695991201e-01, 3.701684133e-01, 3.707263581e-01, 3.712737701e-01, 3.718113914e-01, 3.723398993e-01, 3.728599145e-01, 3.733720075e-01, 3.738767047e-01, 3.743744927e-01, 3.748658234e-01, 3.753511172e-01, 3.758307664e-01, 3.763051383e-01, 3.767745773e-01, 3.772394076e-01, 3.776999349e-01, 3.781564483e-01, 3.786092221e-01, 3.790585167e-01, 3.795045804e-01, 3.799476504e-01, 3.803879539e-01, 3.808257090e-01, 3.812611254e-01, 3.816944058e-01, 3.821257461e-01, 3.825553362e-01, 3.829833611e-01, 3.834100007e-01, 3.838354312e-01, 3.842598250e-01, 3.846833517e-01, 3.851061783e-01, 3.855284696e-01, 3.859503892e-01, 3.863720991e-01, 3.867937610e-01, 3.872155360e-01, 3.876375858e-01, 3.880600722e-01, 3.884831585e-01, 3.889070092e-01, 3.893317908e-01, 3.897576723e-01, 3.901848256e-01, 3.906134258e-01, 3.910436522e-01, 3.914756884e-01, 3.919097233e-01, 3.923459512e-01, 3.927845730e-01, 3.932257969e-01, 3.936698386e-01, 3.941169228e-01, 3.945672839e-01, 3.950211670e-01, 3.954788290e-01, 3.959405398e-01, 3.964065838e-01, 3.968772614e-01, 3.973528904e-01, 3.978338083e-01, 3.983203740e-01, 3.988129706e-01, 3.993120078e-01, 3.998179247e-01, 4.003311941e-01, 4.008523254e-01, 4.013818699e-01, 4.019204259e-01, 4.024686445e-01, 4.030272369e-01, 4.035969825e-01, 4.041787390e-01, 4.047734533e-01, 4.053821758e-01, 4.060060761e-01, 4.066464638e-01, 4.073048115e-01, 4.079827851e-01, 4.086822801e-01, 4.094054671e-01, 4.101548498e-01, 4.109333388e-01, 4.117443466e-01, 4.125919142e-01, 4.134808781e-01, 4.144170995e-01, 4.154077817e-01, 4.164619233e-01, 4.175909817e-01, 4.188098774e-01, 4.201385782e-01, 4.216047161e-01, 4.232481798e-01, 4.251298141e-01, 4.273496630e-01, 4.300911410e-01, 4.337546001e-01, 4.395670998e-01, 1.000000000e+00, 0.000000000e+00, 3.164971837e-01, 3.204785114e-01, 3.229185249e-01, 3.247050209e-01, 3.261247817e-01, 3.273082344e-01, 3.283260963e-01, 3.292211558e-01, 3.300213362e-01, 3.307459004e-01, 3.314087154e-01, 3.320201061e-01, 3.325879739e-01, 3.331185042e-01, 3.336166333e-01, 3.340863650e-01, 3.345309933e-01, 3.349532621e-01, 3.353554815e-01, 3.357396159e-01, 3.361073497e-01, 3.364601388e-01, 3.367992502e-01, 3.371257938e-01, 3.374407472e-01, 3.377449764e-01, 3.380392521e-01, 3.383242635e-01, 3.386006291e-01, 3.388689066e-01, 3.391296004e-01, 3.393831682e-01, 3.396300267e-01, 3.398705567e-01, 3.401051066e-01, 3.403339963e-01, 3.405575204e-01, 3.407759503e-01, 3.409895374e-01, 3.411985141e-01, 3.414030965e-01, 3.416034854e-01, 3.417998679e-01, 3.419924187e-01, 3.421813009e-01, 3.423666674e-01, 3.425486614e-01, 3.427274174e-01, 3.429030620e-01, 3.430757141e-01, 3.432454859e-01, 3.434124834e-01, 3.435768065e-01, 3.437385499e-01, 3.438978032e-01, 3.440546512e-01, 3.442091745e-01, 3.443614496e-01, 3.445115491e-01, 3.446595422e-01, 3.448054948e-01, 3.449494695e-01, 3.450915262e-01, 3.452317219e-01, 3.453701113e-01, 3.455067464e-01, 3.456416771e-01, 3.457749510e-01, 3.459066139e-01, 3.460367096e-01, 3.461652799e-01, 3.462923653e-01, 3.464180045e-01, 3.465422344e-01, 3.466650910e-01, 3.467866085e-01, 3.469068199e-01, 3.470257571e-01, 3.471434507e-01, 3.472599302e-01, 3.473752241e-01, 3.474893598e-01, 3.476023639e-01, 3.477142618e-01, 3.478250784e-01, 3.479348374e-01, 3.480435619e-01, 3.481512743e-01, 3.482579960e-01, 3.483637480e-01, 3.484685504e-01, 3.485724229e-01, 3.486753844e-01, 3.487774532e-01, 3.488786473e-01, 3.489789837e-01, 3.490784794e-01, 3.491771505e-01, 3.492750129e-01, 3.493720818e-01, 3.494683722e-01, 3.495638985e-01, 3.496586747e-01, 3.497527145e-01, 3.498460312e-01, 3.499386378e-01, 3.500305467e-01, 3.501217702e-01, 3.502123202e-01, 3.503022083e-01, 3.503914458e-01, 3.504800436e-01, 3.505680126e-01, 3.506553631e-01, 3.507421053e-01, 3.508282492e-01, 3.509138043e-01, 3.509987802e-01, 3.510831861e-01, 3.511670309e-01, 3.512503234e-01, 3.513330722e-01, 3.514152857e-01, 3.514969719e-01, 3.515781390e-01, 3.516587946e-01, 3.517389464e-01, 3.518186019e-01, 4.225662375e-01, 4.226495746e-01, 4.227334399e-01, 4.228178411e-01, 4.229027866e-01, 4.229882845e-01, 4.230743435e-01, 4.231609723e-01, 4.232481798e-01, 4.233359751e-01, 4.234243677e-01, 4.235133671e-01, 4.236029832e-01, 4.236932262e-01, 4.237841063e-01, 4.238756341e-01, 4.239678206e-01, 4.240606769e-01, 4.241542145e-01, 4.242484452e-01, 4.243433810e-01, 4.244390343e-01, 4.245354178e-01, 4.246325448e-01, 4.247304285e-01, 4.248290829e-01, 4.249285221e-01, 4.250287609e-01, 4.251298141e-01, 4.252316974e-01, 4.253344266e-01, 4.254380182e-01, 4.255424890e-01, 4.256478566e-01, 4.257541387e-01, 4.258613541e-01, 4.259695216e-01, 4.260786610e-01, 4.261887927e-01, 4.262999376e-01, 4.264121174e-01, 4.265253544e-01, 4.266396718e-01, 4.267550935e-01, 4.268716442e-01, 4.269893496e-01, 4.271082360e-01, 4.272283310e-01, 4.273496630e-01, 4.274722614e-01, 4.275961567e-01, 4.277213807e-01, 4.278479663e-01, 4.279759475e-01, 4.281053598e-01, 4.282362402e-01, 4.283686270e-01, 4.285025601e-01, 4.286380809e-01, 4.287752330e-01, 4.289140612e-01, 4.290546127e-01, 4.291969366e-01, 4.293410841e-01, 4.294871089e-01, 4.296350669e-01, 4.297850169e-01, 4.299370201e-01, 4.300911410e-01, 4.302474470e-01, 4.304060090e-01, 4.305669012e-01, 4.307302021e-01, 4.308959938e-01, 4.310643632e-01, 4.312354015e-01, 4.314092052e-01, 4.315858763e-01, 4.317655225e-01, 4.319482579e-01, 4.321342034e-01, 4.323234872e-01, 4.325162458e-01, 4.327126240e-01, 4.329127765e-01, 4.331168680e-01, 4.333250746e-01, 4.335375846e-01, 4.337546001e-01, 4.339763377e-01, 4.342030308e-01, 4.344349303e-01, 4.346723077e-01, 4.349154564e-01, 4.351646945e-01, 4.354203679e-01, 4.356828533e-01, 4.359525622e-01, 4.362299456e-01, 4.365154987e-01, 4.368097674e-01, 4.371133552e-01, 4.374269322e-01, 4.377512446e-01, 4.380871278e-01, 4.384355202e-01, 4.387974820e-01, 4.391742169e-01, 4.395670998e-01, 4.399777109e-01, 4.404078795e-01, 4.408597393e-01, 4.413358016e-01, 4.418390496e-01, 4.423730671e-01, 4.429422123e-01, 4.435518612e-01, 4.442087546e-01, 4.449215089e-01, 4.457013915e-01, 4.465635468e-01, 4.475290311e-01, 4.486283968e-01, 4.499085132e-01, 4.514469445e-01, 4.533869740e-01, 4.560443034e-01, 4.603992527e-01, 1.000000000e+00, }; const float dist_icdf_3_1[] = { 0.000000000e+00, 2.436959399e-01, 2.629281909e-01, 2.754296495e-01, 2.849701321e-01, 2.928081818e-01, 2.995291515e-01, 3.054559995e-01, 3.107869728e-01, 3.156530579e-01, 3.201456074e-01, 3.243310302e-01, 3.282592153e-01, 3.319686571e-01, 3.354897234e-01, 3.388468234e-01, 3.420598935e-01, 3.451454443e-01, 3.481173156e-01, 3.509872337e-01, 3.537652294e-01, 3.564599563e-01, 3.590789383e-01, 3.616287626e-01, 3.641152340e-01, 3.665434972e-01, 3.689181374e-01, 3.712432613e-01, 3.735225647e-01, 3.757593880e-01, 3.779567630e-01, 3.801174518e-01, 3.822439806e-01, 3.843386678e-01, 3.864036479e-01, 3.884408929e-01, 3.904522300e-01, 3.924393573e-01, 3.944038578e-01, 3.963472108e-01, 3.982708031e-01, 4.001759380e-01, 4.020638433e-01, 4.039356792e-01, 4.057925445e-01, 4.076354828e-01, 4.094654873e-01, 4.112835061e-01, 4.130904463e-01, 4.148871779e-01, 4.166745375e-01, 4.184533317e-01, 4.202243400e-01, 4.219883177e-01, 4.237459984e-01, 4.254980964e-01, 4.272453095e-01, 4.289883205e-01, 4.307277995e-01, 4.324644059e-01, 4.341987904e-01, 4.359315964e-01, 4.376634623e-01, 4.393950226e-01, 4.411269101e-01, 4.428597572e-01, 4.445941980e-01, 4.463308695e-01, 4.480704135e-01, 4.498134783e-01, 4.515607205e-01, 4.533128070e-01, 4.550704162e-01, 4.568342410e-01, 4.586049900e-01, 4.603833899e-01, 4.621701882e-01, 4.639661552e-01, 4.657720869e-01, 4.675888078e-01, 4.694171738e-01, 4.712580759e-01, 4.731124434e-01, 4.749812484e-01, 4.768655096e-01, 4.787662976e-01, 4.806847399e-01, 4.826220268e-01, 4.845794185e-01, 4.865582514e-01, 4.885599476e-01, 4.905860229e-01, 4.926380983e-01, 4.947179111e-01, 4.968273289e-01, 4.989683645e-01, 5.011431940e-01, 5.033541769e-01, 5.056038796e-01, 5.078951029e-01, 5.102309139e-01, 5.126146835e-01, 5.150501312e-01, 5.175413774e-01, 5.200930071e-01, 5.227101455e-01, 5.253985515e-01, 5.281647303e-01, 5.310160738e-01, 5.339610356e-01, 5.370093515e-01, 5.401723212e-01, 5.434631723e-01, 5.468975383e-01, 5.504940960e-01, 5.542754316e-01, 5.582692423e-01, 5.625100439e-01, 5.670416667e-01, 5.719210254e-01, 5.772240396e-01, 5.830553878e-01, 5.895655558e-01, 5.969829811e-01, 6.056811079e-01, 6.163396823e-01, 6.304283052e-01, 6.523853680e-01, 1.000000000e+00, 0.000000000e+00, 1.812651769e-01, 1.934447114e-01, 2.011068322e-01, 2.068099038e-01, 2.113974269e-01, 2.152582198e-01, 2.186052647e-01, 2.215684999e-01, 2.242333166e-01, 2.266589793e-01, 2.288883783e-01, 2.309536014e-01, 2.328793101e-01, 2.346848870e-01, 2.363858554e-01, 2.379948494e-01, 2.395222956e-01, 2.409769041e-01, 2.423660292e-01, 2.436959399e-01, 2.449720253e-01, 2.461989539e-01, 2.473807978e-01, 2.485211311e-01, 2.496231090e-01, 2.506895313e-01, 2.517228947e-01, 2.527254350e-01, 2.536991634e-01, 2.546458952e-01, 2.555672751e-01, 2.564647984e-01, 2.573398280e-01, 2.581936107e-01, 2.590272896e-01, 2.598419154e-01, 2.606384566e-01, 2.614178077e-01, 2.621807965e-01, 2.629281909e-01, 2.636607048e-01, 2.643790025e-01, 2.650837038e-01, 2.657753876e-01, 2.664545958e-01, 2.671218360e-01, 2.677775848e-01, 2.684222899e-01, 2.690563729e-01, 2.696802307e-01, 2.702942380e-01, 2.708987487e-01, 2.714940974e-01, 2.720806006e-01, 2.726585586e-01, 2.732282561e-01, 2.737899632e-01, 2.743439369e-01, 2.748904215e-01, 2.754296495e-01, 2.759618427e-01, 2.764872123e-01, 2.770059601e-01, 2.775182786e-01, 2.780243520e-01, 2.785243564e-01, 2.790184602e-01, 2.795068249e-01, 2.799896051e-01, 2.804669493e-01, 2.809389997e-01, 2.814058930e-01, 2.818677605e-01, 2.823247284e-01, 2.827769181e-01, 2.832244463e-01, 2.836674254e-01, 2.841059638e-01, 2.845401658e-01, 2.849701321e-01, 2.853959596e-01, 2.858177422e-01, 2.862355701e-01, 2.866495308e-01, 2.870597086e-01, 2.874661852e-01, 2.878690394e-01, 2.882683477e-01, 2.886641837e-01, 2.890566192e-01, 2.894457234e-01, 2.898315633e-01, 2.902142041e-01, 2.905937088e-01, 2.909701387e-01, 2.913435530e-01, 2.917140093e-01, 2.920815636e-01, 2.924462702e-01, 2.928081818e-01, 2.931673498e-01, 2.935238238e-01, 2.938776524e-01, 2.942288826e-01, 2.945775603e-01, 2.949237301e-01, 2.952674354e-01, 2.956087183e-01, 2.959476202e-01, 2.962841809e-01, 2.966184396e-01, 2.969504344e-01, 2.972802022e-01, 2.976077793e-01, 2.979332009e-01, 2.982565014e-01, 2.985777144e-01, 2.988968726e-01, 2.992140079e-01, 2.995291515e-01, 2.998423340e-01, 3.001535850e-01, 3.004629336e-01, 3.007704082e-01, 3.010760365e-01, 3.013798456e-01, 3.016818621e-01, 3.019821118e-01, 5.868676982e-01, 5.871976595e-01, 5.875296367e-01, 5.878636596e-01, 5.881997589e-01, 5.885379658e-01, 5.888783123e-01, 5.892208311e-01, 5.895655558e-01, 5.899125205e-01, 5.902617606e-01, 5.906133119e-01, 5.909672113e-01, 5.913234967e-01, 5.916822068e-01, 5.920433813e-01, 5.924070609e-01, 5.927732874e-01, 5.931421036e-01, 5.935135535e-01, 5.938876822e-01, 5.942645360e-01, 5.946441626e-01, 5.950266107e-01, 5.954119305e-01, 5.958001737e-01, 5.961913933e-01, 5.965856437e-01, 5.969829811e-01, 5.973834631e-01, 5.977871491e-01, 5.981941001e-01, 5.986043791e-01, 5.990180509e-01, 5.994351823e-01, 5.998558419e-01, 6.002801008e-01, 6.007080321e-01, 6.011397113e-01, 6.015752162e-01, 6.020146272e-01, 6.024580274e-01, 6.029055024e-01, 6.033571410e-01, 6.038130348e-01, 6.042732786e-01, 6.047379704e-01, 6.052072118e-01, 6.056811079e-01, 6.061597676e-01, 6.066433038e-01, 6.071318336e-01, 6.076254784e-01, 6.081243642e-01, 6.086286220e-01, 6.091383878e-01, 6.096538030e-01, 6.101750145e-01, 6.107021754e-01, 6.112354451e-01, 6.117749894e-01, 6.123209815e-01, 6.128736019e-01, 6.134330388e-01, 6.139994892e-01, 6.145731585e-01, 6.151542620e-01, 6.157430247e-01, 6.163396823e-01, 6.169444819e-01, 6.175576829e-01, 6.181795573e-01, 6.188103912e-01, 6.194504852e-01, 6.201001560e-01, 6.207597370e-01, 6.214295801e-01, 6.221100566e-01, 6.228015589e-01, 6.235045023e-01, 6.242193264e-01, 6.249464977e-01, 6.256865111e-01, 6.264398929e-01, 6.272072035e-01, 6.279890400e-01, 6.287860400e-01, 6.295988851e-01, 6.304283052e-01, 6.312750833e-01, 6.321400609e-01, 6.330241436e-01, 6.339283086e-01, 6.348536119e-01, 6.358011976e-01, 6.367723076e-01, 6.377682939e-01, 6.387906316e-01, 6.398409347e-01, 6.409209745e-01, 6.420327009e-01, 6.431782673e-01, 6.443600609e-01, 6.455807378e-01, 6.468432659e-01, 6.481509758e-01, 6.495076241e-01, 6.509174695e-01, 6.523853680e-01, 6.539168919e-01, 6.555184798e-01, 6.571976285e-01, 6.589631422e-01, 6.608254592e-01, 6.627970895e-01, 6.648932102e-01, 6.671324940e-01, 6.695382887e-01, 6.721403469e-01, 6.749774446e-01, 6.781015080e-01, 6.815844332e-01, 6.855300505e-01, 6.900967739e-01, 6.955450675e-01, 7.023522382e-01, 7.115588721e-01, 7.263444178e-01, 1.000000000e+00, }; const float dist_icdf_3_2[] = { 0.000000000e+00, 1.087346134e-01, 1.338426443e-01, 1.515211964e-01, 1.656975989e-01, 1.777697307e-01, 1.884155353e-01, 1.980210383e-01, 2.068292947e-01, 2.150043515e-01, 2.226627340e-01, 2.298905245e-01, 2.367533265e-01, 2.433024186e-01, 2.495787345e-01, 2.556155350e-01, 2.614402598e-01, 2.670758467e-01, 2.725416926e-01, 2.778543677e-01, 2.830281571e-01, 2.880754762e-01, 2.930071956e-01, 2.978328970e-01, 3.025610779e-01, 3.071993172e-01, 3.117544093e-01, 3.162324754e-01, 3.206390544e-01, 3.249791803e-01, 3.292574459e-01, 3.334780575e-01, 3.376448810e-01, 3.417614820e-01, 3.458311592e-01, 3.498569744e-01, 3.538417778e-01, 3.577882306e-01, 3.616988241e-01, 3.655758975e-01, 3.694216527e-01, 3.732381680e-01, 3.770274100e-01, 3.807912442e-01, 3.845314451e-01, 3.882497043e-01, 3.919476388e-01, 3.956267976e-01, 3.992886687e-01, 4.029346846e-01, 4.065662280e-01, 4.101846364e-01, 4.137912073e-01, 4.173872018e-01, 4.209738491e-01, 4.245523501e-01, 4.281238808e-01, 4.316895959e-01, 4.352506316e-01, 4.388081090e-01, 4.423631370e-01, 4.459168148e-01, 4.494702351e-01, 4.530244866e-01, 4.565806566e-01, 4.601398339e-01, 4.637031112e-01, 4.672715881e-01, 4.708463735e-01, 4.744285886e-01, 4.780193698e-01, 4.816198711e-01, 4.852312681e-01, 4.888547603e-01, 4.924915751e-01, 4.961429708e-01, 4.998102407e-01, 5.034947172e-01, 5.071977757e-01, 5.109208396e-01, 5.146653847e-01, 5.184329454e-01, 5.222251199e-01, 5.260435768e-01, 5.298900621e-01, 5.337664069e-01, 5.376745361e-01, 5.416164772e-01, 5.455943712e-01, 5.496104844e-01, 5.536672207e-01, 5.577671369e-01, 5.619129583e-01, 5.661075982e-01, 5.703541780e-01, 5.746560516e-01, 5.790168327e-01, 5.834404261e-01, 5.879310636e-01, 5.924933467e-01, 5.971322945e-01, 6.018534015e-01, 6.066627045e-01, 6.115668621e-01, 6.165732500e-01, 6.216900743e-01, 6.269265092e-01, 6.322928651e-01, 6.378007938e-01, 6.434635448e-01, 6.492962858e-01, 6.553165095e-01, 6.615445560e-01, 6.680042937e-01, 6.747240214e-01, 6.817376828e-01, 6.890865389e-01, 6.968215216e-01, 7.050066409e-01, 7.137240734e-01, 7.230820601e-01, 7.332277433e-01, 7.443692640e-01, 7.568167068e-01, 7.710657654e-01, 7.879939684e-01, 8.094298131e-01, 8.405923610e-01, 1.000000000e+00, 0.000000000e+00, 4.596737520e-02, 5.589988829e-02, 6.272599951e-02, 6.809671822e-02, 7.259612350e-02, 7.650623337e-02, 7.998705699e-02, 8.313903298e-02, 8.602976648e-02, 8.870715908e-02, 9.120651541e-02, 9.355468145e-02, 9.577259612e-02, 9.787693857e-02, 9.988123266e-02, 1.017966115e-01, 1.036323610e-01, 1.053963157e-01, 1.070951527e-01, 1.087346134e-01, 1.103196750e-01, 1.118546828e-01, 1.133434555e-01, 1.147893687e-01, 1.161954228e-01, 1.175642974e-01, 1.188983970e-01, 1.201998880e-01, 1.214707298e-01, 1.227127014e-01, 1.239274230e-01, 1.251163749e-01, 1.262809136e-01, 1.274222857e-01, 1.285416394e-01, 1.296400353e-01, 1.307184547e-01, 1.317778082e-01, 1.328189421e-01, 1.338426443e-01, 1.348496502e-01, 1.358406469e-01, 1.368162778e-01, 1.377771461e-01, 1.387238181e-01, 1.396568266e-01, 1.405766731e-01, 1.414838306e-01, 1.423787456e-01, 1.432618402e-01, 1.441335138e-01, 1.449941447e-01, 1.458440920e-01, 1.466836962e-01, 1.475132810e-01, 1.483331545e-01, 1.491436098e-01, 1.499449263e-01, 1.507373704e-01, 1.515211964e-01, 1.522966473e-01, 1.530639553e-01, 1.538233425e-01, 1.545750217e-01, 1.553191966e-01, 1.560560626e-01, 1.567858071e-01, 1.575086100e-01, 1.582246439e-01, 1.589340751e-01, 1.596370632e-01, 1.603337617e-01, 1.610243187e-01, 1.617088766e-01, 1.623875726e-01, 1.630605392e-01, 1.637279040e-01, 1.643897902e-01, 1.650463169e-01, 1.656975989e-01, 1.663437474e-01, 1.669848698e-01, 1.676210698e-01, 1.682524481e-01, 1.688791020e-01, 1.695011256e-01, 1.701186101e-01, 1.707316442e-01, 1.713403135e-01, 1.719447012e-01, 1.725448880e-01, 1.731409521e-01, 1.737329696e-01, 1.743210142e-01, 1.749051578e-01, 1.754854699e-01, 1.760620183e-01, 1.766348689e-01, 1.772040856e-01, 1.777697307e-01, 1.783318650e-01, 1.788905474e-01, 1.794458353e-01, 1.799977848e-01, 1.805464503e-01, 1.810918849e-01, 1.816341405e-01, 1.821732675e-01, 1.827093151e-01, 1.832423313e-01, 1.837723629e-01, 1.842994557e-01, 1.848236541e-01, 1.853450018e-01, 1.858635413e-01, 1.863793141e-01, 1.868923607e-01, 1.874027208e-01, 1.879104330e-01, 1.884155353e-01, 1.889180645e-01, 1.894180570e-01, 1.899155480e-01, 1.904105723e-01, 1.909031635e-01, 1.913933549e-01, 1.918811789e-01, 1.923666671e-01, 7.397762774e-01, 7.403398693e-01, 7.409063870e-01, 7.414758708e-01, 7.420483622e-01, 7.426239035e-01, 7.432025379e-01, 7.437843097e-01, 7.443692640e-01, 7.449574471e-01, 7.455489063e-01, 7.461436900e-01, 7.467418479e-01, 7.473434305e-01, 7.479484898e-01, 7.485570790e-01, 7.491692525e-01, 7.497850662e-01, 7.504045773e-01, 7.510278443e-01, 7.516549273e-01, 7.522858879e-01, 7.529207894e-01, 7.535596964e-01, 7.542026756e-01, 7.548497952e-01, 7.555011253e-01, 7.561567379e-01, 7.568167068e-01, 7.574811081e-01, 7.581500198e-01, 7.588235222e-01, 7.595016977e-01, 7.601846312e-01, 7.608724102e-01, 7.615651244e-01, 7.622628664e-01, 7.629657314e-01, 7.636738178e-01, 7.643872265e-01, 7.651060620e-01, 7.658304318e-01, 7.665604467e-01, 7.672962213e-01, 7.680378739e-01, 7.687855263e-01, 7.695393048e-01, 7.702993396e-01, 7.710657654e-01, 7.718387217e-01, 7.726183527e-01, 7.734048077e-01, 7.741982412e-01, 7.749988136e-01, 7.758066909e-01, 7.766220455e-01, 7.774450560e-01, 7.782759081e-01, 7.791147945e-01, 7.799619158e-01, 7.808174801e-01, 7.816817043e-01, 7.825548141e-01, 7.834370446e-01, 7.843286410e-01, 7.852298587e-01, 7.861409647e-01, 7.870622375e-01, 7.879939684e-01, 7.889364620e-01, 7.898900371e-01, 7.908550277e-01, 7.918317840e-01, 7.928206733e-01, 7.938220814e-01, 7.948364138e-01, 7.958640971e-01, 7.969055805e-01, 7.979613377e-01, 7.990318682e-01, 8.001176999e-01, 8.012193911e-01, 8.023375326e-01, 8.034727511e-01, 8.046257114e-01, 8.057971204e-01, 8.069877302e-01, 8.081983425e-01, 8.094298131e-01, 8.106830570e-01, 8.119590541e-01, 8.132588559e-01, 8.145835922e-01, 8.159344802e-01, 8.173128333e-01, 8.187200719e-01, 8.201577360e-01, 8.216274992e-01, 8.231311847e-01, 8.246707849e-01, 8.262484829e-01, 8.278666789e-01, 8.295280203e-01, 8.312354380e-01, 8.329921899e-01, 8.348019122e-01, 8.366686825e-01, 8.385970963e-01, 8.405923610e-01, 8.426604130e-01, 8.448080645e-01, 8.470431898e-01, 8.493749656e-01, 8.518141833e-01, 8.543736642e-01, 8.570688191e-01, 8.599184190e-01, 8.629456828e-01, 8.661798526e-01, 8.696585511e-01, 8.734314464e-01, 8.775662193e-01, 8.821588566e-01, 8.873527672e-01, 8.933779421e-01, 9.006430751e-01, 9.100037354e-01, 9.239177305e-01, 1.000000000e+00, }; const float dist_icdf_3_3[] = { 0.000000000e+00, 7.167186913e-02, 9.471219680e-02, 1.117382035e-01, 1.258070441e-01, 1.380505261e-01, 1.490319159e-01, 1.590782570e-01, 1.683987305e-01, 1.771363949e-01, 1.853940284e-01, 1.932483201e-01, 2.007582379e-01, 2.079702462e-01, 2.149217091e-01, 2.216431924e-01, 2.281600709e-01, 2.344936805e-01, 2.406621621e-01, 2.466810932e-01, 2.525639687e-01, 2.583225716e-01, 2.639672645e-01, 2.695072200e-01, 2.749506061e-01, 2.803047359e-01, 2.855761907e-01, 2.907709211e-01, 2.958943309e-01, 3.009513482e-01, 3.059464842e-01, 3.108838841e-01, 3.157673700e-01, 3.206004778e-01, 3.253864892e-01, 3.301284590e-01, 3.348292396e-01, 3.394915020e-01, 3.441177538e-01, 3.487103562e-01, 3.532715380e-01, 3.578034086e-01, 3.623079694e-01, 3.667871243e-01, 3.712426887e-01, 3.756763979e-01, 3.800899146e-01, 3.844848360e-01, 3.888626998e-01, 3.932249899e-01, 3.975731421e-01, 4.019085486e-01, 4.062325624e-01, 4.105465021e-01, 4.148516550e-01, 4.191492817e-01, 4.234406189e-01, 4.277268830e-01, 4.320092734e-01, 4.362889752e-01, 4.405671624e-01, 4.448450008e-01, 4.491236505e-01, 4.534042690e-01, 4.576880137e-01, 4.619760446e-01, 4.662695270e-01, 4.705696344e-01, 4.748775513e-01, 4.791944758e-01, 4.835216226e-01, 4.878602261e-01, 4.922115434e-01, 4.965768580e-01, 5.009574825e-01, 5.053547628e-01, 5.097700819e-01, 5.142048637e-01, 5.186605777e-01, 5.231387435e-01, 5.276409361e-01, 5.321687910e-01, 5.367240108e-01, 5.413083712e-01, 5.459237281e-01, 5.505720260e-01, 5.552553059e-01, 5.599757153e-01, 5.647355186e-01, 5.695371087e-01, 5.743830203e-01, 5.792759446e-01, 5.842187455e-01, 5.892144785e-01, 5.942664115e-01, 5.993780487e-01, 6.045531580e-01, 6.097958022e-01, 6.151103747e-01, 6.205016414e-01, 6.259747884e-01, 6.315354788e-01, 6.371899183e-01, 6.429449337e-01, 6.488080653e-01, 6.547876776e-01, 6.608930937e-01, 6.671347567e-01, 6.735244293e-01, 6.800754397e-01, 6.868029884e-01, 6.937245372e-01, 7.008603055e-01, 7.082339156e-01, 7.158732418e-01, 7.238115502e-01, 7.320890585e-01, 7.407551189e-01, 7.498713590e-01, 7.595163410e-01, 7.697927392e-01, 7.808389100e-01, 7.928486219e-01, 8.061072219e-01, 8.210646014e-01, 8.385036818e-01, 8.600192556e-01, 8.900087909e-01, 1.000000000e+00, 0.000000000e+00, 2.215358026e-02, 2.898882354e-02, 3.394614311e-02, 3.798105938e-02, 4.144648181e-02, 4.451774243e-02, 4.729650110e-02, 4.984770216e-02, 5.221571184e-02, 5.443237088e-02, 5.652141289e-02, 5.850106799e-02, 6.038568517e-02, 6.218678969e-02, 6.391379820e-02, 6.557451766e-02, 6.717550272e-02, 6.872231759e-02, 7.021973180e-02, 7.167186913e-02, 7.308232258e-02, 7.445424449e-02, 7.579041793e-02, 7.709331403e-02, 7.836513831e-02, 7.960786867e-02, 8.082328661e-02, 8.201300327e-02, 8.317848116e-02, 8.432105244e-02, 8.544193455e-02, 8.654224335e-02, 8.762300457e-02, 8.868516351e-02, 8.972959354e-02, 9.075710348e-02, 9.176844399e-02, 9.276431319e-02, 9.374536167e-02, 9.471219680e-02, 9.566538662e-02, 9.660546329e-02, 9.753292615e-02, 9.844824443e-02, 9.935185975e-02, 1.002441883e-01, 1.011256227e-01, 1.019965342e-01, 1.028572736e-01, 1.037081735e-01, 1.045495491e-01, 1.053816995e-01, 1.062049090e-01, 1.070194479e-01, 1.078255736e-01, 1.086235313e-01, 1.094135549e-01, 1.101958675e-01, 1.109706825e-01, 1.117382035e-01, 1.124986257e-01, 1.132521359e-01, 1.139989128e-01, 1.147391281e-01, 1.154729463e-01, 1.162005255e-01, 1.169220174e-01, 1.176375680e-01, 1.183473176e-01, 1.190514013e-01, 1.197499491e-01, 1.204430863e-01, 1.211309337e-01, 1.218136078e-01, 1.224912210e-01, 1.231638817e-01, 1.238316948e-01, 1.244947615e-01, 1.251531797e-01, 1.258070441e-01, 1.264564462e-01, 1.271014748e-01, 1.277422156e-01, 1.283787519e-01, 1.290111642e-01, 1.296395307e-01, 1.302639270e-01, 1.308844268e-01, 1.315011013e-01, 1.321140199e-01, 1.327232497e-01, 1.333288560e-01, 1.339309025e-01, 1.345294507e-01, 1.351245607e-01, 1.357162908e-01, 1.363046979e-01, 1.368898372e-01, 1.374717625e-01, 1.380505261e-01, 1.386261792e-01, 1.391987714e-01, 1.397683512e-01, 1.403349657e-01, 1.408986611e-01, 1.414594822e-01, 1.420174728e-01, 1.425726757e-01, 1.431251326e-01, 1.436748842e-01, 1.442219703e-01, 1.447664296e-01, 1.453083001e-01, 1.458476188e-01, 1.463844220e-01, 1.469187450e-01, 1.474506225e-01, 1.479800882e-01, 1.485071752e-01, 1.490319159e-01, 1.495543420e-01, 1.500744844e-01, 1.505923734e-01, 1.511080387e-01, 1.516215093e-01, 1.521328138e-01, 1.526419800e-01, 1.531490351e-01, 7.879135022e-01, 7.885202823e-01, 7.891298744e-01, 7.897423158e-01, 7.903576445e-01, 7.909758993e-01, 7.915971200e-01, 7.922213470e-01, 7.928486219e-01, 7.934789870e-01, 7.941124856e-01, 7.947491621e-01, 7.953890617e-01, 7.960322308e-01, 7.966787167e-01, 7.973285680e-01, 7.979818345e-01, 7.986385668e-01, 7.992988171e-01, 7.999626387e-01, 8.006300863e-01, 8.013012157e-01, 8.019760844e-01, 8.026547512e-01, 8.033372764e-01, 8.040237217e-01, 8.047141508e-01, 8.054086286e-01, 8.061072219e-01, 8.068099995e-01, 8.075170316e-01, 8.082283907e-01, 8.089441511e-01, 8.096643892e-01, 8.103891836e-01, 8.111186149e-01, 8.118527664e-01, 8.125917235e-01, 8.133355743e-01, 8.140844092e-01, 8.148383217e-01, 8.155974078e-01, 8.163617667e-01, 8.171315005e-01, 8.179067146e-01, 8.186875177e-01, 8.194740220e-01, 8.202663434e-01, 8.210646014e-01, 8.218689198e-01, 8.226794264e-01, 8.234962534e-01, 8.243195376e-01, 8.251494205e-01, 8.259860487e-01, 8.268295742e-01, 8.276801544e-01, 8.285379526e-01, 8.294031383e-01, 8.302758872e-01, 8.311563821e-01, 8.320448128e-01, 8.329413769e-01, 8.338462796e-01, 8.347597348e-01, 8.356819654e-01, 8.366132035e-01, 8.375536914e-01, 8.385036818e-01, 8.394634389e-01, 8.404332387e-01, 8.414133700e-01, 8.424041351e-01, 8.434058508e-01, 8.444188491e-01, 8.454434786e-01, 8.464801056e-01, 8.475291150e-01, 8.485909120e-01, 8.496659235e-01, 8.507545996e-01, 8.518574158e-01, 8.529748743e-01, 8.541075067e-01, 8.552558764e-01, 8.564205807e-01, 8.576022545e-01, 8.588015730e-01, 8.600192556e-01, 8.612560700e-01, 8.625128365e-01, 8.637904334e-01, 8.650898027e-01, 8.664119567e-01, 8.677579852e-01, 8.691290643e-01, 8.705264656e-01, 8.719515676e-01, 8.734058685e-01, 8.748910006e-01, 8.764087479e-01, 8.779610659e-01, 8.795501050e-01, 8.811782388e-01, 8.828480968e-01, 8.845626044e-01, 8.863250302e-01, 8.881390446e-01, 8.900087909e-01, 8.919389732e-01, 8.939349667e-01, 8.960029571e-01, 8.981501188e-01, 9.003848467e-01, 9.027170611e-01, 9.051586178e-01, 9.077238691e-01, 9.104304504e-01, 9.133004115e-01, 9.163618972e-01, 9.196517386e-01, 9.232196333e-01, 9.271352827e-01, 9.315014891e-01, 9.364806173e-01, 9.423557908e-01, 9.497051553e-01, 9.601283182e-01, 1.000000000e+00, }; const float dist_icdf_3_4[] = { 0.000000000e+00, 3.984384380e-02, 5.832579568e-02, 7.301236815e-02, 8.571044308e-02, 9.712997207e-02, 1.076384798e-01, 1.174558331e-01, 1.267261030e-01, 1.355498433e-01, 1.440005755e-01, 1.521340131e-01, 1.599935925e-01, 1.676139708e-01, 1.750233381e-01, 1.822449999e-01, 1.892984943e-01, 1.962004002e-01, 2.029649361e-01, 2.096044107e-01, 2.161295693e-01, 2.225498639e-01, 2.288736650e-01, 2.351084323e-01, 2.412608514e-01, 2.473369461e-01, 2.533421701e-01, 2.592814835e-01, 2.651594167e-01, 2.709801239e-01, 2.767474293e-01, 2.824648650e-01, 2.881357051e-01, 2.937629942e-01, 2.993495720e-01, 3.048980954e-01, 3.104110571e-01, 3.158908025e-01, 3.213395444e-01, 3.267593757e-01, 3.321522814e-01, 3.375201487e-01, 3.428647762e-01, 3.481878827e-01, 3.534911140e-01, 3.587760502e-01, 3.640442118e-01, 3.692970656e-01, 3.745360293e-01, 3.797624769e-01, 3.849777427e-01, 3.901831256e-01, 3.953798928e-01, 4.005692836e-01, 4.057525123e-01, 4.109307719e-01, 4.161052368e-01, 4.212770656e-01, 4.264474043e-01, 4.316173882e-01, 4.367881454e-01, 4.419607986e-01, 4.471364678e-01, 4.523162730e-01, 4.575013361e-01, 4.626927840e-01, 4.678917504e-01, 4.730993786e-01, 4.783168242e-01, 4.835452571e-01, 4.887858648e-01, 4.940398548e-01, 4.993084575e-01, 5.045929293e-01, 5.098945556e-01, 5.152146543e-01, 5.205545791e-01, 5.259157235e-01, 5.312995247e-01, 5.367074679e-01, 5.421410908e-01, 5.476019890e-01, 5.530918211e-01, 5.586123146e-01, 5.641652727e-01, 5.697525810e-01, 5.753762156e-01, 5.810382514e-01, 5.867408718e-01, 5.924863793e-01, 5.982772066e-01, 6.041159307e-01, 6.100052865e-01, 6.159481842e-01, 6.219477273e-01, 6.280072336e-01, 6.341302598e-01, 6.403206282e-01, 6.465824581e-01, 6.529202023e-01, 6.593386884e-01, 6.658431677e-01, 6.724393716e-01, 6.791335790e-01, 6.859326945e-01, 6.928443429e-01, 6.998769823e-01, 7.070400399e-01, 7.143440786e-01, 7.218010013e-01, 7.294243053e-01, 7.372294009e-01, 7.452340172e-01, 7.534587255e-01, 7.619276229e-01, 7.706692436e-01, 7.797177951e-01, 7.891148743e-01, 7.989119121e-01, 8.091737631e-01, 8.199841727e-01, 8.314544783e-01, 8.437382354e-01, 8.570575909e-01, 8.717554671e-01, 8.884132391e-01, 9.081750309e-01, 9.340354421e-01, 1.000000000e+00, 0.000000000e+00, 7.830181122e-03, 1.139137543e-02, 1.418850226e-02, 1.658320402e-02, 1.871779135e-02, 2.066602660e-02, 2.247208377e-02, 2.416493445e-02, 2.576481427e-02, 2.728652759e-02, 2.874129788e-02, 3.013787773e-02, 3.148325148e-02, 3.278309970e-02, 3.404211745e-02, 3.526423897e-02, 3.645280035e-02, 3.761066002e-02, 3.874028962e-02, 3.984384380e-02, 4.092321454e-02, 4.198007405e-02, 4.301590906e-02, 4.403204848e-02, 4.502968601e-02, 4.600989869e-02, 4.697366232e-02, 4.792186435e-02, 4.885531475e-02, 4.977475515e-02, 5.068086670e-02, 5.157427679e-02, 5.245556482e-02, 5.332526719e-02, 5.418388168e-02, 5.503187125e-02, 5.586966732e-02, 5.669767277e-02, 5.751626449e-02, 5.832579568e-02, 5.912659791e-02, 5.991898291e-02, 6.070324421e-02, 6.147965861e-02, 6.224848746e-02, 6.300997789e-02, 6.376436383e-02, 6.451186700e-02, 6.525269779e-02, 6.598705605e-02, 6.671513183e-02, 6.743710601e-02, 6.815315095e-02, 6.886343102e-02, 6.956810312e-02, 7.026731712e-02, 7.096121636e-02, 7.164993796e-02, 7.233361327e-02, 7.301236815e-02, 7.368632331e-02, 7.435559460e-02, 7.502029328e-02, 7.568052626e-02, 7.633639637e-02, 7.698800253e-02, 7.763543997e-02, 7.827880045e-02, 7.891817241e-02, 7.955364111e-02, 8.018528885e-02, 8.081319507e-02, 8.143743649e-02, 8.205808724e-02, 8.267521901e-02, 8.328890113e-02, 8.389920066e-02, 8.450618257e-02, 8.510990973e-02, 8.571044308e-02, 8.630784169e-02, 8.690216281e-02, 8.749346201e-02, 8.808179319e-02, 8.866720866e-02, 8.924975924e-02, 8.982949428e-02, 9.040646175e-02, 9.098070826e-02, 9.155227915e-02, 9.212121850e-02, 9.268756922e-02, 9.325137305e-02, 9.381267065e-02, 9.437150159e-02, 9.492790443e-02, 9.548191674e-02, 9.603357514e-02, 9.658291531e-02, 9.712997207e-02, 9.767477937e-02, 9.821737033e-02, 9.875777727e-02, 9.929603175e-02, 9.983216458e-02, 1.003662058e-01, 1.008981849e-01, 1.014281304e-01, 1.019560706e-01, 1.024820327e-01, 1.030060436e-01, 1.035281295e-01, 1.040483160e-01, 1.045666283e-01, 1.050830908e-01, 1.055977276e-01, 1.061105621e-01, 1.066216173e-01, 1.071309159e-01, 1.076384798e-01, 1.081443306e-01, 1.086484896e-01, 1.091509774e-01, 1.096518144e-01, 1.101510205e-01, 1.106486152e-01, 1.111446177e-01, 1.116390467e-01, 8.387148718e-01, 8.393343603e-01, 8.399561985e-01, 8.405804153e-01, 8.412070404e-01, 8.418361039e-01, 8.424676364e-01, 8.431016696e-01, 8.437382354e-01, 8.443773666e-01, 8.450190967e-01, 8.456634598e-01, 8.463104909e-01, 8.469602257e-01, 8.476127005e-01, 8.482679528e-01, 8.489260206e-01, 8.495869429e-01, 8.502507597e-01, 8.509175116e-01, 8.515872404e-01, 8.522599890e-01, 8.529358009e-01, 8.536147211e-01, 8.542967954e-01, 8.549820707e-01, 8.556705953e-01, 8.563624185e-01, 8.570575909e-01, 8.577561644e-01, 8.584581922e-01, 8.591637288e-01, 8.598728304e-01, 8.605855544e-01, 8.613019598e-01, 8.620221073e-01, 8.627460592e-01, 8.634738795e-01, 8.642056341e-01, 8.649413904e-01, 8.656812183e-01, 8.664251891e-01, 8.671733768e-01, 8.679258570e-01, 8.686827080e-01, 8.694440102e-01, 8.702098467e-01, 8.709803029e-01, 8.717554671e-01, 8.725354303e-01, 8.733202865e-01, 8.741101326e-01, 8.749050690e-01, 8.757051991e-01, 8.765106300e-01, 8.773214726e-01, 8.781378413e-01, 8.789598550e-01, 8.797876365e-01, 8.806213131e-01, 8.814610171e-01, 8.823068853e-01, 8.831590600e-01, 8.840176889e-01, 8.848829255e-01, 8.857549293e-01, 8.866338664e-01, 8.875199097e-01, 8.884132391e-01, 8.893140423e-01, 8.902225152e-01, 8.911388620e-01, 8.920632964e-01, 8.929960414e-01, 8.939373306e-01, 8.948874086e-01, 8.958465316e-01, 8.968149685e-01, 8.977930015e-01, 8.987809273e-01, 8.997790579e-01, 9.007877219e-01, 9.018072659e-01, 9.028380553e-01, 9.038804767e-01, 9.049349386e-01, 9.060018740e-01, 9.070817422e-01, 9.081750309e-01, 9.092822590e-01, 9.104039795e-01, 9.115407821e-01, 9.126932977e-01, 9.138622016e-01, 9.150482183e-01, 9.162521270e-01, 9.174747671e-01, 9.187170449e-01, 9.199799415e-01, 9.212645218e-01, 9.225719443e-01, 9.239034737e-01, 9.252604942e-01, 9.266445266e-01, 9.280572475e-01, 9.295005126e-01, 9.309763844e-01, 9.324871660e-01, 9.340354421e-01, 9.356241297e-01, 9.372565403e-01, 9.389364592e-01, 9.406682455e-01, 9.424569611e-01, 9.443085398e-01, 9.462300117e-01, 9.482298093e-01, 9.503181901e-01, 9.525078404e-01, 9.548147615e-01, 9.572596184e-01, 9.598698874e-01, 9.626834653e-01, 9.657551776e-01, 9.691696553e-01, 9.730703746e-01, 9.777396883e-01, 9.839166584e-01, 1.000000000e+00, }; const float dist_icdf_3_5[] = { 0.000000000e+00, 1.718397325e-02, 2.918666384e-02, 3.982191900e-02, 4.967010892e-02, 5.898056554e-02, 6.789035732e-02, 7.648534670e-02, 8.482394771e-02, 9.294824662e-02, 1.008898774e-01, 1.086734061e-01, 1.163184120e-01, 1.238408338e-01, 1.312538777e-01, 1.385686505e-01, 1.457946137e-01, 1.529399183e-01, 1.600116548e-01, 1.670160458e-01, 1.739585944e-01, 1.808442020e-01, 1.876772621e-01, 1.944617356e-01, 2.012012129e-01, 2.078989648e-01, 2.145579844e-01, 2.211810228e-01, 2.277706187e-01, 2.343291240e-01, 2.408587250e-01, 2.473614616e-01, 2.538392428e-01, 2.602938611e-01, 2.667270044e-01, 2.731402670e-01, 2.795351586e-01, 2.859131132e-01, 2.922754961e-01, 2.986236106e-01, 3.049587043e-01, 3.112819738e-01, 3.175945700e-01, 3.238976024e-01, 3.301921429e-01, 3.364792297e-01, 3.427598703e-01, 3.490350451e-01, 3.553057095e-01, 3.615727972e-01, 3.678372223e-01, 3.740998819e-01, 3.803616579e-01, 3.866234193e-01, 3.928860241e-01, 3.991503211e-01, 4.054171519e-01, 4.116873524e-01, 4.179617545e-01, 4.242411878e-01, 4.305264813e-01, 4.368184648e-01, 4.431179707e-01, 4.494258351e-01, 4.557429002e-01, 4.620700150e-01, 4.684080375e-01, 4.747578362e-01, 4.811202917e-01, 4.874962986e-01, 4.938867672e-01, 5.002926253e-01, 5.067148205e-01, 5.131543219e-01, 5.196121225e-01, 5.260892413e-01, 5.325867260e-01, 5.391056555e-01, 5.456471426e-01, 5.522123371e-01, 5.588024289e-01, 5.654186518e-01, 5.720622868e-01, 5.787346666e-01, 5.854371797e-01, 5.921712756e-01, 5.989384699e-01, 6.057403503e-01, 6.125785830e-01, 6.194549198e-01, 6.263712062e-01, 6.333293900e-01, 6.403315311e-01, 6.473798127e-01, 6.544765537e-01, 6.616242222e-01, 6.688254515e-01, 6.760830583e-01, 6.834000624e-01, 6.907797107e-01, 6.982255036e-01, 7.057412263e-01, 7.133309847e-01, 7.209992476e-01, 7.287508963e-01, 7.365912828e-01, 7.445263000e-01, 7.525624649e-01, 7.607070196e-01, 7.689680550e-01, 7.773546621e-01, 7.858771210e-01, 7.945471389e-01, 8.033781531e-01, 8.123857236e-01, 8.215880493e-01, 8.310066601e-01, 8.406673643e-01, 8.506015785e-01, 8.608482497e-01, 8.714567304e-01, 8.824912671e-01, 8.940383792e-01, 9.062198336e-01, 9.192175665e-01, 9.333279002e-01, 9.491041716e-01, 9.678856524e-01, 1.000000000e+00, 0.000000000e+00, 1.755461680e-03, 2.974383579e-03, 4.049409107e-03, 5.040626314e-03, 5.973930679e-03, 6.863594613e-03, 7.718578005e-03, 8.544987597e-03, 9.347229852e-03, 1.012862089e-02, 1.089173827e-02, 1.163863759e-02, 1.237099276e-02, 1.309019070e-02, 1.379739745e-02, 1.449360569e-02, 1.517966971e-02, 1.585633163e-02, 1.652424157e-02, 1.718397325e-02, 1.783603632e-02, 1.848088621e-02, 1.911893212e-02, 1.975054348e-02, 2.037605530e-02, 2.099577264e-02, 2.160997434e-02, 2.221891612e-02, 2.282283327e-02, 2.342194294e-02, 2.401644609e-02, 2.460652914e-02, 2.519236551e-02, 2.577411682e-02, 2.635193407e-02, 2.692595859e-02, 2.749632292e-02, 2.806315158e-02, 2.862656174e-02, 2.918666384e-02, 2.974356214e-02, 3.029735520e-02, 3.084813633e-02, 3.139599395e-02, 3.194101199e-02, 3.248327021e-02, 3.302284447e-02, 3.355980701e-02, 3.409422669e-02, 3.462616924e-02, 3.515569742e-02, 3.568287124e-02, 3.620774811e-02, 3.673038302e-02, 3.725082869e-02, 3.776913565e-02, 3.828535244e-02, 3.879952567e-02, 3.931170015e-02, 3.982191900e-02, 4.033022371e-02, 4.083665424e-02, 4.134124911e-02, 4.184404549e-02, 4.234507920e-02, 4.284438486e-02, 4.334199589e-02, 4.383794460e-02, 4.433226224e-02, 4.482497903e-02, 4.531612422e-02, 4.580572615e-02, 4.629381225e-02, 4.678040914e-02, 4.726554259e-02, 4.774923764e-02, 4.823151856e-02, 4.871240893e-02, 4.919193163e-02, 4.967010892e-02, 5.014696240e-02, 5.062251311e-02, 5.109678146e-02, 5.156978737e-02, 5.204155017e-02, 5.251208872e-02, 5.298142136e-02, 5.344956598e-02, 5.391653999e-02, 5.438236037e-02, 5.484704369e-02, 5.531060608e-02, 5.577306330e-02, 5.623443073e-02, 5.669472336e-02, 5.715395584e-02, 5.761214249e-02, 5.806929727e-02, 5.852543383e-02, 5.898056554e-02, 5.943470541e-02, 5.988786621e-02, 6.034006042e-02, 6.079130022e-02, 6.124159756e-02, 6.169096411e-02, 6.213941131e-02, 6.258695034e-02, 6.303359217e-02, 6.347934753e-02, 6.392422694e-02, 6.436824068e-02, 6.481139886e-02, 6.525371137e-02, 6.569518790e-02, 6.613583796e-02, 6.657567088e-02, 6.701469579e-02, 6.745292167e-02, 6.789035732e-02, 6.832701137e-02, 6.876289229e-02, 6.919800841e-02, 6.963236788e-02, 7.006597873e-02, 7.049884884e-02, 7.093098592e-02, 7.136239758e-02, 8.893512326e-01, 8.899319144e-01, 8.905140528e-01, 8.910976636e-01, 8.916827628e-01, 8.922693671e-01, 8.928574932e-01, 8.934471581e-01, 8.940383792e-01, 8.946311744e-01, 8.952255618e-01, 8.958215598e-01, 8.964191872e-01, 8.970184634e-01, 8.976194078e-01, 8.982220406e-01, 8.988263822e-01, 8.994324535e-01, 9.000402756e-01, 9.006498706e-01, 9.012612605e-01, 9.018744680e-01, 9.024895165e-01, 9.031064296e-01, 9.037252316e-01, 9.043459474e-01, 9.049686022e-01, 9.055932221e-01, 9.062198336e-01, 9.068484639e-01, 9.074791408e-01, 9.081118930e-01, 9.087467494e-01, 9.093837402e-01, 9.100228958e-01, 9.106642478e-01, 9.113078283e-01, 9.119536703e-01, 9.126018079e-01, 9.132522756e-01, 9.139051093e-01, 9.145603455e-01, 9.152180219e-01, 9.158781772e-01, 9.165408510e-01, 9.172060843e-01, 9.178739189e-01, 9.185443982e-01, 9.192175665e-01, 9.198934697e-01, 9.205721548e-01, 9.212536704e-01, 9.219380665e-01, 9.226253947e-01, 9.233157082e-01, 9.240090618e-01, 9.247055121e-01, 9.254051178e-01, 9.261079392e-01, 9.268140387e-01, 9.275234810e-01, 9.282363328e-01, 9.289526634e-01, 9.296725443e-01, 9.303960498e-01, 9.311232568e-01, 9.318542451e-01, 9.325890976e-01, 9.333279002e-01, 9.340707425e-01, 9.348177174e-01, 9.355689216e-01, 9.363244558e-01, 9.370844250e-01, 9.378489387e-01, 9.386181110e-01, 9.393920613e-01, 9.401709141e-01, 9.409548000e-01, 9.417438555e-01, 9.425382238e-01, 9.433380549e-01, 9.441435064e-01, 9.449547442e-01, 9.457719426e-01, 9.465952853e-01, 9.474249659e-01, 9.482611893e-01, 9.491041716e-01, 9.499541421e-01, 9.508113436e-01, 9.516760340e-01, 9.525484879e-01, 9.534289974e-01, 9.543178747e-01, 9.552154532e-01, 9.561220906e-01, 9.570381705e-01, 9.579641060e-01, 9.589003422e-01, 9.598473609e-01, 9.608056843e-01, 9.617758799e-01, 9.627585673e-01, 9.637544240e-01, 9.647641946e-01, 9.657886998e-01, 9.668288486e-01, 9.678856524e-01, 9.689602419e-01, 9.700538890e-01, 9.711680324e-01, 9.723043116e-01, 9.734646090e-01, 9.746511046e-01, 9.758663486e-01, 9.771133575e-01, 9.783957466e-01, 9.797179158e-01, 9.810853170e-01, 9.825048554e-01, 9.839855139e-01, 9.855393811e-01, 9.871834551e-01, 9.889431082e-01, 9.908596171e-01, 9.930099575e-01, 9.955801360e-01, 1.000000000e+00, }; const float dist_icdf_3_6[] = { 0.000000000e+00, 5.080117766e-03, 1.070137945e-02, 1.654833190e-02, 2.254781636e-02, 2.866409040e-02, 3.487570194e-02, 4.116827592e-02, 4.753148246e-02, 5.395752931e-02, 6.044032428e-02, 6.697497165e-02, 7.355745056e-02, 8.018439980e-02, 8.685296820e-02, 9.356070740e-02, 1.003054928e-01, 1.070854641e-01, 1.138989798e-01, 1.207445815e-01, 1.276209654e-01, 1.345269603e-01, 1.414615086e-01, 1.484236516e-01, 1.554125169e-01, 1.624273078e-01, 1.694672950e-01, 1.765318086e-01, 1.836202320e-01, 1.907319966e-01, 1.978665768e-01, 2.050234861e-01, 2.122022736e-01, 2.194025207e-01, 2.266238386e-01, 2.338658655e-01, 2.411282650e-01, 2.484107238e-01, 2.557129503e-01, 2.630346728e-01, 2.703756383e-01, 2.777356114e-01, 2.851143732e-01, 2.925117201e-01, 2.999274633e-01, 3.073614276e-01, 3.148134509e-01, 3.222833839e-01, 3.297710888e-01, 3.372764393e-01, 3.447993202e-01, 3.523396266e-01, 3.598972638e-01, 3.674721468e-01, 3.750642003e-01, 3.826733580e-01, 3.902995629e-01, 3.979427666e-01, 4.056029293e-01, 4.132800201e-01, 4.209740161e-01, 4.286849029e-01, 4.364126744e-01, 4.441573325e-01, 4.519188877e-01, 4.596973583e-01, 4.674927712e-01, 4.753051614e-01, 4.831345724e-01, 4.909810563e-01, 4.988446736e-01, 5.067254939e-01, 5.146235957e-01, 5.225390666e-01, 5.304720038e-01, 5.384225144e-01, 5.463907153e-01, 5.543767340e-01, 5.623807089e-01, 5.704027895e-01, 5.784431372e-01, 5.865019256e-01, 5.945793415e-01, 6.026755849e-01, 6.107908703e-01, 6.189254274e-01, 6.270795016e-01, 6.352533555e-01, 6.434472698e-01, 6.516615445e-01, 6.598965001e-01, 6.681524792e-01, 6.764298485e-01, 6.847290001e-01, 6.930503539e-01, 7.013943600e-01, 7.097615009e-01, 7.181522952e-01, 7.265673005e-01, 7.350071169e-01, 7.434723924e-01, 7.519638269e-01, 7.604821785e-01, 7.690282700e-01, 7.776029971e-01, 7.862073367e-01, 7.948423585e-01, 8.035092373e-01, 8.122092680e-01, 8.209438843e-01, 8.297146809e-01, 8.385234402e-01, 8.473721669e-01, 8.562631298e-01, 8.651989160e-01, 8.741825006e-01, 8.832173385e-01, 8.923074868e-01, 9.014577740e-01, 9.106740372e-01, 9.199634692e-01, 9.293351428e-01, 9.388008459e-01, 9.483764947e-01, 9.580847322e-01, 9.679602881e-01, 9.780631552e-01, 9.885228861e-01, 1.000000000e+00, 0.000000000e+00, 2.031186508e-04, 4.277904577e-04, 6.613892216e-04, 9.009823117e-04, 1.145134937e-03, 1.392984626e-03, 1.643952451e-03, 1.897621617e-03, 2.153677069e-03, 2.411871935e-03, 2.672007338e-03, 2.933919501e-03, 3.197471119e-03, 3.462545351e-03, 3.729041521e-03, 3.996871944e-03, 4.265959538e-03, 4.536235989e-03, 4.807640322e-03, 5.080117766e-03, 5.353618842e-03, 5.628098622e-03, 5.903516126e-03, 6.179833813e-03, 6.457017165e-03, 6.735034331e-03, 7.013855822e-03, 7.293454263e-03, 7.573804162e-03, 7.854881727e-03, 8.136664696e-03, 8.419132193e-03, 8.702264603e-03, 8.986043456e-03, 9.270451332e-03, 9.555471773e-03, 9.841089200e-03, 1.012728885e-02, 1.041405671e-02, 1.070137945e-02, 1.098924441e-02, 1.127763949e-02, 1.156655318e-02, 1.185597446e-02, 1.214589281e-02, 1.243629815e-02, 1.272718084e-02, 1.301853161e-02, 1.331034159e-02, 1.360260224e-02, 1.389530535e-02, 1.418844305e-02, 1.448200772e-02, 1.477599204e-02, 1.507038896e-02, 1.536519165e-02, 1.566039354e-02, 1.595598827e-02, 1.625196971e-02, 1.654833190e-02, 1.684506910e-02, 1.714217573e-02, 1.743964640e-02, 1.773747588e-02, 1.803565910e-02, 1.833419113e-02, 1.863306719e-02, 1.893228265e-02, 1.923183299e-02, 1.953171384e-02, 1.983192093e-02, 2.013245012e-02, 2.043329736e-02, 2.073445875e-02, 2.103593044e-02, 2.133770871e-02, 2.163978994e-02, 2.194217058e-02, 2.224484717e-02, 2.254781636e-02, 2.285107484e-02, 2.315461942e-02, 2.345844697e-02, 2.376255441e-02, 2.406693876e-02, 2.437159710e-02, 2.467652658e-02, 2.498172439e-02, 2.528718782e-02, 2.559291418e-02, 2.589890087e-02, 2.620514532e-02, 2.651164504e-02, 2.681839755e-02, 2.712540048e-02, 2.743265145e-02, 2.774014817e-02, 2.804788837e-02, 2.835586984e-02, 2.866409040e-02, 2.897254793e-02, 2.928124034e-02, 2.959016557e-02, 2.989932162e-02, 3.020870651e-02, 3.051831831e-02, 3.082815510e-02, 3.113821503e-02, 3.144849626e-02, 3.175899699e-02, 3.206971545e-02, 3.238064989e-02, 3.269179862e-02, 3.300315994e-02, 3.331473222e-02, 3.362651382e-02, 3.393850315e-02, 3.425069864e-02, 3.456309874e-02, 3.487570194e-02, 3.518850674e-02, 3.550151168e-02, 3.581471530e-02, 3.612811617e-02, 3.644171291e-02, 3.675550412e-02, 3.706948845e-02, 3.738366457e-02, 9.350023775e-01, 9.354762671e-01, 9.359504151e-01, 9.364248235e-01, 9.368994943e-01, 9.373744298e-01, 9.378496321e-01, 9.383251034e-01, 9.388008459e-01, 9.392768620e-01, 9.397531539e-01, 9.402297240e-01, 9.407065748e-01, 9.411837086e-01, 9.416611280e-01, 9.421388355e-01, 9.426168337e-01, 9.430951252e-01, 9.435737127e-01, 9.440525989e-01, 9.445317866e-01, 9.450112787e-01, 9.454910780e-01, 9.459711874e-01, 9.464516101e-01, 9.469323490e-01, 9.474134072e-01, 9.478947881e-01, 9.483764947e-01, 9.488585305e-01, 9.493408988e-01, 9.498236030e-01, 9.503066468e-01, 9.507900337e-01, 9.512737675e-01, 9.517578518e-01, 9.522422905e-01, 9.527270877e-01, 9.532122472e-01, 9.536977733e-01, 9.541836701e-01, 9.546699420e-01, 9.551565934e-01, 9.556436288e-01, 9.561310529e-01, 9.566188703e-01, 9.571070860e-01, 9.575957049e-01, 9.580847322e-01, 9.585741732e-01, 9.590640331e-01, 9.595543176e-01, 9.600450322e-01, 9.605361829e-01, 9.610277757e-01, 9.615198166e-01, 9.620123120e-01, 9.625052685e-01, 9.629986927e-01, 9.634925915e-01, 9.639869721e-01, 9.644818417e-01, 9.649772079e-01, 9.654730786e-01, 9.659694616e-01, 9.664663654e-01, 9.669637985e-01, 9.674617697e-01, 9.679602881e-01, 9.684593633e-01, 9.689590051e-01, 9.694592235e-01, 9.699600290e-01, 9.704614327e-01, 9.709634457e-01, 9.714660798e-01, 9.719693473e-01, 9.724732607e-01, 9.729778333e-01, 9.734830789e-01, 9.739890116e-01, 9.744956465e-01, 9.750029992e-01, 9.755110859e-01, 9.760199236e-01, 9.765295303e-01, 9.770399245e-01, 9.775511260e-01, 9.780631552e-01, 9.785760339e-01, 9.790897849e-01, 9.796044321e-01, 9.801200011e-01, 9.806365186e-01, 9.811540131e-01, 9.816725147e-01, 9.821920555e-01, 9.827126696e-01, 9.832343935e-01, 9.837572658e-01, 9.842813285e-01, 9.848066262e-01, 9.853332070e-01, 9.858611231e-01, 9.863904306e-01, 9.869211908e-01, 9.874534703e-01, 9.879873420e-01, 9.885228861e-01, 9.890601910e-01, 9.895993546e-01, 9.901404864e-01, 9.906837088e-01, 9.912291606e-01, 9.917769992e-01, 9.923274056e-01, 9.928805899e-01, 9.934367981e-01, 9.939963231e-01, 9.945595183e-01, 9.951268194e-01, 9.956987754e-01, 9.962760994e-01, 9.968597547e-01, 9.974511113e-01, 9.980522715e-01, 9.986668684e-01, 9.993027529e-01, 1.000000000e+00, }; const float dist_icdf_3_7[] = { 0.000000000e+00, 8.628158357e-04, 2.475092108e-03, 4.583935209e-03, 7.096952025e-03, 9.959998080e-03, 1.313608688e-02, 1.659774071e-02, 2.032341622e-02, 2.429557249e-02, 2.849952084e-02, 3.292269077e-02, 3.755413613e-02, 4.238418878e-02, 4.740420751e-02, 5.260639094e-02, 5.798363470e-02, 6.352942037e-02, 6.923772750e-02, 7.510296296e-02, 8.111990344e-02, 8.728364802e-02, 9.358957879e-02, 1.000333276e-01, 1.066107481e-01, 1.133178917e-01, 1.201509869e-01, 1.271064215e-01, 1.341807267e-01, 1.413705643e-01, 1.486727135e-01, 1.560840614e-01, 1.636015928e-01, 1.712223819e-01, 1.789435850e-01, 1.867624336e-01, 1.946762277e-01, 2.026823310e-01, 2.107781652e-01, 2.189612058e-01, 2.272289774e-01, 2.355790499e-01, 2.440090350e-01, 2.525165830e-01, 2.610993790e-01, 2.697551408e-01, 2.784816155e-01, 2.872765776e-01, 2.961378259e-01, 3.050631818e-01, 3.140504868e-01, 3.230976006e-01, 3.322023993e-01, 3.413627730e-01, 3.505766247e-01, 3.598418680e-01, 3.691564257e-01, 3.785182283e-01, 3.879252121e-01, 3.973753177e-01, 4.068664887e-01, 4.163966700e-01, 4.259638064e-01, 4.355658411e-01, 4.452007141e-01, 4.548663610e-01, 4.645607113e-01, 4.742816867e-01, 4.840272003e-01, 4.937951541e-01, 5.035834381e-01, 5.133899286e-01, 5.232124861e-01, 5.330489543e-01, 5.428971575e-01, 5.527548995e-01, 5.626199611e-01, 5.724900987e-01, 5.823630414e-01, 5.922364896e-01, 6.021081121e-01, 6.119755439e-01, 6.218363833e-01, 6.316881896e-01, 6.415284797e-01, 6.513547250e-01, 6.611643481e-01, 6.709547190e-01, 6.807231513e-01, 6.904668978e-01, 7.001831457e-01, 7.098690119e-01, 7.195215370e-01, 7.291376798e-01, 7.387143103e-01, 7.482482022e-01, 7.577360255e-01, 7.671743367e-01, 7.765595695e-01, 7.858880232e-01, 7.951558504e-01, 8.043590428e-01, 8.134934152e-01, 8.225545877e-01, 8.315379644e-01, 8.404387099e-01, 8.492517217e-01, 8.579715981e-01, 8.665926009e-01, 8.751086105e-01, 8.835130738e-01, 8.917989407e-01, 8.999585873e-01, 9.079837220e-01, 9.158652685e-01, 9.235932192e-01, 9.311564473e-01, 9.385424622e-01, 9.457370844e-01, 9.527240029e-01, 9.594841532e-01, 9.659948145e-01, 9.722282370e-01, 9.781494374e-01, 9.837123866e-01, 9.888526987e-01, 9.934712572e-01, 9.973860259e-01, 1.000000000e+00, 0.000000000e+00, 9.067693191e-06, 2.601788078e-05, 4.820059569e-05, 7.465261083e-05, 1.048127443e-04, 1.383002110e-04, 1.748342306e-04, 2.141964580e-04, 2.562106769e-04, 3.007307106e-04, 3.476327046e-04, 3.968099364e-04, 4.481691751e-04, 5.016280422e-04, 5.571130453e-04, 6.145580775e-04, 6.739032502e-04, 7.350939699e-04, 7.980801956e-04, 8.628158357e-04, 9.292582508e-04, 9.973678400e-04, 1.067107694e-03, 1.138443301e-03, 1.211342297e-03, 1.285774248e-03, 1.361710467e-03, 1.439123847e-03, 1.517988727e-03, 1.598280759e-03, 1.679976805e-03, 1.763054835e-03, 1.847493842e-03, 1.933273767e-03, 2.020375422e-03, 2.108780437e-03, 2.198471197e-03, 2.289430792e-03, 2.381642973e-03, 2.475092108e-03, 2.569763141e-03, 2.665641563e-03, 2.762713374e-03, 2.860965056e-03, 2.960383545e-03, 3.060956206e-03, 3.162670810e-03, 3.265515512e-03, 3.369478830e-03, 3.474549630e-03, 3.580717104e-03, 3.687970758e-03, 3.796300395e-03, 3.905696102e-03, 4.016148234e-03, 4.127647407e-03, 4.240184482e-03, 4.353750556e-03, 4.468336952e-03, 4.583935209e-03, 4.700537073e-03, 4.818134488e-03, 4.936719592e-03, 5.056284701e-03, 5.176822311e-03, 5.298325087e-03, 5.420785855e-03, 5.544197599e-03, 5.668553455e-03, 5.793846703e-03, 5.920070764e-03, 6.047219196e-03, 6.175285686e-03, 6.304264048e-03, 6.434148218e-03, 6.564932251e-03, 6.696610316e-03, 6.829176692e-03, 6.962625765e-03, 7.096952025e-03, 7.232150062e-03, 7.368214563e-03, 7.505140312e-03, 7.642922182e-03, 7.781555134e-03, 7.921034218e-03, 8.061354566e-03, 8.202511392e-03, 8.344499989e-03, 8.487315727e-03, 8.630954049e-03, 8.775410473e-03, 8.920680587e-03, 9.066760048e-03, 9.213644578e-03, 9.361329967e-03, 9.509812068e-03, 9.659086794e-03, 9.809150120e-03, 9.959998080e-03, 1.011162676e-02, 1.026403232e-02, 1.041721095e-02, 1.057115891e-02, 1.072587250e-02, 1.088134808e-02, 1.103758206e-02, 1.119457090e-02, 1.135231109e-02, 1.151079919e-02, 1.167003180e-02, 1.183000553e-02, 1.199071709e-02, 1.215216320e-02, 1.231434061e-02, 1.247724614e-02, 1.264087663e-02, 1.280522896e-02, 1.297030006e-02, 1.313608688e-02, 1.330258642e-02, 1.346979572e-02, 1.363771182e-02, 1.380633185e-02, 1.397565292e-02, 1.414567221e-02, 1.431638691e-02, 1.448779426e-02, 9.697701794e-01, 9.700800780e-01, 9.703892311e-01, 9.706976341e-01, 9.710052825e-01, 9.713121718e-01, 9.716182971e-01, 9.719236538e-01, 9.722282370e-01, 9.725320418e-01, 9.728350634e-01, 9.731372967e-01, 9.734387366e-01, 9.737393780e-01, 9.740392156e-01, 9.743382442e-01, 9.746364583e-01, 9.749338526e-01, 9.752304215e-01, 9.755261595e-01, 9.758210607e-01, 9.761151194e-01, 9.764083299e-01, 9.767006860e-01, 9.769921818e-01, 9.772828111e-01, 9.775725678e-01, 9.778614453e-01, 9.781494374e-01, 9.784365375e-01, 9.787227390e-01, 9.790080350e-01, 9.792924187e-01, 9.795758831e-01, 9.798584211e-01, 9.801400255e-01, 9.804206889e-01, 9.807004039e-01, 9.809791628e-01, 9.812569578e-01, 9.815337811e-01, 9.818096247e-01, 9.820844802e-01, 9.823583394e-01, 9.826311938e-01, 9.829030346e-01, 9.831738531e-01, 9.834436402e-01, 9.837123866e-01, 9.839800831e-01, 9.842467200e-01, 9.845122875e-01, 9.847767757e-01, 9.850401742e-01, 9.853024728e-01, 9.855636606e-01, 9.858237269e-01, 9.860826604e-01, 9.863404498e-01, 9.865970833e-01, 9.868525491e-01, 9.871068348e-01, 9.873599279e-01, 9.876118155e-01, 9.878624846e-01, 9.881119215e-01, 9.883601123e-01, 9.886070430e-01, 9.888526987e-01, 9.890970645e-01, 9.893401250e-01, 9.895818642e-01, 9.898222658e-01, 9.900613130e-01, 9.902989885e-01, 9.905352744e-01, 9.907701522e-01, 9.910036031e-01, 9.912356073e-01, 9.914661446e-01, 9.916951942e-01, 9.919227342e-01, 9.921487423e-01, 9.923731953e-01, 9.925960690e-01, 9.928173386e-01, 9.930369779e-01, 9.932549602e-01, 9.934712572e-01, 9.936858398e-01, 9.938986775e-01, 9.941097386e-01, 9.943189898e-01, 9.945263963e-01, 9.947319219e-01, 9.949355283e-01, 9.951371754e-01, 9.953368212e-01, 9.955344211e-01, 9.957299284e-01, 9.959232935e-01, 9.961144639e-01, 9.963033839e-01, 9.964899943e-01, 9.966742319e-01, 9.968560291e-01, 9.970353134e-01, 9.972120071e-01, 9.973860259e-01, 9.975572790e-01, 9.977256672e-01, 9.978910825e-01, 9.980534063e-01, 9.982125075e-01, 9.983682408e-01, 9.985204433e-01, 9.986689317e-01, 9.988134972e-01, 9.989538995e-01, 9.990898586e-01, 9.992210430e-01, 9.993470525e-01, 9.994673926e-01, 9.995814322e-01, 9.996883319e-01, 9.997869049e-01, 9.998753055e-01, 9.999501124e-01, 1.000000000e+00, }; const float dist_icdf_3_8[] = { 0.000000000e+00, 7.260746841e-09, 1.477806909e-07, 8.612331732e-07, 3.007830713e-06, 7.934854247e-06, 1.752882833e-05, 3.425937221e-05, 6.121739140e-05, 1.021490463e-04, 1.614863454e-04, 2.443748784e-04, 3.566989945e-04, 5.051045878e-04, 6.970195392e-04, 9.406717821e-04, 1.245104881e-03, 1.620190949e-03, 2.076640683e-03, 2.626010211e-03, 3.280704445e-03, 4.053976533e-03, 4.959923000e-03, 6.013474119e-03, 7.230378990e-03, 8.627184825e-03, 1.022120986e-02, 1.203050935e-02, 1.407383400e-02, 1.637058038e-02, 1.894073253e-02, 2.180479447e-02, 2.498371287e-02, 2.849878957e-02, 3.237158339e-02, 3.662380112e-02, 4.127717736e-02, 4.635334302e-02, 5.187368287e-02, 5.785918196e-02, 6.433026168e-02, 7.130660582e-02, 7.880697769e-02, 8.684902918e-02, 9.544910331e-02, 1.046220316e-01, 1.143809287e-01, 1.247369851e-01, 1.356992623e-01, 1.472744914e-01, 1.594668782e-01, 1.722779184e-01, 1.857062260e-01, 1.997473774e-01, 2.143937750e-01, 2.296345338e-01, 2.454553931e-01, 2.618386574e-01, 2.787631687e-01, 2.962043118e-01, 3.141340558e-01, 3.325210327e-01, 3.513306529e-01, 3.705252597e-01, 3.900643214e-01, 4.099046591e-01, 4.300007103e-01, 4.503048243e-01, 4.707675863e-01, 4.913381680e-01, 5.119646978e-01, 5.325946486e-01, 5.531752357e-01, 5.736538210e-01, 5.939783167e-01, 6.140975840e-01, 6.339618206e-01, 6.535229314e-01, 6.727348788e-01, 6.915540062e-01, 7.099393325e-01, 7.278528130e-01, 7.452595647e-01, 7.621280532e-01, 7.784302410e-01, 7.941416955e-01, 8.092416579e-01, 8.237130726e-01, 8.375425797e-01, 8.507204712e-01, 8.632406150e-01, 8.751003476e-01, 8.863003401e-01, 8.968444397e-01, 9.067394917e-01, 9.159951428e-01, 9.246236328e-01, 9.326395744e-01, 9.400597275e-01, 9.469027689e-01, 9.531890613e-01, 9.589404239e-01, 9.641799069e-01, 9.689315719e-01, 9.732202796e-01, 9.770714872e-01, 9.805110549e-01, 9.835650640e-01, 9.862596462e-01, 9.886208241e-01, 9.906743645e-01, 9.924456421e-01, 9.939595152e-01, 9.952402119e-01, 9.963112263e-01, 9.971952242e-01, 9.979139565e-01, 9.984881808e-01, 9.989375875e-01, 9.992807325e-01, 9.995349708e-01, 9.997163933e-01, 9.998397613e-01, 9.999184380e-01, 9.999643114e-01, 9.999877046e-01, 9.999972617e-01, 9.999997899e-01, 1.000000000e+00, 0.000000000e+00, 1.603794521e-14, 3.264263130e-13, 1.902341143e-12, 6.643877156e-12, 1.752703395e-11, 3.871906265e-11, 7.567556292e-11, 1.352253232e-10, 2.256462269e-10, 3.567342945e-10, 5.398672505e-10, 7.880636012e-10, 1.116037950e-09, 1.540253109e-09, 2.078969427e-09, 2.752291707e-09, 3.582213960e-09, 4.592662261e-09, 5.809535875e-09, 7.260746841e-09, 8.976258132e-09, 1.098812053e-08, 1.333050831e-08, 1.603975385e-08, 1.915438117e-08, 2.271513862e-08, 2.676503061e-08, 3.134934855e-08, 3.651570105e-08, 4.231404335e-08, 4.879670608e-08, 5.601842344e-08, 6.403636067e-08, 7.291014104e-08, 8.270187225e-08, 9.347617228e-08, 1.053001949e-07, 1.182436543e-07, 1.323788501e-07, 1.477806909e-07, 1.645267180e-07, 1.826971290e-07, 2.023748002e-07, 2.236453094e-07, 2.465969581e-07, 2.713207930e-07, 2.979106280e-07, 3.264630648e-07, 3.570775143e-07, 3.898562170e-07, 4.249042634e-07, 4.623296138e-07, 5.022431186e-07, 5.447585373e-07, 5.899925582e-07, 6.380648172e-07, 6.890979169e-07, 7.432174450e-07, 8.005519927e-07, 8.612331732e-07, 9.253956390e-07, 9.931771007e-07, 1.064718343e-06, 1.140163245e-06, 1.219658794e-06, 1.303355103e-06, 1.391405432e-06, 1.483966199e-06, 1.581196998e-06, 1.683260620e-06, 1.790323061e-06, 1.902553545e-06, 2.020124537e-06, 2.143211761e-06, 2.271994210e-06, 2.406654168e-06, 2.547377223e-06, 2.694352281e-06, 2.847771581e-06, 3.007830713e-06, 3.174728628e-06, 3.348667660e-06, 3.529853531e-06, 3.718495373e-06, 3.914805740e-06, 4.119000622e-06, 4.331299459e-06, 4.551925155e-06, 4.781104092e-06, 5.019066144e-06, 5.266044692e-06, 5.522276635e-06, 5.788002404e-06, 6.063465978e-06, 6.348914894e-06, 6.644600263e-06, 6.950776781e-06, 7.267702742e-06, 7.595640054e-06, 7.934854247e-06, 8.285614490e-06, 8.648193601e-06, 9.022868063e-06, 9.409918030e-06, 9.809627348e-06, 1.022228356e-05, 1.064817792e-05, 1.108760541e-05, 1.154086475e-05, 1.200825840e-05, 1.249009259e-05, 1.298667732e-05, 1.349832636e-05, 1.402535730e-05, 1.456809152e-05, 1.512685422e-05, 1.570197445e-05, 1.629378508e-05, 1.690262284e-05, 1.752882833e-05, 1.817274601e-05, 1.883472426e-05, 1.951511532e-05, 2.021427536e-05, 2.093256448e-05, 2.167034668e-05, 2.242798994e-05, 2.320586617e-05, 9.997964932e-01, 9.998023198e-01, 9.998080237e-01, 9.998136065e-01, 9.998190699e-01, 9.998244155e-01, 9.998296448e-01, 9.998347596e-01, 9.998397613e-01, 9.998446516e-01, 9.998494321e-01, 9.998541043e-01, 9.998586698e-01, 9.998631301e-01, 9.998674868e-01, 9.998717413e-01, 9.998758953e-01, 9.998799502e-01, 9.998839075e-01, 9.998877688e-01, 9.998915354e-01, 9.998952090e-01, 9.998987908e-01, 9.999022825e-01, 9.999056854e-01, 9.999090010e-01, 9.999122307e-01, 9.999153759e-01, 9.999184380e-01, 9.999214184e-01, 9.999243185e-01, 9.999271398e-01, 9.999298834e-01, 9.999325509e-01, 9.999351435e-01, 9.999376626e-01, 9.999401095e-01, 9.999424855e-01, 9.999447920e-01, 9.999470302e-01, 9.999492015e-01, 9.999513070e-01, 9.999533481e-01, 9.999553261e-01, 9.999572421e-01, 9.999590974e-01, 9.999608932e-01, 9.999626308e-01, 9.999643114e-01, 9.999659361e-01, 9.999675061e-01, 9.999690226e-01, 9.999704868e-01, 9.999718998e-01, 9.999732628e-01, 9.999745769e-01, 9.999758432e-01, 9.999770628e-01, 9.999782368e-01, 9.999793664e-01, 9.999804525e-01, 9.999814963e-01, 9.999824989e-01, 9.999834611e-01, 9.999843842e-01, 9.999852691e-01, 9.999861167e-01, 9.999869283e-01, 9.999877046e-01, 9.999884467e-01, 9.999891556e-01, 9.999898322e-01, 9.999904774e-01, 9.999910922e-01, 9.999916776e-01, 9.999922343e-01, 9.999927633e-01, 9.999932656e-01, 9.999937419e-01, 9.999941931e-01, 9.999946201e-01, 9.999950237e-01, 9.999954048e-01, 9.999957640e-01, 9.999961024e-01, 9.999964205e-01, 9.999967193e-01, 9.999969995e-01, 9.999972617e-01, 9.999975069e-01, 9.999977356e-01, 9.999979486e-01, 9.999981465e-01, 9.999983302e-01, 9.999985002e-01, 9.999986572e-01, 9.999988019e-01, 9.999989348e-01, 9.999990566e-01, 9.999991680e-01, 9.999992694e-01, 9.999993615e-01, 9.999994448e-01, 9.999995198e-01, 9.999995872e-01, 9.999996474e-01, 9.999997010e-01, 9.999997483e-01, 9.999997899e-01, 9.999998263e-01, 9.999998578e-01, 9.999998849e-01, 9.999999081e-01, 9.999999276e-01, 9.999999439e-01, 9.999999574e-01, 9.999999683e-01, 9.999999771e-01, 9.999999839e-01, 9.999999891e-01, 9.999999929e-01, 9.999999957e-01, 9.999999976e-01, 9.999999988e-01, 9.999999995e-01, 9.999999998e-01, 1.000000000e+00, 1.000000000e+00, 1.000000000e+00, }; const float dist_icdf_4_0[] = { 0.000000000e+00, 4.467052359e-01, 4.524901822e-01, 4.561468853e-01, 4.588886998e-01, 4.611122150e-01, 4.629993420e-01, 4.646493976e-01, 4.661228313e-01, 4.674592991e-01, 4.686862873e-01, 4.698236689e-01, 4.708863008e-01, 4.718855962e-01, 4.728305226e-01, 4.737282613e-01, 4.745846574e-01, 4.754045361e-01, 4.761919299e-01, 4.769502454e-01, 4.776823891e-01, 4.783908617e-01, 4.790778320e-01, 4.797451944e-01, 4.803946144e-01, 4.810275646e-01, 4.816453550e-01, 4.822491559e-01, 4.828400186e-01, 4.834188913e-01, 4.839866328e-01, 4.845440240e-01, 4.850917777e-01, 4.856305466e-01, 4.861609307e-01, 4.866834830e-01, 4.871987150e-01, 4.877071012e-01, 4.882090827e-01, 4.887050713e-01, 4.891954520e-01, 4.896805860e-01, 4.901608127e-01, 4.906364524e-01, 4.911078075e-01, 4.915751648e-01, 4.920387966e-01, 4.924989622e-01, 4.929559091e-01, 4.934098742e-01, 4.938610847e-01, 4.943097593e-01, 4.947561087e-01, 4.952003364e-01, 4.956426400e-01, 4.960832111e-01, 4.965222365e-01, 4.969598984e-01, 4.973963755e-01, 4.978318429e-01, 4.982664731e-01, 4.987004361e-01, 4.991339005e-01, 4.995670331e-01, 5.000000000e-01, 5.004329669e-01, 5.008660995e-01, 5.012995639e-01, 5.017335269e-01, 5.021681571e-01, 5.026036245e-01, 5.030401016e-01, 5.034777635e-01, 5.039167889e-01, 5.043573600e-01, 5.047996636e-01, 5.052438913e-01, 5.056902407e-01, 5.061389153e-01, 5.065901258e-01, 5.070440909e-01, 5.075010378e-01, 5.079612034e-01, 5.084248352e-01, 5.088921925e-01, 5.093635476e-01, 5.098391873e-01, 5.103194140e-01, 5.108045480e-01, 5.112949287e-01, 5.117909173e-01, 5.122928988e-01, 5.128012850e-01, 5.133165170e-01, 5.138390693e-01, 5.143694534e-01, 5.149082223e-01, 5.154559760e-01, 5.160133672e-01, 5.165811087e-01, 5.171599814e-01, 5.177508441e-01, 5.183546450e-01, 5.189724354e-01, 5.196053856e-01, 5.202548056e-01, 5.209221680e-01, 5.216091383e-01, 5.223176109e-01, 5.230497546e-01, 5.238080701e-01, 5.245954639e-01, 5.254153426e-01, 5.262717387e-01, 5.271694774e-01, 5.281144038e-01, 5.291136992e-01, 5.301763311e-01, 5.313137127e-01, 5.325407009e-01, 5.338771687e-01, 5.353506024e-01, 5.370006580e-01, 5.388877850e-01, 5.411113002e-01, 5.438531147e-01, 5.475098178e-01, 5.532947641e-01, 1.000000000e+00, 0.000000000e+00, 4.261396487e-01, 4.304173410e-01, 4.330330957e-01, 4.349454447e-01, 4.364635318e-01, 4.377278046e-01, 4.388143512e-01, 4.397691782e-01, 4.406222922e-01, 4.413943829e-01, 4.421003374e-01, 4.427512360e-01, 4.433555549e-01, 4.439199273e-01, 4.444496452e-01, 4.449489995e-01, 4.454215198e-01, 4.458701450e-01, 4.462973494e-01, 4.467052359e-01, 4.470956078e-01, 4.474700231e-01, 4.478298376e-01, 4.481762385e-01, 4.485102716e-01, 4.488328629e-01, 4.491448366e-01, 4.494469294e-01, 4.497398025e-01, 4.500240518e-01, 4.503002164e-01, 4.505687854e-01, 4.508302039e-01, 4.510848785e-01, 4.513331814e-01, 4.515754543e-01, 4.518120116e-01, 4.520431432e-01, 4.522691173e-01, 4.524901822e-01, 4.527065683e-01, 4.529184900e-01, 4.531261470e-01, 4.533297255e-01, 4.535293996e-01, 4.537253324e-01, 4.539176767e-01, 4.541065759e-01, 4.542921649e-01, 4.544745706e-01, 4.546539126e-01, 4.548303040e-01, 4.550038511e-01, 4.551746551e-01, 4.553428112e-01, 4.555084100e-01, 4.556715373e-01, 4.558322746e-01, 4.559906994e-01, 4.561468853e-01, 4.563009024e-01, 4.564528177e-01, 4.566026947e-01, 4.567505944e-01, 4.568965748e-01, 4.570406913e-01, 4.571829971e-01, 4.573235430e-01, 4.574623777e-01, 4.575995476e-01, 4.577350976e-01, 4.578690706e-01, 4.580015076e-01, 4.581324484e-01, 4.582619307e-01, 4.583899913e-01, 4.585166653e-01, 4.586419865e-01, 4.587659875e-01, 4.588886998e-01, 4.590101536e-01, 4.591303782e-01, 4.592494016e-01, 4.593672512e-01, 4.594839531e-01, 4.595995329e-01, 4.597140149e-01, 4.598274229e-01, 4.599397799e-01, 4.600511080e-01, 4.601614287e-01, 4.602707630e-01, 4.603791308e-01, 4.604865518e-01, 4.605930448e-01, 4.606986283e-01, 4.608033200e-01, 4.609071373e-01, 4.610100969e-01, 4.611122150e-01, 4.612135076e-01, 4.613139900e-01, 4.614136770e-01, 4.615125833e-01, 4.616107230e-01, 4.617081097e-01, 4.618047568e-01, 4.619006773e-01, 4.619958839e-01, 4.620903889e-01, 4.621842043e-01, 4.622773417e-01, 4.623698125e-01, 4.624616279e-01, 4.625527986e-01, 4.626433351e-01, 4.627332479e-01, 4.628225468e-01, 4.629112416e-01, 4.629993420e-01, 4.630868572e-01, 4.631737963e-01, 4.632601682e-01, 4.633459815e-01, 4.634312448e-01, 4.635159663e-01, 4.636001541e-01, 4.636838162e-01, 5.363161838e-01, 5.363998459e-01, 5.364840337e-01, 5.365687552e-01, 5.366540185e-01, 5.367398318e-01, 5.368262037e-01, 5.369131428e-01, 5.370006580e-01, 5.370887584e-01, 5.371774532e-01, 5.372667521e-01, 5.373566649e-01, 5.374472014e-01, 5.375383721e-01, 5.376301875e-01, 5.377226583e-01, 5.378157957e-01, 5.379096111e-01, 5.380041161e-01, 5.380993227e-01, 5.381952432e-01, 5.382918903e-01, 5.383892770e-01, 5.384874167e-01, 5.385863230e-01, 5.386860100e-01, 5.387864924e-01, 5.388877850e-01, 5.389899031e-01, 5.390928627e-01, 5.391966800e-01, 5.393013717e-01, 5.394069552e-01, 5.395134482e-01, 5.396208692e-01, 5.397292370e-01, 5.398385713e-01, 5.399488920e-01, 5.400602201e-01, 5.401725771e-01, 5.402859851e-01, 5.404004671e-01, 5.405160469e-01, 5.406327488e-01, 5.407505984e-01, 5.408696218e-01, 5.409898464e-01, 5.411113002e-01, 5.412340125e-01, 5.413580135e-01, 5.414833347e-01, 5.416100087e-01, 5.417380693e-01, 5.418675516e-01, 5.419984924e-01, 5.421309294e-01, 5.422649024e-01, 5.424004524e-01, 5.425376223e-01, 5.426764570e-01, 5.428170029e-01, 5.429593087e-01, 5.431034252e-01, 5.432494056e-01, 5.433973053e-01, 5.435471823e-01, 5.436990976e-01, 5.438531147e-01, 5.440093006e-01, 5.441677254e-01, 5.443284627e-01, 5.444915900e-01, 5.446571888e-01, 5.448253449e-01, 5.449961489e-01, 5.451696960e-01, 5.453460874e-01, 5.455254294e-01, 5.457078351e-01, 5.458934241e-01, 5.460823233e-01, 5.462746676e-01, 5.464706004e-01, 5.466702745e-01, 5.468738530e-01, 5.470815100e-01, 5.472934317e-01, 5.475098178e-01, 5.477308827e-01, 5.479568568e-01, 5.481879884e-01, 5.484245457e-01, 5.486668186e-01, 5.489151215e-01, 5.491697961e-01, 5.494312146e-01, 5.496997836e-01, 5.499759482e-01, 5.502601975e-01, 5.505530706e-01, 5.508551634e-01, 5.511671371e-01, 5.514897284e-01, 5.518237615e-01, 5.521701624e-01, 5.525299769e-01, 5.529043922e-01, 5.532947641e-01, 5.537026506e-01, 5.541298550e-01, 5.545784802e-01, 5.550510005e-01, 5.555503548e-01, 5.560800727e-01, 5.566444451e-01, 5.572487640e-01, 5.578996626e-01, 5.586056171e-01, 5.593777078e-01, 5.602308218e-01, 5.611856488e-01, 5.622721954e-01, 5.635364682e-01, 5.650545553e-01, 5.669669043e-01, 5.695826590e-01, 5.738603513e-01, 1.000000000e+00, }; const float dist_icdf_4_1[] = { 0.000000000e+00, 2.942760427e-01, 3.149979404e-01, 3.283773557e-01, 3.385420074e-01, 3.468640109e-01, 3.539797032e-01, 3.602393943e-01, 3.658577298e-01, 3.709763124e-01, 3.756937647e-01, 3.800816940e-01, 3.841938366e-01, 3.880716133e-01, 3.917476707e-01, 3.952482270e-01, 3.985946785e-01, 4.018047309e-01, 4.048932152e-01, 4.078726882e-01, 4.107538836e-01, 4.135460553e-01, 4.162572435e-01, 4.188944830e-01, 4.214639687e-01, 4.239711877e-01, 4.264210268e-01, 4.288178601e-01, 4.311656214e-01, 4.334678633e-01, 4.357278084e-01, 4.379483903e-01, 4.401322901e-01, 4.422819660e-01, 4.443996800e-01, 4.464875197e-01, 4.485474179e-01, 4.505811690e-01, 4.525904443e-01, 4.545768041e-01, 4.565417095e-01, 4.584865320e-01, 4.604125624e-01, 4.623210188e-01, 4.642130535e-01, 4.660897592e-01, 4.679521747e-01, 4.698012900e-01, 4.716380508e-01, 4.734633630e-01, 4.752780960e-01, 4.770830868e-01, 4.788791426e-01, 4.806670443e-01, 4.824475489e-01, 4.842213922e-01, 4.859892913e-01, 4.877519464e-01, 4.895100437e-01, 4.912642567e-01, 4.930152485e-01, 4.947636734e-01, 4.965101792e-01, 4.982554083e-01, 5.000000000e-01, 5.017445917e-01, 5.034898208e-01, 5.052363266e-01, 5.069847515e-01, 5.087357433e-01, 5.104899563e-01, 5.122480536e-01, 5.140107087e-01, 5.157786078e-01, 5.175524511e-01, 5.193329557e-01, 5.211208574e-01, 5.229169132e-01, 5.247219040e-01, 5.265366370e-01, 5.283619492e-01, 5.301987100e-01, 5.320478253e-01, 5.339102408e-01, 5.357869465e-01, 5.376789812e-01, 5.395874376e-01, 5.415134680e-01, 5.434582905e-01, 5.454231959e-01, 5.474095557e-01, 5.494188310e-01, 5.514525821e-01, 5.535124803e-01, 5.556003200e-01, 5.577180340e-01, 5.598677099e-01, 5.620516097e-01, 5.642721916e-01, 5.665321367e-01, 5.688343786e-01, 5.711821399e-01, 5.735789732e-01, 5.760288123e-01, 5.785360313e-01, 5.811055170e-01, 5.837427565e-01, 5.864539447e-01, 5.892461164e-01, 5.921273118e-01, 5.951067848e-01, 5.981952691e-01, 6.014053215e-01, 6.047517730e-01, 6.082523293e-01, 6.119283867e-01, 6.158061634e-01, 6.199183060e-01, 6.243062353e-01, 6.290236876e-01, 6.341422702e-01, 6.397606057e-01, 6.460202968e-01, 6.531359891e-01, 6.614579926e-01, 6.716226443e-01, 6.850020596e-01, 7.057239573e-01, 1.000000000e+00, 0.000000000e+00, 2.257007217e-01, 2.392522814e-01, 2.477316055e-01, 2.540208669e-01, 2.590666306e-01, 2.633040873e-01, 2.669711435e-01, 2.702127061e-01, 2.731238704e-01, 2.757705562e-01, 2.782004191e-01, 2.804490771e-01, 2.825438811e-01, 2.845063102e-01, 2.863535537e-01, 2.880995920e-01, 2.897559554e-01, 2.913322699e-01, 2.928366589e-01, 2.942760427e-01, 2.956563678e-01, 2.969827826e-01, 2.982597759e-01, 2.994912858e-01, 3.006807873e-01, 3.018313627e-01, 3.029457594e-01, 3.040264374e-01, 3.050756078e-01, 3.060952664e-01, 3.070872205e-01, 3.080531126e-01, 3.089944396e-01, 3.099125703e-01, 3.108087590e-01, 3.116841588e-01, 3.125398319e-01, 3.133767591e-01, 3.141958480e-01, 3.149979404e-01, 3.157838182e-01, 3.165542093e-01, 3.173097924e-01, 3.180512014e-01, 3.187790295e-01, 3.194938321e-01, 3.201961308e-01, 3.208864154e-01, 3.215651468e-01, 3.222327592e-01, 3.228896622e-01, 3.235362425e-01, 3.241728657e-01, 3.247998779e-01, 3.254176069e-01, 3.260263636e-01, 3.266264432e-01, 3.272181261e-01, 3.278016789e-01, 3.283773557e-01, 3.289453981e-01, 3.295060368e-01, 3.300594917e-01, 3.306059731e-01, 3.311456815e-01, 3.316788091e-01, 3.322055395e-01, 3.327260487e-01, 3.332405052e-01, 3.337490707e-01, 3.342519003e-01, 3.347491428e-01, 3.352409412e-01, 3.357274329e-01, 3.362087502e-01, 3.366850201e-01, 3.371563650e-01, 3.376229028e-01, 3.380847471e-01, 3.385420074e-01, 3.389947892e-01, 3.394431945e-01, 3.398873216e-01, 3.403272656e-01, 3.407631181e-01, 3.411949680e-01, 3.416229011e-01, 3.420470002e-01, 3.424673457e-01, 3.428840153e-01, 3.432970844e-01, 3.437066258e-01, 3.441127102e-01, 3.445154062e-01, 3.449147802e-01, 3.453108966e-01, 3.457038180e-01, 3.460936052e-01, 3.464803171e-01, 3.468640109e-01, 3.472447423e-01, 3.476225654e-01, 3.479975327e-01, 3.483696954e-01, 3.487391032e-01, 3.491058044e-01, 3.494698462e-01, 3.498312743e-01, 3.501901334e-01, 3.505464670e-01, 3.509003174e-01, 3.512517258e-01, 3.516007324e-01, 3.519473765e-01, 3.522916962e-01, 3.526337289e-01, 3.529735109e-01, 3.533110777e-01, 3.536464638e-01, 3.539797032e-01, 3.543108288e-01, 3.546398728e-01, 3.549668668e-01, 3.552918414e-01, 3.556148266e-01, 3.559358520e-01, 3.562549461e-01, 3.565721370e-01, 6.434278630e-01, 6.437450539e-01, 6.440641480e-01, 6.443851734e-01, 6.447081586e-01, 6.450331332e-01, 6.453601272e-01, 6.456891712e-01, 6.460202968e-01, 6.463535362e-01, 6.466889223e-01, 6.470264891e-01, 6.473662711e-01, 6.477083038e-01, 6.480526235e-01, 6.483992676e-01, 6.487482742e-01, 6.490996826e-01, 6.494535330e-01, 6.498098666e-01, 6.501687257e-01, 6.505301538e-01, 6.508941956e-01, 6.512608968e-01, 6.516303046e-01, 6.520024673e-01, 6.523774346e-01, 6.527552577e-01, 6.531359891e-01, 6.535196829e-01, 6.539063948e-01, 6.542961820e-01, 6.546891034e-01, 6.550852198e-01, 6.554845938e-01, 6.558872898e-01, 6.562933742e-01, 6.567029156e-01, 6.571159847e-01, 6.575326543e-01, 6.579529998e-01, 6.583770989e-01, 6.588050320e-01, 6.592368819e-01, 6.596727344e-01, 6.601126784e-01, 6.605568055e-01, 6.610052108e-01, 6.614579926e-01, 6.619152529e-01, 6.623770972e-01, 6.628436350e-01, 6.633149799e-01, 6.637912498e-01, 6.642725671e-01, 6.647590588e-01, 6.652508572e-01, 6.657480997e-01, 6.662509293e-01, 6.667594948e-01, 6.672739513e-01, 6.677944605e-01, 6.683211909e-01, 6.688543185e-01, 6.693940269e-01, 6.699405083e-01, 6.704939632e-01, 6.710546019e-01, 6.716226443e-01, 6.721983211e-01, 6.727818739e-01, 6.733735568e-01, 6.739736364e-01, 6.745823931e-01, 6.752001221e-01, 6.758271343e-01, 6.764637575e-01, 6.771103378e-01, 6.777672408e-01, 6.784348532e-01, 6.791135846e-01, 6.798038692e-01, 6.805061679e-01, 6.812209705e-01, 6.819487986e-01, 6.826902076e-01, 6.834457907e-01, 6.842161818e-01, 6.850020596e-01, 6.858041520e-01, 6.866232409e-01, 6.874601681e-01, 6.883158412e-01, 6.891912410e-01, 6.900874297e-01, 6.910055604e-01, 6.919468874e-01, 6.929127795e-01, 6.939047336e-01, 6.949243922e-01, 6.959735626e-01, 6.970542406e-01, 6.981686373e-01, 6.993192127e-01, 7.005087142e-01, 7.017402241e-01, 7.030172174e-01, 7.043436322e-01, 7.057239573e-01, 7.071633411e-01, 7.086677301e-01, 7.102440446e-01, 7.119004080e-01, 7.136464463e-01, 7.154936898e-01, 7.174561189e-01, 7.195509229e-01, 7.217995809e-01, 7.242294438e-01, 7.268761296e-01, 7.297872939e-01, 7.330288565e-01, 7.366959127e-01, 7.409333694e-01, 7.459791331e-01, 7.522683945e-01, 7.607477186e-01, 7.742992783e-01, 1.000000000e+00, }; const float dist_icdf_4_2[] = { 0.000000000e+00, 1.329253218e-01, 1.610934102e-01, 1.806852421e-01, 1.962705253e-01, 2.094622071e-01, 2.210382042e-01, 2.314396010e-01, 2.409431685e-01, 2.497351692e-01, 2.579475763e-01, 2.656776665e-01, 2.729994260e-01, 2.799705799e-01, 2.866371296e-01, 2.930363944e-01, 2.991991170e-01, 3.051509596e-01, 3.109135934e-01, 3.165055077e-01, 3.219426216e-01, 3.272387534e-01, 3.324059874e-01, 3.374549622e-01, 3.423951013e-01, 3.472347992e-01, 3.519815725e-01, 3.566421845e-01, 3.612227478e-01, 3.657288105e-01, 3.701654277e-01, 3.745372232e-01, 3.788484406e-01, 3.831029882e-01, 3.873044766e-01, 3.914562515e-01, 3.955614230e-01, 3.996228896e-01, 4.036433604e-01, 4.076253744e-01, 4.115713170e-01, 4.154834352e-01, 4.193638510e-01, 4.232145731e-01, 4.270375076e-01, 4.308344677e-01, 4.346071819e-01, 4.383573026e-01, 4.420864122e-01, 4.457960304e-01, 4.494876198e-01, 4.531625910e-01, 4.568223083e-01, 4.604680938e-01, 4.641012319e-01, 4.677229732e-01, 4.713345385e-01, 4.749371221e-01, 4.785318955e-01, 4.821200102e-01, 4.857026010e-01, 4.892807890e-01, 4.928556844e-01, 4.964283892e-01, 5.000000000e-01, 5.035716108e-01, 5.071443156e-01, 5.107192110e-01, 5.142973990e-01, 5.178799898e-01, 5.214681045e-01, 5.250628779e-01, 5.286654615e-01, 5.322770268e-01, 5.358987681e-01, 5.395319062e-01, 5.431776917e-01, 5.468374090e-01, 5.505123802e-01, 5.542039696e-01, 5.579135878e-01, 5.616426974e-01, 5.653928181e-01, 5.691655323e-01, 5.729624924e-01, 5.767854269e-01, 5.806361490e-01, 5.845165648e-01, 5.884286830e-01, 5.923746256e-01, 5.963566396e-01, 6.003771104e-01, 6.044385770e-01, 6.085437485e-01, 6.126955234e-01, 6.168970118e-01, 6.211515594e-01, 6.254627768e-01, 6.298345723e-01, 6.342711895e-01, 6.387772522e-01, 6.433578155e-01, 6.480184275e-01, 6.527652008e-01, 6.576048987e-01, 6.625450378e-01, 6.675940126e-01, 6.727612466e-01, 6.780573784e-01, 6.834944923e-01, 6.890864066e-01, 6.948490404e-01, 7.008008830e-01, 7.069636056e-01, 7.133628704e-01, 7.200294201e-01, 7.270005740e-01, 7.343223335e-01, 7.420524237e-01, 7.502648308e-01, 7.590568315e-01, 7.685603990e-01, 7.789617958e-01, 7.905377929e-01, 8.037294747e-01, 8.193147579e-01, 8.389065898e-01, 8.670746782e-01, 1.000000000e+00, 0.000000000e+00, 5.996547206e-02, 7.184741903e-02, 7.992098351e-02, 8.622724115e-02, 9.148204456e-02, 9.602905702e-02, 1.000624113e-01, 1.037035326e-01, 1.070339066e-01, 1.101111201e-01, 1.129775181e-01, 1.156652343e-01, 1.181992850e-01, 1.205995631e-01, 1.228821734e-01, 1.250603540e-01, 1.271451321e-01, 1.291457991e-01, 1.310702644e-01, 1.329253218e-01, 1.347168539e-01, 1.364499918e-01, 1.381292403e-01, 1.397585777e-01, 1.413415371e-01, 1.428812713e-01, 1.443806070e-01, 1.458420891e-01, 1.472680177e-01, 1.486604794e-01, 1.500213735e-01, 1.513524339e-01, 1.526552488e-01, 1.539312764e-01, 1.551818593e-01, 1.564082367e-01, 1.576115548e-01, 1.587928764e-01, 1.599531886e-01, 1.610934102e-01, 1.622143982e-01, 1.633169530e-01, 1.644018236e-01, 1.654697118e-01, 1.665212764e-01, 1.675571368e-01, 1.685778759e-01, 1.695840429e-01, 1.705761565e-01, 1.715547064e-01, 1.725201560e-01, 1.734729441e-01, 1.744134868e-01, 1.753421787e-01, 1.762593951e-01, 1.771654923e-01, 1.780608098e-01, 1.789456708e-01, 1.798203835e-01, 1.806852421e-01, 1.815405272e-01, 1.823865072e-01, 1.832234388e-01, 1.840515676e-01, 1.848711289e-01, 1.856823480e-01, 1.864854413e-01, 1.872806161e-01, 1.880680717e-01, 1.888479995e-01, 1.896205835e-01, 1.903860008e-01, 1.911444216e-01, 1.918960100e-01, 1.926409240e-01, 1.933793159e-01, 1.941113327e-01, 1.948371161e-01, 1.955568029e-01, 1.962705253e-01, 1.969784108e-01, 1.976805830e-01, 1.983771611e-01, 1.990682606e-01, 1.997539932e-01, 2.004344670e-01, 2.011097868e-01, 2.017800541e-01, 2.024453673e-01, 2.031058217e-01, 2.037615099e-01, 2.044125216e-01, 2.050589439e-01, 2.057008614e-01, 2.063383562e-01, 2.069715083e-01, 2.076003950e-01, 2.082250919e-01, 2.088456721e-01, 2.094622071e-01, 2.100747662e-01, 2.106834169e-01, 2.112882249e-01, 2.118892542e-01, 2.124865671e-01, 2.130802245e-01, 2.136702853e-01, 2.142568074e-01, 2.148398469e-01, 2.154194587e-01, 2.159956962e-01, 2.165686117e-01, 2.171382560e-01, 2.177046789e-01, 2.182679288e-01, 2.188280531e-01, 2.193850981e-01, 2.199391090e-01, 2.204901300e-01, 2.210382042e-01, 2.215833738e-01, 2.221256800e-01, 2.226651632e-01, 2.232018627e-01, 2.237358173e-01, 2.242670645e-01, 2.247956414e-01, 2.253215840e-01, 7.746784160e-01, 7.752043586e-01, 7.757329355e-01, 7.762641827e-01, 7.767981373e-01, 7.773348368e-01, 7.778743200e-01, 7.784166262e-01, 7.789617958e-01, 7.795098700e-01, 7.800608910e-01, 7.806149019e-01, 7.811719469e-01, 7.817320712e-01, 7.822953211e-01, 7.828617440e-01, 7.834313883e-01, 7.840043038e-01, 7.845805413e-01, 7.851601531e-01, 7.857431926e-01, 7.863297147e-01, 7.869197755e-01, 7.875134329e-01, 7.881107458e-01, 7.887117751e-01, 7.893165831e-01, 7.899252338e-01, 7.905377929e-01, 7.911543279e-01, 7.917749081e-01, 7.923996050e-01, 7.930284917e-01, 7.936616438e-01, 7.942991386e-01, 7.949410561e-01, 7.955874784e-01, 7.962384901e-01, 7.968941783e-01, 7.975546327e-01, 7.982199459e-01, 7.988902132e-01, 7.995655330e-01, 8.002460068e-01, 8.009317394e-01, 8.016228389e-01, 8.023194170e-01, 8.030215892e-01, 8.037294747e-01, 8.044431971e-01, 8.051628839e-01, 8.058886673e-01, 8.066206841e-01, 8.073590760e-01, 8.081039900e-01, 8.088555784e-01, 8.096139992e-01, 8.103794165e-01, 8.111520005e-01, 8.119319283e-01, 8.127193839e-01, 8.135145587e-01, 8.143176520e-01, 8.151288711e-01, 8.159484324e-01, 8.167765612e-01, 8.176134928e-01, 8.184594728e-01, 8.193147579e-01, 8.201796165e-01, 8.210543292e-01, 8.219391902e-01, 8.228345077e-01, 8.237406049e-01, 8.246578213e-01, 8.255865132e-01, 8.265270559e-01, 8.274798440e-01, 8.284452936e-01, 8.294238435e-01, 8.304159571e-01, 8.314221241e-01, 8.324428632e-01, 8.334787236e-01, 8.345302882e-01, 8.355981764e-01, 8.366830470e-01, 8.377856018e-01, 8.389065898e-01, 8.400468114e-01, 8.412071236e-01, 8.423884452e-01, 8.435917633e-01, 8.448181407e-01, 8.460687236e-01, 8.473447512e-01, 8.486475661e-01, 8.499786265e-01, 8.513395206e-01, 8.527319823e-01, 8.541579109e-01, 8.556193930e-01, 8.571187287e-01, 8.586584629e-01, 8.602414223e-01, 8.618707597e-01, 8.635500082e-01, 8.652831461e-01, 8.670746782e-01, 8.689297356e-01, 8.708542009e-01, 8.728548679e-01, 8.749396460e-01, 8.771178266e-01, 8.794004369e-01, 8.818007150e-01, 8.843347657e-01, 8.870224819e-01, 8.898888799e-01, 8.929660934e-01, 8.962964674e-01, 8.999375887e-01, 9.039709430e-01, 9.085179554e-01, 9.137727588e-01, 9.200790165e-01, 9.281525810e-01, 9.400345279e-01, 1.000000000e+00, }; const float dist_icdf_4_3[] = { 0.000000000e+00, 8.975041338e-02, 1.162473991e-01, 1.355249614e-01, 1.512936819e-01, 1.649122887e-01, 1.770520914e-01, 1.881007254e-01, 1.983050234e-01, 2.078331596e-01, 2.168055629e-01, 2.253118330e-01, 2.334206861e-01, 2.411861398e-01, 2.486515363e-01, 2.558522597e-01, 2.628176282e-01, 2.695722476e-01, 2.761370029e-01, 2.825297973e-01, 2.887661144e-01, 2.948594524e-01, 3.008216629e-01, 3.066632201e-01, 3.123934360e-01, 3.180206352e-01, 3.235522970e-01, 3.289951728e-01, 3.343553839e-01, 3.396385031e-01, 3.448496230e-01, 3.499934147e-01, 3.550741774e-01, 3.600958806e-01, 3.650622015e-01, 3.699765560e-01, 3.748421269e-01, 3.796618880e-01, 3.844386250e-01, 3.891749545e-01, 3.938733402e-01, 3.985361082e-01, 4.031654591e-01, 4.077634807e-01, 4.123321577e-01, 4.168733819e-01, 4.213889598e-01, 4.258806213e-01, 4.303500262e-01, 4.347987708e-01, 4.392283936e-01, 4.436403810e-01, 4.480361724e-01, 4.524171643e-01, 4.567847154e-01, 4.611401499e-01, 4.654847619e-01, 4.698198185e-01, 4.741465637e-01, 4.784662212e-01, 4.827799977e-01, 4.870890860e-01, 4.913946678e-01, 4.956979165e-01, 5.000000000e-01, 5.043020835e-01, 5.086053322e-01, 5.129109140e-01, 5.172200023e-01, 5.215337788e-01, 5.258534363e-01, 5.301801815e-01, 5.345152381e-01, 5.388598501e-01, 5.432152846e-01, 5.475828357e-01, 5.519638276e-01, 5.563596190e-01, 5.607716064e-01, 5.652012292e-01, 5.696499738e-01, 5.741193787e-01, 5.786110402e-01, 5.831266181e-01, 5.876678423e-01, 5.922365193e-01, 5.968345409e-01, 6.014638918e-01, 6.061266598e-01, 6.108250455e-01, 6.155613750e-01, 6.203381120e-01, 6.251578731e-01, 6.300234440e-01, 6.349377985e-01, 6.399041194e-01, 6.449258226e-01, 6.500065853e-01, 6.551503770e-01, 6.603614969e-01, 6.656446161e-01, 6.710048272e-01, 6.764477030e-01, 6.819793648e-01, 6.876065640e-01, 6.933367799e-01, 6.991783371e-01, 7.051405476e-01, 7.112338856e-01, 7.174702027e-01, 7.238629971e-01, 7.304277524e-01, 7.371823718e-01, 7.441477403e-01, 7.513484637e-01, 7.588138602e-01, 7.665793139e-01, 7.746881670e-01, 7.831944371e-01, 7.921668404e-01, 8.016949766e-01, 8.118992746e-01, 8.229479086e-01, 8.350877113e-01, 8.487063181e-01, 8.644750386e-01, 8.837526009e-01, 9.102495866e-01, 1.000000000e+00, 0.000000000e+00, 3.021113725e-02, 3.876273424e-02, 4.487216763e-02, 4.979729147e-02, 5.399731859e-02, 5.769863847e-02, 6.103174370e-02, 6.407960009e-02, 6.689865660e-02, 6.952928409e-02, 7.200148168e-02, 7.433822858e-02, 7.655756669e-02, 7.867395440e-02, 8.069918013e-02, 8.264299815e-02, 8.451358326e-02, 8.631786327e-02, 8.806176714e-02, 8.975041338e-02, 9.138825542e-02, 9.297919519e-02, 9.452667321e-02, 9.603374058e-02, 9.750311731e-02, 9.893723998e-02, 1.003383009e-01, 1.017082806e-01, 1.030489753e-01, 1.043620194e-01, 1.056489052e-01, 1.069109995e-01, 1.081495573e-01, 1.093657344e-01, 1.105605979e-01, 1.117351350e-01, 1.128902615e-01, 1.140268282e-01, 1.151456277e-01, 1.162473991e-01, 1.173328335e-01, 1.184025778e-01, 1.194572384e-01, 1.204973852e-01, 1.215235538e-01, 1.225362490e-01, 1.235359466e-01, 1.245230960e-01, 1.254981222e-01, 1.264614274e-01, 1.274133926e-01, 1.283543795e-01, 1.292847315e-01, 1.302047748e-01, 1.311148201e-01, 1.320151631e-01, 1.329060858e-01, 1.337878571e-01, 1.346607338e-01, 1.355249614e-01, 1.363807745e-01, 1.372283978e-01, 1.380680464e-01, 1.388999264e-01, 1.397242356e-01, 1.405411637e-01, 1.413508929e-01, 1.421535983e-01, 1.429494483e-01, 1.437386048e-01, 1.445212236e-01, 1.452974549e-01, 1.460674433e-01, 1.468313283e-01, 1.475892444e-01, 1.483413214e-01, 1.490876846e-01, 1.498284550e-01, 1.505637498e-01, 1.512936819e-01, 1.520183608e-01, 1.527378923e-01, 1.534523790e-01, 1.541619199e-01, 1.548666114e-01, 1.555665464e-01, 1.562618154e-01, 1.569525060e-01, 1.576387030e-01, 1.583204891e-01, 1.589979443e-01, 1.596711464e-01, 1.603401709e-01, 1.610050912e-01, 1.616659788e-01, 1.623229029e-01, 1.629759312e-01, 1.636251293e-01, 1.642705610e-01, 1.649122887e-01, 1.655503730e-01, 1.661848727e-01, 1.668158456e-01, 1.674433475e-01, 1.680674331e-01, 1.686881556e-01, 1.693055671e-01, 1.699197181e-01, 1.705306581e-01, 1.711384353e-01, 1.717430969e-01, 1.723446887e-01, 1.729432558e-01, 1.735388419e-01, 1.741314899e-01, 1.747212417e-01, 1.753081381e-01, 1.758922193e-01, 1.764735243e-01, 1.770520914e-01, 1.776279580e-01, 1.782011606e-01, 1.787717352e-01, 1.793397167e-01, 1.799051395e-01, 1.804680372e-01, 1.810284426e-01, 1.815863879e-01, 8.184136121e-01, 8.189715574e-01, 8.195319628e-01, 8.200948605e-01, 8.206602833e-01, 8.212282648e-01, 8.217988394e-01, 8.223720420e-01, 8.229479086e-01, 8.235264757e-01, 8.241077807e-01, 8.246918619e-01, 8.252787583e-01, 8.258685101e-01, 8.264611581e-01, 8.270567442e-01, 8.276553113e-01, 8.282569031e-01, 8.288615647e-01, 8.294693419e-01, 8.300802819e-01, 8.306944329e-01, 8.313118444e-01, 8.319325669e-01, 8.325566525e-01, 8.331841544e-01, 8.338151273e-01, 8.344496270e-01, 8.350877113e-01, 8.357294390e-01, 8.363748707e-01, 8.370240688e-01, 8.376770971e-01, 8.383340212e-01, 8.389949088e-01, 8.396598291e-01, 8.403288536e-01, 8.410020557e-01, 8.416795109e-01, 8.423612970e-01, 8.430474940e-01, 8.437381846e-01, 8.444334536e-01, 8.451333886e-01, 8.458380801e-01, 8.465476210e-01, 8.472621077e-01, 8.479816392e-01, 8.487063181e-01, 8.494362502e-01, 8.501715450e-01, 8.509123154e-01, 8.516586786e-01, 8.524107556e-01, 8.531686717e-01, 8.539325567e-01, 8.547025451e-01, 8.554787764e-01, 8.562613952e-01, 8.570505517e-01, 8.578464017e-01, 8.586491071e-01, 8.594588363e-01, 8.602757644e-01, 8.611000736e-01, 8.619319536e-01, 8.627716022e-01, 8.636192255e-01, 8.644750386e-01, 8.653392662e-01, 8.662121429e-01, 8.670939142e-01, 8.679848369e-01, 8.688851799e-01, 8.697952252e-01, 8.707152685e-01, 8.716456205e-01, 8.725866074e-01, 8.735385726e-01, 8.745018778e-01, 8.754769040e-01, 8.764640534e-01, 8.774637510e-01, 8.784764462e-01, 8.795026148e-01, 8.805427616e-01, 8.815974222e-01, 8.826671665e-01, 8.837526009e-01, 8.848543723e-01, 8.859731718e-01, 8.871097385e-01, 8.882648650e-01, 8.894394021e-01, 8.906342656e-01, 8.918504427e-01, 8.930890005e-01, 8.943510948e-01, 8.956379806e-01, 8.969510247e-01, 8.982917194e-01, 8.996616991e-01, 9.010627600e-01, 9.024968827e-01, 9.039662594e-01, 9.054733268e-01, 9.070208048e-01, 9.086117446e-01, 9.102495866e-01, 9.119382329e-01, 9.136821367e-01, 9.154864167e-01, 9.173570019e-01, 9.193008199e-01, 9.213260456e-01, 9.234424333e-01, 9.256617714e-01, 9.279985183e-01, 9.304707159e-01, 9.331013434e-01, 9.359203999e-01, 9.389682563e-01, 9.423013615e-01, 9.460026814e-01, 9.502027085e-01, 9.551278324e-01, 9.612372658e-01, 9.697888628e-01, 1.000000000e+00, }; const float dist_icdf_4_4[] = { 0.000000000e+00, 5.193814818e-02, 7.401811327e-02, 9.120458682e-02, 1.058663166e-01, 1.189202006e-01, 1.308362052e-01, 1.418933697e-01, 1.522734245e-01, 1.621025549e-01, 1.714726111e-01, 1.804529204e-01, 1.890973392e-01, 1.974486983e-01, 2.055417302e-01, 2.134050679e-01, 2.210626508e-01, 2.285347408e-01, 2.358386713e-01, 2.429894119e-01, 2.500000000e-01, 2.568818769e-01, 2.636451519e-01, 2.702988135e-01, 2.768508989e-01, 2.833086329e-01, 2.896785411e-01, 2.959665446e-01, 3.021780381e-01, 3.083179563e-01, 3.143908297e-01, 3.204008323e-01, 3.263518223e-01, 3.322473775e-01, 3.380908251e-01, 3.438852687e-01, 3.496336111e-01, 3.553385743e-01, 3.610027181e-01, 3.666284548e-01, 3.722180640e-01, 3.777737050e-01, 3.832974272e-01, 3.887911812e-01, 3.942568269e-01, 3.996961420e-01, 4.051108296e-01, 4.105025244e-01, 4.158727991e-01, 4.212231702e-01, 4.265551027e-01, 4.318700152e-01, 4.371692843e-01, 4.424542486e-01, 4.477262124e-01, 4.529864496e-01, 4.582362067e-01, 4.634767063e-01, 4.687091501e-01, 4.739347217e-01, 4.791545894e-01, 4.843699088e-01, 4.895818256e-01, 4.947914783e-01, 5.000000000e-01, 5.052085217e-01, 5.104181744e-01, 5.156300912e-01, 5.208454106e-01, 5.260652783e-01, 5.312908499e-01, 5.365232937e-01, 5.417637933e-01, 5.470135504e-01, 5.522737876e-01, 5.575457514e-01, 5.628307157e-01, 5.681299848e-01, 5.734448973e-01, 5.787768298e-01, 5.841272009e-01, 5.894974756e-01, 5.948891704e-01, 6.003038580e-01, 6.057431731e-01, 6.112088188e-01, 6.167025728e-01, 6.222262950e-01, 6.277819360e-01, 6.333715452e-01, 6.389972819e-01, 6.446614257e-01, 6.503663889e-01, 6.561147313e-01, 6.619091749e-01, 6.677526225e-01, 6.736481777e-01, 6.795991677e-01, 6.856091703e-01, 6.916820437e-01, 6.978219619e-01, 7.040334554e-01, 7.103214589e-01, 7.166913671e-01, 7.231491011e-01, 7.297011865e-01, 7.363548481e-01, 7.431181231e-01, 7.500000000e-01, 7.570105881e-01, 7.641613287e-01, 7.714652592e-01, 7.789373492e-01, 7.865949321e-01, 7.944582698e-01, 8.025513017e-01, 8.109026608e-01, 8.195470796e-01, 8.285273889e-01, 8.378974451e-01, 8.477265755e-01, 8.581066303e-01, 8.691637948e-01, 8.810797994e-01, 8.941336834e-01, 9.087954132e-01, 9.259818867e-01, 9.480618518e-01, 1.000000000e+00, 0.000000000e+00, 1.145470721e-02, 1.622542401e-02, 1.989663458e-02, 2.299876875e-02, 2.573727597e-02, 2.821751926e-02, 3.050208680e-02, 3.263175676e-02, 3.463485273e-02, 3.653199618e-02, 3.833875414e-02, 4.006722018e-02, 4.172701134e-02, 4.332592482e-02, 4.487038640e-02, 4.636576607e-02, 4.781660603e-02, 4.922678900e-02, 5.059966497e-02, 5.193814818e-02, 5.324479261e-02, 5.452185137e-02, 5.577132412e-02, 5.699499524e-02, 5.819446496e-02, 5.937117492e-02, 6.052642930e-02, 6.166141254e-02, 6.277720414e-02, 6.387479129e-02, 6.495507948e-02, 6.601890173e-02, 6.706702641e-02, 6.810016409e-02, 6.911897342e-02, 7.012406629e-02, 7.111601237e-02, 7.209534308e-02, 7.306255505e-02, 7.401811327e-02, 7.496245383e-02, 7.589598635e-02, 7.681909623e-02, 7.773214654e-02, 7.863547983e-02, 7.952941972e-02, 8.041427232e-02, 8.129032752e-02, 8.215786021e-02, 8.301713126e-02, 8.386838861e-02, 8.471186806e-02, 8.554779414e-02, 8.637638080e-02, 8.719783215e-02, 8.801234305e-02, 8.882009969e-02, 8.962128013e-02, 9.041605477e-02, 9.120458682e-02, 9.198703271e-02, 9.276354249e-02, 9.353426017e-02, 9.429932405e-02, 9.505886707e-02, 9.581301706e-02, 9.656189703e-02, 9.730562539e-02, 9.804431623e-02, 9.877807951e-02, 9.950702128e-02, 1.002312439e-01, 1.009508460e-01, 1.016659232e-01, 1.023765675e-01, 1.030828682e-01, 1.037849113e-01, 1.044827804e-01, 1.051765561e-01, 1.058663166e-01, 1.065521377e-01, 1.072340928e-01, 1.079122531e-01, 1.085866876e-01, 1.092574634e-01, 1.099246454e-01, 1.105882968e-01, 1.112484789e-01, 1.119052514e-01, 1.125586721e-01, 1.132087973e-01, 1.138556819e-01, 1.144993790e-01, 1.151399407e-01, 1.157774172e-01, 1.164118579e-01, 1.170433105e-01, 1.176718217e-01, 1.182974369e-01, 1.189202006e-01, 1.195401558e-01, 1.201573446e-01, 1.207718083e-01, 1.213835869e-01, 1.219927195e-01, 1.225992444e-01, 1.232031989e-01, 1.238046194e-01, 1.244035415e-01, 1.250000000e-01, 1.255940289e-01, 1.261856614e-01, 1.267749300e-01, 1.273618665e-01, 1.279465020e-01, 1.285288668e-01, 1.291089908e-01, 1.296869029e-01, 1.302626318e-01, 1.308362052e-01, 1.314076506e-01, 1.319769946e-01, 1.325442636e-01, 1.331094831e-01, 1.336726783e-01, 1.342338738e-01, 1.347930939e-01, 1.353503622e-01, 8.646496378e-01, 8.652069061e-01, 8.657661262e-01, 8.663273217e-01, 8.668905169e-01, 8.674557364e-01, 8.680230054e-01, 8.685923494e-01, 8.691637948e-01, 8.697373682e-01, 8.703130971e-01, 8.708910092e-01, 8.714711332e-01, 8.720534980e-01, 8.726381335e-01, 8.732250700e-01, 8.738143386e-01, 8.744059711e-01, 8.750000000e-01, 8.755964585e-01, 8.761953806e-01, 8.767968011e-01, 8.774007556e-01, 8.780072805e-01, 8.786164131e-01, 8.792281917e-01, 8.798426554e-01, 8.804598442e-01, 8.810797994e-01, 8.817025631e-01, 8.823281783e-01, 8.829566895e-01, 8.835881421e-01, 8.842225828e-01, 8.848600593e-01, 8.855006210e-01, 8.861443181e-01, 8.867912027e-01, 8.874413279e-01, 8.880947486e-01, 8.887515211e-01, 8.894117032e-01, 8.900753546e-01, 8.907425366e-01, 8.914133124e-01, 8.920877469e-01, 8.927659072e-01, 8.934478623e-01, 8.941336834e-01, 8.948234439e-01, 8.955172196e-01, 8.962150887e-01, 8.969171318e-01, 8.976234325e-01, 8.983340768e-01, 8.990491540e-01, 8.997687561e-01, 9.004929787e-01, 9.012219205e-01, 9.019556838e-01, 9.026943746e-01, 9.034381030e-01, 9.041869829e-01, 9.049411329e-01, 9.057006759e-01, 9.064657398e-01, 9.072364575e-01, 9.080129673e-01, 9.087954132e-01, 9.095839452e-01, 9.103787199e-01, 9.111799003e-01, 9.119876569e-01, 9.128021679e-01, 9.136236192e-01, 9.144522059e-01, 9.152881319e-01, 9.161316114e-01, 9.169828687e-01, 9.178421398e-01, 9.187096725e-01, 9.195857277e-01, 9.204705803e-01, 9.213645202e-01, 9.222678535e-01, 9.231809038e-01, 9.241040136e-01, 9.250375462e-01, 9.259818867e-01, 9.269374450e-01, 9.279046569e-01, 9.288839876e-01, 9.298759337e-01, 9.308810266e-01, 9.318998359e-01, 9.329329736e-01, 9.339810983e-01, 9.350449205e-01, 9.361252087e-01, 9.372227959e-01, 9.383385875e-01, 9.394735707e-01, 9.406288251e-01, 9.418055350e-01, 9.430050048e-01, 9.442286759e-01, 9.454781486e-01, 9.467552074e-01, 9.480618518e-01, 9.494003350e-01, 9.507732110e-01, 9.521833940e-01, 9.536342339e-01, 9.551296136e-01, 9.566740752e-01, 9.582729887e-01, 9.599327798e-01, 9.616612459e-01, 9.634680038e-01, 9.653651473e-01, 9.673682432e-01, 9.694979132e-01, 9.717824807e-01, 9.742627240e-01, 9.770012312e-01, 9.801033654e-01, 9.837745760e-01, 9.885452928e-01, 1.000000000e+00, }; const float dist_icdf_4_5[] = { 0.000000000e+00, 2.388903283e-02, 3.910358742e-02, 5.220819259e-02, 6.412196115e-02, 7.523158189e-02, 8.574666414e-02, 9.579710309e-02, 1.054704935e-01, 1.148294737e-01, 1.239208162e-01, 1.327806295e-01, 1.414375369e-01, 1.499147229e-01, 1.582313066e-01, 1.664032957e-01, 1.744442676e-01, 1.823658695e-01, 1.901781920e-01, 1.978900537e-01, 2.055092223e-01, 2.130425879e-01, 2.204963009e-01, 2.278758833e-01, 2.351863194e-01, 2.424321300e-01, 2.496174337e-01, 2.567459991e-01, 2.638212872e-01, 2.708464889e-01, 2.778245559e-01, 2.847582274e-01, 2.916500534e-01, 2.985024150e-01, 3.053175414e-01, 3.120975253e-01, 3.188443366e-01, 3.255598340e-01, 3.322457755e-01, 3.389038278e-01, 3.455355747e-01, 3.521425244e-01, 3.587261163e-01, 3.652877272e-01, 3.718286764e-01, 3.783502312e-01, 3.848536108e-01, 3.913399911e-01, 3.978105080e-01, 4.042662613e-01, 4.107083175e-01, 4.171377132e-01, 4.235554577e-01, 4.299625354e-01, 4.363599089e-01, 4.427485204e-01, 4.491292946e-01, 4.555031406e-01, 4.618709535e-01, 4.682336166e-01, 4.745920034e-01, 4.809469789e-01, 4.872994016e-01, 4.936501252e-01, 5.000000000e-01, 5.063498748e-01, 5.127005984e-01, 5.190530211e-01, 5.254079966e-01, 5.317663834e-01, 5.381290465e-01, 5.444968594e-01, 5.508707054e-01, 5.572514796e-01, 5.636400911e-01, 5.700374646e-01, 5.764445423e-01, 5.828622868e-01, 5.892916825e-01, 5.957337387e-01, 6.021894920e-01, 6.086600089e-01, 6.151463892e-01, 6.216497688e-01, 6.281713236e-01, 6.347122728e-01, 6.412738837e-01, 6.478574756e-01, 6.544644253e-01, 6.610961722e-01, 6.677542245e-01, 6.744401660e-01, 6.811556634e-01, 6.879024747e-01, 6.946824586e-01, 7.014975850e-01, 7.083499466e-01, 7.152417726e-01, 7.221754441e-01, 7.291535111e-01, 7.361787128e-01, 7.432540009e-01, 7.503825663e-01, 7.575678700e-01, 7.648136806e-01, 7.721241167e-01, 7.795036991e-01, 7.869574121e-01, 7.944907777e-01, 8.021099463e-01, 8.098218080e-01, 8.176341305e-01, 8.255557324e-01, 8.335967043e-01, 8.417686934e-01, 8.500852771e-01, 8.585624631e-01, 8.672193705e-01, 8.760791838e-01, 8.851705263e-01, 8.945295065e-01, 9.042028969e-01, 9.142533359e-01, 9.247684181e-01, 9.358780389e-01, 9.477918074e-01, 9.608964126e-01, 9.761109672e-01, 1.000000000e+00, 0.000000000e+00, 2.861875328e-03, 4.673544585e-03, 6.226985886e-03, 7.633578893e-03, 8.940294528e-03, 1.017264359e-02, 1.134646155e-02, 1.247244240e-02, 1.355824280e-02, 1.460958601e-02, 1.563089418e-02, 1.662567510e-02, 1.759677143e-02, 1.854652807e-02, 1.947690844e-02, 2.038957776e-02, 2.128596402e-02, 2.216730370e-02, 2.303467659e-02, 2.388903283e-02, 2.473121412e-02, 2.556197066e-02, 2.638197480e-02, 2.719183210e-02, 2.799209048e-02, 2.878324779e-02, 2.956575808e-02, 3.034003700e-02, 3.110646622e-02, 3.186539734e-02, 3.261715512e-02, 3.336204038e-02, 3.410033242e-02, 3.483229117e-02, 3.555815906e-02, 3.627816268e-02, 3.699251418e-02, 3.770141261e-02, 3.840504500e-02, 3.910358742e-02, 3.979720584e-02, 4.048605697e-02, 4.117028896e-02, 4.185004206e-02, 4.252544923e-02, 4.319663666e-02, 4.386372424e-02, 4.452682601e-02, 4.518605059e-02, 4.584150148e-02, 4.649327746e-02, 4.714147286e-02, 4.778617786e-02, 4.842747872e-02, 4.906545804e-02, 4.970019499e-02, 5.033176548e-02, 5.096024238e-02, 5.158569566e-02, 5.220819259e-02, 5.282779784e-02, 5.344457367e-02, 5.405858002e-02, 5.466987467e-02, 5.527851330e-02, 5.588454965e-02, 5.648803555e-02, 5.708902111e-02, 5.768755469e-02, 5.828368310e-02, 5.887745156e-02, 5.946890387e-02, 6.005808240e-02, 6.064502822e-02, 6.122978109e-02, 6.181237958e-02, 6.239286108e-02, 6.297126187e-02, 6.354761716e-02, 6.412196115e-02, 6.469432703e-02, 6.526474707e-02, 6.583325262e-02, 6.639987419e-02, 6.696464143e-02, 6.752758319e-02, 6.808872756e-02, 6.864810188e-02, 6.920573278e-02, 6.976164621e-02, 7.031586744e-02, 7.086842111e-02, 7.141933126e-02, 7.196862130e-02, 7.251631410e-02, 7.306243197e-02, 7.360699668e-02, 7.415002947e-02, 7.469155112e-02, 7.523158189e-02, 7.577014159e-02, 7.630724959e-02, 7.684292480e-02, 7.737718572e-02, 7.791005044e-02, 7.844153667e-02, 7.897166170e-02, 7.950044247e-02, 8.002789557e-02, 8.055403723e-02, 8.107888332e-02, 8.160244942e-02, 8.212475076e-02, 8.264580227e-02, 8.316561858e-02, 8.368421403e-02, 8.420160267e-02, 8.471779827e-02, 8.523281435e-02, 8.574666414e-02, 8.625936065e-02, 8.677091662e-02, 8.728134455e-02, 8.779065671e-02, 8.829886515e-02, 8.880598170e-02, 8.931201794e-02, 8.981698530e-02, 9.101830147e-01, 9.106879821e-01, 9.111940183e-01, 9.117011348e-01, 9.122093433e-01, 9.127186555e-01, 9.132290834e-01, 9.137406393e-01, 9.142533359e-01, 9.147671857e-01, 9.152822017e-01, 9.157983973e-01, 9.163157860e-01, 9.168343814e-01, 9.173541977e-01, 9.178752492e-01, 9.183975506e-01, 9.189211167e-01, 9.194459628e-01, 9.199721044e-01, 9.204995575e-01, 9.210283383e-01, 9.215584633e-01, 9.220899496e-01, 9.226228143e-01, 9.231570752e-01, 9.236927504e-01, 9.242298584e-01, 9.247684181e-01, 9.253084489e-01, 9.258499705e-01, 9.263930033e-01, 9.269375680e-01, 9.274836859e-01, 9.280313787e-01, 9.285806687e-01, 9.291315789e-01, 9.296841326e-01, 9.302383538e-01, 9.307942672e-01, 9.313518981e-01, 9.319112724e-01, 9.324724168e-01, 9.330353586e-01, 9.336001258e-01, 9.341667474e-01, 9.347352529e-01, 9.353056730e-01, 9.358780389e-01, 9.364523828e-01, 9.370287381e-01, 9.376071389e-01, 9.381876204e-01, 9.387702189e-01, 9.393549718e-01, 9.399419176e-01, 9.405310961e-01, 9.411225484e-01, 9.417163169e-01, 9.423124453e-01, 9.429109789e-01, 9.435119644e-01, 9.441154504e-01, 9.447214867e-01, 9.453301253e-01, 9.459414200e-01, 9.465554263e-01, 9.471722022e-01, 9.477918074e-01, 9.484143043e-01, 9.490397576e-01, 9.496682345e-01, 9.502998050e-01, 9.509345420e-01, 9.515725213e-01, 9.522138221e-01, 9.528585271e-01, 9.535067225e-01, 9.541584985e-01, 9.548139494e-01, 9.554731740e-01, 9.561362758e-01, 9.568033633e-01, 9.574745508e-01, 9.581499579e-01, 9.588297110e-01, 9.595139430e-01, 9.602027942e-01, 9.608964126e-01, 9.615949550e-01, 9.622985874e-01, 9.630074858e-01, 9.637218373e-01, 9.644418409e-01, 9.651677088e-01, 9.658996676e-01, 9.666379596e-01, 9.673828449e-01, 9.681346027e-01, 9.688935338e-01, 9.696599630e-01, 9.704342419e-01, 9.712167522e-01, 9.720079095e-01, 9.728081679e-01, 9.736180252e-01, 9.744380293e-01, 9.752687859e-01, 9.761109672e-01, 9.769653234e-01, 9.778326963e-01, 9.787140360e-01, 9.796104222e-01, 9.805230916e-01, 9.814534719e-01, 9.824032286e-01, 9.833743249e-01, 9.843691058e-01, 9.853904140e-01, 9.864417572e-01, 9.875275576e-01, 9.886535385e-01, 9.898273564e-01, 9.910597055e-01, 9.923664211e-01, 9.937730141e-01, 9.953264554e-01, 9.971381247e-01, 1.000000000e+00, }; const float dist_icdf_4_6[] = { 0.000000000e+00, 7.812500000e-03, 1.562500000e-02, 2.343750000e-02, 3.125000000e-02, 3.906250000e-02, 4.687500000e-02, 5.468750000e-02, 6.250000000e-02, 7.031250000e-02, 7.812500000e-02, 8.593750000e-02, 9.375000000e-02, 1.015625000e-01, 1.093750000e-01, 1.171875000e-01, 1.250000000e-01, 1.328125000e-01, 1.406250000e-01, 1.484375000e-01, 1.562500000e-01, 1.640625000e-01, 1.718750000e-01, 1.796875000e-01, 1.875000000e-01, 1.953125000e-01, 2.031250000e-01, 2.109375000e-01, 2.187500000e-01, 2.265625000e-01, 2.343750000e-01, 2.421875000e-01, 2.500000000e-01, 2.578125000e-01, 2.656250000e-01, 2.734375000e-01, 2.812500000e-01, 2.890625000e-01, 2.968750000e-01, 3.046875000e-01, 3.125000000e-01, 3.203125000e-01, 3.281250000e-01, 3.359375000e-01, 3.437500000e-01, 3.515625000e-01, 3.593750000e-01, 3.671875000e-01, 3.750000000e-01, 3.828125000e-01, 3.906250000e-01, 3.984375000e-01, 4.062500000e-01, 4.140625000e-01, 4.218750000e-01, 4.296875000e-01, 4.375000000e-01, 4.453125000e-01, 4.531250000e-01, 4.609375000e-01, 4.687500000e-01, 4.765625000e-01, 4.843750000e-01, 4.921875000e-01, 5.000000000e-01, 5.078125000e-01, 5.156250000e-01, 5.234375000e-01, 5.312500000e-01, 5.390625000e-01, 5.468750000e-01, 5.546875000e-01, 5.625000000e-01, 5.703125000e-01, 5.781250000e-01, 5.859375000e-01, 5.937500000e-01, 6.015625000e-01, 6.093750000e-01, 6.171875000e-01, 6.250000000e-01, 6.328125000e-01, 6.406250000e-01, 6.484375000e-01, 6.562500000e-01, 6.640625000e-01, 6.718750000e-01, 6.796875000e-01, 6.875000000e-01, 6.953125000e-01, 7.031250000e-01, 7.109375000e-01, 7.187500000e-01, 7.265625000e-01, 7.343750000e-01, 7.421875000e-01, 7.500000000e-01, 7.578125000e-01, 7.656250000e-01, 7.734375000e-01, 7.812500000e-01, 7.890625000e-01, 7.968750000e-01, 8.046875000e-01, 8.125000000e-01, 8.203125000e-01, 8.281250000e-01, 8.359375000e-01, 8.437500000e-01, 8.515625000e-01, 8.593750000e-01, 8.671875000e-01, 8.750000000e-01, 8.828125000e-01, 8.906250000e-01, 8.984375000e-01, 9.062500000e-01, 9.140625000e-01, 9.218750000e-01, 9.296875000e-01, 9.375000000e-01, 9.453125000e-01, 9.531250000e-01, 9.609375000e-01, 9.687500000e-01, 9.765625000e-01, 9.843750000e-01, 9.921875000e-01, 1.000000000e+00, 0.000000000e+00, 3.906250000e-04, 7.812500000e-04, 1.171875000e-03, 1.562500000e-03, 1.953125000e-03, 2.343750000e-03, 2.734375000e-03, 3.125000000e-03, 3.515625000e-03, 3.906250000e-03, 4.296875000e-03, 4.687500000e-03, 5.078125000e-03, 5.468750000e-03, 5.859375000e-03, 6.250000000e-03, 6.640625000e-03, 7.031250000e-03, 7.421875000e-03, 7.812500000e-03, 8.203125000e-03, 8.593750000e-03, 8.984375000e-03, 9.375000000e-03, 9.765625000e-03, 1.015625000e-02, 1.054687500e-02, 1.093750000e-02, 1.132812500e-02, 1.171875000e-02, 1.210937500e-02, 1.250000000e-02, 1.289062500e-02, 1.328125000e-02, 1.367187500e-02, 1.406250000e-02, 1.445312500e-02, 1.484375000e-02, 1.523437500e-02, 1.562500000e-02, 1.601562500e-02, 1.640625000e-02, 1.679687500e-02, 1.718750000e-02, 1.757812500e-02, 1.796875000e-02, 1.835937500e-02, 1.875000000e-02, 1.914062500e-02, 1.953125000e-02, 1.992187500e-02, 2.031250000e-02, 2.070312500e-02, 2.109375000e-02, 2.148437500e-02, 2.187500000e-02, 2.226562500e-02, 2.265625000e-02, 2.304687500e-02, 2.343750000e-02, 2.382812500e-02, 2.421875000e-02, 2.460937500e-02, 2.500000000e-02, 2.539062500e-02, 2.578125000e-02, 2.617187500e-02, 2.656250000e-02, 2.695312500e-02, 2.734375000e-02, 2.773437500e-02, 2.812500000e-02, 2.851562500e-02, 2.890625000e-02, 2.929687500e-02, 2.968750000e-02, 3.007812500e-02, 3.046875000e-02, 3.085937500e-02, 3.125000000e-02, 3.164062500e-02, 3.203125000e-02, 3.242187500e-02, 3.281250000e-02, 3.320312500e-02, 3.359375000e-02, 3.398437500e-02, 3.437500000e-02, 3.476562500e-02, 3.515625000e-02, 3.554687500e-02, 3.593750000e-02, 3.632812500e-02, 3.671875000e-02, 3.710937500e-02, 3.750000000e-02, 3.789062500e-02, 3.828125000e-02, 3.867187500e-02, 3.906250000e-02, 3.945312500e-02, 3.984375000e-02, 4.023437500e-02, 4.062500000e-02, 4.101562500e-02, 4.140625000e-02, 4.179687500e-02, 4.218750000e-02, 4.257812500e-02, 4.296875000e-02, 4.335937500e-02, 4.375000000e-02, 4.414062500e-02, 4.453125000e-02, 4.492187500e-02, 4.531250000e-02, 4.570312500e-02, 4.609375000e-02, 4.648437500e-02, 4.687500000e-02, 4.726562500e-02, 4.765625000e-02, 4.804687500e-02, 4.843750000e-02, 4.882812500e-02, 4.921875000e-02, 4.960937500e-02, 5.000000000e-02, 9.500000000e-01, 9.503906250e-01, 9.507812500e-01, 9.511718750e-01, 9.515625000e-01, 9.519531250e-01, 9.523437500e-01, 9.527343750e-01, 9.531250000e-01, 9.535156250e-01, 9.539062500e-01, 9.542968750e-01, 9.546875000e-01, 9.550781250e-01, 9.554687500e-01, 9.558593750e-01, 9.562500000e-01, 9.566406250e-01, 9.570312500e-01, 9.574218750e-01, 9.578125000e-01, 9.582031250e-01, 9.585937500e-01, 9.589843750e-01, 9.593750000e-01, 9.597656250e-01, 9.601562500e-01, 9.605468750e-01, 9.609375000e-01, 9.613281250e-01, 9.617187500e-01, 9.621093750e-01, 9.625000000e-01, 9.628906250e-01, 9.632812500e-01, 9.636718750e-01, 9.640625000e-01, 9.644531250e-01, 9.648437500e-01, 9.652343750e-01, 9.656250000e-01, 9.660156250e-01, 9.664062500e-01, 9.667968750e-01, 9.671875000e-01, 9.675781250e-01, 9.679687500e-01, 9.683593750e-01, 9.687500000e-01, 9.691406250e-01, 9.695312500e-01, 9.699218750e-01, 9.703125000e-01, 9.707031250e-01, 9.710937500e-01, 9.714843750e-01, 9.718750000e-01, 9.722656250e-01, 9.726562500e-01, 9.730468750e-01, 9.734375000e-01, 9.738281250e-01, 9.742187500e-01, 9.746093750e-01, 9.750000000e-01, 9.753906250e-01, 9.757812500e-01, 9.761718750e-01, 9.765625000e-01, 9.769531250e-01, 9.773437500e-01, 9.777343750e-01, 9.781250000e-01, 9.785156250e-01, 9.789062500e-01, 9.792968750e-01, 9.796875000e-01, 9.800781250e-01, 9.804687500e-01, 9.808593750e-01, 9.812500000e-01, 9.816406250e-01, 9.820312500e-01, 9.824218750e-01, 9.828125000e-01, 9.832031250e-01, 9.835937500e-01, 9.839843750e-01, 9.843750000e-01, 9.847656250e-01, 9.851562500e-01, 9.855468750e-01, 9.859375000e-01, 9.863281250e-01, 9.867187500e-01, 9.871093750e-01, 9.875000000e-01, 9.878906250e-01, 9.882812500e-01, 9.886718750e-01, 9.890625000e-01, 9.894531250e-01, 9.898437500e-01, 9.902343750e-01, 9.906250000e-01, 9.910156250e-01, 9.914062500e-01, 9.917968750e-01, 9.921875000e-01, 9.925781250e-01, 9.929687500e-01, 9.933593750e-01, 9.937500000e-01, 9.941406250e-01, 9.945312500e-01, 9.949218750e-01, 9.953125000e-01, 9.957031250e-01, 9.960937500e-01, 9.964843750e-01, 9.968750000e-01, 9.972656250e-01, 9.976562500e-01, 9.980468750e-01, 9.984375000e-01, 9.988281250e-01, 9.992187500e-01, 9.996093750e-01, 1.000000000e+00, }; const float dist_icdf_4_7[] = { 0.000000000e+00, 1.551652911e-03, 4.133543553e-03, 7.330169583e-03, 1.100344347e-02, 1.507557444e-02, 1.949484392e-02, 2.422361887e-02, 2.923288598e-02, 3.449935369e-02, 4.000375384e-02, 4.572977235e-02, 5.166333810e-02, 5.779212953e-02, 6.410522016e-02, 7.059281662e-02, 7.724606031e-02, 8.405687412e-02, 9.101784194e-02, 9.812211241e-02, 1.053633210e-01, 1.127355261e-01, 1.202331562e-01, 1.278509658e-01, 1.355839980e-01, 1.434275526e-01, 1.513771591e-01, 1.594285534e-01, 1.675776573e-01, 1.758205607e-01, 1.841535061e-01, 1.925728748e-01, 2.010751748e-01, 2.096570300e-01, 2.183151703e-01, 2.270464233e-01, 2.358477060e-01, 2.447160180e-01, 2.536484352e-01, 2.626421034e-01, 2.716942336e-01, 2.808020968e-01, 2.899630196e-01, 2.991743797e-01, 3.084336028e-01, 3.177381580e-01, 3.270855557e-01, 3.364733433e-01, 3.458991033e-01, 3.553604500e-01, 3.648550271e-01, 3.743805052e-01, 3.839345799e-01, 3.935149689e-01, 4.031194106e-01, 4.127456619e-01, 4.223914959e-01, 4.320547009e-01, 4.417330776e-01, 4.514244383e-01, 4.611266045e-01, 4.708374058e-01, 4.805546780e-01, 4.902762616e-01, 5.000000000e-01, 5.097237384e-01, 5.194453220e-01, 5.291625942e-01, 5.388733955e-01, 5.485755617e-01, 5.582669224e-01, 5.679452991e-01, 5.776085041e-01, 5.872543381e-01, 5.968805894e-01, 6.064850311e-01, 6.160654201e-01, 6.256194948e-01, 6.351449729e-01, 6.446395500e-01, 6.541008967e-01, 6.635266567e-01, 6.729144443e-01, 6.822618420e-01, 6.915663972e-01, 7.008256203e-01, 7.100369804e-01, 7.191979032e-01, 7.283057664e-01, 7.373578966e-01, 7.463515648e-01, 7.552839820e-01, 7.641522940e-01, 7.729535767e-01, 7.816848297e-01, 7.903429700e-01, 7.989248252e-01, 8.074271252e-01, 8.158464939e-01, 8.241794393e-01, 8.324223427e-01, 8.405714466e-01, 8.486228409e-01, 8.565724474e-01, 8.644160020e-01, 8.721490342e-01, 8.797668438e-01, 8.872644739e-01, 8.946366790e-01, 9.018778876e-01, 9.089821581e-01, 9.159431259e-01, 9.227539397e-01, 9.294071834e-01, 9.358947798e-01, 9.422078705e-01, 9.483366619e-01, 9.542702276e-01, 9.599962462e-01, 9.655006463e-01, 9.707671140e-01, 9.757763811e-01, 9.805051561e-01, 9.849244256e-01, 9.889965565e-01, 9.926698304e-01, 9.958664564e-01, 9.984483471e-01, 1.000000000e+00, 0.000000000e+00, 2.243749270e-05, 5.979876892e-05, 1.061009908e-04, 1.593696159e-04, 2.185005699e-04, 2.827658621e-04, 3.516405100e-04, 4.247236573e-04, 5.016967708e-04, 5.822991568e-04, 6.663125529e-04, 7.535508895e-04, 8.438531901e-04, 9.370784736e-04, 1.033101991e-03, 1.131812377e-03, 1.233109452e-03, 1.336902498e-03, 1.443108875e-03, 1.551652911e-03, 1.662464991e-03, 1.775480799e-03, 1.890640690e-03, 2.007889160e-03, 2.127174395e-03, 2.248447885e-03, 2.371664095e-03, 2.496780174e-03, 2.623755707e-03, 2.752552498e-03, 2.883134372e-03, 3.015467012e-03, 3.149517803e-03, 3.285255698e-03, 3.422651101e-03, 3.561675755e-03, 3.702302650e-03, 3.844505932e-03, 3.988260823e-03, 4.133543553e-03, 4.280331292e-03, 4.428602091e-03, 4.578334827e-03, 4.729509154e-03, 4.882105455e-03, 5.036104805e-03, 5.191488925e-03, 5.348240153e-03, 5.506341403e-03, 5.665776144e-03, 5.826528362e-03, 5.988582541e-03, 6.151923633e-03, 6.316537037e-03, 6.482408578e-03, 6.649524487e-03, 6.817871381e-03, 6.987436246e-03, 7.158206422e-03, 7.330169583e-03, 7.503313729e-03, 7.677627166e-03, 7.853098498e-03, 8.029716611e-03, 8.207470665e-03, 8.386350080e-03, 8.566344527e-03, 8.747443920e-03, 8.929638403e-03, 9.112918345e-03, 9.297274329e-03, 9.482697147e-03, 9.669177790e-03, 9.856707441e-03, 1.004527747e-02, 1.023487943e-02, 1.042550503e-02, 1.061714618e-02, 1.080979492e-02, 1.100344347e-02, 1.119808418e-02, 1.139370956e-02, 1.159031226e-02, 1.178788507e-02, 1.198642092e-02, 1.218591284e-02, 1.238635403e-02, 1.258773777e-02, 1.279005749e-02, 1.299330671e-02, 1.319747908e-02, 1.340256834e-02, 1.360856837e-02, 1.381547311e-02, 1.402327662e-02, 1.423197305e-02, 1.444155667e-02, 1.465202180e-02, 1.486336289e-02, 1.507557444e-02, 1.528865105e-02, 1.550258742e-02, 1.571737831e-02, 1.593301856e-02, 1.614950309e-02, 1.636682689e-02, 1.658498504e-02, 1.680397266e-02, 1.702378498e-02, 1.724441726e-02, 1.746586484e-02, 1.768812314e-02, 1.791118761e-02, 1.813505380e-02, 1.835971728e-02, 1.858517371e-02, 1.881141880e-02, 1.903844831e-02, 1.926625806e-02, 1.949484392e-02, 1.972420181e-02, 1.995432772e-02, 2.018521766e-02, 2.041686772e-02, 2.064927401e-02, 2.088243272e-02, 2.111634006e-02, 2.135099228e-02, 9.786490077e-01, 9.788836599e-01, 9.791175673e-01, 9.793507260e-01, 9.795831323e-01, 9.798147823e-01, 9.800456723e-01, 9.802757982e-01, 9.805051561e-01, 9.807337419e-01, 9.809615517e-01, 9.811885812e-01, 9.814148263e-01, 9.816402827e-01, 9.818649462e-01, 9.820888124e-01, 9.823118769e-01, 9.825341352e-01, 9.827555827e-01, 9.829762150e-01, 9.831960273e-01, 9.834150150e-01, 9.836331731e-01, 9.838504969e-01, 9.840669814e-01, 9.842826217e-01, 9.844974126e-01, 9.847113489e-01, 9.849244256e-01, 9.851366371e-01, 9.853479782e-01, 9.855584433e-01, 9.857680269e-01, 9.859767234e-01, 9.861845269e-01, 9.863914316e-01, 9.865974317e-01, 9.868025209e-01, 9.870066933e-01, 9.872099425e-01, 9.874122622e-01, 9.876136460e-01, 9.878140872e-01, 9.880135791e-01, 9.882121149e-01, 9.884096877e-01, 9.886062904e-01, 9.888019158e-01, 9.889965565e-01, 9.891902051e-01, 9.893828538e-01, 9.895744950e-01, 9.897651206e-01, 9.899547225e-01, 9.901432926e-01, 9.903308222e-01, 9.905173029e-01, 9.907027257e-01, 9.908870817e-01, 9.910703616e-01, 9.912525561e-01, 9.914336555e-01, 9.916136499e-01, 9.917925293e-01, 9.919702834e-01, 9.921469015e-01, 9.923223728e-01, 9.924966863e-01, 9.926698304e-01, 9.928417936e-01, 9.930125638e-01, 9.931821286e-01, 9.933504755e-01, 9.935175914e-01, 9.936834630e-01, 9.938480764e-01, 9.940114175e-01, 9.941734716e-01, 9.943342239e-01, 9.944936586e-01, 9.946517598e-01, 9.948085111e-01, 9.949638952e-01, 9.951178945e-01, 9.952704908e-01, 9.954216652e-01, 9.955713979e-01, 9.957196687e-01, 9.958664564e-01, 9.960117392e-01, 9.961554941e-01, 9.962976973e-01, 9.964383242e-01, 9.965773489e-01, 9.967147443e-01, 9.968504822e-01, 9.969845330e-01, 9.971168656e-01, 9.972474475e-01, 9.973762443e-01, 9.975032198e-01, 9.976283359e-01, 9.977515521e-01, 9.978728256e-01, 9.979921108e-01, 9.981093593e-01, 9.982245192e-01, 9.983375350e-01, 9.984483471e-01, 9.985568911e-01, 9.986630975e-01, 9.987668905e-01, 9.988681876e-01, 9.989668980e-01, 9.990629215e-01, 9.991561468e-01, 9.992464491e-01, 9.993336874e-01, 9.994177008e-01, 9.994983032e-01, 9.995752763e-01, 9.996483595e-01, 9.997172341e-01, 9.997814994e-01, 9.998406304e-01, 9.998938990e-01, 9.999402012e-01, 9.999775625e-01, 1.000000000e+00, }; const float dist_icdf_4_8[] = { 0.000000000e+00, 4.402192196e-08, 7.043504723e-07, 3.565768144e-06, 1.126953612e-05, 2.751324776e-05, 5.705045944e-05, 1.056899347e-04, 1.802942910e-04, 2.887777918e-04, 4.401029805e-04, 6.442758075e-04, 9.123388564e-04, 1.256362232e-03, 1.689431631e-03, 2.225633081e-03, 2.880033782e-03, 3.668658481e-03, 4.608460747e-03, 5.717288520e-03, 7.013843282e-03, 8.517632188e-03, 1.024891250e-02, 1.222862771e-02, 1.447833467e-02, 1.702012127e-02, 1.987651403e-02, 2.307037524e-02, 2.662478931e-02, 3.056293801e-02, 3.490796463e-02, 3.968282695e-02, 4.491013944e-02, 5.061200492e-02, 5.680983645e-02, 6.352417025e-02, 7.077447076e-02, 7.857892924e-02, 8.695425754e-02, 9.591547885e-02, 1.054757176e-01, 1.156459913e-01, 1.264350057e-01, 1.378489582e-01, 1.498913503e-01, 1.625628136e-01, 1.758609520e-01, 1.897802035e-01, 2.043117246e-01, 2.194433002e-01, 2.351592823e-01, 2.514405596e-01, 2.682645600e-01, 2.856052885e-01, 3.034334010e-01, 3.217163154e-01, 3.404183594e-01, 3.595009551e-01, 3.789228389e-01, 3.986403148e-01, 4.186075388e-01, 4.387768317e-01, 4.590990150e-01, 4.795237681e-01, 5.000000000e-01, 5.204762319e-01, 5.409009850e-01, 5.612231683e-01, 5.813924612e-01, 6.013596852e-01, 6.210771611e-01, 6.404990449e-01, 6.595816406e-01, 6.782836846e-01, 6.965665990e-01, 7.143947115e-01, 7.317354400e-01, 7.485594404e-01, 7.648407177e-01, 7.805566998e-01, 7.956882754e-01, 8.102197965e-01, 8.241390480e-01, 8.374371864e-01, 8.501086497e-01, 8.621510418e-01, 8.735649943e-01, 8.843540087e-01, 8.945242824e-01, 9.040845212e-01, 9.130457425e-01, 9.214210708e-01, 9.292255292e-01, 9.364758298e-01, 9.431901635e-01, 9.493879951e-01, 9.550898606e-01, 9.603171731e-01, 9.650920354e-01, 9.694370620e-01, 9.733752107e-01, 9.769296248e-01, 9.801234860e-01, 9.829798787e-01, 9.855216653e-01, 9.877713723e-01, 9.897510875e-01, 9.914823678e-01, 9.929861567e-01, 9.942827115e-01, 9.953915393e-01, 9.963313415e-01, 9.971199662e-01, 9.977743669e-01, 9.983105684e-01, 9.987436378e-01, 9.990876611e-01, 9.993557242e-01, 9.995598970e-01, 9.997112222e-01, 9.998197057e-01, 9.998943101e-01, 9.999429495e-01, 9.999724868e-01, 9.999887305e-01, 9.999964342e-01, 9.999992956e-01, 9.999999560e-01, 1.000000000e+00, 0.000000000e+00, 2.751370195e-13, 4.402192312e-12, 2.228609858e-11, 7.043507700e-11, 1.719606372e-10, 3.565775772e-10, 6.606039836e-10, 1.126961231e-09, 1.805173983e-09, 2.751370191e-09, 4.028281093e-09, 5.705241217e-09, 7.858188378e-09, 1.056966368e-08, 1.392881150e-08, 1.803137952e-08, 2.297971869e-08, 2.888278326e-08, 3.585613075e-08, 4.402192196e-08, 5.350892098e-08, 6.445249515e-08, 7.699461513e-08, 9.128385479e-08, 1.074753913e-07, 1.257310052e-07, 1.462190800e-07, 1.691146027e-07, 1.945991636e-07, 2.228609560e-07, 2.540947767e-07, 2.885020255e-07, 3.262907055e-07, 3.676754230e-07, 4.128773877e-07, 4.621244121e-07, 5.156509121e-07, 5.736979069e-07, 6.365130185e-07, 7.043504723e-07, 7.774710968e-07, 8.561423233e-07, 9.406381866e-07, 1.031239324e-06, 1.128232977e-06, 1.231912988e-06, 1.342579805e-06, 1.460540477e-06, 1.586108656e-06, 1.719604598e-06, 1.861355161e-06, 2.011693806e-06, 2.170960597e-06, 2.339502201e-06, 2.517671886e-06, 2.705829525e-06, 2.904341592e-06, 3.113581164e-06, 3.333927921e-06, 3.565768144e-06, 3.809494718e-06, 4.065507130e-06, 4.334211467e-06, 4.616020422e-06, 4.911353286e-06, 5.220635956e-06, 5.544300929e-06, 5.882787302e-06, 6.236540777e-06, 6.606013655e-06, 6.991664841e-06, 7.393959841e-06, 7.813370759e-06, 8.250376305e-06, 8.705461787e-06, 9.179119116e-06, 9.671846801e-06, 1.018414996e-05, 1.071654029e-05, 1.126953612e-05, 1.184366235e-05, 1.243945051e-05, 1.305743869e-05, 1.369817163e-05, 1.436220062e-05, 1.505008358e-05, 1.576238502e-05, 1.649967605e-05, 1.726253439e-05, 1.805154433e-05, 1.886729680e-05, 1.971038928e-05, 2.058142589e-05, 2.148101732e-05, 2.240978088e-05, 2.336834045e-05, 2.435732654e-05, 2.537737623e-05, 2.642913321e-05, 2.751324776e-05, 2.863037675e-05, 2.978118367e-05, 3.096633858e-05, 3.218651815e-05, 3.344240563e-05, 3.473469088e-05, 3.606407035e-05, 3.743124707e-05, 3.883693069e-05, 4.028183743e-05, 4.176669010e-05, 4.329221812e-05, 4.485915750e-05, 4.646825083e-05, 4.812024729e-05, 4.981590267e-05, 5.155597932e-05, 5.334124620e-05, 5.517247887e-05, 5.705045944e-05, 5.897597664e-05, 6.094982579e-05, 6.297280876e-05, 6.504573406e-05, 6.716941674e-05, 6.934467846e-05, 7.157234745e-05, 7.385325855e-05, 9.999261467e-01, 9.999284277e-01, 9.999306553e-01, 9.999328306e-01, 9.999349543e-01, 9.999370272e-01, 9.999390502e-01, 9.999410240e-01, 9.999429495e-01, 9.999448275e-01, 9.999466588e-01, 9.999484440e-01, 9.999501841e-01, 9.999518798e-01, 9.999535317e-01, 9.999551408e-01, 9.999567078e-01, 9.999582333e-01, 9.999597182e-01, 9.999611631e-01, 9.999625688e-01, 9.999639359e-01, 9.999652653e-01, 9.999665576e-01, 9.999678135e-01, 9.999690337e-01, 9.999702188e-01, 9.999713696e-01, 9.999724868e-01, 9.999735709e-01, 9.999746226e-01, 9.999756427e-01, 9.999766317e-01, 9.999775902e-01, 9.999785190e-01, 9.999794186e-01, 9.999802896e-01, 9.999811327e-01, 9.999819485e-01, 9.999827375e-01, 9.999835003e-01, 9.999842376e-01, 9.999849499e-01, 9.999856378e-01, 9.999863018e-01, 9.999869426e-01, 9.999875605e-01, 9.999881563e-01, 9.999887305e-01, 9.999892835e-01, 9.999898159e-01, 9.999903282e-01, 9.999908209e-01, 9.999912945e-01, 9.999917496e-01, 9.999921866e-01, 9.999926060e-01, 9.999930083e-01, 9.999933940e-01, 9.999937635e-01, 9.999941172e-01, 9.999944557e-01, 9.999947794e-01, 9.999950886e-01, 9.999953840e-01, 9.999956658e-01, 9.999959345e-01, 9.999961905e-01, 9.999964342e-01, 9.999966661e-01, 9.999968864e-01, 9.999970957e-01, 9.999972942e-01, 9.999974823e-01, 9.999976605e-01, 9.999978290e-01, 9.999979883e-01, 9.999981386e-01, 9.999982804e-01, 9.999984139e-01, 9.999985395e-01, 9.999986574e-01, 9.999987681e-01, 9.999988718e-01, 9.999989688e-01, 9.999990594e-01, 9.999991439e-01, 9.999992225e-01, 9.999992956e-01, 9.999993635e-01, 9.999994263e-01, 9.999994843e-01, 9.999995379e-01, 9.999995871e-01, 9.999996323e-01, 9.999996737e-01, 9.999997115e-01, 9.999997459e-01, 9.999997771e-01, 9.999998054e-01, 9.999998309e-01, 9.999998538e-01, 9.999998743e-01, 9.999998925e-01, 9.999999087e-01, 9.999999230e-01, 9.999999355e-01, 9.999999465e-01, 9.999999560e-01, 9.999999641e-01, 9.999999711e-01, 9.999999770e-01, 9.999999820e-01, 9.999999861e-01, 9.999999894e-01, 9.999999921e-01, 9.999999943e-01, 9.999999960e-01, 9.999999972e-01, 9.999999982e-01, 9.999999989e-01, 9.999999993e-01, 9.999999996e-01, 9.999999998e-01, 9.999999999e-01, 1.000000000e+00, 1.000000000e+00, 1.000000000e+00, 1.000000000e+00, }; const float* distributions_table[] = { dist_icdf_0_0, dist_icdf_0_1, dist_icdf_0_2, dist_icdf_0_3, dist_icdf_0_4, dist_icdf_0_5, dist_icdf_0_6, dist_icdf_0_7, dist_icdf_0_8, dist_icdf_0_8, dist_icdf_1_0, dist_icdf_1_1, dist_icdf_1_2, dist_icdf_1_3, dist_icdf_1_4, dist_icdf_1_5, dist_icdf_1_6, dist_icdf_1_7, dist_icdf_1_8, dist_icdf_1_8, dist_icdf_2_0, dist_icdf_2_1, dist_icdf_2_2, dist_icdf_2_3, dist_icdf_2_4, dist_icdf_2_5, dist_icdf_2_6, dist_icdf_2_7, dist_icdf_2_8, dist_icdf_2_8, dist_icdf_3_0, dist_icdf_3_1, dist_icdf_3_2, dist_icdf_3_3, dist_icdf_3_4, dist_icdf_3_5, dist_icdf_3_6, dist_icdf_3_7, dist_icdf_3_8, dist_icdf_3_8, dist_icdf_4_0, dist_icdf_4_1, dist_icdf_4_2, dist_icdf_4_3, dist_icdf_4_4, dist_icdf_4_5, dist_icdf_4_6, dist_icdf_4_7, dist_icdf_4_8, dist_icdf_4_8, dist_icdf_4_0, dist_icdf_4_1, dist_icdf_4_2, dist_icdf_4_3, dist_icdf_4_4, dist_icdf_4_5, dist_icdf_4_6, dist_icdf_4_7, dist_icdf_4_8, dist_icdf_4_8, }; } // namespace marbles ================================================ FILE: lib/marbles/resources.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resources definitions. // // Automatically generated with: // make resources #ifndef MARBLES_RESOURCES_H_ #define MARBLES_RESOURCES_H_ #include "stmlib/stmlib.h" namespace marbles { typedef uint8_t ResourceId; extern const float* lookup_table_table[]; extern const float* distributions_table[]; extern const float lut_raised_cosine[]; extern const float lut_sine[]; extern const float lut_logit[]; extern const float dist_icdf_0_0[]; extern const float dist_icdf_0_1[]; extern const float dist_icdf_0_2[]; extern const float dist_icdf_0_3[]; extern const float dist_icdf_0_4[]; extern const float dist_icdf_0_5[]; extern const float dist_icdf_0_6[]; extern const float dist_icdf_0_7[]; extern const float dist_icdf_0_8[]; extern const float dist_icdf_1_0[]; extern const float dist_icdf_1_1[]; extern const float dist_icdf_1_2[]; extern const float dist_icdf_1_3[]; extern const float dist_icdf_1_4[]; extern const float dist_icdf_1_5[]; extern const float dist_icdf_1_6[]; extern const float dist_icdf_1_7[]; extern const float dist_icdf_1_8[]; extern const float dist_icdf_2_0[]; extern const float dist_icdf_2_1[]; extern const float dist_icdf_2_2[]; extern const float dist_icdf_2_3[]; extern const float dist_icdf_2_4[]; extern const float dist_icdf_2_5[]; extern const float dist_icdf_2_6[]; extern const float dist_icdf_2_7[]; extern const float dist_icdf_2_8[]; extern const float dist_icdf_3_0[]; extern const float dist_icdf_3_1[]; extern const float dist_icdf_3_2[]; extern const float dist_icdf_3_3[]; extern const float dist_icdf_3_4[]; extern const float dist_icdf_3_5[]; extern const float dist_icdf_3_6[]; extern const float dist_icdf_3_7[]; extern const float dist_icdf_3_8[]; extern const float dist_icdf_4_0[]; extern const float dist_icdf_4_1[]; extern const float dist_icdf_4_2[]; extern const float dist_icdf_4_3[]; extern const float dist_icdf_4_4[]; extern const float dist_icdf_4_5[]; extern const float dist_icdf_4_6[]; extern const float dist_icdf_4_7[]; extern const float dist_icdf_4_8[]; #define LUT_RAISED_COSINE 0 #define LUT_RAISED_COSINE_SIZE 257 #define LUT_SINE 1 #define LUT_SINE_SIZE 257 #define LUT_LOGIT 2 #define LUT_LOGIT_SIZE 257 #define DIST_ICDF_0_0 0 #define DIST_ICDF_0_0_SIZE 387 #define DIST_ICDF_0_1 1 #define DIST_ICDF_0_1_SIZE 387 #define DIST_ICDF_0_2 2 #define DIST_ICDF_0_2_SIZE 387 #define DIST_ICDF_0_3 3 #define DIST_ICDF_0_3_SIZE 387 #define DIST_ICDF_0_4 4 #define DIST_ICDF_0_4_SIZE 387 #define DIST_ICDF_0_5 5 #define DIST_ICDF_0_5_SIZE 387 #define DIST_ICDF_0_6 6 #define DIST_ICDF_0_6_SIZE 387 #define DIST_ICDF_0_7 7 #define DIST_ICDF_0_7_SIZE 387 #define DIST_ICDF_0_8 8 #define DIST_ICDF_0_8_SIZE 387 #define DIST_ICDF_0_8_GUARD 9 #define DIST_ICDF_0_8_GUARD_SIZE 387 #define DIST_ICDF_1_0 10 #define DIST_ICDF_1_0_SIZE 387 #define DIST_ICDF_1_1 11 #define DIST_ICDF_1_1_SIZE 387 #define DIST_ICDF_1_2 12 #define DIST_ICDF_1_2_SIZE 387 #define DIST_ICDF_1_3 13 #define DIST_ICDF_1_3_SIZE 387 #define DIST_ICDF_1_4 14 #define DIST_ICDF_1_4_SIZE 387 #define DIST_ICDF_1_5 15 #define DIST_ICDF_1_5_SIZE 387 #define DIST_ICDF_1_6 16 #define DIST_ICDF_1_6_SIZE 387 #define DIST_ICDF_1_7 17 #define DIST_ICDF_1_7_SIZE 387 #define DIST_ICDF_1_8 18 #define DIST_ICDF_1_8_SIZE 387 #define DIST_ICDF_1_8_GUARD 19 #define DIST_ICDF_1_8_GUARD_SIZE 387 #define DIST_ICDF_2_0 20 #define DIST_ICDF_2_0_SIZE 387 #define DIST_ICDF_2_1 21 #define DIST_ICDF_2_1_SIZE 387 #define DIST_ICDF_2_2 22 #define DIST_ICDF_2_2_SIZE 387 #define DIST_ICDF_2_3 23 #define DIST_ICDF_2_3_SIZE 387 #define DIST_ICDF_2_4 24 #define DIST_ICDF_2_4_SIZE 387 #define DIST_ICDF_2_5 25 #define DIST_ICDF_2_5_SIZE 387 #define DIST_ICDF_2_6 26 #define DIST_ICDF_2_6_SIZE 387 #define DIST_ICDF_2_7 27 #define DIST_ICDF_2_7_SIZE 387 #define DIST_ICDF_2_8 28 #define DIST_ICDF_2_8_SIZE 387 #define DIST_ICDF_2_8_GUARD 29 #define DIST_ICDF_2_8_GUARD_SIZE 387 #define DIST_ICDF_3_0 30 #define DIST_ICDF_3_0_SIZE 387 #define DIST_ICDF_3_1 31 #define DIST_ICDF_3_1_SIZE 387 #define DIST_ICDF_3_2 32 #define DIST_ICDF_3_2_SIZE 387 #define DIST_ICDF_3_3 33 #define DIST_ICDF_3_3_SIZE 387 #define DIST_ICDF_3_4 34 #define DIST_ICDF_3_4_SIZE 387 #define DIST_ICDF_3_5 35 #define DIST_ICDF_3_5_SIZE 387 #define DIST_ICDF_3_6 36 #define DIST_ICDF_3_6_SIZE 387 #define DIST_ICDF_3_7 37 #define DIST_ICDF_3_7_SIZE 387 #define DIST_ICDF_3_8 38 #define DIST_ICDF_3_8_SIZE 387 #define DIST_ICDF_3_8_GUARD 39 #define DIST_ICDF_3_8_GUARD_SIZE 387 #define DIST_ICDF_4_0 40 #define DIST_ICDF_4_0_SIZE 387 #define DIST_ICDF_4_1 41 #define DIST_ICDF_4_1_SIZE 387 #define DIST_ICDF_4_2 42 #define DIST_ICDF_4_2_SIZE 387 #define DIST_ICDF_4_3 43 #define DIST_ICDF_4_3_SIZE 387 #define DIST_ICDF_4_4 44 #define DIST_ICDF_4_4_SIZE 387 #define DIST_ICDF_4_5 45 #define DIST_ICDF_4_5_SIZE 387 #define DIST_ICDF_4_6 46 #define DIST_ICDF_4_6_SIZE 387 #define DIST_ICDF_4_7 47 #define DIST_ICDF_4_7_SIZE 387 #define DIST_ICDF_4_8 48 #define DIST_ICDF_4_8_SIZE 387 #define DIST_ICDF_4_8_GUARD 49 #define DIST_ICDF_4_8_GUARD_SIZE 387 #define DIST_ICDF_4_0_GUARD 50 #define DIST_ICDF_4_0_GUARD_SIZE 387 #define DIST_ICDF_4_1_GUARD 51 #define DIST_ICDF_4_1_GUARD_SIZE 387 #define DIST_ICDF_4_2_GUARD 52 #define DIST_ICDF_4_2_GUARD_SIZE 387 #define DIST_ICDF_4_3_GUARD 53 #define DIST_ICDF_4_3_GUARD_SIZE 387 #define DIST_ICDF_4_4_GUARD 54 #define DIST_ICDF_4_4_GUARD_SIZE 387 #define DIST_ICDF_4_5_GUARD 55 #define DIST_ICDF_4_5_GUARD_SIZE 387 #define DIST_ICDF_4_6_GUARD 56 #define DIST_ICDF_4_6_GUARD_SIZE 387 #define DIST_ICDF_4_7_GUARD 57 #define DIST_ICDF_4_7_GUARD_SIZE 387 #define DIST__ICDF_4_8_GUARD 58 #define DIST__ICDF_4_8_GUARD_SIZE 387 #define DIST_ICDF_4_8_GUARD_GUARD 59 #define DIST_ICDF_4_8_GUARD_GUARD_SIZE 387 } // namespace marbles #endif // MARBLES_RESOURCES_H_ ================================================ FILE: lib/marbles/scale_recorder.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Record a note CV distribution - to be used for the quantizer. #ifndef MARBLES_SCALE_RECORDER_H_ #define MARBLES_SCALE_RECORDER_H_ #include "stmlib/stmlib.h" #include "marbles/random/quantizer.h" namespace marbles { class ScaleRecorder { public: ScaleRecorder() { } ~ScaleRecorder() { } struct Degree { float average_voltage; float total_voltage; float count; bool operator< (const Degree& rhs) const { return average_voltage < rhs.average_voltage; } }; void Init() { Clear(); } void Clear() { num_degrees_ = 0; current_voltage_ = 0.0f; total_count_ = 0.0f; } void NewNote(float v) { current_voltage_ = v; } void UpdateVoltage(float v) { ONE_POLE(current_voltage_, v, 0.01f); } void AcceptNote() { const float base_interval = 1.0f; float v = current_voltage_; while (v < 0.0f) { v += base_interval; } float octave = static_cast( static_cast(v / base_interval)) * base_interval; v -= octave; int nearest_degree = -1; for (int i = 0; i < num_degrees_; ++i) { float av = degrees_[i].average_voltage; const float tolerance = 1.0f / 36.0f; if (fabsf(v - av) < tolerance) { nearest_degree = i; break; } if (fabsf((v - base_interval) - av) < tolerance) { v -= base_interval; nearest_degree = i; break; } } if (nearest_degree == -1 && num_degrees_ != kMaxDegrees) { nearest_degree = num_degrees_; Degree* d = °rees_[nearest_degree]; d->total_voltage = 0.0f; d->average_voltage = 0.0f; d->count = 0.0f; ++num_degrees_; } if (nearest_degree != -1) { Degree* d = °rees_[nearest_degree]; d->total_voltage += v; d->count += 1.0f; d->average_voltage = d->total_voltage / d->count; total_count_ += 1.0f; } } bool ExtractScale(Scale* scale) { if (num_degrees_ < 2) { return false; } std::sort(°rees_[0], °rees_[num_degrees_]); float max_count = 0.0f; for (int i = 0; i < num_degrees_; ++i) { max_count = std::max(degrees_[i].count, max_count); } scale->base_interval = 1.0f; scale->num_degrees = num_degrees_; for (int i = 0; i < num_degrees_; ++i) { Degree* d = °rees_[i]; scale->degree[i].voltage = d->average_voltage; scale->degree[i].weight = static_cast( 255.0f * d->count / max_count); if (scale->degree[i].weight == 0) { ++scale->degree[i].weight; } } return true; } private: int num_degrees_; float current_voltage_; float total_count_; Degree degrees_[kMaxDegrees]; DISALLOW_COPY_AND_ASSIGN(ScaleRecorder); }; } // namespace marbles #endif // MARBLES_SCALE_RECORDER_H_ ================================================ FILE: lib/misc/Biquad.cpp ================================================ // // Biquad.cpp // // Created by Nigel Redmon on 11/24/12 // EarLevel Engineering: earlevel.com // Copyright 2012 Nigel Redmon // // For a complete explanation of the Biquad code: // http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/ // // License: // // This source code is provided as is, without warranty. // You may copy and distribute verbatim copies of this document. // You may modify and use this source code to create binary code // for your own purposes, free or commercial. // // [eh2k] perforcance optimizations.. #include #include "Biquad.h" #ifndef M_PI #define M_PI 3.14159265358979323846 /* pi */ #endif #define M_PI_F float(M_PI) #define M_PI_POW_2 M_PI * M_PI #define M_PI_POW_3 M_PI_POW_2 * M_PI #define M_PI_POW_5 M_PI_POW_3 * M_PI_POW_2 inline float tan_pi_f(float f) // stmlib::OnePole::tan(Fc) { // The usual tangent approximation uses 3.1755e-01 and 2.033e-01, but // the coefficients used here are optimized to minimize error for the // 16Hz to 16kHz range, with a sample rate of 48kHz. const float a = 3.260e-01f * M_PI_POW_3; const float b = 1.823e-01f * M_PI_POW_5; float f2 = f * f; return f * (M_PI_F + f2 * (a + b * f2)); } Biquad::Biquad() { type = bq_type_lowpass; a0 = 1.0; a1 = a2 = b1 = b2 = 0.0; Fc = 0.50; Q = 0.707; peakGain = 1.0f; // z1 = z2 = 0.0; } Biquad::Biquad(int type, float Fc, float Q, float peakGainDB) { setBiquad(type, Fc, Q, peakGainDB); // z1 = z2 = 0.0; } Biquad::~Biquad() { } void Biquad::setType(int type) { this->type = type; calcBiquad(); } void Biquad::setQ(float Q) { this->Q = Q; calcBiquad(); } void Biquad::setFc(float Fc) { this->Fc = Fc; calcBiquad(); } void Biquad::setPeakGain(float peakGainDB) { this->peakGain = expf(peakGainDB * 0.11512925464970228420089957273422f); // dB2amp(peakGainDB); calcBiquad(); } void Biquad::setBiquad(int type, float Fc, float Q, float peakGainDB) { this->type = type; this->Q = Q; this->Fc = Fc; setPeakGain(peakGainDB); } void Biquad::calcBiquad(void) { float norm; float V = peakGain; // powf(10, fabsf(peakGain) / 20.0f); float K = tan_pi_f(Fc); // tanf(M_PI * Fc) switch (this->type) { case bq_type_lowpass: norm = 1 / (1 + K / Q + K * K); a0 = K * K * norm; a1 = 2 * a0; a2 = a0; b1 = 2 * (K * K - 1) * norm; b2 = (1 - K / Q + K * K) * norm; break; case bq_type_highpass: norm = 1 / (1 + K / Q + K * K); a0 = 1 * norm; a1 = -2 * a0; a2 = a0; b1 = 2 * (K * K - 1) * norm; b2 = (1 - K / Q + K * K) * norm; break; case bq_type_bandpass: norm = 1 / (1 + K / Q + K * K); a0 = K / Q * norm; a1 = 0; a2 = -a0; b1 = 2 * (K * K - 1) * norm; b2 = (1 - K / Q + K * K) * norm; break; case bq_type_notch: norm = 1 / (1 + K / Q + K * K); a0 = (1 + K * K) * norm; a1 = 2 * (K * K - 1) * norm; a2 = a0; b1 = a1; b2 = (1 - K / Q + K * K) * norm; break; case bq_type_peak: if (peakGain >= 1) { // boost norm = 1 / (1 + 1 / Q * K + K * K); a0 = (1 + V / Q * K + K * K) * norm; a1 = 2 * (K * K - 1) * norm; a2 = (1 - V / Q * K + K * K) * norm; b1 = a1; b2 = (1 - 1 / Q * K + K * K) * norm; } else { // cut norm = 1 / (1 + V / Q * K + K * K); a0 = (1 + 1 / Q * K + K * K) * norm; a1 = 2 * (K * K - 1) * norm; a2 = (1 - 1 / Q * K + K * K) * norm; b1 = a1; b2 = (1 - V / Q * K + K * K) * norm; } break; case bq_type_lowshelf: if (peakGain >= 1) { // boost norm = 1 / (1 + sqrtf(2) * K + K * K); a0 = (1 + sqrtf(2 * V) * K + V * K * K) * norm; a1 = 2 * (V * K * K - 1) * norm; a2 = (1 - sqrtf(2 * V) * K + V * K * K) * norm; b1 = 2 * (K * K - 1) * norm; b2 = (1 - sqrtf(2) * K + K * K) * norm; } else { // cut norm = 1 / (1 + sqrtf(2 * V) * K + V * K * K); a0 = (1 + sqrtf(2) * K + K * K) * norm; a1 = 2 * (K * K - 1) * norm; a2 = (1 - sqrtf(2) * K + K * K) * norm; b1 = 2 * (V * K * K - 1) * norm; b2 = (1 - sqrtf(2 * V) * K + V * K * K) * norm; } break; case bq_type_highshelf: if (peakGain >= 1) { // boost norm = 1 / (1 + sqrtf(2) * K + K * K); a0 = (V + sqrtf(2 * V) * K + K * K) * norm; a1 = 2 * (K * K - V) * norm; a2 = (V - sqrtf(2 * V) * K + K * K) * norm; b1 = 2 * (K * K - 1) * norm; b2 = (1 - sqrtf(2) * K + K * K) * norm; } else { // cut norm = 1 / (V + sqrtf(2 * V) * K + K * K); a0 = (1 + sqrtf(2) * K + K * K) * norm; a1 = 2 * (K * K - 1) * norm; a2 = (1 - sqrtf(2) * K + K * K) * norm; b1 = 2 * (K * K - V) * norm; b2 = (V - sqrtf(2 * V) * K + K * K) * norm; } break; } return; } ================================================ FILE: lib/misc/Biquad.h ================================================ // // Biquad.h // // Created by Nigel Redmon on 11/24/12 // EarLevel Engineering: earlevel.com // Copyright 2012 Nigel Redmon // // For a complete explanation of the Biquad code: // http://www.earlevel.com/main/2012/11/25/biquad-c-source-code/ // // License: // // This source code is provided as is, without warranty. // You may copy and distribute verbatim copies of this document. // You may modify and use this source code to create binary code // for your own purposes, free or commercial. // #ifndef Biquad_h #define Biquad_h enum { bq_type_lowpass = 0, bq_type_highpass, bq_type_bandpass, bq_type_notch, bq_type_peak, bq_type_lowshelf, bq_type_highshelf }; class Biquad { public: Biquad(); Biquad(int type, float Fc, float Q, float peakGainDB); ~Biquad(); void setType(int type); void setQ(float Q); void setFc(float Fc); void setPeakGain(float peakGainDB); void setBiquad(int type, float Fc, float Q, float peakGainDB); float process(float in); float process(float in, float& z1, float& z2); protected: void calcBiquad(void); int type; float a0, a1, a2, b0, b1, b2; float Fc, Q, peakGain; float z1, z2; // float x1; // input delayed by 1 sample // float x2; // input delayed by 2 samples // float y1; // output delayed by 1 sample // float y2; // output delayed by 2 samples }; inline float Biquad::process(float in) { float out = in * a0 + z1; z1 = in * a1 + z2 - b1 * out; z2 = in * a2 - b2 * out; return out; // float x = in; // float y = a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2; // x2 = x1; // x1 = x; // y2 = y1; // y1 = y; // return y; } inline float Biquad::process(float in, float& _z1, float& _z2) { float out = in * a0 + _z1; _z1 = in * a1 + _z2 - b1 * out; _z2 = in * a2 - b2 * out; return out; // float x = in; // float y = a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2; // x2 = x1; // x1 = x; // y2 = y1; // y1 = y; // return y; } #endif // Biquad_h ================================================ FILE: lib/misc/analyze_fft.hxx ================================================ // code based on Teensy Audio analyse_fft1024.cpp #pragma once #include #ifndef FLASHMEM #include "pgmspace.h" #endif const int16_t AudioWindowHanning1024[] __attribute__ ((aligned (4))) FLASHMEM = { 0, 0, 1, 3, 5, 8, 11, 15, 20, 25, 31, 37, 44, 52, 61, 69, 79, 89, 100, 111, 123, 136, 149, 163, 178, 193, 208, 225, 242, 259, 277, 296, 315, 335, 356, 377, 399, 421, 444, 468, 492, 517, 542, 568, 595, 622, 650, 678, 707, 736, 767, 797, 829, 860, 893, 926, 960, 994, 1029, 1064, 1100, 1137, 1174, 1211, 1250, 1288, 1328, 1368, 1408, 1449, 1491, 1533, 1576, 1619, 1663, 1708, 1753, 1798, 1844, 1891, 1938, 1986, 2034, 2083, 2133, 2182, 2233, 2284, 2335, 2387, 2440, 2493, 2547, 2601, 2656, 2711, 2766, 2823, 2879, 2937, 2994, 3053, 3111, 3171, 3230, 3291, 3351, 3413, 3474, 3536, 3599, 3662, 3726, 3790, 3855, 3920, 3985, 4051, 4118, 4185, 4252, 4320, 4388, 4457, 4526, 4596, 4666, 4737, 4808, 4879, 4951, 5023, 5096, 5169, 5243, 5317, 5391, 5466, 5541, 5617, 5693, 5769, 5846, 5923, 6001, 6079, 6158, 6236, 6316, 6395, 6475, 6555, 6636, 6717, 6799, 6880, 6962, 7045, 7128, 7211, 7295, 7379, 7463, 7547, 7632, 7717, 7803, 7889, 7975, 8062, 8148, 8236, 8323, 8411, 8499, 8587, 8676, 8765, 8854, 8944, 9033, 9123, 9214, 9304, 9395, 9486, 9578, 9670, 9761, 9854, 9946, 10039, 10132, 10225, 10318, 10412, 10505, 10599, 10694, 10788, 10883, 10978, 11073, 11168, 11264, 11359, 11455, 11551, 11648, 11744, 11841, 11937, 12034, 12131, 12229, 12326, 12424, 12521, 12619, 12717, 12815, 12914, 13012, 13111, 13209, 13308, 13407, 13506, 13605, 13704, 13804, 13903, 14003, 14102, 14202, 14302, 14401, 14501, 14601, 14701, 14802, 14902, 15002, 15102, 15203, 15303, 15403, 15504, 15604, 15705, 15806, 15906, 16007, 16107, 16208, 16309, 16409, 16510, 16610, 16711, 16812, 16912, 17013, 17113, 17214, 17314, 17415, 17515, 17616, 17716, 17816, 17916, 18017, 18117, 18217, 18317, 18416, 18516, 18616, 18716, 18815, 18915, 19014, 19113, 19213, 19312, 19411, 19509, 19608, 19707, 19805, 19904, 20002, 20100, 20198, 20296, 20393, 20491, 20588, 20685, 20782, 20879, 20976, 21072, 21169, 21265, 21361, 21457, 21552, 21647, 21743, 21838, 21932, 22027, 22121, 22216, 22309, 22403, 22497, 22590, 22683, 22776, 22868, 22961, 23053, 23144, 23236, 23327, 23418, 23509, 23599, 23690, 23780, 23869, 23959, 24048, 24136, 24225, 24313, 24401, 24489, 24576, 24663, 24750, 24836, 24922, 25008, 25093, 25178, 25263, 25347, 25431, 25515, 25599, 25682, 25764, 25847, 25929, 26010, 26091, 26172, 26253, 26333, 26413, 26492, 26571, 26650, 26728, 26806, 26883, 26960, 27037, 27113, 27189, 27265, 27340, 27414, 27488, 27562, 27636, 27708, 27781, 27853, 27925, 27996, 28067, 28137, 28207, 28276, 28345, 28414, 28482, 28550, 28617, 28683, 28750, 28815, 28881, 28946, 29010, 29074, 29137, 29200, 29263, 29325, 29386, 29447, 29508, 29568, 29627, 29686, 29745, 29803, 29860, 29917, 29974, 30029, 30085, 30140, 30194, 30248, 30301, 30354, 30407, 30458, 30510, 30560, 30611, 30660, 30709, 30758, 30806, 30853, 30900, 30947, 30993, 31038, 31083, 31127, 31170, 31213, 31256, 31298, 31339, 31380, 31420, 31460, 31499, 31538, 31576, 31613, 31650, 31686, 31722, 31757, 31791, 31825, 31859, 31891, 31924, 31955, 31986, 32017, 32046, 32076, 32104, 32132, 32160, 32187, 32213, 32239, 32264, 32288, 32312, 32335, 32358, 32380, 32402, 32422, 32443, 32462, 32481, 32500, 32518, 32535, 32551, 32567, 32583, 32598, 32612, 32625, 32638, 32651, 32662, 32673, 32684, 32694, 32703, 32712, 32720, 32727, 32734, 32740, 32746, 32751, 32755, 32759, 32762, 32764, 32766, 32767, 32767, 32767, 32767, 32766, 32764, 32762, 32759, 32755, 32751, 32746, 32740, 32734, 32727, 32720, 32712, 32703, 32694, 32684, 32673, 32662, 32651, 32638, 32625, 32612, 32598, 32583, 32567, 32551, 32535, 32518, 32500, 32481, 32462, 32443, 32422, 32402, 32380, 32358, 32335, 32312, 32288, 32264, 32239, 32213, 32187, 32160, 32132, 32104, 32076, 32046, 32017, 31986, 31955, 31924, 31891, 31859, 31825, 31791, 31757, 31722, 31686, 31650, 31613, 31576, 31538, 31499, 31460, 31420, 31380, 31339, 31298, 31256, 31213, 31170, 31127, 31083, 31038, 30993, 30947, 30900, 30853, 30806, 30758, 30709, 30660, 30611, 30560, 30510, 30458, 30407, 30354, 30301, 30248, 30194, 30140, 30085, 30029, 29974, 29917, 29860, 29803, 29745, 29686, 29627, 29568, 29508, 29447, 29386, 29325, 29263, 29200, 29137, 29074, 29010, 28946, 28881, 28815, 28750, 28683, 28617, 28550, 28482, 28414, 28345, 28276, 28207, 28137, 28067, 27996, 27925, 27853, 27781, 27708, 27636, 27562, 27488, 27414, 27340, 27265, 27189, 27113, 27037, 26960, 26883, 26806, 26728, 26650, 26571, 26492, 26413, 26333, 26253, 26172, 26091, 26010, 25929, 25847, 25764, 25682, 25599, 25515, 25431, 25347, 25263, 25178, 25093, 25008, 24922, 24836, 24750, 24663, 24576, 24489, 24401, 24313, 24225, 24136, 24048, 23959, 23869, 23780, 23690, 23599, 23509, 23418, 23327, 23236, 23144, 23053, 22961, 22868, 22776, 22683, 22590, 22497, 22403, 22309, 22216, 22121, 22027, 21932, 21838, 21743, 21647, 21552, 21457, 21361, 21265, 21169, 21072, 20976, 20879, 20782, 20685, 20588, 20491, 20393, 20296, 20198, 20100, 20002, 19904, 19805, 19707, 19608, 19509, 19411, 19312, 19213, 19113, 19014, 18915, 18815, 18716, 18616, 18516, 18416, 18317, 18217, 18117, 18017, 17916, 17816, 17716, 17616, 17515, 17415, 17314, 17214, 17113, 17013, 16912, 16812, 16711, 16610, 16510, 16409, 16309, 16208, 16107, 16007, 15906, 15806, 15705, 15604, 15504, 15403, 15303, 15203, 15102, 15002, 14902, 14802, 14701, 14601, 14501, 14401, 14302, 14202, 14102, 14003, 13903, 13804, 13704, 13605, 13506, 13407, 13308, 13209, 13111, 13012, 12914, 12815, 12717, 12619, 12521, 12424, 12326, 12229, 12131, 12034, 11937, 11841, 11744, 11648, 11551, 11455, 11359, 11264, 11168, 11073, 10978, 10883, 10788, 10694, 10599, 10505, 10412, 10318, 10225, 10132, 10039, 9946, 9854, 9761, 9670, 9578, 9486, 9395, 9304, 9214, 9123, 9033, 8944, 8854, 8765, 8676, 8587, 8499, 8411, 8323, 8236, 8148, 8062, 7975, 7889, 7803, 7717, 7632, 7547, 7463, 7379, 7295, 7211, 7128, 7045, 6962, 6880, 6799, 6717, 6636, 6555, 6475, 6395, 6316, 6236, 6158, 6079, 6001, 5923, 5846, 5769, 5693, 5617, 5541, 5466, 5391, 5317, 5243, 5169, 5096, 5023, 4951, 4879, 4808, 4737, 4666, 4596, 4526, 4457, 4388, 4320, 4252, 4185, 4118, 4051, 3985, 3920, 3855, 3790, 3726, 3662, 3599, 3536, 3474, 3413, 3351, 3291, 3230, 3171, 3111, 3053, 2994, 2937, 2879, 2823, 2766, 2711, 2656, 2601, 2547, 2493, 2440, 2387, 2335, 2284, 2233, 2182, 2133, 2083, 2034, 1986, 1938, 1891, 1844, 1798, 1753, 1708, 1663, 1619, 1576, 1533, 1491, 1449, 1408, 1368, 1328, 1288, 1250, 1211, 1174, 1137, 1100, 1064, 1029, 994, 960, 926, 893, 860, 829, 797, 767, 736, 707, 678, 650, 622, 595, 568, 542, 517, 492, 468, 444, 421, 399, 377, 356, 335, 315, 296, 277, 259, 242, 225, 208, 193, 178, 163, 149, 136, 123, 111, 100, 89, 79, 69, 61, 52, 44, 37, 31, 25, 20, 15, 11, 8, 5, 3, 1, 0, 0, }; template class AnalyzeFFT { uint16_t output[BITS / 2]; int16_t buffer[BITS * 2] __attribute__((aligned(4))); arm_cfft_radix4_instance_q15 fft_inst; uint32_t *p = (uint32_t *)buffer; // computes ((a[15:0] * b[15:0]) + (a[31:16] * b[31:16])) inline int32_t multiply_16tx16t_add_16bx16b(uint32_t a, uint32_t b) { int32_t out; asm volatile("smuad %0, %1, %2" : "=r"(out) : "r"(a), "r"(b)); return out; } // https://www.esp8266.com/viewtopic.php?p=55534 const uint16_t sqrt_integer_guess_table[33] = {55109, 38968, 27555, 19484, 13778, 9742, 6889, 4871, 3445, 2436, 1723, 1218, 862, 609, 431, 305, 216, 153, 108, 77, 54, 39, 27, 20, 14, 10, 7, 5, 4, 3, 2, 1, 0}; inline uint32_t sqrt_uint32(uint32_t in) { uint32_t n = sqrt_integer_guess_table[__builtin_clz(in)]; n = ((in / n) + n) / 2; n = ((in / n) + n) / 2; n = ((in / n) + n) / 2; return n; } inline uint32_t sqrt_uint32_approx(uint32_t in) { uint32_t n = sqrt_integer_guess_table[__builtin_clz(in)]; n = ((in / n) + n) / 2; n = ((in / n) + n) / 2; return n; } static void apply_window_to_fft_buffer(void *buffer, const void *window) { int16_t *buf = (int16_t *)buffer; const int16_t *win = (int16_t *)window; ; for (int i = 0; i < 1024; i++) { int32_t val = *buf * *win++; //*buf = signed_saturate_rshift(val, 16, 15); *buf = val >> 15; buf += 2; } } public: AnalyzeFFT() { arm_cfft_radix4_init_q15(&fft_inst, BITS, 0, 1); p = (uint32_t *)buffer; memset(output, 0, sizeof(output)); } bool process(const int16_t *in, size_t len, int16_t gain = 1) { for (size_t i = 0; i < len; i++) { *p++ = __SSAT(in[i] * gain, 16); if (p >= (uint32_t *)(&buffer[BITS * 2])) { int16_t bak[LEN_OF(buffer)/2]; memcpy(bak, &buffer[LEN_OF(buffer)/2], sizeof(bak)); apply_window_to_fft_buffer(buffer, AudioWindowHanning1024); arm_cfft_radix4_q15(&fft_inst, buffer); for (size_t i = 0; i < LEN_OF(output); i++) { uint32_t tmp = *((uint32_t *)buffer + i); // real & imag uint32_t magsq = multiply_16tx16t_add_16bx16b(tmp, tmp); output[i] = (output[i] >> 1) + sqrt_uint32_approx(magsq); }; memcpy(buffer, bak, sizeof(bak)); p = (uint32_t *)&buffer[LEN_OF(buffer)/2]; return true; } } return false; } void display(uint8_t *display, int offset = 7) { uint32_t ylim = 64 - offset; constexpr uint32_t dx = 128; constexpr uint32_t bpp = LEN_OF(output) / dx; int x = 0; for (uint32_t i = 0; i < LEN_OF(output); i++) { if (BITS == 1024) { uint32_t sum = 0; int n = std::min(i + bpp, LEN_OF(output)); for (int j = i; j < n; j++) sum += output[j]; float f = (1.0f / 16384.0f) * sum; // f = 20.f * log10f(1+f*10); gfx::drawLine(x, ylim, x, ylim - (f*ylim)); x++; i = (n - 1); } else if (BITS == 256) { auto f = output[i]; gfx::drawLine(i, ylim, i, ylim - f); } else { gfx::drawString(0, 32, "not implemented"); } }; } }; ================================================ FILE: lib/misc/cubic_spline.hxx ================================================ /* * Based on: https://medium.com/@martinmikkelsen/cubic-splines-in-the-c-language-4463fe9a3a83 */ #include #include typedef struct { int N; // number of intervals (points - 1) float *x; // x points float *y; // y points (a[i]) float *b; // . float *c; // . float *d; // . } cspline; // Initialize spline with given (x, y) points void cspline_init(cspline *s, const float *x, const float *y, int N, int stride) { s->N = N; s->x = (float *)malloc((N * 5) * sizeof(float)); s->y = s->x + N; s->b = s->y + N; s->c = s->b + N; s->d = s->c + N; for (int i = 0; i < N; ++i) { s->x[i] = x[i * stride]; s->y[i] = y[i * stride]; } int i; float dx[N - 1]; float p[N - 1]; for (i = 0; i < N - 1; ++i) { dx[i] = x[(i + 1) * stride] - x[i * stride]; if (dx[i] < 0.1f) dx[i] = 0.1f; p[i] = (y[(i + 1) * stride] - y[i * stride]) / dx[i]; } float D[N]; float B[N]; float Q[N - 1]; D[0] = 2; D[N - 1] = 2; B[0] = 3 * p[0]; B[N - 1] = 3 * p[N - 2]; Q[0] = 1; for (i = 0; i < N - 2; ++i) { D[i + 1] = 2 * dx[i] / dx[i + 1] + 2; B[i + 1] = 3 * (p[i] + p[i + 1] * dx[i] / dx[i + 1]); Q[i + 1] = dx[i] / dx[i + 1]; } for (i = 1; i < N; ++i) { D[i] -= Q[i - 1] / D[i - 1]; B[i] -= B[i - 1] / D[i - 1]; } s->b[N - 1] = B[N - 1] / D[N - 1]; for (i = N - 2; i >= 0; --i) { s->b[i] = (B[i] - Q[i] * s->b[i + 1]) / D[i]; } for (i = 0; i < N - 1; ++i) { s->c[i] = (-2 * s->b[i] - s->b[i + 1] + 3 * p[i]) / dx[i]; s->d[i] = (s->b[i] + s->b[i + 1] - 2 * p[i]) / dx[i] / dx[i]; } } float cspline_eval(const cspline *s, float x) { int i; if (x <= s->x[0]) { i = 0; } else if (x >= s->x[s->N - 1]) { i = s->N - 1; } else { int low = 0, high = s->N - 1; while (low < high - 1) { int mid = (low + high) / 2; if (x < s->x[mid]) { high = mid; } else { low = mid; } } i = low; } auto dx = x - s->x[i]; auto y_new = s->y[i] + s->b[i] * dx + s->c[i] * powf(dx, 2) + s->d[i] * powf(dx, 3); return y_new; } void cspline_free(cspline *spline) { free(spline->x); } ================================================ FILE: lib/misc/dspinst.h ================================================ /* Audio Library for Teensy 3.X * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com * * Development of this audio library was funded by PJRC.COM, LLC by sales of * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop * open source software by purchasing Teensy or other PJRC products. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice, development funding notice, and this permission * notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef dspinst_h_ #define dspinst_h_ #include // computes limit((val >> rshift), 2**bits) static inline int32_t signed_saturate_rshift(int32_t val, int bits, int rshift) __attribute__((always_inline, unused)); static inline int32_t signed_saturate_rshift(int32_t val, int bits, int rshift) { #if defined (__ARM_ARCH_7EM__) int32_t out; asm volatile("ssat %0, %1, %2, asr %3" : "=r" (out) : "I" (bits), "r" (val), "I" (rshift)); return out; #else int32_t out, max; out = val >> rshift; max = 1 << (bits - 1); if (out >= 0) { if (out > max - 1) out = max - 1; } else { if (out < -max) out = -max; } return out; #endif } // computes limit(val, 2**bits) static inline int16_t saturate16(int32_t val) __attribute__((always_inline, unused)); static inline int16_t saturate16(int32_t val) { #if defined (__ARM_ARCH_7EM__) int16_t out; int32_t tmp; asm volatile("ssat %0, %1, %2" : "=r" (tmp) : "I" (16), "r" (val) ); out = (int16_t) (tmp); return out; #else if (val > 32767) val = 32767; else if (val < -32768) val = -32768; return val; #endif } // computes ((a[31:0] * b[15:0]) >> 16) static inline int32_t signed_multiply_32x16b(int32_t a, uint32_t b) __attribute__((always_inline, unused)); static inline int32_t signed_multiply_32x16b(int32_t a, uint32_t b) { #if defined (__ARM_ARCH_7EM__) int32_t out; asm volatile("smulwb %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; #elif defined(KINETISL) return ((int64_t)a * (int16_t)(b & 0xFFFF)) >> 16; #endif } // computes ((a[31:0] * b[31:16]) >> 16) static inline int32_t signed_multiply_32x16t(int32_t a, uint32_t b) __attribute__((always_inline, unused)); static inline int32_t signed_multiply_32x16t(int32_t a, uint32_t b) { #if defined (__ARM_ARCH_7EM__) int32_t out; asm volatile("smulwt %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; #elif defined(KINETISL) return ((int64_t)a * (int16_t)(b >> 16)) >> 16; #endif } // computes (((int64_t)a[31:0] * (int64_t)b[31:0]) >> 32) static inline int32_t multiply_32x32_rshift32(int32_t a, int32_t b) __attribute__((always_inline, unused)); static inline int32_t multiply_32x32_rshift32(int32_t a, int32_t b) { #if defined (__ARM_ARCH_7EM__) int32_t out; asm volatile("smmul %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; #elif defined(KINETISL) return ((int64_t)a * (int64_t)b) >> 32; #endif } // computes (((int64_t)a[31:0] * (int64_t)b[31:0] + 0x8000000) >> 32) static inline int32_t multiply_32x32_rshift32_rounded(int32_t a, int32_t b) __attribute__((always_inline, unused)); static inline int32_t multiply_32x32_rshift32_rounded(int32_t a, int32_t b) { #if defined (__ARM_ARCH_7EM__) int32_t out; asm volatile("smmulr %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; #elif defined(KINETISL) return (((int64_t)a * (int64_t)b) + 0x8000000) >> 32; #endif } // computes sum + (((int64_t)a[31:0] * (int64_t)b[31:0] + 0x8000000) >> 32) static inline int32_t multiply_accumulate_32x32_rshift32_rounded(int32_t sum, int32_t a, int32_t b) __attribute__((always_inline, unused)); static inline int32_t multiply_accumulate_32x32_rshift32_rounded(int32_t sum, int32_t a, int32_t b) { #if defined (__ARM_ARCH_7EM__) int32_t out; asm volatile("smmlar %0, %2, %3, %1" : "=r" (out) : "r" (sum), "r" (a), "r" (b)); return out; #elif defined(KINETISL) return sum + ((((int64_t)a * (int64_t)b) + 0x8000000) >> 32); #endif } // computes sum - (((int64_t)a[31:0] * (int64_t)b[31:0] + 0x8000000) >> 32) static inline int32_t multiply_subtract_32x32_rshift32_rounded(int32_t sum, int32_t a, int32_t b) __attribute__((always_inline, unused)); static inline int32_t multiply_subtract_32x32_rshift32_rounded(int32_t sum, int32_t a, int32_t b) { #if defined (__ARM_ARCH_7EM__) int32_t out; asm volatile("smmlsr %0, %2, %3, %1" : "=r" (out) : "r" (sum), "r" (a), "r" (b)); return out; #elif defined(KINETISL) return sum - ((((int64_t)a * (int64_t)b) + 0x8000000) >> 32); #endif } // computes (a[31:16] | (b[31:16] >> 16)) static inline uint32_t pack_16t_16t(int32_t a, int32_t b) __attribute__((always_inline, unused)); static inline uint32_t pack_16t_16t(int32_t a, int32_t b) { #if defined (__ARM_ARCH_7EM__) int32_t out; asm volatile("pkhtb %0, %1, %2, asr #16" : "=r" (out) : "r" (a), "r" (b)); return out; #elif defined(KINETISL) return (a & 0xFFFF0000) | ((uint32_t)b >> 16); #endif } // computes (a[31:16] | b[15:0]) static inline uint32_t pack_16t_16b(int32_t a, int32_t b) __attribute__((always_inline, unused)); static inline uint32_t pack_16t_16b(int32_t a, int32_t b) { #if defined (__ARM_ARCH_7EM__) int32_t out; asm volatile("pkhtb %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; #elif defined(KINETISL) return (a & 0xFFFF0000) | (b & 0x0000FFFF); #endif } // computes ((a[15:0] << 16) | b[15:0]) static inline uint32_t pack_16b_16b(int32_t a, int32_t b) __attribute__((always_inline, unused)); static inline uint32_t pack_16b_16b(int32_t a, int32_t b) { #if defined (__ARM_ARCH_7EM__) int32_t out; asm volatile("pkhbt %0, %1, %2, lsl #16" : "=r" (out) : "r" (b), "r" (a)); return out; #elif defined(KINETISL) return (a << 16) | (b & 0x0000FFFF); #endif } // computes ((a[15:0] << 16) | b[15:0]) /* static inline uint32_t pack_16x16(int32_t a, int32_t b) __attribute__((always_inline, unused)); static inline uint32_t pack_16x16(int32_t a, int32_t b) { int32_t out; asm volatile("pkhbt %0, %1, %2, lsl #16" : "=r" (out) : "r" (b), "r" (a)); return out; } */ #if defined (__ARM_ARCH_7EM__) // computes (((a[31:16] + b[31:16]) << 16) | (a[15:0 + b[15:0])) (saturates) static inline uint32_t signed_add_16_and_16(uint32_t a, uint32_t b) __attribute__((always_inline, unused)); static inline uint32_t signed_add_16_and_16(uint32_t a, uint32_t b) { int32_t out; asm volatile("qadd16 %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; } // computes (((a[31:16] - b[31:16]) << 16) | (a[15:0 - b[15:0])) (saturates) static inline int32_t signed_subtract_16_and_16(int32_t a, int32_t b) __attribute__((always_inline, unused)); static inline int32_t signed_subtract_16_and_16(int32_t a, int32_t b) { int32_t out; asm volatile("qsub16 %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; } // computes out = (((a[31:16]+b[31:16])/2) <<16) | ((a[15:0]+b[15:0])/2) static inline int32_t signed_halving_add_16_and_16(int32_t a, int32_t b) __attribute__((always_inline, unused)); static inline int32_t signed_halving_add_16_and_16(int32_t a, int32_t b) { int32_t out; asm volatile("shadd16 %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; } // computes out = (((a[31:16]-b[31:16])/2) <<16) | ((a[15:0]-b[15:0])/2) static inline int32_t signed_halving_subtract_16_and_16(int32_t a, int32_t b) __attribute__((always_inline, unused)); static inline int32_t signed_halving_subtract_16_and_16(int32_t a, int32_t b) { int32_t out; asm volatile("shsub16 %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; } // computes (sum + ((a[31:0] * b[15:0]) >> 16)) static inline int32_t signed_multiply_accumulate_32x16b(int32_t sum, int32_t a, uint32_t b) __attribute__((always_inline, unused)); static inline int32_t signed_multiply_accumulate_32x16b(int32_t sum, int32_t a, uint32_t b) { int32_t out; asm volatile("smlawb %0, %2, %3, %1" : "=r" (out) : "r" (sum), "r" (a), "r" (b)); return out; } // computes (sum + ((a[31:0] * b[31:16]) >> 16)) static inline int32_t signed_multiply_accumulate_32x16t(int32_t sum, int32_t a, uint32_t b) __attribute__((always_inline, unused)); static inline int32_t signed_multiply_accumulate_32x16t(int32_t sum, int32_t a, uint32_t b) { int32_t out; asm volatile("smlawt %0, %2, %3, %1" : "=r" (out) : "r" (sum), "r" (a), "r" (b)); return out; } // computes logical and, forces compiler to allocate register and use single cycle instruction static inline uint32_t logical_and(uint32_t a, uint32_t b) __attribute__((always_inline, unused)); static inline uint32_t logical_and(uint32_t a, uint32_t b) { asm volatile("and %0, %1" : "+r" (a) : "r" (b)); return a; } // computes ((a[15:0] * b[15:0]) + (a[31:16] * b[31:16])) static inline int32_t multiply_16tx16t_add_16bx16b(uint32_t a, uint32_t b) __attribute__((always_inline, unused)); static inline int32_t multiply_16tx16t_add_16bx16b(uint32_t a, uint32_t b) { int32_t out; asm volatile("smuad %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; } // computes ((a[15:0] * b[31:16]) + (a[31:16] * b[15:0])) static inline int32_t multiply_16tx16b_add_16bx16t(uint32_t a, uint32_t b) __attribute__((always_inline, unused)); static inline int32_t multiply_16tx16b_add_16bx16t(uint32_t a, uint32_t b) { int32_t out; asm volatile("smuadx %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; } // // computes sum += ((a[15:0] * b[15:0]) + (a[31:16] * b[31:16])) static inline int64_t multiply_accumulate_16tx16t_add_16bx16b(int64_t sum, uint32_t a, uint32_t b) { asm volatile("smlald %Q0, %R0, %1, %2" : "+r" (sum) : "r" (a), "r" (b)); return sum; } // // computes sum += ((a[15:0] * b[31:16]) + (a[31:16] * b[15:0])) static inline int64_t multiply_accumulate_16tx16b_add_16bx16t(int64_t sum, uint32_t a, uint32_t b) { asm volatile("smlaldx %Q0, %R0, %1, %2" : "+r" (sum) : "r" (a), "r" (b)); return sum; } // computes ((a[15:0] * b[15:0]) static inline int32_t multiply_16bx16b(uint32_t a, uint32_t b) __attribute__((always_inline, unused)); static inline int32_t multiply_16bx16b(uint32_t a, uint32_t b) { int32_t out; asm volatile("smulbb %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; } // computes ((a[15:0] * b[31:16]) static inline int32_t multiply_16bx16t(uint32_t a, uint32_t b) __attribute__((always_inline, unused)); static inline int32_t multiply_16bx16t(uint32_t a, uint32_t b) { int32_t out; asm volatile("smulbt %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; } // computes ((a[31:16] * b[15:0]) static inline int32_t multiply_16tx16b(uint32_t a, uint32_t b) __attribute__((always_inline, unused)); static inline int32_t multiply_16tx16b(uint32_t a, uint32_t b) { int32_t out; asm volatile("smultb %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; } // computes ((a[31:16] * b[31:16]) static inline int32_t multiply_16tx16t(uint32_t a, uint32_t b) __attribute__((always_inline, unused)); static inline int32_t multiply_16tx16t(uint32_t a, uint32_t b) { int32_t out; asm volatile("smultt %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; } // computes (a - b), result saturated to 32 bit integer range static inline int32_t substract_32_saturate(uint32_t a, uint32_t b) __attribute__((always_inline, unused)); static inline int32_t substract_32_saturate(uint32_t a, uint32_t b) { int32_t out; asm volatile("qsub %0, %1, %2" : "=r" (out) : "r" (a), "r" (b)); return out; } // Multiply two S.31 fractional integers, and return the 32 most significant // bits after a shift left by the constant z. // This comes from rockbox.org static inline int32_t FRACMUL_SHL(int32_t x, int32_t y, int z) { int32_t t, t2; asm ("smull %[t], %[t2], %[a], %[b]\n\t" "mov %[t2], %[t2], asl %[c]\n\t" "orr %[t], %[t2], %[t], lsr %[d]\n\t" : [t] "=&r" (t), [t2] "=&r" (t2) : [a] "r" (x), [b] "r" (y), [c] "Mr" ((z) + 1), [d] "Mr" (31 - (z))); return t; } #endif //get Q from PSR static inline uint32_t get_q_psr(void) __attribute__((always_inline, unused)); static inline uint32_t get_q_psr(void) { uint32_t out; asm ("mrs %0, APSR" : "=r" (out)); return (out & 0x8000000)>>27; } //clear Q BIT in PSR static inline void clr_q_psr(void) __attribute__((always_inline, unused)); static inline void clr_q_psr(void) { uint32_t t; asm ("mov %[t],#0\n" "msr APSR_nzcvq,%0\n" : [t] "=&r" (t)::"cc"); } #endif ================================================ FILE: lib/misc/euclidean.h ================================================ // Copyright (C)2023 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include #include // found here: // https://louridas.github.io/rwa/assignments/musical-rhythms/#toussaint:2005 // https://cgm.cs.mcgill.ca/~godfried/publications/banff.pdf // https://github.com/grindcode/rhythms/blob/main/src/lib.rs#L129 // https://github.com/computermusicdesign/euclidean-rhythm/blob/master/max-example/euclidSimple.js void simple_pattern(uint8_t *pattern, int len, int pulses, int rotate) { pulses = std::min(pulses, len); uint8_t bucket = 0; uint8_t offset = 2 + rotate; if (len > 0 && pulses > 0) offset += len / pulses - 1; for (uint8_t i = 0; i < len; i++) { uint8_t pos = (offset + i) % len; bucket += pulses; if (bucket >= len) { bucket -= len; pattern[pos] = 1; } else { pattern[pos] = 0; } } } // based on https://bitbucket.org/sjcastroe/bjorklunds-algorithm/src/master/Bjorklund's%20Algorithm/bjorklund.cpp void bjorklund_pattern(uint8_t *pattern, int len, int pulses, int rotate) { struct Pattern { uint32_t hits; size_t len; void append(const Pattern &second) { hits |= (second.hits << len); len += second.len; } }; if (pulses > len) pulses = len; Pattern x = {0x1, 1}; int x_amount = pulses; Pattern y = {0x0, 1}; int y_amount = len - pulses; do { int x_temp = x_amount; int y_temp = y_amount; Pattern y_copy = y; if (x_temp >= y_temp) { x_amount = y_temp; y_amount = x_temp - y_temp; y = x; } else { x_amount = x_temp; y_amount = y_temp - x_temp; } x.append(y_copy); } while (x_amount > 1 && y_amount > 1); int k = 0; for (int i = 1; i <= x_amount; i++) for (auto j = 0; j < x.len; j++) pattern[(k++ + rotate) % len] = (x.hits & (0x1 << j)); for (int i = 1; i <= y_amount; i++) for (auto j = 0; j < y.len; j++) pattern[(k++ + rotate) % len] = (y.hits & (0x1 << j)); } #ifndef make_pattern #define make_pattern bjorklund_pattern #endif ================================================ FILE: lib/misc/nes_noise.hxx ================================================ // Copyright (C)2023 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // For details see: // https://www.nesdev.org/wiki/APU_Noise #include constexpr float clock_NTSC = 1789773.f; constexpr float clock_PAL = 1662607.f; class NESNoise { public: NESNoise() { mode_bit = 1; period_index = 8; shift_reg = 1 | (uint32_t)this; } void init(uint16_t shift_reg = 1, uint8_t mode_bit = 1, uint8_t period_index = 8) { this->mode_bit = mode_bit; this->period_index = period_index; this->shift_reg = shift_reg; } template T generateSample(T level) { while (true) { tick++; sampling -= 1.f; if (sampling < 0) { if (ntsc) sampling += (clock_NTSC / samplerate); else sampling += (clock_PAL / samplerate); return (shift_reg & 0x1) ? 0 : level; } if ((tick % 2) == 0) { if (timer_counter > 0) { timer_counter--; } else { if (ntsc) timer_counter = periodLookup_NTSC[period_index % 16]; else timer_counter = periodLookup_PAL[period_index % 16]; uint32_t feedback = 1 & ((shift_reg & 0x0001) ^ ((mode_bit == 0) ? ((shift_reg >> 6) & 0x0001) : ((shift_reg >> 1) & 0x0001))); shift_reg >>= 1; shift_reg |= (feedback << 14); } } } return 0; } uint8_t mode_bit; uint8_t period_index; uint16_t shift_reg; private: uint16_t timer_counter = 0; float sampling = 0; uint32_t tick = 0; const uint16_t periodLookup_NTSC[16] = {4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068}; const uint16_t periodLookup_PAL[16] = {4, 8, 14, 30, 60, 88, 118, 148, 188, 236, 354, 472, 708, 944, 1890, 3778}; }; ================================================ FILE: lib/misc/noise.hxx ================================================ // Copyright (C)2021 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #pragma once #include // 31-bit Park-Miller-Carta Pseudo-Random Number Generator // http://www.firstpr.com.au/dsp/rand31/ struct WhiteNoise { uint32_t seed; WhiteNoise() { seed = (uint32_t)(void *)this; } int32_t next() // 0 to INT32_MAX { uint32_t lo, hi; lo = seed; hi = 16807 * (lo >> 16); lo = 16807 * (lo & 0xFFFF); lo += (hi & 0x7FFF) << 16; lo += hi >> 15; lo = (lo & 0x7FFFFFFF) + (lo >> 31); seed = lo; return (int32_t)lo; } float nextf(float min, float max) { return ((float)next() / INT32_MAX) * (max - min) + min; } }; struct BrownNoise { WhiteNoise _white; float out = 0; void init() { out = 0; } float nextf(float min, float max) { float white = _white.nextf(-1, +1); // MoogLadders -> BrowningFilter this->out = (this->out + 0.02f * white) / 1.02f; return this->out * (max - min) + min; } }; /** Based on "The Voss algorithm" http://www.firstpr.com.au/dsp/pink-noise/ */ template struct PinkNoise { WhiteNoise white; int key = 0; float values[N] = {}; float nextf(float min, float max) { int last_key = key; key++; if (key > (0x1 << N)) key = 0; // Exclusive-Or previous value with current value. This gives // a list of bits that have changed. int diff = last_key ^ key; float sum = 0.f; for (int i = 0; i < N; i++) { if (diff & (1 << i)) { values[i] = white.nextf(min, max) / N; } sum += values[i]; } return sum; } }; ================================================ FILE: lib/misc/patterns_303.h ================================================ #include constexpr uint8_t REST = 0x0; /* between 0x0 and 0xA, the VCO voltage pins, so these notes arent really * 'effective' in that they all sound the same. */ // lowest octave constexpr uint8_t C1 = 0x0B; constexpr uint8_t C1_SHARP = 0x0C; constexpr uint8_t D1 = 0x0D; constexpr uint8_t D1_SHARP = 0x0E; constexpr uint8_t E1 = 0x0F; constexpr uint8_t F1 = 0x10; constexpr uint8_t F1_SHARP = 0x11; constexpr uint8_t G1 = 0x12; constexpr uint8_t G1_SHARP = 0x13; // middle octave constexpr uint8_t A1 = 0x14; constexpr uint8_t A1_SHARP = 0x15; constexpr uint8_t B1 = 0x16; constexpr uint8_t C2 = 0x17; constexpr uint8_t C2_SHARP = 0x18; constexpr uint8_t D2 = 0x19; constexpr uint8_t D2_SHARP = 0x1A; constexpr uint8_t E2 = 0x1B; constexpr uint8_t F2 = 0x1C; constexpr uint8_t F2_SHARP = 0x1D; constexpr uint8_t G2 = 0x1E; constexpr uint8_t G2_SHARP = 0x1F; // high octave constexpr uint8_t A2 = 0x20; constexpr uint8_t A2_SHARP = 0x21; constexpr uint8_t B2 = 0x22; constexpr uint8_t C3 = 0x23; constexpr uint8_t C3_SHARP = 0x24; constexpr uint8_t D3 = 0x25; constexpr uint8_t D3_SHARP = 0x26; constexpr uint8_t E3 = 0x27; constexpr uint8_t F3 = 0x28; constexpr uint8_t F3_SHARP = 0x29; constexpr uint8_t G3 = 0x2A; constexpr uint8_t G3_SHARP = 0x2B; constexpr uint8_t A3 = 0x2C; constexpr uint8_t A3_SHARP = 0x2D; constexpr uint8_t B3 = 0x2E; constexpr uint8_t C4 = 0x2F; constexpr uint8_t C4_SHARP = 0x30; constexpr uint8_t D4 = 0x31; constexpr uint8_t D4_SHARP = 0x32; constexpr uint8_t E4 = 0x33; constexpr uint8_t F4 = 0x34; constexpr uint8_t F4_SHARP = 0x35; constexpr uint8_t G4 = 0x36; constexpr uint8_t G4_SHARP = 0x37; constexpr uint8_t A4 = 0x38; constexpr uint8_t A4_SHARP = 0x39; constexpr uint8_t B4 = 0x3A; constexpr uint8_t C5 = 0x3B; constexpr uint8_t C5_SHARP = 0x3C; constexpr uint8_t D5 = 0x3D; constexpr uint8_t D5_SHARP = 0x3E; // no more notes! constexpr uint8_t NOTE_MASK = 0x3F; constexpr uint8_t SLIDE = 0x80; constexpr uint8_t ACCENT = 0x40; //"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" // Daft Punk - Da Funk const uint8_t da_funk[16] = {A2_SHARP, F4, D3 | SLIDE, C5, A3_SHARP | SLIDE | ACCENT, G3, F2_SHARP | SLIDE | ACCENT, G3_SHARP, A4_SHARP | SLIDE, A2, C4 | SLIDE, D4 | SLIDE | ACCENT, F3, D3 | SLIDE, F2 | SLIDE, D3_SHARP | SLIDE}; //Copyright, see: https://modwiggler.com/forum/viewtopic.php?t=156515 const uint8_t x0xb0x_patterns[][16] = { {0xD5,0x15,0xD5,0x15,0x15,0x21,0x95,0x15,0x52,0x55,0x15,0x15,0xE1,0x21,0x95,0x15}, //PAT 00 0 = GGGG GGGG GGGG GGGG a#_DAS a#_D__ a#_DAS a#_D__ a#_D__ a#____ a#_D_S a#_D__ g _DA_ a#_DA_ a#_D__ a#_D__ a#__AS a#____ a#_D_S a#_D__ {0x97,0x17,0x97,0x17,0x95,0x95,0x95,0x15,0x97,0x97,0x17,0x55,0x15,0xD7,0x17,0x55}, //PAT 00 1 = GGGG GGGG GGGG GGGG c ___S c ____ c ___S c ____ a#_D_S a#_D_S a#_D_S a#_D__ c ___S c ___S c ____ a#_DA_ a#_D__ c __AS c ____ a#_DA_ {0x1E,0x2D,0xAA,0x28,0xE6,0x58,0xD7,0x64,0xA6,0x1A,0xA8,0xEA,0x21,0x9E,0x97,0xAF}, //PAT 00 2 = GGGG GGGG GGGG GGGG g ____ a#U___ g U__S f U___ d#U_AS c#__A_ c __AS c#U_A_ d#U__S d#____ f U__S g U_AS a#____ g ___S c ___S C'U__S {0xD7,0x23,0x17,0x17,0x17,0x5A,0x17,0x17,0xA3,0x2F,0x17,0x18,0x17,0x66,0x1A,0x58}, //PAT 00 3 = GGGG GGGG GGGG GGGG c __AS C'____ c ____ c ____ c ____ d#__A_ c ____ c ____ C'___S C'U___ c ____ c#____ c ____ d#U_A_ d#____ c#__A_ {0xE0,0x00,0x20,0x14,0x00,0x58,0x20,0x14,0x20,0x00,0x20,0xAA,0x00,0x20,0xD8,0x00}, //PAT 00 4 = G-GG -GGG G-GG -GG- a __AS a ____ a _D__ c#__A_ a ____ a _D__ a ____ a ____ g U__S a ____ c#__AS c#____ c ____ d#U_A_ d#____ c#__A_ {0xDA,0x5A,0x58,0x5A,0x5F,0x5A,0x66,0x5A,0x64,0x5A,0x69,0x5A,0x61,0x64,0x66,0x6A}, //PAT 00 5 = GGGG GGGG GGGG GGGG d#__AS d#__A_ c#__A_ d#__A_ g#__A_ d#__A_ d#U_A_ d#__A_ c#U_A_ d#__A_ f#U_A_ d#__A_ a#__A_ c#U_A_ d#U_A_ g U_A_ {0x57,0x00,0x17,0x58,0x00,0x17,0x17,0x00,0x57,0x17,0x18,0x17,0x00,0x17,0x17,0x00}, //PAT 00 6 = G-GG -GG- GGGG -GG- c __A_ c ____ c#__A_ c ____ c ____ c __A_ c ____ c#____ c ____ c ____ c ____ d#__A_ a#__A_ c#U_A_ d#U_A_ g U_A_ {0x0C,0x24,0x0C,0x21,0xAC,0x20,0x4C,0x61,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //PAT 00 7 = GGGG GGGG c#_D__ c#U___ c#_D__ a#____ a U__S a ____ c#_DA_ a#__A_ {0x9E,0x9E,0x1E,0x1E,0x00,0x12,0x1E,0x00,0x21,0x00,0x95,0x15,0x15,0x21,0x00,0x15}, //PAT 01 0 = GGGG -GG- G-GG GG-G g ___S g ___S g ____ g ____ g _D__ g ____ a#____ a#_D_S a#_D__ a#_D__ a#____ a#_D__ a#__A_ c#U_A_ d#U_A_ g U_A_ {0xE0,0x56,0x16,0xE2,0x60,0x5F,0x11,0x16,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //PAT 01 1 = GGGG GGGG a __AS b _DA_ b _D__ b __AS a __A_ g#__A_ f#_D__ b _D__ {0x16,0x93,0x13,0x16,0x96,0x16,0x13,0x96,0x96,0x16,0x16,0x16,0x13,0xAE,0xAE,0x2E}, //PAT 01 2 = GGGG GGGG GGGG GGGG b _D__ g#_D_S g#_D__ b _D__ b _D_S b _D__ g#_D__ b _D_S b _D_S b _D__ b _D__ b _D__ g#_D__ b U__S b U__S b U___ {0x9D,0x9D,0x9D,0x5D,0x5D,0x00,0x5D,0xDD,0x1D,0x1D,0x5D,0x11,0xE9,0x29,0x1D,0x11}, //PAT 01 3 = GGGG G-GG GGGG GGGG f#___S f#___S f#___S f#__A_ f#__A_ f#__A_ f#__AS f#____ f#____ f#__A_ f#_D__ f#U_AS f#U___ f#____ f#_D__ b U___ {0xD1,0xD1,0x00,0x91,0x00,0x00,0xD1,0x5D,0x5D,0x5D,0x00,0x9D,0x00,0x5D,0xDD,0x1D}, //PAT 01 4 = GG-G --GG GG-G -GGG f#_DAS f#_DAS f#_D_S f#_DAS f#__A_ f#__A_ f#__A_ f#___S f#__A_ f#__AS f#____ f#U_AS f#U___ f#____ f#_D__ b U___ {0xDE,0x5E,0xDE,0xDE,0x5E,0x5E,0x62,0x5E,0x62,0xDE,0x5E,0x22,0xDE,0xDE,0x5E,0x62}, //PAT 01 5 = GGGG GGGG GGGG GGGG g __AS g __A_ g __AS g __AS g __A_ g __A_ b __A_ g __A_ b __A_ g __AS g __A_ b ____ g __AS g __AS g __A_ b __A_ {0xD4,0x94,0x14,0x94,0xA5,0x25,0xA7,0x27,0x27,0xEA,0x2A,0x25,0xFF,0xFF,0xFF,0xFF}, //PAT 01 6 = GGGG GGGG GGGG a _DAS a _D_S a _D__ a _D_S d U__S d U___ e U__S e U___ e U___ g U_AS g U___ d U___ {0x91,0x91,0x5D,0xD1,0x11,0x25,0xA6,0x26,0x27,0xEA,0x2A,0x20,0xFF,0xFF,0xFF,0xFF}, //PAT 01 7 = GGGG GGGG GGGG f#_D_S f#_D_S f#__A_ f#_DAS f#_D__ d U___ d#U__S d#U___ e U___ g U_AS g U___ a ____ {0x23,0x22,0xD7,0x17,0x97,0x17,0xD9,0x19,0x9B,0x1B,0xDC,0x1C,0x9C,0x1C,0xDC,0x1C}, //PAT 02 0 = GGGG GGGG GGGG GGGG C'____ b ____ c __AS c ____ c ___S c ____ d __AS d ____ e ___S e ____ f __AS f ____ f ___S f ____ f __AS f ____ {0x97,0x17,0xE3,0x23,0xA3,0xA3,0x23,0x2D,0x97,0x17,0x17,0x9E,0xAA,0x17,0x2D,0x2A}, //PAT 02 1 = GGGG GGGG GGGG GGGG c ___S c ____ C'__AS C'____ C'___S C'___S C'____ a#U___ c ___S c ____ c ____ g ___S g U__S c ____ a#U___ g U___ {0x63,0x63,0x57,0x57,0x23,0xCB,0x4B,0x63,0x23,0xD7,0x0B,0xE3,0x63,0x23,0xAD,0xA3}, //PAT 02 2 = GGGG GGGG GGGG GGGG C'__A_ C'__A_ c __A_ c __A_ C'____ c _DAS c _DA_ C'__A_ C'____ c __AS c _D__ C'__AS C'__A_ C'____ a#U__S C'___S {0x19,0x19,0xDC,0x1C,0xDC,0x1C,0x1B,0x9C,0x1B,0x1B,0xDC,0x1C,0xDC,0x1C,0x1B,0x9C}, //PAT 02 3 = GGGG GGGG GGGG GGGG d ____ d ____ f __AS f ____ f __AS f ____ e ____ f ___S e ____ e ____ f __AS f ____ f __AS f ____ e ____ f ___S {0x54,0x20,0x20,0x20,0x14,0x20,0x54,0x20,0x14,0x20,0x12,0x5E,0x2A,0x1E,0x52,0x5E}, //PAT 02 4 = GGGG GGGG GGGG GGGG a _DA_ a ____ a ____ a ____ a _D__ a ____ a _DA_ a ____ a _D__ a ____ g _D__ g __A_ g U___ g ____ g _DA_ g __A_ {0x96,0x16,0x96,0x16,0x16,0x18,0x1A,0x16,0x96,0x16,0x94,0x94,0xAC,0xAC,0xAC,0x2C}, //PAT 02 5 = GGGG GGGG GGGG GGGG b _D_S b _D__ b _D_S b _D__ b _D__ c#____ d#____ b _D__ b _D_S b _D__ a _D_S a _D_S a U__S a U__S a U__S a U___ {0x53,0x53,0x53,0x9F,0x93,0x9F,0x93,0x9F,0x8B,0x6C,0xEC,0x6C,0x14,0x6C,0x6C,0x6C}, //PAT 02 6 = GGGG GGGG GGGG GGGG g#_DA_ g#_DA_ g#_DA_ g#___S g#_D_S g#___S g#_D_S g#___S c _D_S a U_A_ a U_AS a U_A_ a _D__ a U_A_ a U_A_ a U_A_ {0x66,0x29,0x24,0x1C,0x17,0x28,0x19,0x18,0x96,0x9F,0x95,0xA2,0x93,0x15,0x9F,0x9F}, //PAT 02 7 = GGGG GGGG GGGG GGGG d#U_A_ f#U___ c#U___ f ____ c ____ f U___ d ____ c#____ b _D_S g#___S a#_D_S b ___S g#_D_S a#_D__ g#___S g#___S {0xDA,0x9A,0x1A,0xDA,0x9A,0x1A,0xD8,0x98,0x18,0xDF,0x9F,0x1F,0xDD,0x9D,0x1D,0x00}, //PAT 03 0 = GGGG GGGG GGGG GGG- d#__AS d#___S d#____ d#__AS d#___S d#____ c#__AS c#___S c#____ g#__AS g#___S g#____ f#__AS f#___S f#____ g#___S {0x55,0x92,0x12,0x12,0x55,0x12,0xD5,0x15,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //PAT 03 1 = GGGG GGGG a#_DA_ g _D_S g _D__ g _D__ a#_DA_ g _D__ a#_DAS a#_D__ {0x14,0x99,0x19,0x17,0x97,0x97,0x17,0x9F,0x9F,0x1F,0x1D,0xA1,0x21,0xE2,0xA2,0x22}, //PAT 03 2 = GGGG GGGG GGGG GGGG a _D__ d ___S d ____ c ____ c ___S c ___S c ____ g#___S g#___S g#____ f#____ a#___S a#____ b __AS b ___S b ____ {0x97,0x17,0x8B,0xD7,0x23,0x63,0x23,0x23,0xD7,0x23,0x17,0x5C,0x9C,0x25,0x5C,0x5C}, //PAT 03 3 = GGGG GGGG GGGG GGGG c ___S c ____ c _D_S c __AS C'____ C'__A_ C'____ C'____ c __AS C'____ c ____ f __A_ f ___S d U___ f __A_ f __A_ {0x9C,0x9C,0x1C,0x1C,0x00,0x90,0x10,0x5C,0x5C,0x9A,0x8E,0x1A,0xA6,0x28,0x6B,0x68}, //PAT 03 4 = GGGG -GGG GGGG GGGG f ___S f ___S f ____ f ____ f _D_S f _D__ f __A_ f __A_ d#___S d#_D_S d#____ d#U__S f U___ g#U_A_ f U_A_ f __A_ {0x63,0xAF,0x2F,0x17,0xEF,0x97,0x0B,0x23,0x1A,0x25,0x6D,0xA6,0x17,0x6D,0x9A,0x26}, //PAT 03 5 = GGGG GGGG GGGG GGGG C'__A_ C'U__S C'U___ c ____ C'U_AS c ___S c _D__ C'____ d#____ d U___ a#U_A_ d#U__S c ____ a#U_A_ d#___S d#U___ {0x57,0x17,0x0B,0x57,0x2F,0x23,0x57,0x0B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //PAT 03 6 = GGGG GGGG c __A_ c ____ c _D__ c __A_ C'U___ C'____ c __A_ c _D__ {0x8F,0x5B,0x1B,0x67,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //PAT 03 7 = GGGG e _D_S e __A_ e ____ e U_A_ {0x19,0x00,0x1B,0x1B,0x1B,0x99,0x19,0x94,0x14,0x14,0x14,0x00,0x94,0x14,0x12,0x14}, //PAT 04 0 = G-GG GGGG GGG- GGGG d ____ e ____ e ____ e ____ d ___S d ____ a _D_S a _D__ a _D__ a _D__ a _D_S a _D__ g _D__ a _D__ d#___S d#U___ {0x9B,0x1B,0x9E,0x1E,0x9E,0x1E,0x1B,0x1E,0x1B,0x1B,0x9B,0x1B,0x1E,0x52,0x1B,0x1E}, //PAT 04 1 = GGGG GGGG GGGG GGGG e ___S e ____ g ___S g ____ g ___S g ____ e ____ g ____ e ____ e ____ e ___S e ____ g ____ g _DA_ e ____ g ____ {0x1A,0x1A,0x1A,0x1A,0x21,0x24,0x9A,0x1A,0x9A,0x1A,0x26,0x9A,0x1A,0x13,0x98,0x1F}, //PAT 04 2 = GGGG GGGG GGGG GGGG d#____ d#____ d#____ d#____ a#____ c#U___ d#___S d#____ d#___S d#____ d#U___ d#___S d#____ g#_D__ c#___S g#____ {0x1B,0x20,0x9B,0x1B,0xA7,0xA7,0x27,0xA0,0x20,0x94,0x14,0x1B,0xA0,0xA0,0xA0,0x20}, //PAT 04 3 = GGGG GGGG GGGG GGGG e ____ a ____ e ___S e ____ e U__S e U__S e U___ a ___S a ____ a _D_S a _D__ e ____ a ___S a ___S a ___S a ____ {0xD4,0x14,0xE0,0x20,0xD9,0x99,0x99,0x19,0xD9,0x99,0x19,0xD4,0x14,0xE5,0x25,0x14}, //PAT 04 4 = GGGG GGGG GGGG GGGG a _DAS a _D__ a __AS a ____ d __AS d ___S d ___S d ____ d __AS d ___S d ____ a _DAS a _D__ d U_AS d U___ a _D__ {0x57,0x17,0x9C,0x1C,0x97,0x17,0xD7,0x17,0x1C,0x1C,0x97,0x17,0xE3,0x23,0xDC,0x1C}, //PAT 04 5 = GGGG GGGG GGGG GGGG c __A_ c ____ f ___S f ____ c ___S c ____ c __AS c ____ f ____ f ____ c ___S c ____ C'__AS C'____ f __AS f ____ {0xD7,0x17,0x17,0xE3,0xA3,0xA3,0x23,0xD7,0x97,0x97,0x97,0x17,0xA3,0x23,0xA3,0x23}, //PAT 04 6 = GGGG GGGG GGGG GGGG c __AS c ____ c ____ C'__AS C'___S C'___S C'____ c __AS c ___S c ___S c ___S c ____ C'___S C'____ C'___S C'____ {0xEE,0x2E,0x28,0x6E,0xAF,0xAE,0xAF,0x1C,0x16,0x60,0xE0,0x20,0x22,0x22,0x96,0x16}, //PAT 04 7 = GGGG GGGG GGGG GGGG b U_AS b U___ f U___ b U_A_ C'U__S b U__S C'U__S f ____ b _D__ a __A_ a __AS a ____ b ____ b ____ b _D_S b _D__ {0x1E,0x20,0x20,0x1E,0x1E,0x20,0x2C,0x24,0x1E,0x9E,0xA0,0x14,0x97,0x17,0x9E,0x1E}, //PAT 05 0 = GGGG GGGG GGGG GGGG g ____ a ____ a ____ g ____ g ____ a ____ a U___ c#U___ g ____ g ___S a ___S a _D__ c ___S c ____ g ___S g ____ {0x12,0x52,0xD7,0x97,0x97,0x17,0xD7,0x97,0x97,0x17,0xD7,0x17,0xD9,0x19,0x00,0x00}, //PAT 05 1 = GGGG GGGG GGGG GG-- g _D__ g _DA_ c __AS c ___S c ___S c ____ c __AS c ___S c ___S c ____ c __AS c ____ d __AS d ____ g ___S g ____ {0x14,0x14,0x20,0x20,0x10,0x10,0xA0,0x20,0x20,0x00,0x14,0xD4,0x14,0x14,0xD4,0x14}, //PAT 05 2 = GGGG GGGG G-GG GGGG a _D__ a _D__ a ____ a ____ f _D__ f _D__ a ___S a ____ a ____ a _D__ a _DAS a _D__ a _D__ a _DAS a _D__ g ____ {0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,0x9A,0x1A,0xE1,0x21,0xDF,0x1F,0x1A,0x1A,0x5A,0x1A}, //PAT 05 3 = GGGG GGGG GGGG GGGG d#____ d#____ d#____ d#____ d#____ d#____ d#___S d#____ a#__AS a#____ g#__AS g#____ d#____ d#____ d#__A_ d#____ {0x57,0x16,0xA2,0x22,0x16,0x94,0x16,0x14,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //PAT 05 4 = GGGG GGGG c __A_ b _D__ b ___S b ____ b _D__ a _D_S b _D__ a _D__ {0xE8,0x28,0x68,0xE8,0xA8,0xA8,0x8C,0x8C,0x8C,0x8C,0x8F,0x8F,0x0F,0x1B,0x9D,0x1D}, //PAT 05 5 = GGGG GGGG GGGG GGGG f U_AS f U___ f U_A_ f U_AS f U__S f U__S c#_D_S c#_D_S c#_D_S c#_D_S e _D_S e _D_S e _D__ e ____ f#___S f#____ {0xD1,0x91,0x91,0x8F,0x8D,0x0B,0x9B,0x9B,0x9B,0x1B,0xDD,0x1D,0xDD,0x9D,0x9D,0x1D}, //PAT 05 6 = GGGG GGGG GGGG GGGG f#_DAS f#_D_S f#_D_S e _D_S d _D_S c _D__ e ___S e ___S e ___S e ____ f#__AS f#____ f#__AS f#___S f#___S f#____ {0x98,0x18,0x98,0x18,0x9C,0x1C,0x18,0x1C,0x98,0x18,0x98,0x18,0x9C,0x1C,0x18,0x5C}, //PAT 05 7 = GGGG GGGG GGGG GGGG c#___S c#____ c#___S c#____ f ___S f ____ c#____ f ____ c#___S c#____ c#___S c#____ f ___S f ____ c#____ f __A_ {0x99,0x19,0x19,0x19,0xEF,0x2F,0x19,0x0D,0xAF,0x2F,0x19,0x0D,0x57,0x59,0x59,0x59}, //PAT 06 0 = GGGG GGGG GGGG GGGG d ___S d ____ d ____ d ____ C'U_AS C'U___ d ____ d _D__ C'U__S C'U___ d ____ d _D__ c __A_ d __A_ d __A_ d __A_ {0xD2,0x12,0x1E,0xDE,0x1E,0xDE,0x1E,0x1E,0x92,0x9E,0x9E,0x9E,0x12,0x9E,0x1E,0x12}, //PAT 06 1 = GGGG GGGG GGGG GGGG g _DAS g _D__ g ____ g __AS g ____ g __AS g ____ g ____ g _D_S g ___S g ___S g ___S g _D__ g ___S g ____ g _D__ {0x99,0x19,0x99,0x19,0xD7,0x17,0x57,0x17,0xE3,0x23,0xA3,0x17,0x63,0x23,0x65,0x25}, //PAT 06 2 = GGGG GGGG GGGG GGGG d ___S d ____ d ___S d ____ c __AS c ____ c __A_ c ____ C'__AS C'____ C'___S c ____ C'__A_ C'____ d U_A_ d U___ {0x1E,0x1E,0x1E,0x1E,0xDE,0x9E,0x99,0x99,0x92,0x92,0x92,0x92,0x92,0x8F,0x8F,0x5E}, //PAT 06 3 = GGGG GGGG GGGG GGGG g ____ g ____ g ____ g ____ g __AS g ___S d ___S d ___S g _D_S g _D_S g _D_S g _D_S g _D_S e _D_S e _D_S g __A_ {0x92,0x12,0x9E,0x1E,0x1E,0x92,0x12,0x1E,0x9E,0x1E,0x9E,0x1E,0x92,0x92,0x9E,0x1E}, //PAT 06 4 = GGGG GGGG GGGG GGGG g _D_S g _D__ g ___S g ____ g ____ g _D_S g _D__ g ____ g ___S g ____ g ___S g ____ g _D_S g _D_S g ___S g ____ {0x1E,0x1C,0x9E,0x1E,0x9E,0x1E,0x1C,0x9E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //PAT 06 5 = GGGG GGGG g ____ f ____ g ___S g ____ g ___S g ____ f ____ g ___S {0xA4,0x24,0x2F,0xAA,0x1E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //PAT 06 6 = GGGG G c#U__S c#U___ C'U___ g U__S g ____ {0x20,0x22,0x8F,0x8F,0xA3,0x23,0xDF,0x9F,0x8F,0x8F,0x29,0xAB,0x2B,0x29,0xA8,0x0F}, //PAT 06 7 = GGGG GGGG GGGG GGGG a ____ b ____ e _D_S e _D_S C'___S C'____ g#__AS g#___S e _D_S e _D_S f#U___ g#U__S g#U___ f#U___ f U__S e _D__ {0x24,0x96,0x16,0x97,0x97,0x17,0x00,0x1B,0x1B,0x1C,0x2B,0x29,0x28,0xA9,0xA9,0x29}, //PAT 07 0 = GGGG GG-G GGGG GGGG c#U___ b _D_S b _D__ c ___S c ___S c ____ e ____ e ____ f ____ g#U___ f#U___ f U___ f#U__S f#U__S f#U___ e _D__ {0x9F,0x9F,0x9F,0x1F,0x97,0x17,0x97,0x17,0x99,0x19,0x99,0x19,0x2B,0xAB,0xAB,0xAB}, //PAT 07 1 = GGGG GGGG GGGG GGGG g#___S g#___S g#___S g#____ c ___S c ____ c ___S c ____ d ___S d ____ d ___S d ____ g#U___ g#U__S g#U__S g#U__S {0x94,0x94,0x97,0x17,0xDC,0x1C,0xDA,0x1A,0x9C,0x9C,0x9C,0x1C,0x1A,0x9E,0xDE,0x1C}, //PAT 07 2 = GGGG GGGG GGGG GGGG a _D_S a _D_S c ___S c ____ f __AS f ____ d#__AS d#____ f ___S f ___S f ___S f ____ d#____ g ___S g __AS f ____ {0xA6,0xA6,0x16,0x1A,0x26,0xA7,0x18,0xA0,0x90,0x10,0x17,0x14,0x91,0x91,0x94,0x94}, //PAT 07 3 = GGGG GGGG GGGG GGGG d#U__S d#U__S b _D__ d#____ d#U___ e U__S c#____ a ___S f _D_S f _D__ c ____ a _D__ f#_D_S f#_D_S a _D_S a _D_S {0x8E,0x0E,0x18,0x9A,0x1A,0x98,0x18,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //PAT 07 4 = GGGG GGGG d#_D_S d#_D__ c#____ d#___S d#____ c#___S c#____ g#____ {0x1B,0x99,0x19,0x1B,0x99,0x19,0x1B,0x99,0x19,0x1B,0x99,0x19,0xFF,0xFF,0xFF,0xFF}, //PAT 07 5 = GGGG GGGG GGGG e ____ d ___S d ____ e ____ d ___S d ____ e ____ d ___S d ____ e ____ d ___S d ____ {0x67,0x67,0xA7,0x27,0xE7,0x27,0x67,0x27,0x9B,0x9B,0x8F,0x8F,0x8F,0x8F,0x8F,0x8F}, //PAT 07 6 = GGGG GGGG GGGG GGGG e U_A_ e U_A_ e U__S e U___ e U_AS e U___ e U_A_ e U___ e ___S e ___S e _D_S e _D_S e _D_S e _D_S e _D_S e _D_S {0x00,0xA0,0xA0,0x20,0x00,0x00,0x57,0x00,0x20,0x00,0x20,0x00,0x20,0x25,0x67,0x2A}, //PAT 14 0 = -GGG --G- G-G- GGGG a ___S a ___S a ____ c __A_ a ____ a ____ a ____ d U___ e U_A_ g U___ e _D_S e _D_S e _D_S e _D_S e _D_S e _D_S {0x00,0x5E,0x00,0x21,0x00,0x00,0x00,0x21,0x00,0xAD,0x2D,0x2D,0x1F,0x00,0x2D,0x00}, //PAT 14 1 = -G-G ---G -GGG G-G- g __A_ a#____ a#____ a#U__S a#U___ a#U___ g#____ a#U___ e U_A_ g U___ e _D_S e _D_S e _D_S e _D_S e _D_S e _D_S {0xD9,0x19,0x58,0x59,0x5E,0x59,0x65,0x59,0x64,0x59,0x68,0x59,0x60,0x64,0x65,0x64}, //PAT 15 0 = GGGG GGGG GGGG GGGG d __AS d ____ c#__A_ d __A_ g __A_ d __A_ d U_A_ d __A_ c#U_A_ d __A_ f U_A_ d __A_ a __A_ c#U_A_ d U_A_ c#U_A_ {0x9E,0x12,0x9E,0x9E,0x1E,0x1E,0x22,0x1E,0x22,0x9E,0x1E,0x22,0x9E,0x9E,0x1E,0x22}, //PAT 15 1 = GGGG GGGG GGGG GGGG g ___S g _D__ g ___S g ___S g ____ g ____ b ____ g ____ b ____ g ___S g ____ b ____ g ___S g ___S g ____ b ____ {0x17,0xA4,0x97,0x17,0xA7,0x9B,0x1B,0x1A,0xA6,0xA4,0x1A,0x1A,0x1A,0x1A,0x1B,0x17}, //PAT 15 2 = GGGG GGGG GGGG GGGG c ____ c#U__S c ___S c ____ e U__S e ___S e ____ d#____ d#U__S c#U__S d#____ d#____ d#____ d#____ e ____ c ____ {0x18,0x18,0x17,0x0B,0x24,0x17,0x29,0x0B,0x1D,0x17,0x18,0x18,0x17,0x17,0x18,0x18}, //PAT 15 3 = GGGG GGGG GGGG GGGG c#____ c#____ c ____ c _D__ c#U___ c ____ f#U___ c _D__ f#____ c ____ c#____ c#____ c ____ c ____ c#____ c#____ {0x1C,0x9D,0x1D,0x1D,0xA9,0x18,0xA9,0xA8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //PAT 15 4 = GGGG GGGG f ____ f#___S f#____ f#____ f#U__S c#____ f#U__S f U__S {0x26,0x25,0x24,0x25,0xA7,0x9B,0x1B,0xA6,0x98,0x26,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //PAT 15 5 = GGGG GGGG GG d#U___ d U___ c#U___ d U___ e U__S e ___S e ____ d#U__S c#___S d#U___ {0x95,0x15,0xA1,0x21,0x90,0x10,0x9C,0x1C,0x9F,0x1F,0x1C,0x9F,0x1F,0x1C,0xA1,0x21}, //PAT 15 6 = GGGG GGGG GGGG GGGG a#_D_S a#_D__ a#___S a#____ f _D_S f _D__ f ___S f ____ g#___S g#____ f ____ g#___S g#____ f ____ a#___S a#____ {0xA1,0x21,0xA1,0x21,0xA1,0x21,0x99,0x19,0x9A,0x1A,0x9B,0x1B,0x9C,0x1C,0x9C,0x9C}, //PAT 15 7 = GGGG GGGG GGGG GGGG a#___S a#____ a#___S a#____ a#___S a#____ d ___S d ____ d#___S d#____ e ___S e ____ f ___S f ____ f ___S f ___S // --- GENERATED BY CHATGPT - ADDITIONAL ACID PATTERNS --- {0xD5,0x95,0x15,0xA5,0x15,0xD7,0x97,0x17,0xD5,0x95,0x15,0xA5,0x17,0x97,0xD5,0x15}, // PAT 16 0 – Acid Tracks style rolling A# {0x9E,0x1E,0x9E,0xDE,0x1E,0x9E,0x92,0x12,0x9E,0x1E,0x9E,0xDE,0x92,0x12,0x9E,0x1E}, // PAT 16 1 – Wink style G minor pulse {0xA3,0x23,0xE3,0x63,0x23,0xA3,0x2F,0xAF,0xA3,0x23,0xE3,0x63,0xAF,0x2F,0x23,0xA3}, // PAT 16 2 – Hardfloor octave bounce {0x1A,0x9A,0xDA,0x5A,0x1A,0x9A,0xD8,0x98,0x1A,0x9A,0xDA,0x5A,0x98,0x18,0x1A,0x9A}, // PAT 16 3 – Armando style D# riff {0x97,0x17,0x57,0x17,0x97,0xD7,0x17,0x97,0x17,0x57,0x17,0x97,0xD7,0x17,0x97,0x17}, // PAT 17 0 – Pierre style C loop {0xE8,0xA8,0x68,0xE8,0x8C,0x8C,0x8F,0x0F,0xE8,0xA8,0x68,0xE8,0x8F,0x0F,0x8C,0x8C}, // PAT 17 1 – Plastikman low F grind {0x12,0x92,0x12,0xDE,0x1E,0x92,0x12,0x1E,0x12,0x92,0x12,0xDE,0x92,0x12,0x1E,0x12}, // PAT 17 2 – Minimal G modulation {0x63,0x23,0xD7,0x97,0x23,0x63,0xA3,0x23,0x63,0x23,0xD7,0x97,0xA3,0x23,0x63,0x23}, // PAT 17 3 – C/C' octave stab {0x95,0x15,0xA1,0x21,0x90,0x10,0x9C,0x1C,0x9F,0x1F,0x1C,0x9F,0x1F,0x1C,0xA1,0x21}, // PAT 18 0 – Descending acid phrase {0x1E,0x1C,0x9E,0x1E,0x9E,0x1E,0x1C,0x9E,0x1E,0x1C,0x9E,0x1E,0x9E,0x1E,0x1C,0x9E}, // PAT 18 1 – G / F toggle {0xA6,0x26,0xA7,0x27,0xA6,0x26,0xA8,0x28,0xA6,0x26,0xA7,0x27,0x28,0xA8,0x26,0xA6}, // PAT 18 2 – D# rising octave drive {0x99,0x19,0xEF,0x2F,0x19,0x0D,0xAF,0x2F,0x19,0x0D,0xEF,0x2F,0x19,0x0D,0xAF,0x2F}, // PAT 18 3 – Acid Tracks breakdown echo {0xD4,0x14,0xE0,0x20,0xD9,0x99,0x19,0xD9,0xD4,0x14,0xE5,0x25,0x14,0x99,0x19,0xD9}, // PAT 19 0 – Classic A/D interplay {0x8F,0x8F,0xA3,0x23,0xDF,0x9F,0x8F,0x8F,0x29,0xAB,0x2B,0x29,0xA8,0x0F,0x8F,0x8F}, // PAT 19 1 – Dark late-night acid {0x24,0x96,0x16,0x97,0x17,0x00,0x1B,0x1C,0x2B,0x29,0x28,0xA9,0x29,0x17,0x96,0x24}, // PAT 19 2 – Mixed register phrase {0x9F,0x97,0x99,0x2B,0xAB,0x9F,0x97,0x99,0x2B,0xAB,0x9F,0x97,0x99,0x2B,0xAB,0x9F}, // PAT 19 3 – Peak-time loop {0x97,0x17,0xD7,0x17,0x57,0x17,0x97,0x17,0xD7,0x17,0x57,0x17,0x97,0x17,0xD7,0x17}, // PAT 19 4 – rolling C acid loop {0x1E,0x9E,0xDE,0x9E,0x1E,0x92,0x12,0x1E,0x9E,0xDE,0x9E,0x1E,0x92,0x12,0x1E,0x9E}, // PAT 19 5 – G minor tension phrase {0xA3,0x23,0x63,0x23,0xE3,0x23,0xA3,0x2F,0xAF,0x23,0x63,0x23,0xE3,0x2F,0x23,0xA3}, // PAT 19 6 – octave stab drive {0xDA,0x9A,0x1A,0xD8,0x98,0x18,0xDF,0x9F,0x1F,0xDD,0x9D,0x1D,0xDA,0x9A,0x1A,0x00}, // PAT 19 7 – descending D# acid {0xE8,0x68,0xA8,0x8C,0x8F,0x0F,0xE8,0x68,0xA8,0x8F,0x0F,0x8C,0xE8,0x68,0xA8,0x8F}, // PAT 20 0 – low F grind {0x12,0x92,0x1E,0xDE,0x92,0x12,0x1E,0x12,0x92,0x1E,0xDE,0x92,0x12,0x1E,0x12,0x92}, // PAT 20 1 – minimal G modulation {0x63,0x23,0x57,0x17,0xD7,0x97,0x23,0x63,0xA3,0x23,0x57,0x17,0xD7,0x97,0x23,0x63}, // PAT 20 2 – C / C' bounce {0x95,0x15,0xA1,0x21,0x90,0x10,0x9C,0x1C,0x9F,0x1F,0x1C,0x9F,0x1F,0x1C,0xA1,0x21}, // PAT 20 3 – descending acid sweep {0x1A,0x1A,0x9A,0xDA,0x5A,0x1A,0xD8,0x98,0x1A,0x9A,0xDA,0x5A,0x98,0x18,0x1A,0x9A}, // PAT 20 4 – D# driving riff {0x9F,0x97,0x17,0x99,0x19,0x2B,0xAB,0x9F,0x97,0x17,0x99,0x19,0x2B,0xAB,0x9F,0x97}, // PAT 20 5 – peak-time loop {0x24,0x96,0x16,0x97,0x17,0x1B,0x1C,0x2B,0x29,0x28,0xA9,0x29,0x17,0x96,0x24,0x00}, // PAT 20 6 – mixed register closer }; ================================================ FILE: lib/msfa/aligned_buf.h ================================================ /* * 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. */ // A convenient wrapper for buffers with alignment constraints // Note that if we were on C++11, we'd use aligned_storage or somesuch. #ifndef __ALIGNED_BUF_H #define __ALIGNED_BUF_H #include template class AlignedBuf { public: T *get() { return (T *)((((intptr_t)storage_) + alignment - 1) & -alignment); } private: unsigned char storage_[size * sizeof(T) + alignment]; }; #endif // __ALIGNED_BUF_H ================================================ FILE: lib/msfa/controllers.h ================================================ /* 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 __CONTROLLERS_H #define __CONTROLLERS_H #include "synth.h" #include #include #include #define MIDI_CONTROLLER_MODE_MAX 2 // State of MIDI controllers const int kControllerPitch = 0; const int kControllerPitchRange = 1; const int kControllerPitchStep = 2; class FmCore; class FmMod { public: uint8_t range; bool pitch; bool amp; bool eg; uint8_t ctrl_mode; uint8_t _dummy_; FmMod() { range = 0; ctrl_mode = 0; pitch = false; amp = false; eg = false; } void setRange(uint8_t r) { range = r < 0 && r > 99 ? 0 : r; } void setTarget(uint8_t assign) { assign = assign < 0 && assign > 7 ? 0 : assign; pitch = assign & 1; // PITCH amp = assign & 2; // AMP eg = assign & 4; // EG } void setMode(uint8_t m) { ctrl_mode = m > MIDI_CONTROLLER_MODE_MAX ? 0 : m; } }; class Controllers { void applyMod(int cc, FmMod &mod) { uint8_t total = 0; float range = mod.range / 100.f; switch (mod.ctrl_mode) { case 0: total = uint8_t(float(cc) * range); // LINEAR mode break; case 1: total = uint8_t(127.f * range - (float(cc) * range)); // REVERSE mode break; case 2: total = uint8_t(range * float(cc) + (1.f - range) * 127.f); // DIRECT BC mode by Thierry (opus.quatre) break; } if (mod.amp) amp_mod = max(amp_mod, total); if (mod.pitch) pitch_mod = max(pitch_mod, total); if (mod.eg) eg_mod = max(eg_mod, total); } public: int32_t values_[3]; uint8_t amp_mod; uint8_t pitch_mod; uint8_t eg_mod; uint8_t aftertouch_cc; uint8_t breath_cc; uint8_t foot_cc; uint8_t modwheel_cc; int masterTune; uint8_t opSwitch; FmMod wheel; FmMod foot; FmMod breath; FmMod at; Controllers() { amp_mod = 0; pitch_mod = 0; eg_mod = 0; } void refresh() { amp_mod = pitch_mod = eg_mod = 0; applyMod(modwheel_cc, wheel); applyMod(breath_cc, breath); applyMod(foot_cc, foot); applyMod(aftertouch_cc, at); if ( ! ((wheel.eg || foot.eg) || (breath.eg || at.eg)) ) eg_mod = 127; } }; #endif // __CONTROLLERS_H ================================================ FILE: lib/msfa/doc/origin.url ================================================ https://github.com/google/music-synthesizer-for-android/tree/master/app/src/main/jni https://github.com/asb2m10/dexed/tree/master/Source/msfa https://codeberg.org/dcoredump/MicroDexed https://github.com/mmontag/dx7-synth-js/blob/master/src/sysex-dx7.js https://github.com/pichenettes/plaits-editor/blob/main/six_op_processor.js ================================================ FILE: lib/msfa/dx7note.cc ================================================ /* Copyright 2016-2017 Pascal Gauthier. 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 #include #include "synth.h" #include "freqlut.h" #include "porta.h" #include "exp2.h" #include "controllers.h" #include "dx7note.h" const int FEEDBACK_BITDEPTH = 8; int32_t midinote_to_logfreq(int midinote) { //const int32_t base = 50857777; // (1 << 24) * (log(440) / log(2) - 69/12) const int32_t base = 50857777; // (1 << 24) * (LOG_FUNC(440) / LOG_FUNC(2) - 69/12) const int32_t step = (1 << 24) / 12; return base + step * midinote; } int32_t logfreq_round2semi(int freq) { const int base = 50857777; // (1 << 24) * (log(440) / log(2) - 69/12) const int step = (1 << 24) / 12; const int rem = (freq - base) % step; return freq - rem; } const int32_t coarsemul[] = { -16777216, 0, 16777216, 26591258, 33554432, 38955489, 43368474, 47099600, 50331648, 53182516, 55732705, 58039632, 60145690, 62083076, 63876816, 65546747, 67108864, 68576247, 69959732, 71268397, 72509921, 73690858, 74816848, 75892776, 76922906, 77910978, 78860292, 79773775, 80654032, 81503396, 82323963, 83117622 }; int32_t osc_freq(int midinote, int mode, int coarse, int fine, int detune) { // TODO: pitch randomization int32_t logfreq; if (mode == 0) { logfreq = midinote_to_logfreq(midinote); // could use more precision, closer enough for now. those numbers comes from my DX7 //FRAC_NUM detuneRatio = 0.0209 * exp(-0.396 * (((float)logfreq) / (1 << 24))) / 7; float detuneRatio = 0.0209f * expf(-0.396f * (((float)logfreq) / (1 << 24))) / 7; logfreq += detuneRatio * logfreq * (detune - 7); logfreq += coarsemul[coarse & 31]; if (fine) { // (1 << 24) / log(2) //logfreq += (int32_t)floor(24204406.323123 * log(1 + 0.01 * fine) + 0.5); logfreq += (int32_t)floor(24204406.323123 * log(1 + 0.01 * fine) + 0.5); } // // This was measured at 7.213Hz per count at 9600Hz, but the exact // // value is somewhat dependent on midinote. Close enough for now. // //logfreq += 12606 * (detune -7); } else { // ((1 << 24) * log(10) / log(2) * .01) << 3 logfreq = (4458616 * ((coarse & 3) * 100 + fine)) >> 3; logfreq += detune > 7 ? 13457 * (detune - 7) : 0; } return logfreq; } const uint8_t velocity_data[64] = { 0, 70, 86, 97, 106, 114, 121, 126, 132, 138, 142, 148, 152, 156, 160, 163, 166, 170, 173, 174, 178, 181, 184, 186, 189, 190, 194, 196, 198, 200, 202, 205, 206, 209, 211, 214, 216, 218, 220, 222, 224, 225, 227, 229, 230, 232, 233, 235, 237, 238, 240, 241, 242, 243, 244, 246, 246, 248, 249, 250, 251, 252, 253, 254 }; // See "velocity" section of notes. Returns velocity delta in microsteps. int ScaleVelocity(int velocity, int sensitivity) { int clamped_vel = max(0, min(127, velocity)); int vel_value = velocity_data[clamped_vel >> 1] - 239; int scaled_vel = ((sensitivity * vel_value + 7) >> 3) << 4; return scaled_vel; } int ScaleRate(int midinote, int sensitivity) { int x = min(31, max(0, midinote / 3 - 7)); int qratedelta = (sensitivity * x) >> 3; #ifdef SUPER_PRECISE int rem = x & 7; if (sensitivity == 3 && rem == 3) { qratedelta -= 1; } else if (sensitivity == 7 && rem > 0 && rem < 4) { qratedelta += 1; } #endif return qratedelta; } const uint8_t exp_scale_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 14, 16, 19, 23, 27, 33, 39, 47, 56, 66, 80, 94, 110, 126, 142, 158, 174, 190, 206, 222, 238, 250 }; int ScaleCurve(int group, int depth, int curve) { int scale; if (curve == 0 || curve == 3) { // linear scale = (group * depth * 329) >> 12; } else { // exponential int n_scale_data = sizeof(exp_scale_data); int raw_exp = exp_scale_data[min(group, n_scale_data - 1)]; scale = (raw_exp * depth * 329) >> 15; } if (curve < 2) { scale = -scale; } return scale; } int ScaleLevel(int midinote, int break_pt, int left_depth, int right_depth, int left_curve, int right_curve) { int offset = midinote - break_pt - 17; if (offset >= 0) { return ScaleCurve((offset + 1) / 3, right_depth, right_curve); } else { return ScaleCurve(-(offset - 1) / 3, left_depth, left_curve); } } static const uint8_t pitchmodsenstab[] = { 0, 10, 20, 33, 55, 92, 153, 255 }; // 0, 66, 109, 255 static const uint32_t ampmodsenstab[] = { 0, 4342338, 7171437, 16777216 }; Dx7Note::Dx7Note() { for (int op = 0; op < 6; op++) { params_[op].phase = 0; params_[op].gain_out = 0; } } //void Dx7Note::init(const uint8_t patch[156], int midinote, int velocity) { void Dx7Note::init(const uint8_t patch[156], int midinote, int velocity) { int rates[4]; int levels[4]; for (int op = 0; op < 6; op++) { int off = op * 21; for (int i = 0; i < 4; i++) { rates[i] = patch[off + i]; levels[i] = patch[off + 4 + i]; } int outlevel = patch[off + 16]; outlevel = Env::scaleoutlevel(outlevel); int level_scaling = ScaleLevel(midinote, patch[off + 8], patch[off + 9], patch[off + 10], patch[off + 11], patch[off + 12]); outlevel += level_scaling; outlevel = min(127, outlevel); outlevel = outlevel << 5; outlevel += ScaleVelocity(velocity, patch[off + 15]); outlevel = max(0, outlevel); int rate_scaling = ScaleRate(midinote, patch[off + 13]); env_[op].init(rates, levels, outlevel, rate_scaling); 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); opMode[op] = mode; basepitch_[op] = freq; ampmodsens_[op] = ampmodsenstab[patch[off + 14] & 3]; } for (int i = 0; i < 4; i++) { rates[i] = patch[126 + i]; levels[i] = patch[130 + i]; } pitchenv_.set(rates, levels); algorithm_ = patch[134]; int feedback = patch[135]; fb_shift_ = feedback != 0 ? FEEDBACK_BITDEPTH - feedback : 16; pitchmoddepth_ = (patch[139] * 165) >> 6; pitchmodsens_ = pitchmodsenstab[patch[143] & 7]; ampmoddepth_ = (patch[140] * 165) >> 6; } void Dx7Note::compute(int32_t *buf, FmCore *core, int32_t lfo_val, int32_t lfo_delay, const Controllers *ctrls) { // ==== PITCH ==== uint32_t pmd = pitchmoddepth_ * lfo_delay; // Q32 int32_t senslfo = pitchmodsens_ * (lfo_val - (1 << 23)); int32_t pmod_1 = (((int64_t) pmd) * (int64_t) senslfo) >> 39; pmod_1 = abs(pmod_1); int32_t pmod_2 = (int32_t)(((int64_t)ctrls->pitch_mod * (int64_t)senslfo) >> 14); pmod_2 = abs(pmod_2); int32_t pitch_mod = max(pmod_1, pmod_2); pitch_mod = pitchenv_.getsample() + (pitch_mod * (senslfo < 0 ? -1 : 1)); // ---- PITCH BEND ---- int pitchbend = ctrls->values_[kControllerPitch]; int32_t pb = (pitchbend - 0x2000); if (pb != 0) { if (ctrls->values_[kControllerPitchStep] == 0) { pb = ((float) (pb << 11)) * ((float) ctrls->values_[kControllerPitchRange]) / 12.0f; } else { int stp = 12 / ctrls->values_[kControllerPitchStep]; pb = pb * stp / 8191; pb = (pb * (8191 / stp)) << 11; } } int32_t pitch_base = pb + ctrls->masterTune; pitch_mod += pitch_base; // ==== AMP MOD ==== lfo_val = (1 << 24) - lfo_val; uint32_t amod_1 = (uint32_t)(((int64_t) ampmoddepth_ * (int64_t) lfo_delay) >> 8); // Q24 :D amod_1 = (uint32_t)(((int64_t) amod_1 * (int64_t) lfo_val) >> 24); uint32_t amod_2 = (uint32_t)(((int64_t) ctrls->amp_mod * (int64_t) lfo_val) >> 7); // Q?? :| uint32_t amd_mod = max(amod_1, amod_2); // ==== EG AMP MOD ==== uint32_t amod_3 = (ctrls->eg_mod + 1) << 17; amd_mod = max((1 << 24) - amod_3, amd_mod); // ==== OP RENDER ==== for (int op = 0; op < 6; op++) { // if ( ctrls->opSwitch[op] == '0' ) { if (!(ctrls->opSwitch & (1 << op))) { env_[op].getsample(); // advance the envelop even if it is not playing params_[op].level_in = 0; } else { //int32_t gain = pow(2, 10 + level * (1.0 / (1 << 24))); int32_t basepitch = basepitch_[op]; if ( opMode[op] ) params_[op].freq = Freqlut::lookup(basepitch + pitch_base); else { params_[op].freq = Freqlut::lookup(basepitch + pitch_mod); } int32_t level = env_[op].getsample(); if (ampmodsens_[op] != 0) { uint32_t sensamp = (uint32_t)(((uint64_t) amd_mod) * ((uint64_t) ampmodsens_[op]) >> 24); // TODO: mehhh.. this needs some real tuning. //uint32_t pt = exp(((float)sensamp) / 262144 * 0.07 + 12.2); uint32_t pt = expf(((float)sensamp) / 262144 * 0.07f + 12.2f); uint32_t ldiff = (uint32_t)(((uint64_t)level) * (((uint64_t)pt << 4)) >> 28); level -= ldiff; } params_[op].level_in = level; } } core->render(buf, params_, algorithm_, fb_buf_, fb_shift_); } void Dx7Note::keyup() { for (int op = 0; op < 6; op++) { env_[op].keydown(false); } pitchenv_.keydown(false); } void Dx7Note::update(const uint8_t patch[156], int midinote, int velocity) { int rates[4]; int levels[4]; for (int op = 0; op < 6; op++) { int off = op * 21; 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); basepitch_[op] = freq; ampmodsens_[op] = ampmodsenstab[patch[off + 14] & 3]; opMode[op] = mode; for (int i = 0; i < 4; i++) { rates[i] = patch[off + i]; levels[i] = patch[off + 4 + i]; } int outlevel = patch[off + 16]; outlevel = Env::scaleoutlevel(outlevel); int level_scaling = ScaleLevel(midinote, patch[off + 8], patch[off + 9], patch[off + 10], patch[off + 11], patch[off + 12]); outlevel += level_scaling; outlevel = min(127, outlevel); outlevel = outlevel << 5; outlevel += ScaleVelocity(velocity, patch[off + 15]); outlevel = max(0, outlevel); int rate_scaling = ScaleRate(midinote, patch[off + 13]); env_[op].update(rates, levels, outlevel, rate_scaling); } algorithm_ = patch[134]; int feedback = patch[135]; fb_shift_ = feedback != 0 ? FEEDBACK_BITDEPTH - feedback : 16; pitchmoddepth_ = (patch[139] * 165) >> 6; pitchmodsens_ = pitchmodsenstab[patch[143] & 7]; ampmoddepth_ = (patch[140] * 165) >> 6; } void Dx7Note::peekVoiceStatus(VoiceStatus &status) { for (int i = 0; i < 6; i++) { status.amp[i] = Exp2::lookup(params_[i].level_in - (14 * (1 << 24))); env_[i].getPosition(&status.ampStep[i]); } pitchenv_.getPosition(&status.pitchStep); } /** Used in monophonic mode to transfer voice state from different notes */ void Dx7Note::transferState(Dx7Note &src) { for (int i = 0; i < 6; i++) { env_[i].transfer(src.env_[i]); params_[i].gain_out = src.params_[i].gain_out; params_[i].phase = src.params_[i].phase; } } void Dx7Note::transferSignal(Dx7Note &src) { for (int i = 0; i < 6; i++) { params_[i].gain_out = src.params_[i].gain_out; params_[i].phase = src.params_[i].phase; } } void Dx7Note::oscSync() { for (int i = 0; i < 6; i++) { params_[i].gain_out = 0; params_[i].phase = 0; } } ================================================ FILE: lib/msfa/dx7note.h ================================================ /* Copyright 2016-2017 Pascal Gauthier. 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. */ #ifndef SYNTH_DX7NOTE_H_ #define SYNTH_DX7NOTE_H_ // This is the logic to put together a note from the MIDI description // and run the low-level modules. // It will continue to evolve a bit, as note-stealing logic, scaling, // and real-time control of parameters live here. #include "env.h" #include "pitchenv.h" #include "fm_core.h" struct VoiceStatus { uint32_t amp[6]; char ampStep[6]; char pitchStep; }; class Dx7Note { public: Dx7Note(); void init(const uint8_t patch[156], int midinote, int velocity); // Note: this _adds_ to the buffer. Interesting question whether it's // worth it... void compute(int32_t *buf, FmCore *core, int32_t lfo_val, int32_t lfo_delay, const Controllers *ctrls); void keyup(); // TODO: some way of indicating end-of-note. Maybe should be a return // value from the compute method? (Having a count return from keyup // is also tempting, but if there's a dynamic parameter change after // keyup, that won't work. // PG:add the update void update(const uint8_t patch[156], int midinote, int velocity); void peekVoiceStatus(VoiceStatus &status); void transferState(Dx7Note& src); void transferSignal(Dx7Note &src); void oscSync(); private: Env env_[6]; FmOpParams params_[6]; PitchEnv pitchenv_; int32_t basepitch_[6]; int32_t fb_buf_[2]; int32_t fb_shift_; int32_t ampmodsens_[6]; int32_t opMode[6]; int ampmoddepth_; int algorithm_; int pitchmoddepth_; int pitchmodsens_; }; #endif // SYNTH_DX7NOTE_H_ ================================================ FILE: lib/msfa/env.cc ================================================ /* * Copyright 2017 Pascal Gauthier. * 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 #include "synth.h" #include "env.h" //using namespace std; uint32_t Env::sr_multiplier = (1<<24); const int levellut[] = { 0, 5, 9, 13, 17, 20, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 42, 43, 45, 46 }; #ifdef ACCURATE_ENVELOPE const int statics[] = { 1764000, 1764000, 1411200, 1411200, 1190700, 1014300, 992250, 882000, 705600, 705600, 584325, 507150, 502740, 441000, 418950, 352800, 308700, 286650, 253575, 220500, 220500, 176400, 145530, 145530, 125685, 110250, 110250, 88200, 88200, 74970, 61740, 61740, 55125, 48510, 44100, 37485, 31311, 30870, 27562, 27562, 22050, 18522, 17640, 15435, 14112, 13230, 11025, 9261, 9261, 7717, 6615, 6615, 5512, 5512, 4410, 3969, 3969, 3439, 2866, 2690, 2249, 1984, 1896, 1808, 1411, 1367, 1234, 1146, 926, 837, 837, 705, 573, 573, 529, 441, 441 // and so on, I stopped measuring after R=76 (needs to be double-checked anyway) }; #endif void Env::init_sr(double sampleRate) { sr_multiplier = (44100.0 / sampleRate) * (1<<24); } void Env::init(const int r[4], const int l[4], int ol, int rate_scaling) { for (int i = 0; i < 4; i++) { rates_[i] = r[i]; levels_[i] = l[i]; } outlevel_ = ol; rate_scaling_ = rate_scaling; level_ = 0; down_ = true; advance(0); } int32_t Env::getsample() { #ifdef ACCURATE_ENVELOPE if (staticcount_) { staticcount_ -= N; if (staticcount_ <= 0) { staticcount_ = 0; advance(ix_ + 1); } } #endif if (ix_ < 3 || ((ix_ < 4) && !down_)) { if (staticcount_) { ; } else if (rising_) { const int jumptarget = 1716; if (level_ < (jumptarget << 16)) { level_ = jumptarget << 16; } level_ += (((17 << 24) - level_) >> 24) * inc_; // TODO: should probably be more accurate when inc is large if (level_ >= targetlevel_) { level_ = targetlevel_; advance(ix_ + 1); } } else { // !rising level_ -= inc_; if (level_ <= targetlevel_) { level_ = targetlevel_; advance(ix_ + 1); } } } // TODO: this would be a good place to set level to 0 when under threshold return level_; } void Env::keydown(bool d) { if (down_ != d) { down_ = d; advance(d ? 0 : 3); } } int Env::scaleoutlevel(int outlevel) { return outlevel >= 20 ? 28 + outlevel : levellut[outlevel]; } void Env::advance(int newix) { ix_ = newix; if (ix_ < 4) { int newlevel = levels_[ix_]; int actuallevel = scaleoutlevel(newlevel) >> 1; actuallevel = (actuallevel << 6) + outlevel_ - 4256; actuallevel = actuallevel < 16 ? 16 : actuallevel; // level here is same as Java impl targetlevel_ = actuallevel << 16; rising_ = (targetlevel_ > level_); // rate int qrate = (rates_[ix_] * 41) >> 6; qrate += rate_scaling_; qrate = min(qrate, 63); #ifdef ACCURATE_ENVELOPE if (targetlevel_ == level_ || (ix_ == 0 && newlevel == 0)) { // approximate number of samples at 44.100 kHz to achieve the time // empirically gathered using 2 TF1s, could probably use some double-checking // and cleanup, but it's pretty close for now. int staticrate = rates_[ix_]; staticrate += rate_scaling_; // needs to be checked, as well, but seems correct staticrate = min(staticrate, 99); staticcount_ = staticrate < 77 ? statics[staticrate] : 20 * (99 - staticrate); if (staticrate < 77 && (ix_ == 0 && newlevel == 0)) { staticcount_ /= 20; // attack is scaled faster } staticcount_ = (int)(((int64_t)staticcount_ * (int64_t)sr_multiplier) >> 24); } else { staticcount_ = 0; } #endif inc_ = (4 + (qrate & 3)) << (2 + LG_N + (qrate >> 2)); // meh, this should be fixed elsewhere inc_ = (int)(((int64_t)inc_ * (int64_t)sr_multiplier) >> 24); } } void Env::update(const int r[4], const int l[4], int ol, int rate_scaling) { for (int i = 0; i < 4; i++) { rates_[i] = r[i]; levels_[i] = l[i]; } outlevel_ = ol; rate_scaling_ = rate_scaling; if ( down_ ) { // for now we simply reset ourselves at level 3 int newlevel = levels_[2]; int actuallevel = scaleoutlevel(newlevel) >> 1; actuallevel = (actuallevel << 6) - 4256; actuallevel = actuallevel < 16 ? 16 : actuallevel; targetlevel_ = actuallevel << 16; advance(2); } } void Env::getPosition(char *step) { *step = ix_; } void Env::transfer(Env &src) { for(int i=0;i<4;i++) { rates_[i] = src.rates_[i]; levels_[i] = src.levels_[i]; } outlevel_ = src.outlevel_; rate_scaling_ = src.rate_scaling_; level_ = src.level_; targetlevel_ = src.targetlevel_; rising_= src.rising_; ix_ = src.ix_; down_ = src.down_; #ifdef ACCURATE_ENVELOPE staticcount_ = src.staticcount_; #endif inc_ = src.inc_; } ================================================ FILE: lib/msfa/env.h ================================================ /* * Copyright 2017 Pascal Gauthier. * 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. */ #ifndef __ENV_H #define __ENV_H #include "synth.h" // DX7 envelope generation #define ACCURATE_ENVELOPE class Env { public: // The rates and levels arrays are calibrated to match the Dx7 parameters // (ie, value 0..99). The outlevel parameter is calibrated in microsteps // (ie units of approx .023 dB), with 99 * 32 = nominal full scale. The // rate_scaling parameter is in qRate units (ie 0..63). void init(const int rates[4], const int levels[4], int outlevel, int rate_scaling); void update(const int rates[4], const int levels[4], int outlevel, int rate_scaling); // Result is in Q24/doubling log format. Also, result is subsampled // for every N samples. // A couple more things need to happen for this to be used as a gain // value. First, the # of outputs scaling needs to be applied. Also, // modulation. // Then, of course, log to linear. int32_t getsample(); void keydown(bool down); static int scaleoutlevel(int outlevel); void getPosition(char *step); static void init_sr(double sample_rate); void transfer(Env &src); private: // PG: This code is normalized to 44100, need to put a multiplier // if we are not using 44100. static uint32_t sr_multiplier; int rates_[4]; int levels_[4]; int outlevel_; int rate_scaling_; // Level is stored so that 2^24 is one doubling, ie 16 more bits than // the DX7 itself (fraction is stored in level rather than separate // counter) int32_t level_; int targetlevel_; bool rising_; int ix_; int inc_; #ifdef ACCURATE_ENVELOPE int staticcount_; #endif bool down_; void advance(int newix); }; #endif // __ENV_H ================================================ FILE: lib/msfa/exp2.cc ================================================ /* * 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 "synth.h" #include "exp2.h" #if 1 //eh2k #ifndef FLASHMEM #include "pgmspace.h" #endif const int32_t exp2tab[2048] FLASHMEM = { 727064,1073741824,727555,1074468888,728049,1075196443,728541,1075924492,729035,1076653033,729529,1077382068,730022,1078111597,730517,1078841619,731011,1079572136,731507,1080303147,732002,1081034654, 732497,1081766656,732993,1082499153,733490,1083232146,733986,1083965636,734484,1084699622,734981,1085434106,735478,1086169087,735976,1086904565,736475,1087640541,736974,1088377016,737472,1089113990, 737972,1089851462,738472,1090589434,738971,1091327906,739472,1092066877,739973,1092806349,740474,1093546322,740975,1094286796,741477,1095027771,741979,1095769248,742481,1096511227,742985,1097253708, 743487,1097996693,743990,1098740180,744495,1099484170,744999,1100228665,745503,1100973664,746007,1101719167,746513,1102465174,747019,1103211687,747524,1103958706,748031,1104706230,748537,1105454261, 749044,1106202798,749551,1106951842,750058,1107701393,750567,1108451451,751075,1109202018,751583,1109953093,752092,1110704676,752602,1111456768,753111,1112209370,753621,1112962481,754131,1113716102, 754642,1114470233,755153,1115224875,755664,1115980028,756176,1116735692,756688,1117491868,757201,1118248556,757713,1119005757,758226,1119763470,758740,1120521696,759253,1121280436,759768,1122039689, 760282,1122799457,760797,1123559739,761312,1124320536,761827,1125081848,762343,1125843675,762860,1126606018,763376,1127368878,763893,1128132254,764410,1128896147,764928,1129660557,765446,1130425485, 765964,1131190931,766483,1131956895,767001,1132723378,767521,1133490379,768041,1134257900,768561,1135025941,769081,1135794502,769603,1136563583,770123,1137333186,770644,1138103309,771167,1138873953, 771689,1139645120,772211,1140416809,772734,1141189020,773257,1141961754,773781,1142735011,774305,1143508792,774829,1144283097,775354,1145057926,775879,1145833280,776404,1146609159,776930,1147385563, 777456,1148162493,777983,1148939949,778509,1149717932,779037,1150496441,779564,1151275478,780092,1152055042,780620,1152835134,781148,1153615754,781678,1154396902,782207,1155178580,782736,1155960787, 783267,1156743523,783797,1157526790,784327,1158310587,784859,1159094914,785390,1159879773,785922,1160665163,786454,1161451085,786987,1162237539,787520,1163024526,788053,1163812046,788586,1164600099, 789121,1165388685,789654,1166177806,790190,1166967460,790724,1167757650,791260,1168548374,791796,1169339634,792332,1170131430,792868,1170923762,793406,1171716630,793942,1172510036,794480,1173303978, 795018,1174098458,795557,1174893476,796095,1175689033,796634,1176485128,797174,1177281762,797713,1178078936,798254,1178876649,798794,1179674903,799335,1180473697,799876,1181273032,800418,1182072908, 800960,1182873326,801502,1183674286,802045,1184475788,802588,1185277833,803131,1186080421,803676,1186883552,804219,1187687228,804764,1188491447,805309,1189296211,805854,1190101520,806400,1190907374, 806946,1191713774,807493,1192520720,808039,1193328213,808586,1194136252,809134,1194944838,809682,1195753972,810230,1196563654,810778,1197373884,811328,1198184662,811877,1198995990,812427,1199807867, 812976,1200620294,813528,1201433270,814078,1202246798,814629,1203060876,815181,1203875505,815733,1204690686,816286,1205506419,816838,1206322705,817391,1207139543,817945,1207956934,818499,1208774879, 819052,1209593378,819608,1210412430,820162,1211232038,820718,1212052200,821273,1212872918,821830,1213694191,822386,1214516021,822943,1215338407,823500,1216161350,824058,1216984850,824616,1217808908, 825174,1218633524,825733,1219458698,826292,1220284431,826851,1221110723,827412,1221937574,827972,1222764986,828532,1223592958,829093,1224421490,829655,1225250583,830217,1226080238,830778,1226910455, 831342,1227741233,831904,1228572575,832467,1229404479,833031,1230236946,833596,1231069977,834159,1231903573,834725,1232737732,835290,1233572457,835855,1234407747,836422,1235243602,836987,1236080024, 837555,1236917011,838121,1237754566,838689,1238592687,839257,1239431376,839826,1240270633,840394,1241110459,840963,1241950853,841532,1242791816,842103,1243633348,842672,1244475451,843243,1245318123, 843814,1246161366,844386,1247005180,844957,1247849566,845529,1248694523,846102,1249540052,846675,1250386154,847248,1251232829,847822,1252080077,848396,1252927899,848971,1253776295,849545,1254625266, 850120,1255474811,850697,1256324931,851272,1257175628,851848,1258026900,852426,1258878748,853003,1259731174,853580,1260584177,854158,1261437757,854737,1262291915,855315,1263146652,855894,1264001967, 856475,1264857861,857054,1265714336,857634,1266571390,858215,1267429024,858796,1268287239,859378,1269146035,859960,1270005413,860542,1270865373,861124,1271725915,861708,1272587039,862291,1273448747, 862875,1274311038,863460,1275173913,864044,1276037373,864629,1276901417,865215,1277766046,865800,1278631261,866387,1279497061,866973,1280363448,867561,1281230421,868147,1282097982,868736,1282966129, 869324,1283834865,869913,1284704189,870502,1285574102,871091,1286444604,871681,1287315695,872271,1288187376,872862,1289059647,873453,1289932509,874044,1290805962,874636,1291680006,875228,1292554642, 875822,1293429870,876414,1294305692,877007,1295182106,877602,1296059113,878195,1296936715,878791,1297814910,879385,1298693701,879981,1299573086,880576,1300453067,881173,1301333643,881770,1302214816, 882367,1303096586,882964,1303978953,883562,1304861917,884160,1305745479,884759,1306629639,885358,1307514398,885958,1308399756,886558,1309285714,887158,1310172272,887758,1311059430,888360,1311947188, 888961,1312835548,889563,1313724509,890166,1314614072,890768,1315504238,891372,1316395006,891975,1317286378,892579,1318178353,893183,1319070932,893788,1319964115,894394,1320857903,894999,1321752297, 895605,1322647296,896211,1323542901,896819,1324439112,897425,1325335931,898034,1326233356,898641,1327131390,899250,1328030031,899859,1328929281,900468,1329829140,901078,1330729608,901688,1331630686, 902298,1332532374,902910,1333434672,903521,1334337582,904132,1335241103,904745,1336145235,905358,1337049980,905971,1337955338,906584,1338861309,907198,1339767893,907812,1340675091,908427,1341582903, 909042,1342491330,909658,1343400372,910273,1344310030,910890,1345220303,911507,1346131193,912124,1347042700,912741,1347954824,913360,1348867565,913978,1349780925,914597,1350694903,915216,1351609500, 915836,1352524716,916457,1353440552,917076,1354357009,917698,1355274085,918319,1356191783,918941,1357110102,919563,1358029043,920186,1358948606,920809,1359868792,921432,1360789601,922057,1361711033, 922680,1362633090,923306,1363555770,923930,1364479076,924557,1365403006,925182,1366327563,925809,1367252745,926435,1368178554,927063,1369104989,927691,1370032052,928319,1370959743,928948,1371888062, 929576,1372817010,930206,1373746586,930836,1374676792,931466,1375607628,932097,1376539094,932728,1377471191,933360,1378403919,933991,1379337279,934624,1380271270,935257,1381205894,935890,1382141151, 936524,1383077041,937158,1384013565,937793,1384950723,938428,1385888516,939063,1386826944,939699,1387766007,940335,1388705706,940972,1389646041,941609,1390587013,942247,1391528622,942885,1392470869, 943523,1393413754,944162,1394357277,944801,1395301439,945442,1396246240,946081,1397191682,946722,1398137763,947363,1399084485,948005,1400031848,948646,1400979853,949289,1401928499,949931,1402877788, 950575,1403827719,951219,1404778294,951862,1405729513,952507,1406681375,953153,1407633882,953797,1408587035,954443,1409540832,955090,1410495275,955736,1411450365,956384,1412406101,957031,1413362485, 957679,1414319516,958328,1415277195,958976,1416235523,959626,1417194499,960276,1418154125,960926,1419114401,961576,1420075327,962228,1421036903,962879,1421999131,963532,1422962010,964183,1423925542, 964837,1424889725,965490,1425854562,966144,1426820052,966797,1427786196,967453,1428752993,968107,1429720446,968764,1430688553,969419,1431657317,970075,1432626736,970733,1433596811,971389,1434567544, 972048,1435538933,972706,1436510981,973364,1437483687,974023,1438457051,974683,1439431074,975343,1440405757,976004,1441381100,976664,1442357104,977325,1443333768,977988,1444311093,978649,1445289081, 979313,1446267730,979975,1447247043,980639,1448227018,981303,1449207657,981967,1450188960,982633,1451170927,983298,1452153560,983963,1453136858,984630,1454120821,985297,1455105451,985963,1456090748, 986632,1457076711,987299,1458063343,987968,1459050642,988637,1460038610,989306,1461027247,989977,1462016553,990646,1463006530,991318,1463997176,991988,1464988494,992661,1465980482,993332,1466973143, 994005,1467966475,994679,1468960480,995351,1469955159,996026,1470950510,996700,1471946536,997375,1472943236,998051,1473940611,998726,1474938662,999403,1475937388,1000079,1476936791,1000756,1477936870, 1001434,1478937626,1002112,1479939060,1002791,1480941172,1003470,1481943963,1004149,1482947433,1004829,1483951582,1005510,1484956411,1006190,1485961921,1006872,1486968111,1007554,1487974983,1008235,1488982537, 1008919,1489990772,1009602,1490999691,1010285,1492009293,1010969,1493019578,1011654,1494030547,1012339,1495042201,1013025,1496054540,1013710,1497067565,1014397,1498081275,1015083,1499095672,1015771,1500110755, 1016459,1501126526,1017147,1502142985,1017836,1503160132,1018525,1504177968,1019215,1505196493,1019905,1506215708,1020596,1507235613,1021286,1508256209,1021978,1509277495,1022670,1510299473,1023363,1511322143, 1024055,1512345506,1024749,1513369561,1025443,1514394310,1026138,1515419753,1026832,1516445891,1027527,1517472723,1028223,1518500250,1028919,1519528473,1029617,1520557392,1030313,1521587009,1031011,1522617322, 1031709,1523648333,1032407,1524680042,1033107,1525712449,1033806,1526745556,1034507,1527779362,1035207,1528813869,1035907,1529849076,1036610,1530884983,1037311,1531921593,1038013,1532958904,1038717,1533996917, 1039419,1535035634,1040124,1536075053,1040828,1537115177,1041532,1538156005,1042238,1539197537,1042944,1540239775,1043650,1541282719,1044356,1542326369,1045064,1543370725,1045771,1544415789,1046480,1545461560, 1047188,1546508040,1047897,1547555228,1048607,1548603125,1049316,1549651732,1050028,1550701048,1050738,1551751076,1051450,1552801814,1052161,1553853264,1052875,1554905425,1053587,1555958300,1054300,1557011887, 1055015,1558066187,1055729,1559121202,1056443,1560176931,1057159,1561233374,1057875,1562290533,1058591,1563348408,1059308,1564406999,1060026,1565466307,1060743,1566526333,1061461,1567587076,1062180,1568648537, 1062899,1569710717,1063619,1570773616,1064340,1571837235,1065060,1572901575,1065781,1573966635,1066503,1575032416,1067224,1576098919,1067948,1577166143,1068671,1578234091,1069394,1579302762,1070119,1580372156, 1070843,1581442275,1071568,1582513118,1072294,1583584686,1073020,1584656980,1073746,1585730000,1074474,1586803746,1075201,1587878220,1075929,1588953421,1076658,1590029350,1077386,1591106008,1078116,1592183394, 1078847,1593261510,1079577,1594340357,1080307,1595419934,1081040,1596500241,1081771,1597581281,1082504,1598663052,1083237,1599745556,1083970,1600828793,1084704,1601912763,1085439,1602997467,1086174,1604082906, 1086909,1605169080,1087645,1606255989,1088382,1607343634,1089119,1608432016,1089856,1609521135,1090594,1610610991,1091333,1611701585,1092071,1612792918,1092811,1613884989,1093551,1614977800,1094292,1616071351, 1095032,1617165643,1095774,1618260675,1096516,1619356449,1097259,1620452965,1098001,1621550224,1098745,1622648225,1099489,1623746970,1100233,1624846459,1100979,1625946692,1101724,1627047671,1102470,1628149395, 1103216,1629251865,1103963,1630355081,1104711,1631459044,1105459,1632563755,1106208,1633669214,1106957,1634775422,1107706,1635882379,1108456,1636990085,1109207,1638098541,1109958,1639207748,1110709,1640317706, 1111462,1641428415,1112214,1642539877,1112967,1643652091,1113721,1644765058,1114475,1645878779,1115230,1646993254,1115985,1648108484,1116740,1649224469,1117497,1650341209,1118253,1651458706,1119011,1652576959, 1119768,1653695970,1120527,1654815738,1121285,1655936265,1122044,1657057550,1122805,1658179594,1123564,1659302399,1124326,1660425963,1125086,1661550289,1125849,1662675375,1126611,1663801224,1127374,1664927835, 1128137,1666055209,1128901,1667183346,1129665,1668312247,1130430,1669441912,1131196,1670572342,1131962,1671703538,1132728,1672835500,1133496,1673968228,1134262,1675101724,1135031,1676235986,1135800,1677371017, 1136568,1678506817,1137338,1679643385,1138108,1680780723,1138879,1681918831,1139650,1683057710,1140422,1684197360,1141194,1685337782,1141967,1686478976,1142740,1687620943,1143513,1688763683,1144288,1689907196, 1145063,1691051484,1145838,1692196547,1146615,1693342385,1147390,1694489000,1148167,1695636390,1148945,1696784557,1149723,1697933502,1150502,1699083225,1151280,1700233727,1152060,1701385007,1152840,1702537067, 1153621,1703689907,1154402,1704843528,1155183,1705997930,1155966,1707153113,1156749,1708309079,1157531,1709465828,1158316,1710623359,1159100,1711781675,1159885,1712940775,1160670,1714100660,1161456,1715261330, 1162243,1716422786,1163029,1717585029,1163817,1718748058,1164605,1719911875,1165394,1721076480,1166183,1722241874,1166972,1723408057,1167763,1724575029,1168553,1725742792,1169345,1726911345,1170137,1728080690, 1170928,1729250827,1171722,1730421755,1172515,1731593477,1173309,1732765992,1174104,1733939301,1174898,1735113405,1175694,1736288303,1176491,1737463997,1177286,1738640488,1178084,1739817774,1178882,1740995858, 1179680,1742174740,1180479,1743354420,1181278,1744534899,1182078,1745716177,1182878,1746898255,1183680,1748081133,1184481,1749264813,1185283,1750449294,1186085,1751634577,1186889,1752820662,1187692,1754007551, 1188497,1755195243,1189301,1756383740,1190107,1757573041,1190912,1758763148,1191719,1759954060,1192526,1761145779,1193333,1762338305,1194142,1763531638,1194950,1764725780,1195759,1765920730,1196569,1767116489, 1197379,1768313058,1198190,1769510437,1199001,1770708627,1199813,1771907628,1200625,1773107441,1201439,1774308066,1202252,1775509505,1203066,1776711757,1203881,1777914823,1204695,1779118704,1205512,1780323399, 1206328,1781528911,1207145,1782735239,1207962,1783942384,1208780,1785150346,1209598,1786359126,1210418,1787568724,1211237,1788779142,1212058,1789990379,1212878,1791202437,1213699,1792415315,1214522,1793629014, 1215343,1794843536,1216167,1796058879,1216990,1797275046,1217814,1798492036,1218639,1799709850,1219464,1800928489,1220290,1802147953,1221116,1803368243,1221942,1804589359,1222771,1805811301,1223598,1807034072, 1224427,1808257670,1225256,1809482097,1226085,1810707353,1226916,1811933438,1227746,1813160354,1228578,1814388100,1229410,1815616678,1230242,1816846088,1231076,1818076330,1231908,1819307406,1232743,1820539314, 1233578,1821772057,1234413,1823005635,1235249,1824240048,1236086,1825475297,1236922,1826711383,1237760,1827948305,1238598,1829186065,1239437,1830424663,1240276,1831664100,1241115,1832904376,1241957,1834145491, 1242797,1835387448,1243638,1836630245,1244481,1837873883,1245324,1839118364,1246167,1840363688,1247010,1841609855,1247855,1842856865,1248700,1844104720,1249545,1845353420,1250392,1846602965,1251238,1847853357, 1252086,1849104595,1252933,1850356681,1253782,1851609614,1254630,1852863396,1255481,1854118026,1256330,1855373507,1257181,1856629837,1258032,1857887018,1258884,1859145050,1259737,1860403934,1260590,1861663671, 1261443,1862924261,1262297,1864185704,1263152,1865448001,1264008,1866711153,1264863,1867975161,1265720,1869240024,1266577,1870505744,1267434,1871772321,1268293,1873039755,1269151,1874308048,1270011,1875577199, 1270871,1876847210,1271732,1878118081,1272592,1879389813,1273454,1880662405,1274317,1881935859,1275179,1883210176,1276043,1884485355,1276907,1885761398,1277772,1887038305,1278636,1888316077,1279503,1889594713, 1280369,1890874216,1281236,1892154585,1282103,1893435821,1282972,1894717924,1283840,1896000896,1284710,1897284736,1285580,1898569446,1286450,1899855026,1287321,1901141476,1288193,1902428797,1289065,1903716990, 1289938,1905006055,1290812,1906295993,1291685,1907586805,1292561,1908878490,1293435,1910171051,1294311,1911464486,1295188,1912758797,1296065,1914053985,1296942,1915350050,1297821,1916646992,1298699,1917944813, 1299579,1919243512,1300458,1920543091,1301340,1921843549,1302220,1923144889,1303102,1924447109,1303985,1925750211,1304867,1927054196,1305751,1928359063,1306636,1929664814,1307520,1930971450,1308405,1932278970, 1309291,1933587375,1310178,1934896666,1311065,1936206844,1311953,1937517909,1312842,1938829862,1313730,1940142704,1314619,1941456434,1315510,1942771053,1316401,1944086563,1317292,1945402964,1318184,1946720256, 1319077,1948038440,1319970,1949357517,1320863,1950677487,1321758,1951998350,1322653,1953320108,1323549,1954642761,1324445,1955966310,1325341,1957290755,1326239,1958616096,1327137,1959942335,1328036,1961269472, 1328935,1962597508,1329835,1963926443,1330735,1965256278,1331637,1966587013,1332538,1967918650,1333440,1969251188,1334344,1970584628,1335247,1971918972,1336151,1973254219,1337055,1974590370,1337961,1975927425, 1338867,1977265386,1339774,1978604253,1340681,1979944027,1341589,1981284708,1342497,1982626297,1343406,1983968794,1344316,1985312200,1345226,1986656516,1346137,1988001742,1347048,1989347879,1347961,1990694927, 1348873,1992042888,1349787,1993391761,1350701,1994741548,1351615,1996092249,1352531,1997443864,1353446,1998796395,1354363,2000149841,1355280,2001504204,1356198,2002859484,1357116,2004215682,1358034,2005572798, 1358955,2006930832,1359875,2008289787,1360795,2009649662,1361717,2011010457,1362639,2012372174,1363562,2013734813,1364485,2015098375,1365408,2016462860,1366334,2017828268,1367258,2019194602,1368185,2020561860, 1369111,2021930045,1370038,2023299156,1370965,2024669194,1371894,2026040159,1372823,2027412053,1373753,2028784876,1374683,2030158629,1375613,2031533312,1376545,2032908925,1377477,2034285470,1378410,2035662947, 1379343,2037041357,1380278,2038420700,1381211,2039800978,1382148,2041182189,1383083,2042564337,1384019,2043947420,1384957,2045331439,1385894,2046716396,1386833,2048102290,1387772,2049489123,1388712,2050876895, 1389652,2052265607,1390593,2053655259,1391535,2055045852,1392476,2056437387,1393420,2057829863,1394363,2059223283,1395308,2060617646,1396252,2062012954,1397198,2063409206,1398144,2064806404,1399090,2066204548, 1400038,2067603638,1400986,2069003676,1401935,2070404662,1402883,2071806597,1403834,2073209480,1404785,2074613314,1405735,2076018099,1406688,2077423834,1407639,2078830522,1408594,2080238161,1409546,2081646755, 1410502,2083056301,1411456,2084466803,1412412,2085878259,1413369,2087290671,1414326,2088704040,1415283,2090118366,1416242,2091533649,1417200,2092949891,1418160,2094367091,1419121,2095785251,1420081,2097204372, 1421043,2098624453,1422006,2100045496,1422968,2101467502,1423932,2102890470,1424895,2104314402,1425861,2105739297,1426826,2107165158,1427793,2108591984,1428759,2110019777,1429726,2111448536,1430695,2112878262, 1431664,2114308957,1432633,2115740621,1433603,2117173254,1434573,2118606857,1435545,2120041430,1436518,2121476975,1437489,2122913493,1438464,2124350982,1439437,2125789446,1440412,2127228883,1441387,2128669295, 1442364,2130110682,1443340,2131553046,1444317,2132996386,1445295,2134440703,1446274,2135885998,1447253,2137332272,1448234,2138779525,1449214,2140227759,1450195,2141676973,1451177,2143127168,1452160,2144578345, 1453143,2146030505, }; void Exp2::init() {} const int32_t tanhtab[2048] FLASHMEM = { 727064,1073741824,727555,1074468888,728049,1075196443,728541,1075924492,729035,1076653033,729529,1077382068,730022,1078111597,730517,1078841619,731011,1079572136,731507,1080303147,732002,1081034654, 732497,1081766656,732993,1082499153,733490,1083232146,733986,1083965636,734484,1084699622,734981,1085434106,735478,1086169087,735976,1086904565,736475,1087640541,736974,1088377016,737472,1089113990, 737972,1089851462,738472,1090589434,738971,1091327906,739472,1092066877,739973,1092806349,740474,1093546322,740975,1094286796,741477,1095027771,741979,1095769248,742481,1096511227,742985,1097253708, 743487,1097996693,743990,1098740180,744495,1099484170,744999,1100228665,745503,1100973664,746007,1101719167,746513,1102465174,747019,1103211687,747524,1103958706,748031,1104706230,748537,1105454261, 749044,1106202798,749551,1106951842,750058,1107701393,750567,1108451451,751075,1109202018,751583,1109953093,752092,1110704676,752602,1111456768,753111,1112209370,753621,1112962481,754131,1113716102, 754642,1114470233,755153,1115224875,755664,1115980028,756176,1116735692,756688,1117491868,757201,1118248556,757713,1119005757,758226,1119763470,758740,1120521696,759253,1121280436,759768,1122039689, 760282,1122799457,760797,1123559739,761312,1124320536,761827,1125081848,762343,1125843675,762860,1126606018,763376,1127368878,763893,1128132254,764410,1128896147,764928,1129660557,765446,1130425485, 765964,1131190931,766483,1131956895,767001,1132723378,767521,1133490379,768041,1134257900,768561,1135025941,769081,1135794502,769603,1136563583,770123,1137333186,770644,1138103309,771167,1138873953, 771689,1139645120,772211,1140416809,772734,1141189020,773257,1141961754,773781,1142735011,774305,1143508792,774829,1144283097,775354,1145057926,775879,1145833280,776404,1146609159,776930,1147385563, 777456,1148162493,777983,1148939949,778509,1149717932,779037,1150496441,779564,1151275478,780092,1152055042,780620,1152835134,781148,1153615754,781678,1154396902,782207,1155178580,782736,1155960787, 783267,1156743523,783797,1157526790,784327,1158310587,784859,1159094914,785390,1159879773,785922,1160665163,786454,1161451085,786987,1162237539,787520,1163024526,788053,1163812046,788586,1164600099, 789121,1165388685,789654,1166177806,790190,1166967460,790724,1167757650,791260,1168548374,791796,1169339634,792332,1170131430,792868,1170923762,793406,1171716630,793942,1172510036,794480,1173303978, 795018,1174098458,795557,1174893476,796095,1175689033,796634,1176485128,797174,1177281762,797713,1178078936,798254,1178876649,798794,1179674903,799335,1180473697,799876,1181273032,800418,1182072908, 800960,1182873326,801502,1183674286,802045,1184475788,802588,1185277833,803131,1186080421,803676,1186883552,804219,1187687228,804764,1188491447,805309,1189296211,805854,1190101520,806400,1190907374, 806946,1191713774,807493,1192520720,808039,1193328213,808586,1194136252,809134,1194944838,809682,1195753972,810230,1196563654,810778,1197373884,811328,1198184662,811877,1198995990,812427,1199807867, 812976,1200620294,813528,1201433270,814078,1202246798,814629,1203060876,815181,1203875505,815733,1204690686,816286,1205506419,816838,1206322705,817391,1207139543,817945,1207956934,818499,1208774879, 819052,1209593378,819608,1210412430,820162,1211232038,820718,1212052200,821273,1212872918,821830,1213694191,822386,1214516021,822943,1215338407,823500,1216161350,824058,1216984850,824616,1217808908, 825174,1218633524,825733,1219458698,826292,1220284431,826851,1221110723,827412,1221937574,827972,1222764986,828532,1223592958,829093,1224421490,829655,1225250583,830217,1226080238,830778,1226910455, 831342,1227741233,831904,1228572575,832467,1229404479,833031,1230236946,833596,1231069977,834159,1231903573,834725,1232737732,835290,1233572457,835855,1234407747,836422,1235243602,836987,1236080024, 837555,1236917011,838121,1237754566,838689,1238592687,839257,1239431376,839826,1240270633,840394,1241110459,840963,1241950853,841532,1242791816,842103,1243633348,842672,1244475451,843243,1245318123, 843814,1246161366,844386,1247005180,844957,1247849566,845529,1248694523,846102,1249540052,846675,1250386154,847248,1251232829,847822,1252080077,848396,1252927899,848971,1253776295,849545,1254625266, 850120,1255474811,850697,1256324931,851272,1257175628,851848,1258026900,852426,1258878748,853003,1259731174,853580,1260584177,854158,1261437757,854737,1262291915,855315,1263146652,855894,1264001967, 856475,1264857861,857054,1265714336,857634,1266571390,858215,1267429024,858796,1268287239,859378,1269146035,859960,1270005413,860542,1270865373,861124,1271725915,861708,1272587039,862291,1273448747, 862875,1274311038,863460,1275173913,864044,1276037373,864629,1276901417,865215,1277766046,865800,1278631261,866387,1279497061,866973,1280363448,867561,1281230421,868147,1282097982,868736,1282966129, 869324,1283834865,869913,1284704189,870502,1285574102,871091,1286444604,871681,1287315695,872271,1288187376,872862,1289059647,873453,1289932509,874044,1290805962,874636,1291680006,875228,1292554642, 875822,1293429870,876414,1294305692,877007,1295182106,877602,1296059113,878195,1296936715,878791,1297814910,879385,1298693701,879981,1299573086,880576,1300453067,881173,1301333643,881770,1302214816, 882367,1303096586,882964,1303978953,883562,1304861917,884160,1305745479,884759,1306629639,885358,1307514398,885958,1308399756,886558,1309285714,887158,1310172272,887758,1311059430,888360,1311947188, 888961,1312835548,889563,1313724509,890166,1314614072,890768,1315504238,891372,1316395006,891975,1317286378,892579,1318178353,893183,1319070932,893788,1319964115,894394,1320857903,894999,1321752297, 895605,1322647296,896211,1323542901,896819,1324439112,897425,1325335931,898034,1326233356,898641,1327131390,899250,1328030031,899859,1328929281,900468,1329829140,901078,1330729608,901688,1331630686, 902298,1332532374,902910,1333434672,903521,1334337582,904132,1335241103,904745,1336145235,905358,1337049980,905971,1337955338,906584,1338861309,907198,1339767893,907812,1340675091,908427,1341582903, 909042,1342491330,909658,1343400372,910273,1344310030,910890,1345220303,911507,1346131193,912124,1347042700,912741,1347954824,913360,1348867565,913978,1349780925,914597,1350694903,915216,1351609500, 915836,1352524716,916457,1353440552,917076,1354357009,917698,1355274085,918319,1356191783,918941,1357110102,919563,1358029043,920186,1358948606,920809,1359868792,921432,1360789601,922057,1361711033, 922680,1362633090,923306,1363555770,923930,1364479076,924557,1365403006,925182,1366327563,925809,1367252745,926435,1368178554,927063,1369104989,927691,1370032052,928319,1370959743,928948,1371888062, 929576,1372817010,930206,1373746586,930836,1374676792,931466,1375607628,932097,1376539094,932728,1377471191,933360,1378403919,933991,1379337279,934624,1380271270,935257,1381205894,935890,1382141151, 936524,1383077041,937158,1384013565,937793,1384950723,938428,1385888516,939063,1386826944,939699,1387766007,940335,1388705706,940972,1389646041,941609,1390587013,942247,1391528622,942885,1392470869, 943523,1393413754,944162,1394357277,944801,1395301439,945442,1396246240,946081,1397191682,946722,1398137763,947363,1399084485,948005,1400031848,948646,1400979853,949289,1401928499,949931,1402877788, 950575,1403827719,951219,1404778294,951862,1405729513,952507,1406681375,953153,1407633882,953797,1408587035,954443,1409540832,955090,1410495275,955736,1411450365,956384,1412406101,957031,1413362485, 957679,1414319516,958328,1415277195,958976,1416235523,959626,1417194499,960276,1418154125,960926,1419114401,961576,1420075327,962228,1421036903,962879,1421999131,963532,1422962010,964183,1423925542, 964837,1424889725,965490,1425854562,966144,1426820052,966797,1427786196,967453,1428752993,968107,1429720446,968764,1430688553,969419,1431657317,970075,1432626736,970733,1433596811,971389,1434567544, 972048,1435538933,972706,1436510981,973364,1437483687,974023,1438457051,974683,1439431074,975343,1440405757,976004,1441381100,976664,1442357104,977325,1443333768,977988,1444311093,978649,1445289081, 979313,1446267730,979975,1447247043,980639,1448227018,981303,1449207657,981967,1450188960,982633,1451170927,983298,1452153560,983963,1453136858,984630,1454120821,985297,1455105451,985963,1456090748, 986632,1457076711,987299,1458063343,987968,1459050642,988637,1460038610,989306,1461027247,989977,1462016553,990646,1463006530,991318,1463997176,991988,1464988494,992661,1465980482,993332,1466973143, 994005,1467966475,994679,1468960480,995351,1469955159,996026,1470950510,996700,1471946536,997375,1472943236,998051,1473940611,998726,1474938662,999403,1475937388,1000079,1476936791,1000756,1477936870, 1001434,1478937626,1002112,1479939060,1002791,1480941172,1003470,1481943963,1004149,1482947433,1004829,1483951582,1005510,1484956411,1006190,1485961921,1006872,1486968111,1007554,1487974983,1008235,1488982537, 1008919,1489990772,1009602,1490999691,1010285,1492009293,1010969,1493019578,1011654,1494030547,1012339,1495042201,1013025,1496054540,1013710,1497067565,1014397,1498081275,1015083,1499095672,1015771,1500110755, 1016459,1501126526,1017147,1502142985,1017836,1503160132,1018525,1504177968,1019215,1505196493,1019905,1506215708,1020596,1507235613,1021286,1508256209,1021978,1509277495,1022670,1510299473,1023363,1511322143, 1024055,1512345506,1024749,1513369561,1025443,1514394310,1026138,1515419753,1026832,1516445891,1027527,1517472723,1028223,1518500250,1028919,1519528473,1029617,1520557392,1030313,1521587009,1031011,1522617322, 1031709,1523648333,1032407,1524680042,1033107,1525712449,1033806,1526745556,1034507,1527779362,1035207,1528813869,1035907,1529849076,1036610,1530884983,1037311,1531921593,1038013,1532958904,1038717,1533996917, 1039419,1535035634,1040124,1536075053,1040828,1537115177,1041532,1538156005,1042238,1539197537,1042944,1540239775,1043650,1541282719,1044356,1542326369,1045064,1543370725,1045771,1544415789,1046480,1545461560, 1047188,1546508040,1047897,1547555228,1048607,1548603125,1049316,1549651732,1050028,1550701048,1050738,1551751076,1051450,1552801814,1052161,1553853264,1052875,1554905425,1053587,1555958300,1054300,1557011887, 1055015,1558066187,1055729,1559121202,1056443,1560176931,1057159,1561233374,1057875,1562290533,1058591,1563348408,1059308,1564406999,1060026,1565466307,1060743,1566526333,1061461,1567587076,1062180,1568648537, 1062899,1569710717,1063619,1570773616,1064340,1571837235,1065060,1572901575,1065781,1573966635,1066503,1575032416,1067224,1576098919,1067948,1577166143,1068671,1578234091,1069394,1579302762,1070119,1580372156, 1070843,1581442275,1071568,1582513118,1072294,1583584686,1073020,1584656980,1073746,1585730000,1074474,1586803746,1075201,1587878220,1075929,1588953421,1076658,1590029350,1077386,1591106008,1078116,1592183394, 1078847,1593261510,1079577,1594340357,1080307,1595419934,1081040,1596500241,1081771,1597581281,1082504,1598663052,1083237,1599745556,1083970,1600828793,1084704,1601912763,1085439,1602997467,1086174,1604082906, 1086909,1605169080,1087645,1606255989,1088382,1607343634,1089119,1608432016,1089856,1609521135,1090594,1610610991,1091333,1611701585,1092071,1612792918,1092811,1613884989,1093551,1614977800,1094292,1616071351, 1095032,1617165643,1095774,1618260675,1096516,1619356449,1097259,1620452965,1098001,1621550224,1098745,1622648225,1099489,1623746970,1100233,1624846459,1100979,1625946692,1101724,1627047671,1102470,1628149395, 1103216,1629251865,1103963,1630355081,1104711,1631459044,1105459,1632563755,1106208,1633669214,1106957,1634775422,1107706,1635882379,1108456,1636990085,1109207,1638098541,1109958,1639207748,1110709,1640317706, 1111462,1641428415,1112214,1642539877,1112967,1643652091,1113721,1644765058,1114475,1645878779,1115230,1646993254,1115985,1648108484,1116740,1649224469,1117497,1650341209,1118253,1651458706,1119011,1652576959, 1119768,1653695970,1120527,1654815738,1121285,1655936265,1122044,1657057550,1122805,1658179594,1123564,1659302399,1124326,1660425963,1125086,1661550289,1125849,1662675375,1126611,1663801224,1127374,1664927835, 1128137,1666055209,1128901,1667183346,1129665,1668312247,1130430,1669441912,1131196,1670572342,1131962,1671703538,1132728,1672835500,1133496,1673968228,1134262,1675101724,1135031,1676235986,1135800,1677371017, 1136568,1678506817,1137338,1679643385,1138108,1680780723,1138879,1681918831,1139650,1683057710,1140422,1684197360,1141194,1685337782,1141967,1686478976,1142740,1687620943,1143513,1688763683,1144288,1689907196, 1145063,1691051484,1145838,1692196547,1146615,1693342385,1147390,1694489000,1148167,1695636390,1148945,1696784557,1149723,1697933502,1150502,1699083225,1151280,1700233727,1152060,1701385007,1152840,1702537067, 1153621,1703689907,1154402,1704843528,1155183,1705997930,1155966,1707153113,1156749,1708309079,1157531,1709465828,1158316,1710623359,1159100,1711781675,1159885,1712940775,1160670,1714100660,1161456,1715261330, 1162243,1716422786,1163029,1717585029,1163817,1718748058,1164605,1719911875,1165394,1721076480,1166183,1722241874,1166972,1723408057,1167763,1724575029,1168553,1725742792,1169345,1726911345,1170137,1728080690, 1170928,1729250827,1171722,1730421755,1172515,1731593477,1173309,1732765992,1174104,1733939301,1174898,1735113405,1175694,1736288303,1176491,1737463997,1177286,1738640488,1178084,1739817774,1178882,1740995858, 1179680,1742174740,1180479,1743354420,1181278,1744534899,1182078,1745716177,1182878,1746898255,1183680,1748081133,1184481,1749264813,1185283,1750449294,1186085,1751634577,1186889,1752820662,1187692,1754007551, 1188497,1755195243,1189301,1756383740,1190107,1757573041,1190912,1758763148,1191719,1759954060,1192526,1761145779,1193333,1762338305,1194142,1763531638,1194950,1764725780,1195759,1765920730,1196569,1767116489, 1197379,1768313058,1198190,1769510437,1199001,1770708627,1199813,1771907628,1200625,1773107441,1201439,1774308066,1202252,1775509505,1203066,1776711757,1203881,1777914823,1204695,1779118704,1205512,1780323399, 1206328,1781528911,1207145,1782735239,1207962,1783942384,1208780,1785150346,1209598,1786359126,1210418,1787568724,1211237,1788779142,1212058,1789990379,1212878,1791202437,1213699,1792415315,1214522,1793629014, 1215343,1794843536,1216167,1796058879,1216990,1797275046,1217814,1798492036,1218639,1799709850,1219464,1800928489,1220290,1802147953,1221116,1803368243,1221942,1804589359,1222771,1805811301,1223598,1807034072, 1224427,1808257670,1225256,1809482097,1226085,1810707353,1226916,1811933438,1227746,1813160354,1228578,1814388100,1229410,1815616678,1230242,1816846088,1231076,1818076330,1231908,1819307406,1232743,1820539314, 1233578,1821772057,1234413,1823005635,1235249,1824240048,1236086,1825475297,1236922,1826711383,1237760,1827948305,1238598,1829186065,1239437,1830424663,1240276,1831664100,1241115,1832904376,1241957,1834145491, 1242797,1835387448,1243638,1836630245,1244481,1837873883,1245324,1839118364,1246167,1840363688,1247010,1841609855,1247855,1842856865,1248700,1844104720,1249545,1845353420,1250392,1846602965,1251238,1847853357, 1252086,1849104595,1252933,1850356681,1253782,1851609614,1254630,1852863396,1255481,1854118026,1256330,1855373507,1257181,1856629837,1258032,1857887018,1258884,1859145050,1259737,1860403934,1260590,1861663671, 1261443,1862924261,1262297,1864185704,1263152,1865448001,1264008,1866711153,1264863,1867975161,1265720,1869240024,1266577,1870505744,1267434,1871772321,1268293,1873039755,1269151,1874308048,1270011,1875577199, 1270871,1876847210,1271732,1878118081,1272592,1879389813,1273454,1880662405,1274317,1881935859,1275179,1883210176,1276043,1884485355,1276907,1885761398,1277772,1887038305,1278636,1888316077,1279503,1889594713, 1280369,1890874216,1281236,1892154585,1282103,1893435821,1282972,1894717924,1283840,1896000896,1284710,1897284736,1285580,1898569446,1286450,1899855026,1287321,1901141476,1288193,1902428797,1289065,1903716990, 1289938,1905006055,1290812,1906295993,1291685,1907586805,1292561,1908878490,1293435,1910171051,1294311,1911464486,1295188,1912758797,1296065,1914053985,1296942,1915350050,1297821,1916646992,1298699,1917944813, 1299579,1919243512,1300458,1920543091,1301340,1921843549,1302220,1923144889,1303102,1924447109,1303985,1925750211,1304867,1927054196,1305751,1928359063,1306636,1929664814,1307520,1930971450,1308405,1932278970, 1309291,1933587375,1310178,1934896666,1311065,1936206844,1311953,1937517909,1312842,1938829862,1313730,1940142704,1314619,1941456434,1315510,1942771053,1316401,1944086563,1317292,1945402964,1318184,1946720256, 1319077,1948038440,1319970,1949357517,1320863,1950677487,1321758,1951998350,1322653,1953320108,1323549,1954642761,1324445,1955966310,1325341,1957290755,1326239,1958616096,1327137,1959942335,1328036,1961269472, 1328935,1962597508,1329835,1963926443,1330735,1965256278,1331637,1966587013,1332538,1967918650,1333440,1969251188,1334344,1970584628,1335247,1971918972,1336151,1973254219,1337055,1974590370,1337961,1975927425, 1338867,1977265386,1339774,1978604253,1340681,1979944027,1341589,1981284708,1342497,1982626297,1343406,1983968794,1344316,1985312200,1345226,1986656516,1346137,1988001742,1347048,1989347879,1347961,1990694927, 1348873,1992042888,1349787,1993391761,1350701,1994741548,1351615,1996092249,1352531,1997443864,1353446,1998796395,1354363,2000149841,1355280,2001504204,1356198,2002859484,1357116,2004215682,1358034,2005572798, 1358955,2006930832,1359875,2008289787,1360795,2009649662,1361717,2011010457,1362639,2012372174,1363562,2013734813,1364485,2015098375,1365408,2016462860,1366334,2017828268,1367258,2019194602,1368185,2020561860, 1369111,2021930045,1370038,2023299156,1370965,2024669194,1371894,2026040159,1372823,2027412053,1373753,2028784876,1374683,2030158629,1375613,2031533312,1376545,2032908925,1377477,2034285470,1378410,2035662947, 1379343,2037041357,1380278,2038420700,1381211,2039800978,1382148,2041182189,1383083,2042564337,1384019,2043947420,1384957,2045331439,1385894,2046716396,1386833,2048102290,1387772,2049489123,1388712,2050876895, 1389652,2052265607,1390593,2053655259,1391535,2055045852,1392476,2056437387,1393420,2057829863,1394363,2059223283,1395308,2060617646,1396252,2062012954,1397198,2063409206,1398144,2064806404,1399090,2066204548, 1400038,2067603638,1400986,2069003676,1401935,2070404662,1402883,2071806597,1403834,2073209480,1404785,2074613314,1405735,2076018099,1406688,2077423834,1407639,2078830522,1408594,2080238161,1409546,2081646755, 1410502,2083056301,1411456,2084466803,1412412,2085878259,1413369,2087290671,1414326,2088704040,1415283,2090118366,1416242,2091533649,1417200,2092949891,1418160,2094367091,1419121,2095785251,1420081,2097204372, 1421043,2098624453,1422006,2100045496,1422968,2101467502,1423932,2102890470,1424895,2104314402,1425861,2105739297,1426826,2107165158,1427793,2108591984,1428759,2110019777,1429726,2111448536,1430695,2112878262, 1431664,2114308957,1432633,2115740621,1433603,2117173254,1434573,2118606857,1435545,2120041430,1436518,2121476975,1437489,2122913493,1438464,2124350982,1439437,2125789446,1440412,2127228883,1441387,2128669295, 1442364,2130110682,1443340,2131553046,1444317,2132996386,1445295,2134440703,1446274,2135885998,1447253,2137332272,1448234,2138779525,1449214,2140227759,1450195,2141676973,1451177,2143127168,1452160,2144578345, 1453143,2146030505, }; void Tanh::init() {} #else int32_t exp2tab[EXP2_N_SAMPLES << 1]; void Exp2::init() { double inc = exp2(1.0 / EXP2_N_SAMPLES); double y = 1 << 30; for (int i = 0; i < EXP2_N_SAMPLES; i++) { exp2tab[(i << 1) + 1] = (int32_t)floor(y + 0.5); y *= inc; } for (int i = 0; i < EXP2_N_SAMPLES - 1; i++) { exp2tab[i << 1] = exp2tab[(i << 1) + 3] - exp2tab[(i << 1) + 1]; } exp2tab[(EXP2_N_SAMPLES << 1) - 2] = (1U << 31) - exp2tab[(EXP2_N_SAMPLES << 1) - 1]; } int32_t tanhtab[TANH_N_SAMPLES << 1]; static double dtanh(double y) { return 1 - y * y; } void Tanh::init() { double step = 4.0 / TANH_N_SAMPLES; double y = 0; for (int i = 0; i < TANH_N_SAMPLES; i++) { tanhtab[(i << 1) + 1] = (1 << 24) * y + 0.5; //printf("%d\n", tanhtab[(i << 1) + 1]); // Use a basic 4th order Runge-Kutte to compute tanh from its // differential equation. double k1 = dtanh(y); double k2 = dtanh(y + 0.5 * step * k1); double k3 = dtanh(y + 0.5 * step * k2); double k4 = dtanh(y + step * k3); double dy = (step / 6) * (k1 + k4 + 2 * (k2 + k3)); y += dy; } for (int i = 0; i < TANH_N_SAMPLES - 1; i++) { tanhtab[i << 1] = tanhtab[(i << 1) + 3] - tanhtab[(i << 1) + 1]; } int32_t lasty = (1 << 24) * y + 0.5; tanhtab[(TANH_N_SAMPLES << 1) - 2] = lasty - tanhtab[(TANH_N_SAMPLES << 1) - 1]; } #endif ================================================ FILE: lib/msfa/exp2.h ================================================ /* * 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. */ #pragma once class Exp2 { public: Exp2(); static void init(); // Q24 in, Q24 out static int32_t lookup(int32_t x); }; #define EXP2_LG_N_SAMPLES 10 #define EXP2_N_SAMPLES (1 << EXP2_LG_N_SAMPLES) #define EXP2_INLINE extern const int32_t exp2tab[EXP2_N_SAMPLES << 1]; #ifdef EXP2_INLINE inline int32_t Exp2::lookup(int32_t x) { const int SHIFT = 24 - EXP2_LG_N_SAMPLES; int lowbits = x & ((1 << SHIFT) - 1); int x_int = (x >> (SHIFT - 1)) & ((EXP2_N_SAMPLES - 1) << 1); int dy = exp2tab[x_int]; int y0 = exp2tab[x_int + 1]; int y = y0 + (((int64_t)dy * (int64_t)lowbits) >> SHIFT); return y >> (6 - (x >> 24)); } #endif class Tanh { public: static void init(); // Q24 in, Q24 out static int32_t lookup(int32_t x); }; #define TANH_LG_N_SAMPLES 10 #define TANH_N_SAMPLES (1 << TANH_LG_N_SAMPLES) extern const int32_t tanhtab[TANH_N_SAMPLES << 1]; inline int32_t Tanh::lookup(int32_t x) { int32_t signum = x >> 31; x ^= signum; if (x >= (4 << 24)) { if (x >= (17 << 23)) { return signum ^ (1 << 24); } int32_t sx = ((int64_t)-48408812 * (int64_t)x) >> 24; return signum ^ ((1 << 24) - 2 * Exp2::lookup(sx)); } else { const int SHIFT = 26 - TANH_LG_N_SAMPLES; int lowbits = x & ((1 << SHIFT) - 1); int x_int = (x >> (SHIFT - 1)) & ((TANH_N_SAMPLES - 1) << 1); int dy = tanhtab[x_int]; int y0 = tanhtab[x_int + 1]; int y = y0 + (((int64_t)dy * (int64_t)lowbits) >> SHIFT); return y ^ signum; } } ================================================ FILE: lib/msfa/fm_core.cc ================================================ /* * 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 #endif #include "synth.h" #include "exp2.h" #include "fm_op_kernel.h" #include "fm_core.h" //using namespace std; const FmAlgorithm FmCore::algorithms[32] = { { { 0xc1, 0x11, 0x11, 0x14, 0x01, 0x14 } }, // 1 { { 0x01, 0x11, 0x11, 0x14, 0xc1, 0x14 } }, // 2 { { 0xc1, 0x11, 0x14, 0x01, 0x11, 0x14 } }, // 3 { { 0xc1, 0x11, 0x94, 0x01, 0x11, 0x14 } }, // 4 { { 0xc1, 0x14, 0x01, 0x14, 0x01, 0x14 } }, // 5 { { 0xc1, 0x94, 0x01, 0x14, 0x01, 0x14 } }, // 6 { { 0xc1, 0x11, 0x05, 0x14, 0x01, 0x14 } }, // 7 { { 0x01, 0x11, 0xc5, 0x14, 0x01, 0x14 } }, // 8 { { 0x01, 0x11, 0x05, 0x14, 0xc1, 0x14 } }, // 9 { { 0x01, 0x05, 0x14, 0xc1, 0x11, 0x14 } }, // 10 { { 0xc1, 0x05, 0x14, 0x01, 0x11, 0x14 } }, // 11 { { 0x01, 0x05, 0x05, 0x14, 0xc1, 0x14 } }, // 12 { { 0xc1, 0x05, 0x05, 0x14, 0x01, 0x14 } }, // 13 { { 0xc1, 0x05, 0x11, 0x14, 0x01, 0x14 } }, // 14 { { 0x01, 0x05, 0x11, 0x14, 0xc1, 0x14 } }, // 15 { { 0xc1, 0x11, 0x02, 0x25, 0x05, 0x14 } }, // 16 { { 0x01, 0x11, 0x02, 0x25, 0xc5, 0x14 } }, // 17 { { 0x01, 0x11, 0x11, 0xc5, 0x05, 0x14 } }, // 18 { { 0xc1, 0x14, 0x14, 0x01, 0x11, 0x14 } }, // 19 { { 0x01, 0x05, 0x14, 0xc1, 0x14, 0x14 } }, // 20 { { 0x01, 0x14, 0x14, 0xc1, 0x14, 0x14 } }, // 21 { { 0xc1, 0x14, 0x14, 0x14, 0x01, 0x14 } }, // 22 { { 0xc1, 0x14, 0x14, 0x01, 0x14, 0x04 } }, // 23 { { 0xc1, 0x14, 0x14, 0x14, 0x04, 0x04 } }, // 24 { { 0xc1, 0x14, 0x14, 0x04, 0x04, 0x04 } }, // 25 { { 0xc1, 0x05, 0x14, 0x01, 0x14, 0x04 } }, // 26 { { 0x01, 0x05, 0x14, 0xc1, 0x14, 0x04 } }, // 27 { { 0x04, 0xc1, 0x11, 0x14, 0x01, 0x14 } }, // 28 { { 0xc1, 0x14, 0x01, 0x14, 0x04, 0x04 } }, // 29 { { 0x04, 0xc1, 0x11, 0x14, 0x04, 0x04 } }, // 30 { { 0xc1, 0x14, 0x04, 0x04, 0x04, 0x04 } }, // 31 { { 0xc4, 0x04, 0x04, 0x04, 0x04, 0x04 } }, // 32 }; int n_out(const FmAlgorithm &alg) { int count = 0; for (int i = 0; i < 6; i++) { if ((alg.ops[i] & 7) == OUT_BUS_ADD) count++; } return count; } void FmCore::dump() { #ifdef VERBOSE for (int i = 0; i < 32; i++) { cout << (i + 1) << ":"; const FmAlgorithm &alg = algorithms[i]; for (int j = 0; j < 6; j++) { int flags = alg.ops[j]; cout << " "; if (flags & FB_IN) cout << "["; cout << (flags & IN_BUS_ONE ? "1" : flags & IN_BUS_TWO ? "2" : "0") << "->"; cout << (flags & OUT_BUS_ONE ? "1" : flags & OUT_BUS_TWO ? "2" : "0"); if (flags & OUT_BUS_ADD) cout << "+"; //cout << alg.ops[j].in << "->" << alg.ops[j].out; if (flags & FB_OUT) cout << "]"; } cout << " " << n_out(alg); cout << endl; } #endif } void FmCore::render(int32_t *output, FmOpParams *params, int algorithm, int32_t *fb_buf, int32_t feedback_shift) { const int kLevelThresh = 1120; const FmAlgorithm alg = algorithms[algorithm]; bool has_contents[3] = { true, false, false }; for (int op = 0; op < 6; op++) { int flags = alg.ops[op]; bool add = (flags & OUT_BUS_ADD) != 0; FmOpParams ¶m = params[op]; int inbus = (flags >> 4) & 3; int outbus = flags & 3; int32_t *outptr = (outbus == 0) ? output : buf_[outbus - 1].get(); int32_t gain1 = param.gain_out; int32_t gain2 = Exp2::lookup(param.level_in - (14 * (1 << 24))); param.gain_out = gain2; if (gain1 >= kLevelThresh || gain2 >= kLevelThresh) { if (!has_contents[outbus]) { add = false; } if (inbus == 0 || !has_contents[inbus]) { // todo: more than one op in a feedback loop if ((flags & 0xc0) == 0xc0 && feedback_shift < 16) { // cout << op << " fb " << inbus << outbus << add << endl; FmOpKernel::compute_fb(outptr, param.phase, param.freq, gain1, gain2, fb_buf, feedback_shift, add); } else { // cout << op << " pure " << inbus << outbus << add << endl; FmOpKernel::compute_pure(outptr, param.phase, param.freq, gain1, gain2, add); } } else { // cout << op << " normal " << inbus << outbus << " " << param.freq << add << endl; FmOpKernel::compute(outptr, buf_[inbus - 1].get(), param.phase, param.freq, gain1, gain2, add); } has_contents[outbus] = true; } else if (!add) { has_contents[outbus] = false; } param.phase += param.freq << LG_N; } } ================================================ FILE: lib/msfa/fm_core.h ================================================ /* * 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. */ #ifndef __FM_CORE_H #define __FM_CORE_H #include "aligned_buf.h" #include "fm_op_kernel.h" #include "synth.h" #include "controllers.h" class FmOperatorInfo { public: int in; int out; }; enum FmOperatorFlags { OUT_BUS_ONE = 1 << 0, OUT_BUS_TWO = 1 << 1, OUT_BUS_ADD = 1 << 2, IN_BUS_ONE = 1 << 4, IN_BUS_TWO = 1 << 5, FB_IN = 1 << 6, FB_OUT = 1 << 7 }; class FmAlgorithm { public: int ops[6]; }; class FmCore { public: virtual ~FmCore() {}; static void dump(); virtual void render(int32_t *output, FmOpParams *params, int algorithm, int32_t *fb_buf, int32_t feedback_gain); protected: AlignedBufbuf_[2]; const static FmAlgorithm algorithms[32]; }; #endif // __FM_CORE_H ================================================ FILE: lib/msfa/fm_op_kernel.cc ================================================ /* * 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 #include #ifdef HAVE_NEON #include #endif #include "synth.h" #include "sin.h" #include "fm_op_kernel.h" #ifdef HAVE_NEONx static bool hasNeon() { return true; return (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0; } extern "C" void neon_fm_kernel(const int *in, const int *busin, int *out, int count, int32_t phase0, int32_t freq, int32_t gain1, int32_t dgain); const int32_t __attribute__ ((aligned(16))) zeros[N] = {0}; #else static bool hasNeon() { return false; } #endif void FmOpKernel::compute(int32_t *output, const int32_t *input, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; if (hasNeon()) { #ifdef HAVE_NEON neon_fm_kernel(input, add ? output : zeros, output, N, phase0, freq, gain, dgain); #endif } else { if (add) { for (int i = 0; i < N; i++) { gain += dgain; int32_t y = Sin::lookup(phase + input[i]); int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24; output[i] += y1; phase += freq; } } else { for (int i = 0; i < N; i++) { gain += dgain; int32_t y = Sin::lookup(phase + input[i]); int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24; output[i] = y1; phase += freq; } } } } void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; if (hasNeon()) { #ifdef HAVE_NEON neon_fm_kernel(zeros, add ? output : zeros, output, N, phase0, freq, gain, dgain); #endif } else { if (add) { for (int i = 0; i < N; i++) { gain += dgain; int32_t y = Sin::lookup(phase); int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24; output[i] += y1; phase += freq; } } else { for (int i = 0; i < N; i++) { gain += dgain; int32_t y = Sin::lookup(phase); int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24; output[i] = y1; phase += freq; } } } } #define noDOUBLE_ACCURACY #define HIGH_ACCURACY void FmOpKernel::compute_fb(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, int32_t *fb_buf, int fb_shift, bool add) { int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; int32_t y0 = fb_buf[0]; int32_t y = fb_buf[1]; if (add) { for (int i = 0; i < N; i++) { gain += dgain; int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); y0 = y; y = Sin::lookup(phase + scaled_fb); y = ((int64_t)y * (int64_t)gain) >> 24; output[i] += y; phase += freq; } } else { for (int i = 0; i < N; i++) { gain += dgain; int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); y0 = y; y = Sin::lookup(phase + scaled_fb); y = ((int64_t)y * (int64_t)gain) >> 24; output[i] = y; phase += freq; } } fb_buf[0] = y0; fb_buf[1] = y; } //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// // Experimental sine wave generators below #if 0 // Results: accuracy 64.3 mean, 170 worst case // high accuracy: 5.0 mean, 49 worst case void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; #ifdef HIGH_ACCURACY int32_t u = Sin::compute10(phase << 6); u = ((int64_t)u * gain) >> 30; int32_t v = Sin::compute10((phase << 6) + (1 << 28)); // quarter cycle v = ((int64_t)v * gain) >> 30; int32_t s = Sin::compute10(freq << 6); int32_t c = Sin::compute10((freq << 6) + (1 << 28)); #else int32_t u = Sin::compute(phase); u = ((int64_t)u * gain) >> 24; int32_t v = Sin::compute(phase + (1 << 22)); // quarter cycle v = ((int64_t)v * gain) >> 24; int32_t s = Sin::compute(freq) << 6; int32_t c = Sin::compute(freq + (1 << 22)) << 6; #endif for (int i = 0; i < N; i++) { output[i] = u; int32_t t = ((int64_t)v * (int64_t)c - (int64_t)u * (int64_t)s) >> 30; u = ((int64_t)u * (int64_t)c + (int64_t)v * (int64_t)s) >> 30; v = t; } } #endif #if 0 // Results: accuracy 392.3 mean, 15190 worst case (near freq = 0.5) // for freq < 0.25, 275.2 mean, 716 worst // high accuracy: 57.4 mean, 7559 worst // freq < 0.25: 17.9 mean, 78 worst void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; #ifdef HIGH_ACCURACY int32_t u = floor(gain * sin(phase * (M_PI / (1 << 23))) + 0.5); int32_t v = floor(gain * cos((phase - freq * 0.5) * (M_PI / (1 << 23))) + 0.5); int32_t a = floor((1 << 25) * sin(freq * (M_PI / (1 << 24))) + 0.5); #else int32_t u = Sin::compute(phase); u = ((int64_t)u * gain) >> 24; int32_t v = Sin::compute(phase + (1 << 22) - (freq >> 1)); v = ((int64_t)v * gain) >> 24; int32_t a = Sin::compute(freq >> 1) << 1; #endif for (int i = 0; i < N; i++) { output[i] = u; v -= ((int64_t)a * (int64_t)u) >> 24; u += ((int64_t)a * (int64_t)v) >> 24; } } #endif #if 0 // Results: accuracy 370.0 mean, 15480 worst case (near freq = 0.5) // with double accuracy initialization: mean 1.55, worst 58 (near freq = 0) // with high accuracy: mean 4.2, worst 292 (near freq = 0.5) void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; #ifdef DOUBLE_ACCURACY int32_t u = floor((1 << 30) * sin(phase * (M_PI / (1 << 23))) + 0.5); double a_d = sin(freq * (M_PI / (1 << 24))); int32_t v = floor((1LL << 31) * a_d * cos((phase - freq * 0.5) * (M_PI / (1 << 23))) + 0.5); int32_t aa = floor((1LL << 31) * a_d * a_d + 0.5); #else #ifdef HIGH_ACCURACY int32_t u = Sin::compute10(phase << 6); int32_t v = Sin::compute10((phase << 6) + (1 << 28) - (freq << 5)); int32_t a = Sin::compute10(freq << 5); v = ((int64_t)v * (int64_t)a) >> 29; int32_t aa = ((int64_t)a * (int64_t)a) >> 29; #else int32_t u = Sin::compute(phase) << 6; int32_t v = Sin::compute(phase + (1 << 22) - (freq >> 1)); int32_t a = Sin::compute(freq >> 1); v = ((int64_t)v * (int64_t)a) >> 17; int32_t aa = ((int64_t)a * (int64_t)a) >> 17; #endif #endif if (aa < 0) aa = (1 << 31) - 1; for (int i = 0; i < N; i++) { gain += dgain; output[i] = ((int64_t)u * (int64_t)gain) >> 30; v -= ((int64_t)aa * (int64_t)u) >> 29; u += v; } } #endif #if 0 // Results:: accuracy 112.3 mean, 4262 worst (near freq = 0.5) // high accuracy 2.9 mean, 143 worst void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; #ifdef HIGH_ACCURACY int32_t u = Sin::compute10(phase << 6); int32_t lastu = Sin::compute10((phase - freq) << 6); int32_t a = Sin::compute10((freq << 6) + (1 << 28)) << 1; #else int32_t u = Sin::compute(phase) << 6; int32_t lastu = Sin::compute(phase - freq) << 6; int32_t a = Sin::compute(freq + (1 << 22)) << 7; #endif if (a < 0 && freq < 256) a = (1 << 31) - 1; if (a > 0 && freq > 0x7fff00) a = -(1 << 31); for (int i = 0; i < N; i++) { gain += dgain; output[i] = ((int64_t)u * (int64_t)gain) >> 30; //output[i] = u; int32_t newu = (((int64_t)u * (int64_t)a) >> 30) - lastu; lastu = u; u = newu; } } #endif ================================================ FILE: lib/msfa/fm_op_kernel.h ================================================ /* * 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. */ #ifndef __FM_OP_KERNEL_H #define __FM_OP_KERNEL_H struct FmOpParams { int32_t level_in; // value to be computed (from level to gain[0]) int32_t gain_out; // computed value (gain[1] to gain[0]) int32_t freq; int32_t phase; }; class FmOpKernel { public: // gain1 and gain2 represent linear step: gain for sample i is // gain1 + (1 + i) / 64 * (gain2 - gain1) // This is the basic FM operator. No feedback. static void compute(int32_t *output, const int32_t *input, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add); // This is a sine generator, no feedback. static void compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add); // One op with feedback, no add. static void compute_fb(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, int32_t *fb_buf, int fb_gain, bool add); }; #endif ================================================ FILE: lib/msfa/freqlut.cc ================================================ /* * 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. */ // Resolve frequency signal (1.0 in Q24 format = 1 octave) to phase delta. // The LUT is just a global, and we'll need the init function to be called before // use. #include #include #include "freqlut.h" #define LG_N_SAMPLES 10 #define N_SAMPLES (1 << LG_N_SAMPLES) #define SAMPLE_SHIFT (24 - LG_N_SAMPLES) #define MAX_LOGFREQ_INT 20 #if 1 //eh2k #ifndef FLASHMEM #include "pgmspace.h" #endif const int32_t lut[N_SAMPLES + 1] FLASHMEM = { 366503872,366752043,367000382,367248889,367497565,367746409,367995421,368244602,368493952,368743470,368993158,369243014,369493040,369743235,369993600,370244134,370494838,370745711,370996754,371247968,371499351,371750905, 372002628,372254523,372506588,372758823,373011230,373263807,373516556,373769475,374022566,374275828,374529262,374782867,375036644,375290593,375544714,375799006,376053472,376308109,376562919,376817901,377073056,377328384, 377583884,377839558,378095405,378351425,378607618,378863985,379120525,379377239,379634127,379891189,380148425,380405835,380663420,380921179,381179112,381437220,381695503,381953961,382212594,382471402,382730385,382989543, 383248877,383508387,383768072,384027933,384287970,384548183,384808573,385069139,385329881,385590799,385851895,386113167,386374616,386636242,386898045,387160026,387422184,387684519,387947032,388209723,388472592,388735639, 388998863,389262267,389525848,389789608,390053546,390317664,390581960,390846435,391111089,391375922,391640935,391906127,392171499,392437050,392702781,392968692,393234783,393501055,393767506,394034138,394300951,394567944, 394835118,395102473,395370009,395637727,395905625,396173705,396441966,396710409,396979034,397247841,397516829,397786000,398055353,398324889,398594607,398864507,399134591,399404857,399675306,399945939,400216755,400487754, 400758936,401030302,401301852,401573586,401845504,402117606,402389892,402662363,402935018,403207857,403480882,403754091,404027485,404301065,404574829,404848779,405122915,405397236,405671743,405946436,406221314,406496379, 406771631,407047068,407322692,407598503,407874500,408150685,408427056,408703615,408980360,409257293,409534414,409811722,410089219,410366903,410644775,410922835,411201083,411479520,411758146,412036960,412315962,412595154, 412874535,413154105,413433864,413713813,413993952,414274280,414554797,414835505,415116403,415397491,415678769,415960238,416241898,416523748,416805789,417088021,417370444,417653058,417935864,418218861,418502050,418785431, 419069003,419352768,419636724,419920873,420205214,420489748,420774475,421059394,421344506,421629812,421915310,422201002,422486887,422772966,423059239,423345705,423632365,423919220,424206269,424493512,424780949,425068581, 425356408,425644430,425932647,426221059,426509667,426798469,427087468,427376662,427666052,427955638,428245419,428535398,428825572,429115943,429406511,429697275,429988236,430279394,430570750,430862302,431154052,431446000, 431738145,432030489,432323030,432615769,432908706,433201842,433495176,433788709,434082441,434376371,434670501,434964830,435259358,435554085,435849012,436144139,436439466,436734992,437030719,437326646,437622773,437919101, 438215629,438512359,438809289,439106420,439403752,439701286,439999021,440296958,440595097,440893437,441191980,441490724,441789671,442088821,442388173,442687727,442987485,443287445,443587609,443887975,444188546,444489319, 444790297,445091478,445392863,445694452,445996245,446298243,446600445,446902852,447205464,447508280,447811302,448114529,448417961,448721599,449025442,449329491,449633745,449938206,450242873,450547746,450852826,451158112, 451463605,451769305,452075212,452381326,452687647,452994176,453300912,453607856,453915008,454222368,454529936,454837712,455145697,455453890,455762292,456070902,456379722,456688750,456997988,457307436,457617093,457926959, 458237036,458547322,458857819,459168525,459479442,459790570,460101908,460413457,460725217,461037189,461349371,461661765,461974370,462287187,462600216,462913457,463226910,463540575,463854453,464168543,464482845,464797361, 465112090,465427031,465742186,466057555,466373136,466688932,467004941,467321165,467637602,467954254,468271120,468588201,468905496,469223007,469540732,469858672,470176828,470495199,470813786,471132589,471451607,471770841, 472090292,472409959,472729842,473049942,473370258,473690792,474011542,474332510,474653695,474975098,475296718,475618556,475940612,476262886,476585378,476908089,477231018,477554166,477877532,478201118,478524923,478848946, 479173190,479497653,479822335,480147238,480472360,480797703,481123266,481449049,481775053,482101277,482427723,482754390,483081277,483408387,483735717,484063270,484391044,484719040,485047258,485375698,485704361,486033246, 486362354,486691685,487021239,487351016,487681017,488011240,488341688,488672359,489003254,489334373,489665716,489997284,490329076,490661093,490993335,491325801,491658493,491991410,492324553,492657921,492991515,493325334, 493659380,493993652,494328150,494662875,494997826,495333005,495668410,496004042,496339902,496675989,497012303,497348845,497685616,498022614,498359840,498697295,499034978,499372890,499711031,500049401,500387999,500726827, 501065885,501405172,501744689,502084436,502424412,502764619,503105057,503445725,503786623,504127752,504469113,504810704,505152527,505494581,505836867,506179385,506522135,506865116,507208330,507551777,507895455,508239367, 508583512,508927889,509272500,509617344,509962421,510307733,510653278,510999057,511345070,511691317,512037799,512384516,512731467,513078653,513426074,513773731,514121623,514469750,514818114,515166713,515515548,515864619, 516213927,516563471,516913252,517263270,517613525,517964017,518314746,518665713,519016918,519368360,519720040,520071959,520424115,520776511,521129144,521482017,521835128,522188479,522542069,522895898,523249967,523604275, 523958824,524313613,524668641,525023911,525379420,525735171,526091162,526447395,526803869,527160584,527517540,527874739,528232179,528589861,528947785,529305952,529664361,530023013,530381908,530741046,531100427,531460052, 531819920,532180031,532540387,532900986,533261830,533622918,533984250,534345827,534707649,535069716,535432028,535794586,536157389,536520437,536883732,537247272,537611059,537975092,538339371,538703897,539068670,539433690, 539798957,540164472,540530234,540896243,541262501,541629006,541995760,542362762,542730012,543097511,543465259,543833256,544201503,544569998,544938743,545307738,545676983,546046477,546416222,546786217,547156463,547526959, 547897707,548268705,548639955,549011456,549383208,549755212,550127468,550499977,550872737,551245750,551619015,551992533,552366305,552740329,553114606,553489137,553863922,554238960,554614252,554989798,555365599,555741654, 556117964,556494528,556871348,557248423,557625753,558003338,558381179,558759276,559137629,559516239,559895104,560274226,560653605,561033241,561413134,561793284,562173691,562554356,562935279,563316460,563697899,564079596, 564461552,564843766,565226239,565608971,565991962,566375213,566758723,567142492,567526522,567910812,568295362,568680172,569065243,569450574,569836167,570222020,570608135,570994511,571381149,571768049,572155211,572542634, 572930321,573318269,573706481,574094955,574483692,574872693,575261957,575651484,576041276,576431331,576821650,577212234,577603082,577994195,578385572,578777215,579169123,579561296,579953735,580346439,580739410,581132646, 581526149,581919918,582313954,582708256,583102826,583497663,583892767,584288139,584683778,585079686,585475861,585872305,586269017,586665998,587063247,587460766,587858553,588256610,588654937,589053533,589452400,589851536, 590250942,590650620,591050567,591450786,591851275,592252036,592653068,593054371,593455947,593857794,594259913,594662305,595064969,595467906,595871115,596274598,596678354,597082383,597486686,597891262,598296113,598701238, 599106637,599512310,599918258,600324481,600730979,601137753,601544802,601952126,602359726,602767603,603175755,603584184,603992889,604401871,604811130,605220667,605630480,606040571,606450940,606861586,607272511,607683714, 608095195,608506955,608918994,609331312,609743908,610156785,610569941,610983376,611397092,611811088,612225364,612639920,613054758,613469876,613885275,614300956,614716918,615133161,615549687,615966494,616383584,616800957, 617218611,617636549,618054770,618473274,618892061,619311132,619730486,620150125,620570047,620990254,621410746,621831522,622252583,622673930,623095561,623517479,623939681,624362170,624784945,625208006,625631353,626054988, 626478909,626903117,627327612,627752395,628177465,628602824,629028470,629454404,629880627,630307139,630733939,631161028,631588407,632016075,632444032,632872280,633300817,633729644,634158762,634588170,635017869,635447860, 635878141,636308713,636739578,637170733,637602181,638033921,638465954,638898279,639330896,639763807,640197011,640630508,641064298,641498382,641932761,642367433,642802400,643237661,643673217,644109068,644545214,644981655, 645418392,645855425,646292753,646730378,647168299,647606516,648045031,648483842,648922950,649362356,649802059,650242060,650682359,651122956,651563851,652005045,652446538,652888329,653330420,653772810,654215500,654658489, 655101778,655545368,655989258,656433448,656877939,657322732,657767825,658213220,658658916,659104914,659551215,659997817,660444722,660891929,661339439,661787253,662235369,662683789,663132512,663581540,664030871,664480507, 664930447,665380692,665831242,666282096,666733256,667184722,667636493,668088570,668540954,668993643,669446639,669899942,670353552,670807469,671261693,671716225,672171065,672626213,673081668,673537433,673993506,674449887, 674906578,675363578,675820887,676278506,676736435,677194674,677653224,678112083,678571254,679030735,679490528,679950632,680411047,680871774,681332814,681794165,682255829,682717805,683180094,683642697,684105612,684568841, 685032383,685496240,685960410,686424895,686889695,687354809,687820238,688285982,688752042,689218417,689685108,690152115,690619438,691087077,691555034,692023307,692491897,692960805,693430030,693899572,694369433,694839612, 695310109,695780925,696252060,696723513,697195286,697667378,698139790,698612522,699085574,699558947,700032639,700506653,700980988,701455643,701930620,702405919,702881540,703357482,703833747,704310335,704787245,705264478, 705742034,706219914,706698117,707176644,707655495,708134670,708614170,709093994,709574144,710054618,710535418,711016543,711497994,711979772,712461875,712944305,713427061,713910145,714393555,714877293,715361358,715845751, 716330472,716815522,717300900,717786606,718272641,718759006,719245700,719732723,720220076,720707759,721195773,721684116,722172791,722661796,723151133,723640800,724130800,724621131,725111794,725602790,726094118,726585778, 727077772,727570098,728062758,728555752,729049080,729542741,730036737,730531067,731025732,731520732,732016067,732511738,733007744, }; void Freqlut::init(float sample_rate) { } #else int32_t lut[N_SAMPLES + 1]; void Freqlut::init(float sample_rate) { double y = (1LL << (24 + MAX_LOGFREQ_INT)) / sample_rate; double inc = pow(2, 1.0 / N_SAMPLES); for (int i = 0; i < N_SAMPLES + 1; i++) { lut[i] = (int32_t)floor(y + 0.5); y *= inc; } } #endif // Note: if logfreq is more than 20.0, the results will be inaccurate. However, // that will be many times the Nyquist rate. int32_t Freqlut::lookup(int32_t logfreq) { int ix = (logfreq & 0xffffff) >> SAMPLE_SHIFT; int32_t y0 = lut[ix]; int32_t y1 = lut[ix + 1]; int lowbits = logfreq & ((1 << SAMPLE_SHIFT) - 1); int32_t y = y0 + ((((int64_t)(y1 - y0) * (int64_t)lowbits)) >> SAMPLE_SHIFT); int hibits = logfreq >> 24; return y >> (MAX_LOGFREQ_INT - hibits); } ================================================ FILE: lib/msfa/freqlut.h ================================================ /* * 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. */ #pragma once class Freqlut { public: static void init(float sample_rate); static int32_t lookup(int32_t logfreq); }; ================================================ FILE: lib/msfa/lfo.cc ================================================ /* * 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. */ // Low frequency oscillator, compatible with DX7 #include "synth.h" #include "sin.h" #include "lfo.h" uint32_t Lfo::unit_; void Lfo::init(float sample_rate) { // constant is 1 << 32 / 15.5s / 11 Lfo::unit_ = (int32_t)(N * 25190424 / sample_rate + 0.5f); } void Lfo::reset(const uint8_t params[6]) { int rate = params[0]; // 0..99 int sr = rate == 0 ? 1 : (165 * rate) >> 6; sr *= sr < 160 ? 11 : (11 + ((sr - 160) >> 4)); delta_ = unit_ * sr; int a = 99 - params[1]; // LFO delay if (a == 99) { delayinc_ = ~0u; delayinc2_ = ~0u; } else { a = (16 + (a & 15)) << (1 + (a >> 4)); delayinc_ = unit_ * a; a &= 0xff80; a = max(0x80, a); delayinc2_ = unit_ * a; } waveform_ = params[5]; sync_ = params[4] != 0; } int32_t Lfo::getsample() { phase_ += delta_; int32_t x; switch (waveform_) { case 0: // triangle x = phase_ >> 7; x ^= -(phase_ >> 31); x &= (1 << 24) - 1; return x; case 1: // sawtooth down return (~phase_ ^ (1U << 31)) >> 8; case 2: // sawtooth up return (phase_ ^ (1U << 31)) >> 8; case 3: // square return ((~phase_) >> 7) & (1 << 24); case 4: // sine return (1 << 23) + (Sin::lookup(phase_ >> 8) >> 1); case 5: // s&h if (phase_ < delta_) { randstate_ = (randstate_ * 179 + 17) & 0xff; } x = randstate_ ^ 0x80; return (x + 1) << 16; } return 1 << 23; } int32_t Lfo::getdelay() { uint32_t delta = delaystate_ < (1U << 31) ? delayinc_ : delayinc2_; uint64_t d = ((uint64_t)delaystate_) + delta; if (d > ~0u) { return 1 << 24; } delaystate_ = d; if (d < (1U << 31)) { return 0; } else { return (d >> 7) & ((1 << 24) - 1); } } void Lfo::keydown() { if (sync_) { phase_ = (1U << 31) - 1; } delaystate_ = 0; } ================================================ FILE: lib/msfa/lfo.h ================================================ /* * 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. */ // Low frequency oscillator, compatible with DX7 #pragma once class Lfo { public: static void init(float sample_rate); void reset(const uint8_t params[6]); // result is 0..1 in Q24 int32_t getsample(); // result is 0..1 in Q24 int32_t getdelay(); void keydown(); private: static uint32_t unit_; uint32_t phase_; // Q32 uint32_t delta_; uint8_t waveform_; uint8_t randstate_; bool sync_; uint32_t delaystate_; uint32_t delayinc_; uint32_t delayinc2_; }; ================================================ FILE: lib/msfa/midinotes.h ================================================ /************************************************* MIDI note values *************************************************/ #ifndef _MIDINOTES_H #define _MIDINOTES_H #define MIDI_A0 21 #define MIDI_AIS0 22 #define MIDI_B0 23 #define MIDI_C1 24 #define MIDI_CIS1 25 #define MIDI_D1 26 #define MIDI_DIS1 27 #define MIDI_E1 28 #define MIDI_F1 29 #define MIDI_FIS1 30 #define MIDI_G1 31 #define MIDI_GIS1 32 #define MIDI_A1 33 #define MIDI_AIS1 34 #define MIDI_B1 35 #define MIDI_C2 36 #define MIDI_CIS2 37 #define MIDI_D2 38 #define MIDI_DIS2 39 #define MIDI_E2 40 #define MIDI_F2 41 #define MIDI_FIS2 42 #define MIDI_G2 43 #define MIDI_GIS2 44 #define MIDI_A2 45 #define MIDI_AIS2 46 #define MIDI_B2 47 #define MIDI_C3 48 #define MIDI_CIS3 49 #define MIDI_D3 50 #define MIDI_DIS3 51 #define MIDI_E3 52 #define MIDI_F3 53 #define MIDI_FIS3 54 #define MIDI_G3 55 #define MIDI_GIS3 56 #define MIDI_A3 57 #define MIDI_AIS3 58 #define MIDI_B3 59 #define MIDI_C4 60 #define MIDI_CIS4 61 #define MIDI_D4 62 #define MIDI_DIS4 63 #define MIDI_E4 64 #define MIDI_F4 65 #define MIDI_FIS4 66 #define MIDI_G4 67 #define MIDI_GIS4 68 #define MIDI_A4 69 #define MIDI_AIS4 70 #define MIDI_B4 71 #define MIDI_C5 72 #define MIDI_CIS5 73 #define MIDI_D5 74 #define MIDI_DIS5 75 #define MIDI_E5 76 #define MIDI_F5 77 #define MIDI_FIS5 78 #define MIDI_G5 79 #define MIDI_GIS5 80 #define MIDI_A5 81 #define MIDI_AIS5 82 #define MIDI_B5 83 #define MIDI_C6 84 #define MIDI_CIS6 85 #define MIDI_D6 86 #define MIDI_DIS6 87 #define MIDI_E6 88 #define MIDI_F6 89 #define MIDI_FIS6 90 #define MIDI_G6 91 #define MIDI_GIS6 92 #define MIDI_A6 93 #define MIDI_AIS6 94 #define MIDI_B6 95 #define MIDI_C7 96 #define MIDI_CIS7 97 #define MIDI_D7 98 #define MIDI_DIS7 99 #define MIDI_E7 100 #define MIDI_F7 101 #define MIDI_FIS7 102 #define MIDI_G7 103 #define MIDI_GIS7 104 #define MIDI_A7 105 #define MIDI_AIS7 106 #define MIDI_B7 107 #define MIDI_C8 108 #endif ================================================ FILE: lib/msfa/module.h ================================================ /* * 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. */ #ifndef SYNTH_MODULE_H #define SYNTH_MODULE_H #include class Module { public: static const int lg_n = 6; static const int n = 1 << lg_n; virtual void process(const int32_t **inbufs, const int32_t *control_in, const int32_t *control_last, int32_t **outbufs) = 0; }; #endif // SYNTH_MODULE_H ================================================ FILE: lib/msfa/patch.cc ================================================ /* * 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 } void PackPatch(const char patch[156], char bulk[128]) { for (int op = 0; op < 6; op++) { memcpy(bulk + op * 17, patch + op * 21, 11); bulk[op * 17 + 11] = (patch[op * 21 + 11] & 3) | ((patch[op * 21 + 12] & 3) << 2); bulk[op * 17 + 12] = (patch[op * 21 + 13] & 7) | ((patch[op * 21 + 20]) << 3); bulk[op * 17 + 13] = (patch[op * 21 + 14] & 3) | ((patch[op * 21 + 15]) << 2); bulk[op * 17 + 14] = patch[op * 21 + 16]; bulk[op * 17 + 15] = (patch[op * 21 + 17] & 1) | ((patch[op * 21 + 18]) << 1); bulk[op * 17 + 16] = patch[op * 21 + 19]; } memcpy(bulk + 102, patch + 126, 9); bulk[111] = (patch[135] & 7) | ((patch[136]) << 3); memcpy(bulk + 112, patch + 137, 4); bulk[116] = (patch[141] & 1) | ((patch[142] & 7) << 1) | ((patch[143] & 15) << 4); memcpy(bulk + 117, patch + 144, 11); } ================================================ FILE: lib/msfa/patch.h ================================================ /* * 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]); void PackPatch(const char patch[156], char bulk[128]); #endif ================================================ FILE: lib/msfa/pitchenv.cc ================================================ /* * 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 "synth.h" #include "pitchenv.h" int PitchEnv::unit_; void PitchEnv::init(float sample_rate) { unit_ = N * (1 << 24) / (21.3f * sample_rate) + 0.5f; } const uint8_t pitchenv_rate[] = { 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 33, 34, 36, 37, 38, 39, 41, 42, 44, 46, 47, 49, 51, 53, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 79, 82, 85, 88, 91, 94, 98, 102, 106, 110, 115, 120, 125, 130, 135, 141, 147, 153, 159, 165, 171, 178, 185, 193, 202, 211, 232, 243, 254, 255 }; const int8_t pitchenv_tab[] = { -128, -116, -104, -95, -85, -76, -68, -61, -56, -52, -49, -46, -43, -41, -39, -37, -35, -33, -32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 38, 40, 43, 46, 49, 53, 58, 65, 73, 82, 92, 103, 115, 127 }; void PitchEnv::set(const int r[4], const int l[4]) { for (int i = 0; i < 4; i++) { rates_[i] = r[i]; levels_[i] = l[i]; } level_ = pitchenv_tab[l[3]] << 19; down_ = true; advance(0); } int32_t PitchEnv::getsample() { if (ix_ < 3 || ((ix_ < 4) && !down_)) { if (rising_) { level_ += inc_; if (level_ >= targetlevel_) { level_ = targetlevel_; advance(ix_ + 1); } } else { // !rising level_ -= inc_; if (level_ <= targetlevel_) { level_ = targetlevel_; advance(ix_ + 1); } } } return level_; } void PitchEnv::keydown(bool d) { if (down_ != d) { down_ = d; advance(d ? 0 : 3); } } void PitchEnv::advance(int newix) { ix_ = newix; if (ix_ < 4) { int newlevel = levels_[ix_]; targetlevel_ = pitchenv_tab[newlevel] << 19; rising_ = (targetlevel_ > level_); inc_ = pitchenv_rate[rates_[ix_]] * unit_; } } void PitchEnv::getPosition(char *step) { *step = ix_; } ================================================ FILE: lib/msfa/pitchenv.h ================================================ /* * 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 __PITCHENV_H #define __PITCHENV_H // Computation of the DX7 pitch envelope class PitchEnv { public: static void init(float sample_rate); // The rates and levels arrays are calibrated to match the Dx7 parameters // (ie, value 0..99). void set(const int rates[4], const int levels[4]); // Result is in Q24/octave int32_t getsample(); void keydown(bool down); void getPosition(char *step); private: static int unit_; int rates_[4]; int levels_[4]; int32_t level_; int targetlevel_; bool rising_; int ix_; int inc_; bool down_; void advance(int newix); }; extern const uint8_t pitchenv_rate[]; extern const int8_t pitchenv_tab[]; #endif // __PITCHENV_H ================================================ FILE: lib/msfa/porta.cc ================================================ /* Copyright 2019 Jean Pierre Cimalando. 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 "porta.h" #include "synth.h" void Porta::init_sr(float sampleRate) { // compute portamento for CC 7-bit range for (unsigned int i = 0; i < 128; ++i) { // number of semitones travelled auto sps = 350.f * powf(2.0, -0.062f * i); // per second auto spf = sps / sampleRate; // per frame auto spp = spf * N; // per period const int step = (1 << 24) / 12; rates[i] = (int32_t)(0.5f + step * spp); // to pitch units } } int32_t Porta::rates[128]; ================================================ FILE: lib/msfa/porta.h ================================================ /* Copyright 2019 Jean Pierre Cimalando. 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_PORTA_H_ #define SYNTH_PORTA_H_ #include struct Porta { public: static void init_sr(float sampleRate); static int32_t rates[128]; }; #endif // SYNTH_PORTA_H_ ================================================ FILE: lib/msfa/sin.cc ================================================ /* * 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. */ #define _USE_MATH_DEFINES #include #include "synth.h" #include "sin.h" #if 1 //eh2k #ifndef FLASHMEM #include "pgmspace.h" #endif const int32_t sintab[2048] FLASHMEM = { 102943, 0, 102939, 102943, 102932, 205882, 102920, 308814, 102904, 411734, 102885, 514638, 102861, 617523, 102835, 720384, 102804, 823219, 102768, 926023, 102730, 1028791, 102688, 1131521, 102641, 1234209, 102590, 1336850, 102536, 1439440, 102479, 1541976, 102416, 1644455, 102351, 1746871, 102281, 1849222, 102207, 1951503, 102131, 2053710, 102049, 2155841, 101964, 2257890, 101875, 2359854, 101782, 2461729, 101686, 2563511, 101586, 2665197, 101482, 2766783, 101373, 2868265, 101262, 2969638, 101146, 3070900, 101026, 3172046, 100904, 3273072, 100776, 3373976, 100646, 3474752, 100511, 3575398, 100372, 3675909, 100231, 3776281, 100084, 3876512, 99935, 3976596, 99781, 4076531, 99624, 4176312, 99463, 4275936, 99299, 4375399, 99129, 4474698, 98958, 4573827, 98782, 4672785, 98602, 4771567, 98418, 4870169, 98232, 4968587, 98041, 5066819, 97846, 5164860, 97649, 5262706, 97446, 5360355, 97241, 5457801, 97032, 5555042, 96819, 5652074, 96602, 5748893, 96383, 5845495, 96159, 5941878, 95931, 6038037, 95701, 6133968, 95466, 6229669, 95228, 6325135, 94986, 6420363, 94741, 6515349, 94492, 6610090, 94239, 6704582, 93984, 6798821, 93724, 6892805, 93461, 6986529, 93194, 7079990, 92925, 7173184, 92650, 7266109, 92374, 7358759, 92093, 7451133, 91810, 7543226, 91521, 7635036, 91231, 7726557, 90937, 7817788, 90639, 7908725, 90337, 7999364, 90033, 8089701, 89725, 8179734, 89414, 8269459, 89099, 8358873, 88781, 8447972, 88460, 8536753, 88135, 8625213, 87806, 8713348, 87476, 8801154, 87141, 8888630, 86802, 8975771, 86462, 9062573, 86117, 9149035, 85770, 9235152, 85418, 9320922, 85065, 9406340, 84707, 9491405, 84346, 9576112, 83983, 9660458, 83616, 9744441, 83246, 9828057, 82873, 9911303, 82496, 9994176, 82117, 10076672, 81735, 10158789, 81349, 10240524, 80961, 10321873, 80569, 10402834, 80174, 10483403, 79776, 10563577, 79376, 10643353, 78972, 10722729, 78565, 10801701, 78156, 10880266, 77743, 10958422, 77328, 11036165, 76909, 11113493, 76488, 11190402, 76063, 11266890, 75637, 11342953, 75207, 11418590, 74774, 11493797, 74338, 11568571, 73900, 11642909, 73459, 11716809, 73015, 11790268, 72569, 11863283, 72119, 11935852, 71667, 12007971, 71212, 12079638, 70754, 12150850, 70295, 12221604, 69832, 12291899, 69366, 12361731, 68898, 12431097, 68428, 12499995, 67955, 12568423, 67478, 12636378, 67001, 12703856, 66519, 12770857, 66037, 12837376, 65550, 12903413, 65062, 12968963, 64572, 13034025, 64078, 13098597, 63583, 13162675, 63085, 13226258, 62585, 13289343, 62081, 13351928, 61577, 13414009, 61070, 13475586, 60559, 13536656, 60048, 13597215, 59534, 13657263, 59017, 13716797, 58499, 13775814, 57977, 13834313, 57455, 13892290, 56930, 13949745, 56402, 14006675, 55872, 14063077, 55342, 14118949, 54807, 14174291, 54272, 14229098, 53734, 14283370, 53194, 14337104, 52652, 14390298, 52109, 14442950, 51563, 14495059, 51015, 14546622, 50466, 14597637, 49914, 14648103, 49361, 14698017, 48805, 14747378, 48249, 14796183, 47689, 14844432, 47129, 14892121, 46567, 14939250, 46002, 14985817, 45436, 15031819, 44869, 15077255, 44299, 15122124, 43729, 15166423, 43155, 15210152, 42582, 15253307, 42005, 15295889, 41428, 15337894, 40849, 15379322, 40269, 15420171, 39686, 15460440, 39103, 15500126, 38518, 15539229, 37931, 15577747, 37344, 15615678, 36754, 15653022, 36163, 15689776, 35571, 15725939, 34978, 15761510, 34383, 15796488, 33787, 15830871, 33190, 15864658, 32591, 15897848, 31992, 15930439, 31390, 15962431, 30788, 15993821, 30185, 16024609, 29581, 16054794, 28975, 16084375, 28368, 16113350, 27761, 16141718, 27152, 16169479, 26542, 16196631, 25931, 16223173, 25320, 16249104, 24706, 16274424, 24093, 16299130, 23479, 16323223, 22863, 16346702, 22247, 16369565, 21630, 16391812, 21011, 16413442, 20393, 16434453, 19774, 16454846, 19153, 16474620, 18532, 16493773, 17911, 16512305, 17288, 16530216, 16665, 16547504, 16041, 16564169, 15418, 16580210, 14792, 16595628, 14167, 16610420, 13541, 16624587, 12915, 16638128, 12288, 16651043, 11661, 16663331, 11032, 16674992, 10405, 16686024, 9776, 16696429, 9147, 16706205, 8517, 16715352, 7888, 16723869, 7258, 16731757, 6628, 16739015, 5997, 16745643, 5367, 16751640, 4735, 16757007, 4105, 16761742, 3474, 16765847, 2842, 16769321, 2210, 16772163, 1579, 16774373, 948, 16775952, 316, 16776900, -316, 16777216, -948, 16776900, -1579, 16775952, -2210, 16774373, -2842, 16772163, -3474, 16769321, -4105, 16765847, -4735, 16761742, -5367, 16757007, -5997, 16751640, -6628, 16745643, -7258, 16739015, -7888, 16731757, -8518, 16723869, -9146, 16715351, -9776, 16706205, -10405, 16696429, -11033, 16686024, -11660, 16674991, -12288, 16663331, -12915, 16651043, -13541, 16638128, -14167, 16624587, -14792, 16610420, -15418, 16595628, -16041, 16580210, -16665, 16564169, -17289, 16547504, -17910, 16530215, -18532, 16512305, -19154, 16493773, -19773, 16474619, -20393, 16454846, -21012, 16434453, -21629, 16413441, -22247, 16391812, -22863, 16369565, -23479, 16346702, -24093, 16323223, -24707, 16299130, -25319, 16274423, -25931, 16249104, -26542, 16223173, -27152, 16196631, -27761, 16169479, -28368, 16141718, -28975, 16113350, -29581, 16084375, -30185, 16054794, -30788, 16024609, -31391, 15993821, -31991, 15962430, -32591, 15930439, -33190, 15897848, -33787, 15864658, -34383, 15830871, -34978, 15796488, -35571, 15761510, -36164, 15725939, -36754, 15689775, -37343, 15653021, -37931, 15615678, -38518, 15577747, -39103, 15539229, -39686, 15500126, -40269, 15460440, -40849, 15420171, -41428, 15379322, -42005, 15337894, -42582, 15295889, -43156, 15253307, -43728, 15210151, -44299, 15166423, -44869, 15122124, -45436, 15077255, -46002, 15031819, -46567, 14985817, -47129, 14939250, -47689, 14892121, -48249, 14844432, -48806, 14796183, -49360, 14747377, -49914, 14698017, -50466, 14648103, -51015, 14597637, -51563, 14546622, -52109, 14495059, -52652, 14442950, -53195, 14390298, -53734, 14337103, -54271, 14283369, -54808, 14229098, -55341, 14174290, -55873, 14118949, -56402, 14063076, -56929, 14006674, -57455, 13949745, -57978, 13892290, -58498, 13834312, -59018, 13775814, -59533, 13716796, -60048, 13657263, -60560, 13597215, -61069, 13536655, -61577, 13475586, -62082, 13414009, -62584, 13351927, -63085, 13289343, -63583, 13226258, -64078, 13162675, -64572, 13098597, -65062, 13034025, -65551, 12968963, -66036, 12903412, -66520, 12837376, -67000, 12770856, -67479, 12703856, -67955, 12636377, -68427, 12568422, -68899, 12499995, -69366, 12431096, -69832, 12361730, -70294, 12291898, -70755, 12221604, -71212, 12150849, -71667, 12079637, -72119, 12007970, -72568, 11935851, -73015, 11863283, -73459, 11790268, -73901, 11716809, -74338, 11642908, -74774, 11568570, -75207, 11493796, -75636, 11418589, -76064, 11342953, -76488, 11266889, -76909, 11190401, -77328, 11113492, -77743, 11036164, -78155, 10958421, -78566, 10880266, -78972, 10801700, -79375, 10722728, -79777, 10643353, -80174, 10563576, -80569, 10483402, -80960, 10402833, -81349, 10321873, -81735, 10240524, -82117, 10158789, -82497, 10076672, -82873, 9994175, -83245, 9911302, -83616, 9828057, -83983, 9744441, -84347, 9660458, -84707, 9576111, -85064, 9491404, -85419, 9406340, -85769, 9320921, -86117, 9235152, -86462, 9149035, -86803, 9062573, -87141, 8975770, -87475, 8888629, -87807, 8801154, -88135, 8713347, -88459, 8625212, -88781, 8536753, -89099, 8447972, -89414, 8358873, -89725, 8269459, -90033, 8179734, -90338, 8089701, -90639, 7999363, -90936, 7908724, -91231, 7817788, -91522, 7726557, -91809, 7635035, -92093, 7543226, -92374, 7451133, -92651, 7358759, -92924, 7266108, -93195, 7173184, -93461, 7079989, -93724, 6986528, -93984, 6892804, -94239, 6798820, -94492, 6704581, -94741, 6610089, -94986, 6515348, -95228, 6420362, -95466, 6325134, -95700, 6229668, -95932, 6133968, -96159, 6038036, -96382, 5941877, -96603, 5845495, -96819, 5748892, -97032, 5652073, -97241, 5555041, -97446, 5457800, -97648, 5360354, -97847, 5262706, -98040, 5164859, -98232, 5066819, -98419, 4968587, -98602, 4870168, -98782, 4771566, -98957, 4672784, -99130, 4573827, -99298, 4474697, -99463, 4375399, -99624, 4275936, -99782, 4176312, -99934, 4076530, -100085, 3976596, -100230, 3876511, -100373, 3776281, -100511, 3675908, -100645, 3575397, -100777, 3474752, -100903, 3373975, -101027, 3273072, -101146, 3172045, -101261, 3070899, -101374, 2969638, -101481, 2868264, -101586, 2766783, -101686, 2665197, -101783, 2563511, -101875, 2461728, -101964, 2359853, -102049, 2257889, -102130, 2155840, -102208, 2053710, -102281, 1951502, -102350, 1849221, -102417, 1746871, -102478, 1644454, -102536, 1541976, -102591, 1439440, -102641, 1336849, -102687, 1234208, -102730, 1131521, -102769, 1028791, -102803, 926022, -102835, 823219, -102862, 720384, -102885, 617522, -102904, 514637, -102920, 411733, -102931, 308813, -102939, 205882, -102943, 102943, -102943, 0, -102939, -102943, -102932, -205882, -102920, -308814, -102904, -411734, -102885, -514638, -102861, -617523, -102835, -720384, -102804, -823219, -102768, -926023, -102730, -1028791, -102688, -1131521, -102641, -1234209, -102590, -1336850, -102536, -1439440, -102479, -1541976, -102416, -1644455, -102351, -1746871, -102281, -1849222, -102207, -1951503, -102131, -2053710, -102049, -2155841, -101964, -2257890, -101875, -2359854, -101782, -2461729, -101686, -2563511, -101586, -2665197, -101482, -2766783, -101373, -2868265, -101262, -2969638, -101146, -3070900, -101026, -3172046, -100904, -3273072, -100776, -3373976, -100646, -3474752, -100511, -3575398, -100372, -3675909, -100231, -3776281, -100084, -3876512, -99935, -3976596, -99781, -4076531, -99624, -4176312, -99463, -4275936, -99299, -4375399, -99129, -4474698, -98958, -4573827, -98782, -4672785, -98602, -4771567, -98418, -4870169, -98232, -4968587, -98041, -5066819, -97846, -5164860, -97649, -5262706, -97446, -5360355, -97241, -5457801, -97032, -5555042, -96819, -5652074, -96602, -5748893, -96383, -5845495, -96159, -5941878, -95931, -6038037, -95701, -6133968, -95466, -6229669, -95228, -6325135, -94986, -6420363, -94741, -6515349, -94492, -6610090, -94239, -6704582, -93984, -6798821, -93724, -6892805, -93461, -6986529, -93194, -7079990, -92925, -7173184, -92650, -7266109, -92374, -7358759, -92093, -7451133, -91810, -7543226, -91521, -7635036, -91231, -7726557, -90937, -7817788, -90639, -7908725, -90337, -7999364, -90033, -8089701, -89725, -8179734, -89414, -8269459, -89099, -8358873, -88781, -8447972, -88460, -8536753, -88135, -8625213, -87806, -8713348, -87476, -8801154, -87141, -8888630, -86802, -8975771, -86462, -9062573, -86117, -9149035, -85770, -9235152, -85418, -9320922, -85065, -9406340, -84707, -9491405, -84346, -9576112, -83983, -9660458, -83616, -9744441, -83246, -9828057, -82873, -9911303, -82496, -9994176, -82117, -10076672, -81735, -10158789, -81349, -10240524, -80961, -10321873, -80569, -10402834, -80174, -10483403, -79776, -10563577, -79376, -10643353, -78972, -10722729, -78565, -10801701, -78156, -10880266, -77743, -10958422, -77328, -11036165, -76909, -11113493, -76488, -11190402, -76063, -11266890, -75637, -11342953, -75207, -11418590, -74774, -11493797, -74338, -11568571, -73900, -11642909, -73459, -11716809, -73015, -11790268, -72569, -11863283, -72119, -11935852, -71667, -12007971, -71212, -12079638, -70754, -12150850, -70295, -12221604, -69832, -12291899, -69366, -12361731, -68898, -12431097, -68428, -12499995, -67955, -12568423, -67478, -12636378, -67001, -12703856, -66519, -12770857, -66037, -12837376, -65550, -12903413, -65062, -12968963, -64572, -13034025, -64078, -13098597, -63583, -13162675, -63085, -13226258, -62585, -13289343, -62081, -13351928, -61577, -13414009, -61070, -13475586, -60559, -13536656, -60048, -13597215, -59534, -13657263, -59017, -13716797, -58499, -13775814, -57977, -13834313, -57455, -13892290, -56930, -13949745, -56402, -14006675, -55872, -14063077, -55342, -14118949, -54807, -14174291, -54272, -14229098, -53734, -14283370, -53194, -14337104, -52652, -14390298, -52109, -14442950, -51563, -14495059, -51015, -14546622, -50466, -14597637, -49914, -14648103, -49361, -14698017, -48805, -14747378, -48249, -14796183, -47689, -14844432, -47129, -14892121, -46567, -14939250, -46002, -14985817, -45436, -15031819, -44869, -15077255, -44299, -15122124, -43729, -15166423, -43155, -15210152, -42582, -15253307, -42005, -15295889, -41428, -15337894, -40849, -15379322, -40269, -15420171, -39686, -15460440, -39103, -15500126, -38518, -15539229, -37931, -15577747, -37344, -15615678, -36754, -15653022, -36163, -15689776, -35571, -15725939, -34978, -15761510, -34383, -15796488, -33787, -15830871, -33190, -15864658, -32591, -15897848, -31992, -15930439, -31390, -15962431, -30788, -15993821, -30185, -16024609, -29581, -16054794, -28975, -16084375, -28368, -16113350, -27761, -16141718, -27152, -16169479, -26542, -16196631, -25931, -16223173, -25320, -16249104, -24706, -16274424, -24093, -16299130, -23479, -16323223, -22863, -16346702, -22247, -16369565, -21630, -16391812, -21011, -16413442, -20393, -16434453, -19774, -16454846, -19153, -16474620, -18532, -16493773, -17911, -16512305, -17288, -16530216, -16665, -16547504, -16041, -16564169, -15418, -16580210, -14792, -16595628, -14167, -16610420, -13541, -16624587, -12915, -16638128, -12288, -16651043, -11661, -16663331, -11032, -16674992, -10405, -16686024, -9776, -16696429, -9147, -16706205, -8517, -16715352, -7888, -16723869, -7258, -16731757, -6628, -16739015, -5997, -16745643, -5367, -16751640, -4735, -16757007, -4105, -16761742, -3474, -16765847, -2842, -16769321, -2210, -16772163, -1579, -16774373, -948, -16775952, -316, -16776900, 316, -16777216, 948, -16776900, 1579, -16775952, 2210, -16774373, 2842, -16772163, 3474, -16769321, 4105, -16765847, 4735, -16761742, 5367, -16757007, 5997, -16751640, 6628, -16745643, 7258, -16739015, 7888, -16731757, 8518, -16723869, 9146, -16715351, 9776, -16706205, 10405, -16696429, 11033, -16686024, 11660, -16674991, 12288, -16663331, 12915, -16651043, 13541, -16638128, 14167, -16624587, 14792, -16610420, 15418, -16595628, 16041, -16580210, 16665, -16564169, 17289, -16547504, 17910, -16530215, 18532, -16512305, 19154, -16493773, 19773, -16474619, 20393, -16454846, 21012, -16434453, 21629, -16413441, 22247, -16391812, 22863, -16369565, 23479, -16346702, 24093, -16323223, 24707, -16299130, 25319, -16274423, 25931, -16249104, 26542, -16223173, 27152, -16196631, 27761, -16169479, 28368, -16141718, 28975, -16113350, 29581, -16084375, 30185, -16054794, 30788, -16024609, 31391, -15993821, 31991, -15962430, 32591, -15930439, 33190, -15897848, 33787, -15864658, 34383, -15830871, 34978, -15796488, 35571, -15761510, 36164, -15725939, 36754, -15689775, 37343, -15653021, 37931, -15615678, 38518, -15577747, 39103, -15539229, 39686, -15500126, 40269, -15460440, 40849, -15420171, 41428, -15379322, 42005, -15337894, 42582, -15295889, 43156, -15253307, 43728, -15210151, 44299, -15166423, 44869, -15122124, 45436, -15077255, 46002, -15031819, 46567, -14985817, 47129, -14939250, 47689, -14892121, 48249, -14844432, 48806, -14796183, 49360, -14747377, 49914, -14698017, 50466, -14648103, 51015, -14597637, 51563, -14546622, 52109, -14495059, 52652, -14442950, 53195, -14390298, 53734, -14337103, 54271, -14283369, 54808, -14229098, 55341, -14174290, 55873, -14118949, 56402, -14063076, 56929, -14006674, 57455, -13949745, 57978, -13892290, 58498, -13834312, 59018, -13775814, 59533, -13716796, 60048, -13657263, 60560, -13597215, 61069, -13536655, 61577, -13475586, 62082, -13414009, 62584, -13351927, 63085, -13289343, 63583, -13226258, 64078, -13162675, 64572, -13098597, 65062, -13034025, 65551, -12968963, 66036, -12903412, 66520, -12837376, 67000, -12770856, 67479, -12703856, 67955, -12636377, 68427, -12568422, 68899, -12499995, 69366, -12431096, 69832, -12361730, 70294, -12291898, 70755, -12221604, 71212, -12150849, 71667, -12079637, 72119, -12007970, 72568, -11935851, 73015, -11863283, 73459, -11790268, 73901, -11716809, 74338, -11642908, 74774, -11568570, 75207, -11493796, 75636, -11418589, 76064, -11342953, 76488, -11266889, 76909, -11190401, 77328, -11113492, 77743, -11036164, 78155, -10958421, 78566, -10880266, 78972, -10801700, 79375, -10722728, 79777, -10643353, 80174, -10563576, 80569, -10483402, 80960, -10402833, 81349, -10321873, 81735, -10240524, 82117, -10158789, 82497, -10076672, 82873, -9994175, 83245, -9911302, 83616, -9828057, 83983, -9744441, 84347, -9660458, 84707, -9576111, 85064, -9491404, 85419, -9406340, 85769, -9320921, 86117, -9235152, 86462, -9149035, 86803, -9062573, 87141, -8975770, 87475, -8888629, 87807, -8801154, 88135, -8713347, 88459, -8625212, 88781, -8536753, 89099, -8447972, 89414, -8358873, 89725, -8269459, 90033, -8179734, 90338, -8089701, 90639, -7999363, 90936, -7908724, 91231, -7817788, 91522, -7726557, 91809, -7635035, 92093, -7543226, 92374, -7451133, 92651, -7358759, 92924, -7266108, 93195, -7173184, 93461, -7079989, 93724, -6986528, 93984, -6892804, 94239, -6798820, 94492, -6704581, 94741, -6610089, 94986, -6515348, 95228, -6420362, 95466, -6325134, 95700, -6229668, 95932, -6133968, 96159, -6038036, 96382, -5941877, 96603, -5845495, 96819, -5748892, 97032, -5652073, 97241, -5555041, 97446, -5457800, 97648, -5360354, 97847, -5262706, 98040, -5164859, 98232, -5066819, 98419, -4968587, 98602, -4870168, 98782, -4771566, 98957, -4672784, 99130, -4573827, 99298, -4474697, 99463, -4375399, 99624, -4275936, 99782, -4176312, 99934, -4076530, 100085, -3976596, 100230, -3876511, 100373, -3776281, 100511, -3675908, 100645, -3575397, 100777, -3474752, 100903, -3373975, 101027, -3273072, 101146, -3172045, 101261, -3070899, 101374, -2969638, 101481, -2868264, 101586, -2766783, 101686, -2665197, 101783, -2563511, 101875, -2461728, 101964, -2359853, 102049, -2257889, 102130, -2155840, 102208, -2053710, 102281, -1951502, 102350, -1849221, 102417, -1746871, 102478, -1644454, 102536, -1541976, 102591, -1439440, 102641, -1336849, 102687, -1234208, 102730, -1131521, 102769, -1028791, 102803, -926022, 102835, -823219, 102862, -720384, 102885, -617522, 102904, -514637, 102920, -411733, 102931, -308813, 102939, -205882, 102943, -102943}; void Sin::init() { } #else #define R (1 << 29) #ifdef SIN_DELTA int32_t sintab[SIN_N_SAMPLES << 1]; #else int32_t sintab[SIN_N_SAMPLES + 1]; #endif void Sin::init() { double dphase = 2 * M_PI / SIN_N_SAMPLES; int32_t c = (int32_t)floor(cos(dphase) * (1 << 30) + 0.5); int32_t s = (int32_t)floor(sin(dphase) * (1 << 30) + 0.5); int32_t u = 1 << 30; int32_t v = 0; for (int i = 0; i < SIN_N_SAMPLES / 2; i++) { #ifdef SIN_DELTA sintab[(i << 1) + 1] = (v + 32) >> 6; sintab[((i + SIN_N_SAMPLES / 2) << 1) + 1] = -((v + 32) >> 6); #else sintab[i] = (v + 32) >> 6; sintab[i + SIN_N_SAMPLES / 2] = -((v + 32) >> 6); #endif int32_t t = ((int64_t)u * (int64_t)s + (int64_t)v * (int64_t)c + R) >> 30; u = ((int64_t)u * (int64_t)c - (int64_t)v * (int64_t)s + R) >> 30; v = t; } #ifdef SIN_DELTA for (int i = 0; i < SIN_N_SAMPLES - 1; i++) { sintab[i << 1] = sintab[(i << 1) + 3] - sintab[(i << 1) + 1]; } sintab[(SIN_N_SAMPLES << 1) - 2] = -sintab[(SIN_N_SAMPLES << 1) - 1]; #else sintab[SIN_N_SAMPLES] = 0; #endif } #ifndef SIN_INLINE int32_t Sin::lookup(int32_t phase) { const int SHIFT = 24 - SIN_LG_N_SAMPLES; int lowbits = phase & ((1 << SHIFT) - 1); #ifdef SIN_DELTA int phase_int = (phase >> (SHIFT - 1)) & ((SIN_N_SAMPLES - 1) << 1); int dy = sintab[phase_int]; int y0 = sintab[phase_int + 1]; return y0 + (((int64_t)dy * (int64_t)lowbits) >> SHIFT); #else int phase_int = (phase >> SHIFT) & (SIN_N_SAMPLES - 1); int y0 = sintab[phase_int]; int y1 = sintab[phase_int + 1]; return y0 + (((int64_t)(y1 - y0) * (int64_t)lowbits) >> SHIFT); #endif } #endif #endif #if 0 // The following is an implementation designed not to use any lookup tables, // based on the following implementation by Basile Graf: // http://www.rossbencina.com/static/code/sinusoids/even_polynomial_sin_approximation.txt #define C0 (1 << 24) #define C1 (331121857 >> 2) #define C2 (1084885537 >> 4) #define C3 (1310449902 >> 6) int32_t Sin::compute(int32_t phase) { int32_t x = (phase & ((1 << 23) - 1)) - (1 << 22); int32_t x2 = ((int64_t)x * (int64_t)x) >> 22; int32_t x4 = ((int64_t)x2 * (int64_t)x2) >> 24; int32_t x6 = ((int64_t)x2 * (int64_t)x4) >> 24; int32_t y = C0 - (((int64_t)C1 * (int64_t)x2) >> 24) + (((int64_t)C2 * (int64_t)x4) >> 24) - (((int64_t)C3 * (int64_t)x6) >> 24); y ^= -((phase >> 23) & 1); return y; } #endif #if 1 // coefficients are Chebyshev polynomial, computed by compute_cos_poly.py #define C8_0 16777216 #define C8_2 -331168742 #define C8_4 1089453524 #define C8_6 -1430910663 #define C8_8 950108533 int32_t Sin::compute(int32_t phase) { int32_t x = (phase & ((1 << 23) - 1)) - (1 << 22); int32_t x2 = ((int64_t)x * (int64_t)x) >> 16; int32_t y = (((((((((((((int64_t)C8_8 * (int64_t)x2) >> 32) + C8_6) * (int64_t)x2) >> 32) + C8_4) * (int64_t)x2) >> 32) + C8_2) * (int64_t)x2) >> 32) + C8_0); y ^= -((phase >> 23) & 1); return y; } #endif #define C10_0 (1 << 30) #define C10_2 -1324675874 // scaled * 4 #define C10_4 1089501821 #define C10_6 -1433689867 #define C10_8 1009356886 #define C10_10 -421101352 int32_t Sin::compute10(int32_t phase) { int32_t x = (phase & ((1 << 29) - 1)) - (1 << 28); int32_t x2 = ((int64_t)x * (int64_t)x) >> 26; int32_t y = ((((((((((((((((int64_t)C10_10 * (int64_t)x2) >> 34) + C10_8) * (int64_t)x2) >> 34) + C10_6) * (int64_t)x2) >> 34) + C10_4) * (int64_t)x2) >> 32) + C10_2) * (int64_t)x2) >> 30) + C10_0); y ^= -((phase >> 29) & 1); return y; } ================================================ FILE: lib/msfa/sin.h ================================================ /* * 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. */ #pragma once class Sin { public: Sin(); static void init(); static int32_t lookup(int32_t phase); static int32_t compute(int32_t phase); // A more accurate sine, both input and output Q30 static int32_t compute10(int32_t phase); }; #define SIN_LG_N_SAMPLES 10 #define SIN_N_SAMPLES (1 << SIN_LG_N_SAMPLES) #define SIN_INLINE // Use twice as much RAM for the LUT but avoid a little computation #define SIN_DELTA #ifdef SIN_DELTA extern const int32_t sintab[SIN_N_SAMPLES << 1]; #else extern const int32_t sintab[SIN_N_SAMPLES + 1]; #endif #ifdef SIN_INLINE inline int32_t Sin::lookup(int32_t phase) { const int SHIFT = 24 - SIN_LG_N_SAMPLES; int lowbits = phase & ((1 << SHIFT) - 1); #ifdef SIN_DELTA int phase_int = (phase >> (SHIFT - 1)) & ((SIN_N_SAMPLES - 1) << 1); int dy = sintab[phase_int]; int y0 = sintab[phase_int + 1]; return y0 + (((int64_t)dy * (int64_t)lowbits) >> SHIFT); #else int phase_int = (phase >> SHIFT) & (SIN_N_SAMPLES - 1); int y0 = sintab[phase_int]; int y1 = sintab[phase_int + 1]; return y0 + (((int64_t)(y1 - y0) * (int64_t)lowbits) >> SHIFT); #endif } #endif ================================================ FILE: lib/msfa/synth.h ================================================ /* * 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. */ #ifndef __SYNTH_H #define __SYNTH_H // This IS not be present on MSVC. // See http://stackoverflow.com/questions/126279/c99-stdint-h-header-and-ms-visual-studio #include #ifdef _MSC_VER typedef __int32 int32_t; typedef unsigned __int32 uint32_t; typedef __int16 SInt16; #endif constexpr static int LG_N = 6; constexpr static int N = (1 << LG_N); #if defined(__APPLE__) #include #define SynthMemoryBarrier() OSMemoryBarrier() #elif defined(__GNUC__) #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) #define SynthMemoryBarrier() __sync_synchronize() #endif #endif // #undef SynthMemoryBarrier() #ifndef SynthMemoryBarrier // need to understand why this must be defined // #warning Memory barrier is not enabled #define SynthMemoryBarrier() #endif template inline static T min(const T& a, const T& b) { return a < b ? a : b; } template inline static T max(const T& a, const T& b) { return a > b ? a : b; } #define QER(n,b) ( ((float)n)/(1< #include #define INLINE inline #ifndef REAL_T_IS_DOUBLE #define REAL_T_IS_FLOAT #endif #ifdef REAL_T_IS_FLOAT typedef float real_t; //[eh2k] #else typedef double real_t; #endif //_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON) constexpr int SAMPLE_RATE = 48000; //------------------------------------------------------------------------------------------------- // mathematical constants: #define PI 3.1415926535897932384626433832795 #define EULER 2.7182818284590452353602874713527 #define SQRT2 1.4142135623730950488016887242097 #define ONE_OVER_SQRT2 0.70710678118654752440084436210485 #define LN10 2.3025850929940456840179914546844 #define ONE_OVER_LN10 0.43429448190325182765112891891661 #define LN2 0.69314718055994530941723212145818 #define ONE_OVER_LN2 1.4426950408889634073599246810019 #define SEMITONE_FACTOR 1.0594630943592952645618252949463 //------------------------------------------------------------------------------------------------- // type definitions: // unsigned 64 bit integers: #ifdef _MSC_VER typedef unsigned __int64 UINT64; #else typedef unsigned long long UINT64; #endif // signed 64 bit integers: #ifdef _MSC_VER typedef signed __int64 INT64; #else typedef signed long long INT64; #endif // unsigned 32 bit integers: #ifdef _MSC_VER typedef unsigned __int32 UINT32; #else typedef unsigned long UINT32; #endif // ...constants for numerical precision issues, denorm, etc.: #define TINY FLT_MIN #define EPS DBL_EPSILON // define infinity values: inline real_t dummyFunction(real_t x) { return x; } #define INF (1.0/dummyFunction(0.0)) #define NEG_INF (-1.0/dummyFunction(0.0)) //------------------------------------------------------------------------------------------------- // debug stuff: // this will try to break the debugger if one is currently hosting this app: #ifdef _DEBUG #ifdef _MSC_VER #pragma intrinsic (__debugbreak) #define DEBUG_BREAK __debugbreak(); #else #define DEBUG_BREAK {} #endif #else #define DEBUG_BREAK {} // evaluate to no op in release builds #endif // an replacement of the ASSERT macro #define rassert(expression) { if (! (expression)) DEBUG_BREAK } //------------------------------------------------------------------------------------------------- // bit twiddling: //extract the exponent from a IEEE 754 real_ting point number (single and double precision): #ifdef REAL_T_IS_FLOAT #define EXPOF(value) (((*((reinterpret_cast(&value)))&0x7FFFFFFF)>>23)-127) #else #define EXPOF(value) (((*((reinterpret_cast(&value)))&0x7FFFFFFFFFFFFFFFULL)>>52)-1023) #endif // ULL indicates an unsigned long long literal constant #endif ================================================ FILE: lib/open303/src/GlobalFunctions.cpp ================================================ #include "GlobalFunctions.h" ================================================ FILE: lib/open303/src/GlobalFunctions.h ================================================ #ifndef GlobalFunctions_h #define GlobalFunctions_h #include #include #include "GlobalDefinitions.h" namespace rosic { //[eh2k] start namespace //[eh2k]> #ifdef REAL_T_IS_FLOAT INLINE real_t sin(real_t x) { return sinf(x); } INLINE real_t sinh(real_t x) { return sinhf(x); } INLINE real_t cos(real_t x) { return cosf(x); } INLINE real_t cosh(real_t x) { return coshf(x); } INLINE real_t log(real_t x) { return logf(x); } INLINE real_t fabs(real_t x) { return fabsf(x); } INLINE real_t floor(real_t x) { return floorf(x); } INLINE real_t sqrt(real_t x) { return sqrtf(x); } INLINE real_t exp(real_t x) { return expf(x); } INLINE real_t pow(real_t x, real_t y) { return powf(x, y); } INLINE real_t fmod(real_t x, real_t y) { return fmodf(x, y); } INLINE real_t atan(real_t x) { return atanf(x); } INLINE real_t tan(real_t x) { return tanf(x); } INLINE real_t ceil(real_t x) { return ceilf(x); } #endif //<[eh2k] /** This file contains a bunch of useful macros and functions which are not wrapped into the rosic namespace to facilitate their global use. */ /** Converts a raw amplitude value/factor to a value in decibels. */ INLINE real_t amp2dB(real_t amp); /** Converts a raw amplitude value/factor to a value in decibels with a check, if the amplitude is close to zero (to avoid log-of-zero and related errors). */ INLINE real_t amp2dBWithCheck(real_t amp, real_t lowAmplitude = 0.000001); /** Returns the index of the maximum value in an array of doubles where the array should be of length numValues. */ template INLINE int arrayMaxIndex(T* theArray, int numValues); /** Returns the index of the minimum value in an array of doubles where the array should be of length numValues. */ template INLINE int arrayMinIndex(T* theArray, int numValues); /** Converts a time-stamp given in beats into seconds acording to a tempo measured in beats per minute (bpm). */ INLINE real_t beatsToSeconds(real_t beat, real_t bpm); /** Converts a value in decibels to a raw amplitude value/factor. */ INLINE real_t dB2amp(real_t x); /** Converts an angle in degrees into radiant. */ INLINE real_t degreeToRadiant(real_t degrees); /** Frees the memory associated with the pointer ans sets the poiter itself to NULL */ //INLINE void deleteAndNullifyPointer(void *pointer); /** Returns the Euclidean distance between points at coordinates (x1,y1), (x2,y2). */ INLINE real_t euclideanDistance(real_t x1, real_t y1, real_t x2, real_t y2); /** Calculates the exponential function with base 10. */ INLINE real_t exp10(real_t x); /** Calculates the exponential function with base 2. */ INLINE real_t exp2(real_t x); /** Calculates the factorial of some integer n >= 0. */ //INLINE int factorial(int n); /** Converts a frequency in Hz into a MIDI-note value assuming A4 = 440 Hz. */ INLINE real_t freqToPitch(real_t freq); /** Converts a frequency in Hz into a MIDI-note value for tunings different than the default 440 Hz. */ INLINE real_t freqToPitch(real_t freq, real_t masterTuneA4); /** Checks a pointer for nullity and if it is not NULL, it calls delete for the associated object and then sets the pointer to NULL. */ INLINE void ifNotNullDeleteAndSetNull(void* pointer); /** Maps an integer index in the range 0...numIndices-1 into a normalized floating point number in the range 0...1. */ INLINE float indexToNormalizedValue(int index, int numIndices); /** Checks, if x is close to some target-value within some tolerance. */ INLINE bool isCloseTo(real_t x, real_t targetValue, real_t tolerance); /** Checks, if x is even. */ INLINE bool isEven(int x); /** Checks, if x is odd. */ INLINE bool isOdd(int x); /** Checks, if x is a power of 2. */ INLINE bool isPowerOfTwo(unsigned int x); /** Calculates the logarithm to base 2. */ INLINE real_t log2(real_t x); /** Calculates logarithm to an arbitrary base b. */ INLINE real_t logB(real_t x, real_t b); /** Converts a value between inMin and inMax into a value between outMin and outMax where the mapping is linear for the input and the output. Example: y = linToLin(x, 0.0, 1.0, -96.0, 24.0) will map the input x assumed to lie inside 0.0...1.0 to the range between -96.0...24.0. This function is useful to convert between parameter representations between 0.0...1.0 and the clear-text parameters. */ INLINE real_t linToLin(real_t in, real_t inMin, real_t inMax, real_t outMin, real_t outMax); /** Converts a value between inMin and inMax into a value between outMin and outMax where the mapping of the output is exponential. Example: y = linToExp(x, 0.0, 1.0, 20.0, 20000.0) will map the input x assumed to lie inside 0.0...1.0 to the range between 20.0...20000.0 where equal differences in the input lead to equal factors in the output. Make sure that the outMin value is greater than zero! */ INLINE real_t linToExp(real_t in, real_t inMin, real_t inMax, real_t outMin, real_t outMax); /** Same as linToExp but adds an offset afterwards and compensates for that offset by scaling the offsetted value so as to hit the outMax correctly. */ INLINE real_t linToExpWithOffset(real_t in, real_t inMin, real_t inMax, real_t outMin, real_t outMax, real_t offset = 0.0); /** The Inverse of "linToExp" */ INLINE real_t expToLin(real_t in, real_t inMin, real_t inMax, real_t outMin, real_t outMax); /** The Inverse of "linToExpWithOffset" */ INLINE real_t expToLinWithOffset(real_t in, real_t inMin, real_t inMax, real_t outMin, real_t outMax, real_t offset = 0.0); /** Returns a power of two which is greater than or equal to the input argument. */ template INLINE T nextPowerOfTwo(T x); /** Maps a normalized floating point number in the range 0...1 into an integer index in the range 0...numIndices-1. */ INLINE int normalizedValueToIndex(float normalizedValue, int numIndices); /** Converts a picth-offset in semitones value into a frequency multiplication factor. */ INLINE real_t pitchOffsetToFreqFactor(real_t pitchOffset); /** Converts a MIDI-note value into a frequency in Hz assuming A4 = 440 Hz. */ INLINE real_t pitchToFreq(real_t pitch); /** Converts a MIDI-note value into a frequency in Hz for arbitrary master-tunings of A4. */ INLINE real_t pitchToFreq(real_t pitch, real_t masterTuneA4); /** Converts an angle in radiant into degrees. */ INLINE real_t radiantToDegree(real_t radiant); /** Generates a random number that is uniformly distributed between min and max (inclusive). The underlying integer pseudo random number generator is a linear congruential with period length of 2^32. It is based on Numerical Recipies in C (2nd edition), page 284. You may pass a seed to the first call to initialize it - otherwise it will use 0 as seed. A negative number (as in the default argument) will indicate to not initialize the state and just generate a random number based on the last state (which is the case for a typical call). */ INLINE real_t randomUniform(real_t min = 0.0, real_t max = 1.0, int seed = -1); /** Returns the nearest integer (as real_t, without typecast). */ INLINE real_t round(real_t x); /** Converts a time value in seconds into a time value measured in beats. */ INLINE real_t secondsToBeats(real_t timeInSeconds, real_t bpm); /** Returns the sign of x as real_t. */ INLINE real_t sign(real_t x); /** Converts a time-stamp given in whole notes into seconds according to a tempo measured in beats per minute (bpm). */ INLINE real_t wholeNotesToSeconds(real_t noteValue, real_t bpm); //================================================================================================= //implementation: INLINE real_t amp2dB(real_t amp) { return 8.6858896380650365530225783783321 * log(amp); //return 20*log10(amp); // naive version } INLINE real_t amp2dBWithCheck(real_t amp, real_t lowAmplitude) { if( amp >= lowAmplitude ) return 8.6858896380650365530225783783321 * log(amp); else return 8.6858896380650365530225783783321 * log(lowAmplitude); } template INLINE int arrayMaxIndex(T* theArray, int numValues) { int maxIndex = 0; real_t maxValue = theArray[0]; for(int i=0; i maxValue ) { maxValue = theArray[i]; maxIndex = i; } } return maxIndex; } template INLINE int arrayMinIndex(T* theArray, int numValues) { int minIndex = 0; real_t minValue = theArray[0]; for(int i=0; i INLINE T nextPowerOfTwo(T x) { T accu = 1; while(accu < x) accu *= 2; return accu; } INLINE int normalizedValueToIndex(float normalizedValue, int numIndices) { return (int) floor(normalizedValue*numIndices); } INLINE real_t pitchOffsetToFreqFactor(real_t pitchOffset) { return exp(0.057762265046662109118102676788181 * pitchOffset); //return pow(2.0, pitchOffset/12.0); // naive, slower but numerically more precise } INLINE real_t pitchToFreq(real_t pitch) { return 8.1757989156437073336828122976033 * exp(0.057762265046662109118102676788181*pitch); //return 440.0*( pow(2.0, (pitch-69.0)/12.0) ); // naive, slower but numerically more precise } INLINE real_t pitchToFreq(real_t pitch, real_t masterTuneA4) { return masterTuneA4 * 0.018581361171917516667460937040007 * exp(0.057762265046662109118102676788181*pitch); } INLINE real_t radiantToDegree(real_t radiant) { return (180.0/PI)*radiant; } INLINE real_t randomUniform(real_t min, real_t max, int seed) { static unsigned long state = 0; if( seed >= 0 ) state = seed; // initialization, if desired state = 1664525*state + 1013904223; // mod implicitely by integer overflow return min + (max-min) * ((1.0/4294967296.0) * state); // transform to desired range } INLINE real_t round(real_t x) { if( x-floor(x) >= 0.5 ) return ceil(x); else return floor(x); } INLINE real_t secondsToBeats(real_t timeInSeconds, real_t bpm) { return timeInSeconds*(bpm/60.0); } INLINE real_t sign(real_t x) { if(x<0) return -1.0; else if(x>0) return 1.0; else return 0; } INLINE real_t wholeNotesToSeconds(real_t noteValue, real_t bpm) { return (240.0/bpm)*noteValue; } } //[eh2k] end namespace #endif // #ifndef GlobalFunctions_h ================================================ FILE: lib/open303/src/rosic_AnalogEnvelope.cpp ================================================ #include "rosic_AnalogEnvelope.h" using namespace rosic; //------------------------------------------------------------------------------------------------- // construction/destruction: AnalogEnvelope::AnalogEnvelope() { sampleRate = SAMPLE_RATE; startLevel = 0.0; attackTime = 0.0; peakLevel = 1.0; holdTime = 0.0; decayTime = 0.1; sustainLevel = 0.5; releaseTime = 0.01; endLevel = 0.0; time = 0.0; timeScale = 1.0; peakByVel = 1.0; peakByKey = 1.0; timeScaleByVel = 1.0; timeScaleByKey = 1.0; increment = 1000.0*timeScale/sampleRate; tauScale = 1.0; peakScale = 1.0; noteIsOn = false; outputIsZero = true; previousOutput = 0.0; // call these functions to trigger the coefficient calculations: setAttack(attackTime); setDecay(decayTime); setRelease(releaseTime); } AnalogEnvelope::~AnalogEnvelope() { } //------------------------------------------------------------------------------------------------- // parameter settings: void AnalogEnvelope::setSampleRate(real_t newSampleRate) { if( newSampleRate > 0.0 ) sampleRate = newSampleRate; // adjust time increment: increment = 1000.0*timeScale/sampleRate; //re-calculate coefficients for the 3 filters: setAttack (attackTime); setDecay (decayTime); setRelease(releaseTime); } void AnalogEnvelope::setAttack(real_t newAttackTime) { if( newAttackTime > 0.0 ) { attackTime = newAttackTime; real_t tau = (sampleRate*0.001*attackTime) * tauScale/timeScale; attackCoeff = 1.0 - exp( -1.0 / tau ); } else // newAttackTime <= 0 { attackTime = 0.0; attackCoeff = 1.0; } calculateAccumulatedTimes(); } void AnalogEnvelope::setHold(real_t newHoldTime) { if( newHoldTime >= 0 ) holdTime = newHoldTime; calculateAccumulatedTimes(); } void AnalogEnvelope::setDecay(real_t newDecayTime) { if( newDecayTime > 0.0 ) { decayTime = newDecayTime; real_t tau = (sampleRate*0.001*decayTime) * tauScale/timeScale; decayCoeff = 1.0 - exp( -1.0 / tau ); } else // newDecayTime <= 0 { decayTime = 0.0; decayCoeff = 1.0; } calculateAccumulatedTimes(); } void AnalogEnvelope::setRelease(real_t newReleaseTime) { if( newReleaseTime > 0.0 ) { releaseTime = newReleaseTime; real_t tau = (sampleRate*0.001*releaseTime) * tauScale/timeScale; releaseCoeff = 1.0 - exp( -1.0 / tau ); } else // newReleaseTime <= 0 { releaseTime = 0.0; releaseCoeff = 1.0; } calculateAccumulatedTimes(); } void AnalogEnvelope::setTimeScale(real_t newTimeScale) { if( newTimeScale > 0 ) timeScale = newTimeScale; increment = 1000.0*timeScale/sampleRate; //re-calculate coefficients for the 3 filters: setAttack (attackTime); setDecay (decayTime); setRelease(releaseTime); } void AnalogEnvelope::setTauScale(real_t newTauScale) { if( newTauScale > 0 ) tauScale = newTauScale; setAttack(attackTime); setDecay(decayTime); setRelease(releaseTime); } void AnalogEnvelope::setPeakScale(real_t newPeakScale) { if( newPeakScale > 0 ) peakScale = newPeakScale; } //------------------------------------------------------------------------------------------------- // others: void AnalogEnvelope::reset() { time = 0.0; } void AnalogEnvelope::noteOn(bool startFromCurrentLevel, int newKey, int newVel) { if( !startFromCurrentLevel ) previousOutput = startLevel; // may lead to clicks // \todo: calculate key and velocity scale factors for duration and peak-value... // reset time for the new note: time = 0.0; noteIsOn = true; outputIsZero = false; } void AnalogEnvelope::noteOff() { noteIsOn = false; // advance time to the beginnig of the release phase: time = (attackTime + holdTime + decayTime + increment); } bool AnalogEnvelope::endIsReached() { //return false; // test if( noteIsOn == false && previousOutput < 0.000001 ) return true; else return false; } //------------------------------------------------------------------------------------------------- // internal functions: void AnalogEnvelope::calculateAccumulatedTimes() { attPlusHld = attackTime + holdTime; attPlusHldPlusDec = attPlusHld + decayTime; attPlusHldPlusDecPlusRel = attPlusHldPlusDec + releaseTime; } ================================================ FILE: lib/open303/src/rosic_AnalogEnvelope.h ================================================ #ifndef rosic_AnalogEnvelope_h #define rosic_AnalogEnvelope_h // rosic-indcludes: #include "rosic_RealFunctions.h" namespace rosic { /** This is a class which generates an exponential envelope with adjustable start-, attack-, peak-, hold-, decay-, sustain-, release- and end-values. It is based on feeding a stairstep-like input signal into a RC-filter unit. The filter input signal is switched to a new value according to the time and level values, at the same time the filter is switched to it's new time constant. This also implies, that the level-value will not really be reached (in theory) but only approached asymptotically. So the time values are not really the time between the levels, but rather time constants tau of the RC unit. The time constant tau is defined as the time until the filter reaches 63.2% of the end value (for an incoming step-function). This time constant can be scaled to re-define the ramp time to other values than 63.2%. */ class AnalogEnvelope { public: //--------------------------------------------------------------------------------------------- // construction/destruction: /** Constructor. */ AnalogEnvelope(); /** Destructor. */ ~AnalogEnvelope(); //--------------------------------------------------------------------------------------------- // parameter settings: /** sets the sample-rate. */ void setSampleRate(real_t newSampleRate); /** Sets the point where the envelope starts (as raw value). */ void setStartLevel(real_t newStart) { startLevel = newStart; } /** Sets the point where the envelope starts (in dB). */ void setStartInDecibels(real_t newStart) { setStartLevel(dB2amp(newStart)); } /** Sets the point where the envelope starts (in semitones). */ void setStartInSemitones(real_t newStart) { setStartLevel(pitchOffsetToFreqFactor(newStart)); } /** Sets the highest point of the envelope (as raw value). */ void setPeakLevel(real_t newPeak) { peakLevel = newPeak; } /** Sets the highest point of the envelope (in dB). */ void setPeakInDecibels(real_t newPeak) { setPeakLevel(dB2amp(newPeak)); } /** Sets the highest point of the envelope (in semitones). */ void setPeakInSemitones(real_t newPeak) { setPeakLevel(pitchOffsetToFreqFactor(newPeak)); } /** Sets the velocity dependence of the peak level as scaling factor of the peak by notes with velocity == 127. Notes with velocity == 1 will use the reciprocal value and notes with velocity == 64 will use the unmodified peak value. */ void setPeakLevelByVel(real_t newPeakByVel) { peakByVel = newPeakByVel; } /** Sets the velocity dependence of the peak level in dB - notes with velocity == 127 will peak this value louder, notes with velocity == 0 will peak this value more quiet and notes with velocity == 64 will have an unmodified peak amplitude. */ void setPeakByVelInDecibels(real_t newPeakByVel) { setPeakLevelByVel(dB2amp(newPeakByVel)); } /** Sets the velocity dependence of the peak level in semitones .... */ void setPeakByVelInSemitones(real_t newPeakByVel) { setPeakLevelByVel(pitchOffsetToFreqFactor(newPeakByVel)); } /** Sets the sustain level (as raw value). */ void setSustainLevel(real_t newSustain) { sustainLevel = newSustain; } /** Sets the sustain level (in dB). */ void setSustainInDecibels(real_t newSustain) { setSustainLevel(dB2amp(newSustain)); } /** Sets the sustain level (in semitones). */ void setSustainInSemitones(real_t newSustain) { setSustainLevel(pitchOffsetToFreqFactor(newSustain)); } /** Sets the end point of the envelope (as raw value). */ void setEndLevel(real_t newEnd) { endLevel = newEnd; } /** Sets the end point of the envelope (in dB). */ void setEndInDecibels(real_t newEnd) { setEndLevel(dB2amp(newEnd)); } /** Sets the end point of the envelope (in semitones). */ void setEndInSemitones(real_t newEnd) { setEndLevel(pitchOffsetToFreqFactor(newEnd)); } /** Sets the length of the attack phase (in milliseconds). */ void setAttack(real_t newAttackTime); /** Sets the hold time (in milliseconds). */ void setHold(real_t newHoldTime); /** Sets the length of the decay phase (in milliseconds). */ void setDecay(real_t newDecayTime); /** Sets the length of the release phase (in milliseconds). */ void setRelease(real_t newReleaseTime); /** Scales the A,D,H and R times by adjusting the increment. It is 1 if not used - a timescale of 2 means the envelope is twice as fast, 0.5 means half as fast -> useful for implementing a key/velocity-tracking feature for the overall length for the envelope. */ void setTimeScale(real_t newTimeScale); /** Scales the time constants tau. Can be used to reach other values than 63.2% in the specified time values */ void setTauScale(real_t newTauScale); /** Scales the peak-value of the envelope - useful for velocity response. */ void setPeakScale(real_t newPeakScale); /** Sets the internal state of the RC-filter. */ void setInternalState(real_t newState) { previousOutput = newState; } //--------------------------------------------------------------------------------------------- // inquiry: /** Returns the length of the attack phase (in milliseconds). */ real_t getAttack() const { return attackTime; } /** Returns the length of the decay phase (in milliseconds). */ real_t getDecay() const { return decayTime; } /** Returns the sustain level (as raw value). */ real_t getSustain() const { return sustainLevel; } /** Returns the length of the release phase (in milliseconds). */ real_t getRelease() const { return releaseTime; } /** Returns, when currently a note is on (the noteIsOn flag is set). */ bool isNoteOn() const { return noteIsOn; } /** True, if output is below 40 dB. */ bool endIsReached(); //--------------------------------------------------------------------------------------------- // audio processing: /** Calculates one output sample at a time. */ INLINE real_t getSample(); //--------------------------------------------------------------------------------------------- // others: /** Causes the envelope to start with its attack-phase. When the parameter 'startFromCurrentValue' is true, the internal state will not be reset to startLevel, such that the curve begins at the level, where the envelope currently is. */ void noteOn(bool startFromCurrentLevel = false, int newKey = 64, int newVel = 64); /** Causes the envelope to start with its release-phase. */ void noteOff(); /** Resets the time variable. */ void reset(); protected: /** Calculates our members that represent accumulated time values from attack, hold, etc. */ void calculateAccumulatedTimes(); // level and time parameters: real_t startLevel, peakLevel, sustainLevel, endLevel; real_t attackTime, holdTime, decayTime, releaseTime; // in seconds real_t peakByVel, peakByKey, timeScaleByVel, timeScaleByKey; // accumulated time values: real_t attPlusHld, attPlusHldPlusDec, attPlusHldPlusDecPlusRel; real_t time; // time since the last call to to trigger() real_t timeScale; // scale the time constants in the filters according to real_t increment; // increment for the time variable per sample real_t tauScale; // scale factor for the time constants of the filters real_t peakScale; // scale factor for the peak-value real_t attackCoeff, decayCoeff, releaseCoeff; // filter coefficients real_t previousOutput; // previous output sample real_t sampleRate; // sample-rate bool outputIsZero; // indicates if envelope has reached its end bool noteIsOn; // indicates if note is being held }; //----------------------------------------------------------------------------------------------- // inlined functions: INLINE real_t AnalogEnvelope::getSample() { real_t out; // attack or hold phase: if(time <= attPlusHld) // noteIsOn has not to be checked, because, time is advanced to the // beginning of the release phase in noteOff() { out = previousOutput + attackCoeff * (peakScale*peakLevel - previousOutput); time += increment; } // decay phase: else if(time <= (attPlusHldPlusDec)) // noteIsOn has not to be checked { out = previousOutput + decayCoeff * (sustainLevel - previousOutput); time += increment; } // sustain phase: else if(noteIsOn) { out = previousOutput + decayCoeff * (sustainLevel - previousOutput); // time is not incremented in sustain } // release phase: else { out = previousOutput + releaseCoeff * (endLevel - previousOutput); time += increment; } // store output sample for next call: previousOutput = out; // + TINY; // TINY is to avoid denorm problems return out; } } // end namespace rosic #endif // rosic_AnalogEnvelope_h ================================================ FILE: lib/open303/src/rosic_BiquadFilter.cpp ================================================ #include "rosic_BiquadFilter.h" using namespace rosic; //------------------------------------------------------------------------------------------------- // construction/destruction: BiquadFilter::BiquadFilter() { frequency = 1000.0; gain = 0.0; bandwidth = 2.0*asinh(1.0/sqrt(2.0))/log(2.0); sampleRate = SAMPLE_RATE; mode = BYPASS; calcCoeffs(); reset(); } //------------------------------------------------------------------------------------------------- // parameter settings: void BiquadFilter::setSampleRate(real_t newSampleRate) { if( newSampleRate > 0.0 ) sampleRate = newSampleRate; calcCoeffs(); } void BiquadFilter::setMode(int newMode) { mode = newMode; // 0:bypass, 1:Low Pass, 2:High Pass calcCoeffs(); } void BiquadFilter::setFrequency(real_t newFrequency) { frequency = newFrequency; calcCoeffs(); } void BiquadFilter::setGain(real_t newGain) { gain = newGain; calcCoeffs(); } void BiquadFilter::setBandwidth(real_t newBandwidth) { bandwidth = newBandwidth; calcCoeffs(); } //------------------------------------------------------------------------------------------------- //others: void BiquadFilter::calcCoeffs() { real_t w = 2*PI*frequency/sampleRate; real_t s, c; switch(mode) { case LOWPASS6: { // formula from dspguide: real_t x = exp(-w); a1 = x; a2 = 0.0; b0 = 1.0-x; b1 = 0.0; b2 = 0.0; } break; case LOWPASS12: { // formula from Robert Bristow Johnson's biquad cookbook: sinCos(w, &s, &c); real_t q = dB2amp(gain); real_t alpha = s/(2.0*q); real_t scale = 1.0/(1.0+alpha); a1 = 2.0*c * scale; a2 = (alpha-1.0) * scale; b1 = (1.0-c) * scale; b0 = 0.5*b1; b2 = b0; } break; case HIGHPASS6: { // formula from dspguide: real_t x = exp(-w); a1 = x; a2 = 0.0; b0 = 0.5*(1.0+x); b1 = -b0; b2 = 0.0; } break; case HIGHPASS12: { // formula from Robert Bristow Johnson's biquad cookbook: sinCos(w, &s, &c); real_t q = dB2amp(gain); real_t alpha = s/(2.0*q); real_t scale = 1.0/(1.0+alpha); a1 = 2.0*c * scale; a2 = (alpha-1.0) * scale; b1 = -(1.0+c) * scale; b0 = -0.5*b1; b2 = b0; } break; case BANDPASS: { // formula from Robert Bristow Johnson's biquad cookbook: sinCos(w, &s, &c); real_t alpha = s * sinh( 0.5*log(2.0) * bandwidth * w / s ); real_t scale = 1.0/(1.0+alpha); a1 = 2.0*c * scale; a2 = (alpha-1.0) * scale; b1 = 0.0; b0 = 0.5*s * scale; b2 = -b0; } break; case BANDREJECT: { // formula from Robert Bristow Johnson's biquad cookbook: sinCos(w, &s, &c); real_t alpha = s * sinh( 0.5*log(2.0) * bandwidth * w / s ); real_t scale = 1.0/(1.0+alpha); a1 = 2.0*c * scale; a2 = (alpha-1.0) * scale; b0 = 1.0 * scale; b1 = -2.0*c * scale; b2 = 1.0 * scale; } break; case PEAK: { // formula from Robert Bristow Johnson's biquad cookbook: sinCos(w, &s, &c); real_t alpha = s * sinh( 0.5*log(2.0) * bandwidth * w / s ); real_t A = dB2amp(gain); real_t scale = 1.0/(1.0+alpha/A); a1 = 2.0*c * scale; a2 = ((alpha/A) - 1.0) * scale; b0 = (1.0+alpha*A) * scale; b1 = -2.0*c * scale; b2 = (1.0-alpha*A) * scale; } break; case LOW_SHELF: { // formula from Robert Bristow Johnson's biquad cookbook: sinCos(w, &s, &c); real_t A = dB2amp(0.5*gain); real_t q = 1.0 / (2.0*sinh( 0.5*log(2.0) * bandwidth )); real_t beta = sqrt(A) / q; real_t scale = 1.0 / ( (A+1.0) + (A-1.0)*c + beta*s); a1 = 2.0 * ( (A-1.0) + (A+1.0)*c ) * scale; a2 = - ( (A+1.0) + (A-1.0)*c - beta*s ) * scale; b0 = A * ( (A+1.0) - (A-1.0)*c + beta*s ) * scale; b1 = 2.0 * A * ( (A-1.0) - (A+1.0)*c ) * scale; b2 = A * ( (A+1.0) - (A-1.0)*c - beta*s ) * scale; } break; // \todo: implement shelving and allpass modes default: // bypass { b0 = 1.0; b1 = 0.0; b2 = 0.0; a1 = 0.0; a2 = 0.0; }break; } } void BiquadFilter::reset() { x1 = 0.0; x2 = 0.0; y1 = 0.0; y2 = 0.0; } ================================================ FILE: lib/open303/src/rosic_BiquadFilter.h ================================================ #ifndef rosic_BiquadFilter_h #define rosic_BiquadFilter_h // rosic-indcludes: #include "rosic_RealFunctions.h" namespace rosic { /** This is an implementation of a simple one-pole filter unit. */ class BiquadFilter { public: /** Enumeration of the available filter modes. */ enum modes { BYPASS = 0, LOWPASS6, LOWPASS12, HIGHPASS6, HIGHPASS12, BANDPASS, BANDREJECT, PEAK, LOW_SHELF, //HIGH_SHELF, //ALLPASS, NUM_FILTER_MODES }; //--------------------------------------------------------------------------------------------- // construction/destruction: /** Constructor. */ BiquadFilter(); //--------------------------------------------------------------------------------------------- // parameter settings: /** Sets the sample-rate (in Hz) at which the filter runs. */ void setSampleRate(real_t newSampleRate); /** Sets the filter mode as one of the values in enum modes. */ void setMode(int newMode); /** Sets the center frequency in Hz. */ void setFrequency(real_t newFrequency); /** Sets the boost/cut gain in dB. */ void setGain(real_t newGain); /** Sets the bandwidth in octaves. */ void setBandwidth(real_t newBandwidth); //--------------------------------------------------------------------------------------------- // inquiry /** Sets the filter mode as one of the values in enum modes. */ int getMode() const { return mode; } /** Returns the center frequency in Hz. */ real_t getFrequency() const { return frequency; } /** Returns the boost/cut gain in dB. */ real_t getGain() const { return gain; } /** Returns the bandwidth in octaves. */ real_t getBandwidth() const { return bandwidth; } //--------------------------------------------------------------------------------------------- // audio processing: /** Calculates a single filtered output-sample. */ INLINE real_t getSample(real_t in); //--------------------------------------------------------------------------------------------- // others: /** Resets the internal buffers (for the \f$ x[n-1], y[n-1] \f$-samples) to zero. */ void reset(); //============================================================================================= protected: // internal functions: void calcCoeffs(); // calculates filter coefficients from filter parameters real_t b0, b1, b2, a1, a2; real_t x1, x2, y1, y2; real_t frequency, gain, bandwidth; real_t sampleRate; int mode; }; //----------------------------------------------------------------------------------------------- // inlined functions: INLINE real_t BiquadFilter::getSample(real_t in) { // calculate the output sample: real_t y = b0*in + b1*x1 + b2*x2 + a1*y1 + a2*y2 + TINY; // update the buffer variables: x2 = x1; x1 = in; y2 = y1; y1 = y; return y; } } // end namespace rosic #endif // rosic_BiquadFilter_h ================================================ FILE: lib/open303/src/rosic_BlendOscillator.cpp ================================================ #include "rosic_BlendOscillator.h" using namespace rosic; //------------------------------------------------------------------------------------------------- // construction/destruction: BlendOscillator::BlendOscillator() { // init member variables: tableLengthDbl = (real_t) WaveTableLength; // typecasted version sampleRate = SAMPLE_RATE; freq = 440.0; increment = (tableLengthDbl*freq)/sampleRate; phaseIndex = 0.0; startIndex = 0.0; waveTable1 = NULL; waveTable2 = NULL; // somewhat redundant: setSampleRate(sampleRate); // sampleRate = 44100 Hz by default setFrequency (freq); // frequency = 440 Hz by default setStartPhase(0.0); // sartPhase = 0 by default //setWaveForm1(MipMappedWaveTable::SAW); //setWaveForm2(MipMappedWaveTable::SQUARE); resetPhase(); } BlendOscillator::~BlendOscillator() { } //------------------------------------------------------------------------------------------------- // parameter settings: void BlendOscillator::setSampleRate(real_t newSampleRate) { if( newSampleRate > 0.0 ) sampleRate = newSampleRate; sampleRateRec = 1.0 / sampleRate; increment = tableLengthDbl*freq*sampleRateRec; } void BlendOscillator::setWaveTables(const WaveTable* newWaveTable1, const WaveTable* newWaveTable2) { waveTable1 = newWaveTable1; waveTable2 = newWaveTable2; } void BlendOscillator::setStartPhase(real_t StartPhase) { if( (StartPhase>=0) && (StartPhase<=360) ) startIndex = (StartPhase/360.0)*tableLengthDbl; } //------------------------------------------------------------------------------------------------- // event processing: void BlendOscillator::resetPhase() { phaseIndex = startIndex; } void BlendOscillator::setPhase(real_t PhaseIndex) { phaseIndex = startIndex+PhaseIndex; } ================================================ FILE: lib/open303/src/rosic_BlendOscillator.h ================================================ #ifndef rosic_BlendOscillator_h #define rosic_BlendOscillator_h // rosic-indcludes: #include "rosic_NumberManipulations.h" namespace rosic { /** This is an oscillator that can continuously blend between two waveforms - this is more efficient than using two separate oscillators because the phase-accumulator has to be calculated only once for both waveforms. */ static constexpr int WaveTableLength = 2048; typedef real_t WaveTable[12][2052]; class BlendOscillator { public: //--------------------------------------------------------------------------------------------- // construction/destruction: /** Constructor. */ BlendOscillator(); /** Destructor. */ ~BlendOscillator(); //--------------------------------------------------------------------------------------------- // parameter settings: /** Sets the sample-rateRate(). */ void setSampleRate(real_t newSampleRate); /** Set start phase (range 0 - 360 degrees). */ void setStartPhase(real_t StartPhase); /** An object of class WaveTable should be passed with this function which will be used in the oscillator. Not to have "our own" WaveTable-object as member-variable avoids the need to have the same waveform for different synth-voices multiple times in the memory. This function sets the 1st wavetable. */ void setWaveTables(const WaveTable* newWaveTable1, const WaveTable* newWaveTable2); /** Sets the blend/mix factor between the two waveforms. The value is expected between 0...1 where 0 means waveform1 only, 1 means waveform2 only - in between there will be a linear blend between the two waveforms. */ void setBlendFactor(real_t newBlendFactor) { blend = newBlendFactor; } /** Sets the frequency of the oscillator. */ INLINE void setFrequency(real_t newFrequency); /** Sets the phase increment from outside. */ INLINE void setIncrement(real_t newIncrement) { increment = newIncrement; } //--------------------------------------------------------------------------------------------- // inquiry: /** Returns the blend/mix factor between the two waveforms as a value between 0...1 where 0 means waveform1 only, 1 means waveform2 only - in between there will be a linear blend between the two waveforms. */ real_t getBlendFactor() const { return blend; } /** Returns the phase increment. */ INLINE real_t getIncrement() const { return increment; } //--------------------------------------------------------------------------------------------- // audio processing: /** Calculates one output sample at a time. */ INLINE real_t getSample(); //--------------------------------------------------------------------------------------------- // others: /** Calculates the phase-increments for first and second half-period according to freq and pulseWidth. */ INLINE void calculateIncrement(); INLINE real_t interpolateLinear(const real_t* tableSet, int integerPart, real_t fractionalPart); /** Resets the phaseIndex to startIndex. */ void resetPhase(); /** Reset the phaseIndex to startIndex+PhaseIndex. */ void setPhase(real_t PhaseIndex); //============================================================================================= protected: real_t tableLengthDbl; // tableLength as real_t variable real_t phaseIndex; // current phase index real_t freq; // frequency of the oscillator real_t increment; // phase increment per sample real_t blend; // the blend factor between the two waveforms real_t startIndex; // start-phase-index of the osc (range: 0 - tableLength) real_t sampleRate; // the samplerate real_t sampleRateRec; // 1/sampleRate const WaveTable *waveTable1, *waveTable2; // the 2 wavetables between which we blend }; //----------------------------------------------------------------------------------------------- // inlined functions: INLINE void BlendOscillator::setFrequency(real_t newFrequency) { if( (newFrequency > 0.0) && (newFrequency < 20000.0) ) freq = newFrequency; } INLINE void BlendOscillator::calculateIncrement() { increment = tableLengthDbl*freq*sampleRateRec; } INLINE real_t BlendOscillator::interpolateLinear(const real_t* tableSet, int integerPart, real_t fractionalPart) { return (1.0-fractionalPart) * tableSet[integerPart] + fractionalPart * tableSet[integerPart+1]; } INLINE real_t BlendOscillator::getSample() { real_t out1, out2; int tableNumber; // from this increment, decide which table is to be used: tableNumber = ((int)EXPOF(increment)); //tableNumber += 1; // generate frequencies up to nyquist/2 on the highest note tableNumber += 2; // generate frequencies up to nyquist/4 on the highest note // \todo: make this number adjustable from outside // wraparound if necessary: while( phaseIndex>=tableLengthDbl ) phaseIndex -= tableLengthDbl; int intIndex = floorInt(phaseIndex); real_t frac = phaseIndex - (real_t) intIndex; out1 = (1.0-blend) * interpolateLinear(&(*waveTable1)[tableNumber][0], intIndex, frac); out2 = blend * interpolateLinear(&(*waveTable2)[tableNumber][0], intIndex, frac); out2 *= 0.5; // \todo: this is preliminary to scale the square in AciDevil we need to // implement something more general here (like a kind of crest-compensation in // the wavetable-class) phaseIndex += increment; return out1 + out2; } } // end namespace rosic #endif // rosic_BlendOscillator_h ================================================ FILE: lib/open303/src/rosic_DecayEnvelope.cpp ================================================ #include "rosic_DecayEnvelope.h" using namespace rosic; //------------------------------------------------------------------------------------------------- // construction/destruction: DecayEnvelope::DecayEnvelope() { c = 1.0; y = 1.0; yInit = 1.0; tau = 200.0; fs = SAMPLE_RATE; normalizeSum = false; calculateCoefficient(); } DecayEnvelope::~DecayEnvelope() { } //------------------------------------------------------------------------------------------------- // parameter settings: void DecayEnvelope::setSampleRate(real_t newSampleRate) { if( newSampleRate > 0.0 ) { fs = newSampleRate; calculateCoefficient(); } } void DecayEnvelope::setDecayTimeConstant(real_t newTimeConstant) { if( newTimeConstant > 0.001 ) // at least 0.001 ms decay { tau = newTimeConstant; calculateCoefficient(); } } void DecayEnvelope::setNormalizeSum(bool shouldNormalizeSum) { normalizeSum = shouldNormalizeSum; calculateCoefficient(); } //------------------------------------------------------------------------------------------------- // others: void DecayEnvelope::trigger() { y = yInit; } bool DecayEnvelope::endIsReached(real_t threshold) { if( y < threshold ) return true; else return false; } //------------------------------------------------------------------------------------------------- // internal functions: void DecayEnvelope::calculateCoefficient() { c = exp( -1.0 / (0.001*tau*fs) ); if( normalizeSum == true ) yInit = (1.0-c)/c; else yInit = 1.0/c; } ================================================ FILE: lib/open303/src/rosic_DecayEnvelope.h ================================================ #ifndef rosic_DecayEnvelope_h #define rosic_DecayEnvelope_h // rosic-indcludes: #include "rosic_RealFunctions.h" namespace rosic { /** This is a class implements an envelope generator that realizes a pure exponential decay. The output of the envelope is normalized to the range 0...1. */ class DecayEnvelope { public: //--------------------------------------------------------------------------------------------- // construction/destruction: /** Constructor. */ DecayEnvelope(); /** Destructor. */ ~DecayEnvelope(); //--------------------------------------------------------------------------------------------- // parameter settings: /** Sets the sample-rate. */ void setSampleRate(real_t newSampleRate); /** Sets the time constant for the multiplicative accumulator (which we consider as primarily responsible for the decaying part) in milliseconds. */ void setDecayTimeConstant(real_t newTimeConstant); /** Switches into a mode where the normalization is not made with respect to the peak amplitude but to the sum of the impulse response - if true, the output will be equivalent to a leaky integrator's impulse response. */ void setNormalizeSum(bool shouldNormalizeSum); //--------------------------------------------------------------------------------------------- // inquiry: /** Returns the length of the decay phase (in milliseconds). */ real_t getDecayTimeConstant() const { return tau; } /** True, if output is below some threshold. */ bool endIsReached(real_t threshold); //--------------------------------------------------------------------------------------------- // audio processing: /** Calculates one output sample at a time. */ INLINE real_t getSample(); //--------------------------------------------------------------------------------------------- // others: /** Triggers the envelope - the next sample retrieved via getSample() will be 1. */ void trigger(); protected: /** Calculates the coefficient for multiplicative accumulation. */ void calculateCoefficient(); real_t c; // coefficient for multiplicative accumulation real_t y; // previous output real_t yInit; // initial yalue for previous output (= y/c) real_t tau; // time-constant (in milliseconds) real_t fs; // sample-rate bool normalizeSum; // flag to indicate that the output should be normalized such that the // sum of the impulse response is unity (instead of the peak) - if true // the output will be equivalent to a leaky integrator's impulse // response }; //----------------------------------------------------------------------------------------------- // inlined functions: INLINE real_t DecayEnvelope::getSample() { y *= c; return y; } } // end namespace rosic #endif // rosic_DecayEnvelope_h ================================================ FILE: lib/open303/src/rosic_EllipticQuarterBandFilter.cpp ================================================ #include "rosic_EllipticQuarterBandFilter.h" using namespace rosic; //------------------------------------------------------------------------------------------------- // construction/destruction: EllipticQuarterBandFilter::EllipticQuarterBandFilter() { reset(); } //------------------------------------------------------------------------------------------------- // parameter settings: void EllipticQuarterBandFilter::reset() { for(int i=0; i<12; i++) w[i] = 0.0; } ================================================ FILE: lib/open303/src/rosic_EllipticQuarterBandFilter.h ================================================ #ifndef rosic_EllipticQuarterBandFilter_h #define rosic_EllipticQuarterBandFilter_h #include // for memmove // rosic-indcludes: #include "GlobalDefinitions.h" namespace rosic { /** This is an elliptic subband filter of 12th order using a Direct Form II implementation structure. */ class EllipticQuarterBandFilter { public: //--------------------------------------------------------------------------------------------- // construction/destruction: /** Constructor. */ EllipticQuarterBandFilter(); //--------------------------------------------------------------------------------------------- // parameter settings: /** Resets the filter state. */ void reset(); //--------------------------------------------------------------------------------------------- // audio processing: /** Calculates a single filtered output-sample. */ INLINE real_t getSample(real_t in); //============================================================================================= protected: // state buffer: real_t w[12]; }; //----------------------------------------------------------------------------------------------- // inlined functions: INLINE real_t EllipticQuarterBandFilter::getSample(real_t in) { const real_t a01 = -9.1891604652189471; const real_t a02 = 40.177553696870497; const real_t a03 = -110.11636661771178; const real_t a04 = 210.18506612078195; const real_t a05 = -293.84744771903240; const real_t a06 = 308.16345558359234; const real_t a07 = -244.06786780384243; const real_t a08 = 144.81877911392738; const real_t a09 = -62.770692151724198; const real_t a10 = 18.867762095902137; const real_t a11 = -3.5327094230551848; const real_t a12 = 0.31183189275203149; const real_t b00 = 0.00013671732099945628; const real_t b01 = -0.00055538501265606384; const real_t b02 = 0.0013681887636296387; const real_t b03 = -0.0022158566490711852; const real_t b04 = 0.0028320091007278322; const real_t b05 = -0.0029776933151090413; const real_t b06 = 0.0030283628243514991; const real_t b07 = -0.0029776933151090413; const real_t b08 = 0.0028320091007278331; const real_t b09 = -0.0022158566490711861; const real_t b10 = 0.0013681887636296393; const real_t b11 = -0.00055538501265606384; const real_t b12 = 0.00013671732099945636; // calculate intermediate and output sample via direct form II - the parentheses facilitate // out-of-order execution of the independent additions (for performance optimization): real_t tmp = (in + TINY) - ( (a01*w[0] + a02*w[1] ) + (a03*w[2] + a04*w[3] ) ) - ( (a05*w[4] + a06*w[5] ) + (a07*w[6] + a08*w[7] ) ) - ( (a09*w[8] + a10*w[9] ) + (a11*w[10] + a12*w[11] ) ); real_t y = b00*tmp + ( (b01*w[0] + b02*w[1]) + (b03*w[2] + b04*w[3] ) ) + ( (b05*w[4] + b06*w[5]) + (b07*w[6] + b08*w[7] ) ) + ( (b09*w[8] + b10*w[9]) + (b11*w[10] + b12*w[11] ) ); // update state variables: memmove(&w[1], &w[0], 11*sizeof(real_t)); w[0] = tmp; return y; } } // end namespace rosic #endif // rosic_EllipticQuarterBandFilter_h ================================================ FILE: lib/open303/src/rosic_FunctionTemplates.cpp ================================================ #include "rosic_FunctionTemplates.h" using namespace rosic; ================================================ FILE: lib/open303/src/rosic_FunctionTemplates.h ================================================ #ifndef rosic_FunctionTemplates_h #define rosic_FunctionTemplates_h // rosic includes: //#include "GlobalDefinitions.h" #include "rosic_RealFunctions.h" #include namespace rosic { // todo write functions for element-wise multiply, divide, negate, // max, min, absMax, createCopy, filter, impulseResponse, impulseResponseLength, // fillWith(real_t value = 0.0), circularShift, resample, // maybe introduce a range (start....end) to which the process is to be applied /** Returns the absolute value of the input argument for types that define the comparison operators: '<', '>', the unary operator '-' and a constructor that takes an int and initializes to zero when 0 is passed. */ template T absT(T x); /** Adds the elements of 'buffer1' and 'buffer2' - type must define operator '+'. The 'result' buffer may be the same as 'buffer1' or 'buffer2'. */ template void add(T *buffer1, T *buffer2, T *result, int length); /** Circularly shifts the content of the buffer by 'numPositions' to the right - for leftward shifts use negative values for numPositions. If the absolute value of 'numPositions' is greater than the length of the buffer, it will use numPositions modulo the length - so if the length is 6 and numPositions is 8, it will whift by 2 positions. */ template void circularShift(T *buffer, int length, int numPositions); /** Restricts the values in the buffer to the range between min and max for types that define the operators '<' and '>'. */ template void clipBuffer(T *buffer, int length, T min, T max); /** Copies the data of one array into another one. */ template void copyBuffer(T *source, T *destination, int length); /** Fills the passed array with all zeros - the type must have a constructor that takes an int and initializes to the zero element when 0 is passed. */ template void fillWithZeros(T *buffer, int length); /** Finds and returns the maximum absolute value of the buffer. */ template T maxAbs(T *buffer, int length); /** Returns the index of maximum value of the buffer (">"-operator must be defined). */ template INLINE int maxIndex(T *buffer, int length); /** Returns the maximum value of the buffer (">"-operator must be defined). */ template INLINE T maxValue(T *buffer, int length); /** Returns the index of minimum value of the buffer ("<"-operator must be defined). */ template INLINE int minIndex(T *buffer, int length); /** Returns the minimum value of the buffer ("<"-operator must be defined). */ template INLINE T minValue(T *buffer, int length); /** Computes the mean (i.e. the DC-component) from the passed buffer. The type must define operators: +=, / and a constructor which takes an int and initializes to zero when 0 is passed and a typecast from int. */ template T mean(T *buffer, int length); /** Returns the median of the passed buffer. */ template T median(T *buffer, int length); /** Multiplies the elements of 'buffer1' and 'buffer2' - type must define operator '*'. The 'result' buffer may be the same as 'buffer1' or 'buffer2'. */ template void multiply(T *buffer1, T *buffer2, T *result, int length); /** Normalizes the maximum value of the passed array. The type must define: >, *=, / and a constructor that takes an int and initializes to 0 when 0 is passed. Additionaly, it must be suitable for absT - that additionaly requires definition of unary '-' and '<'. */ template void normalize(T *buffer, int length, T maximum); /** Rearranges/permutes and array of type T into bit-reversed order. The 'length' MUST be the 'numBits' th power of two (this is not checked for). */ template INLINE void orderBitReversedOutOfPlace(T *inBuffer, T *outBuffer, int length, int numBits); /** Returns the product of the elements in the buffer for types which define the multiplication operator (the *= version thereof) and a constructor which can take an int paramater as argument and initializes to the multiplicative neutral element of that class when 1 is passed . */ template INLINE T product(T *buffer, int length); /** Removes mean (i.e. the DC-component) from the passed buffer. The type must define operators: +=, -=, / and a constructor which takes an int and initializes to zero when 0 is passed and a typecast from int. */ template void removeMean(T *buffer, int length); /** Reverses the order of the elements the passed array. */ template void reverse(T *buffer, int length); /** The maximum of two objects on which the ">"-operator is defined. */ template INLINE T rmax(T in1, T in2); /** The maximum of four objects on which the ">"-operator is defined. */ template INLINE T rmax(T in1, T in2, T in3, T in4); /** The minimum of two objects on which the ">"-operator is defined. */ template INLINE T rmin(T in1, T in2); /** The minimum of four objects on which the ">"-operator is defined. */ template INLINE T rmin(T in1, T in2, T in3, T in4); /** Scales the buffer by a constant factor. */ template void scale(T *buffer, int length, T scaleFactor); /** Subtracts the elements of 'buffer2' from 'buffer1' - type must define operator '-'. The 'result' buffer may be the same as 'buffer1' or 'buffer2'. */ template void subtract(T *buffer1, T *buffer2, T *result, int length); /** Returns the sum of the elements in the buffer for types which define the addition operator (the += version thereof) and a constructor which can take an int paramater as argument and initializes to the additive neutral element of that class when 0 is passed . */ template INLINE T sum(T *buffer, int length); /** Swaps two objects of class T. */ template INLINE void swap(T &in1, T &in2); //=============================================================================================== // implementation: template T absT(T x) { if( x > T(0) ) return x; else if( x < T(0) ) return -x; else return T(0); } template void add(T *buffer1, T *buffer2, T *result, int length) { for(int i=0; i void circularShift(T *buffer, int length, int numPositions) { int na = abs(numPositions); while( na > length ) na -=length; T *tmp = new T[na]; if( numPositions < 0 ) { memcpy( tmp, buffer, na*sizeof(T)); memmove( buffer, &buffer[na], (length-na)*sizeof(T)); memcpy( &buffer[length-na], tmp, na*sizeof(T)); } else if( numPositions > 0 ) { memcpy( tmp, &buffer[length-na], na*sizeof(T)); memmove(&buffer[na], buffer, (length-na)*sizeof(T)); memcpy( buffer, tmp, na*sizeof(T)); } delete[] tmp; } template void clipBuffer(T *buffer, int length, T min, T max) { for(int i=0; i max ) buffer[i] = max; } } template void copyBuffer(T *source, T *destination, int length) { for(int i=0; i void fillWithZeros(T *buffer, int length) { for(int i=0; i T maxAbs(T *buffer, int length) { T max = T(0); for(int i=0; i max) max = absT(buffer[i]); } return max; } template int maxIndex(T *buffer, int length) { T value = buffer[0]; int index = 0; for(int i=0; i value ) { value = buffer[i]; index = i; } } return index; } template T maxValue(T *buffer, int length) { return buffer[maxIndex(buffer, length)]; } template int minIndex(T *buffer, int length) { T value = buffer[0]; int index = 0; for(int i=0; i T minValue(T *buffer, int length) { return buffer[minIndex(buffer, length)]; } template T mean(T *buffer, int length) { return sum(buffer, length) / (T) length; } template void multiply(T *buffer1, T *buffer2, T *result, int length) { for(int i=0; i void normalize(T *buffer, int length, T maximum) { T max = maxAbs(buffer, length);; T scale = maximum / max; for(int i=0; i INLINE T product(T *buffer, int length) { T accu = T(1); // constructor call with 1 should initilize to multiplicative neutral element for(int n=0; n void removeMean(T *buffer, int length) { T m = mean(buffer, length); for(int i=0; i INLINE T rmax(T in1, T in2) { if( in1 > in2 ) return in1; else return in2; } template INLINE T rmax(T in1, T in2, T in3, T in4) { return rmax(rmax(in1, in2), rmax(in3, in4)); } template INLINE T rmin(T in1, T in2) { if( in1 < in2 ) return in1; else return in2; } template INLINE T rmin(T in1, T in2, T in3, T in4) { return rmin(rmin(in1, in2), rmin(in3, in4)); } template void reverse(T *buffer, int length) { T tmp; int lengthMinus1 = length-1; for(int i=0; i<=(length-2)/2; i++) { tmp = buffer[lengthMinus1-i]; buffer[lengthMinus1-i] = buffer[i]; buffer[i] = tmp; } } template void scale(T *buffer, int length, T scaleFactor) { for(int n=0; n void subtract(T *buffer1, T *buffer2, T *result, int length) { for(int i=0; i INLINE T sum(T *buffer, int length) { T accu = T(0); // constructor call with 0 should initilizes to additive neutral element for(int n=0; n INLINE void swap(T &in1, T &in2) { T tmp = in1; in1 = in2; in2 = tmp; } } // end namespace rosic #endif // #ifndef rosic_FunctionTemplates_h ================================================ FILE: lib/open303/src/rosic_LeakyIntegrator.cpp ================================================ #include "rosic_LeakyIntegrator.h" using namespace rosic; //------------------------------------------------------------------------------------------------- // construction/destruction: LeakyIntegrator::LeakyIntegrator() { sampleRate = SAMPLE_RATE; tau = 10.0f; y1 = 0.0; calculateCoefficient(); } LeakyIntegrator::~LeakyIntegrator() { } //------------------------------------------------------------------------------------------------- // parameter settings: void LeakyIntegrator::setSampleRate(real_t newSampleRate) { if( newSampleRate > 0.0 ) { sampleRate = newSampleRate; calculateCoefficient(); } } void LeakyIntegrator::setTimeConstant(real_t newTimeConstant) { if( newTimeConstant >= 0.0 && newTimeConstant != tau ) { tau = newTimeConstant; calculateCoefficient(); } } //------------------------------------------------------------------------------------------------- // inquiry: real_t LeakyIntegrator::getNormalizer(real_t tau1, real_t tau2, real_t fs) { real_t td = 0.001*tau1; real_t ta = 0.001*tau2; // catch some special cases: if( ta == 0.0 && td == 0.0 ) return 1.0; else if( ta == 0.0 ) { return 1.0 / (1.0-exp(-1.0/(fs*td))); } else if( td == 0.0 ) { return 1.0 / (1.0-exp(-1.0/(fs*ta))); } // compute the filter coefficients: real_t x = exp( -1.0 / (fs*td) ); real_t bd = 1-x; real_t ad = -x; x = exp( -1.0 / (fs*ta) ); real_t ba = 1-x; real_t aa = -x; // compute the location and height of the peak: real_t xp; if( ta == td ) { real_t tp = ta; real_t np = fs*tp; xp = (np+1.0)*ba*ba*pow(aa, np); } else { real_t tp = log(ta/td) / ( (1.0/td) - (1.0/ta) ); real_t np = fs*tp; real_t s = 1.0 / (aa-ad); real_t b01 = s * aa*ba*bd; real_t b02 = s * ad*ba*bd; real_t a01 = s * (ad-aa)*aa; real_t a02 = s * (ad-aa)*ad; xp = b01*pow(a01, np) - b02*pow(a02, np); } // return the normalizer as reciprocal of the peak height: return 1.0/xp; } //------------------------------------------------------------------------------------------------- // others: void LeakyIntegrator::reset() { y1 = 0; } void LeakyIntegrator::calculateCoefficient() { if( tau > 0.0 ) coeff = exp( -1.0 / (sampleRate*0.001*tau) ); else coeff = 0.0; } ================================================ FILE: lib/open303/src/rosic_LeakyIntegrator.h ================================================ #ifndef rosic_LeakyIntegrator_h #define rosic_LeakyIntegrator_h // rosic-indcludes: #include "rosic_RealFunctions.h" namespace rosic { /** This is a leaky integrator type lowpass filter with user adjustable time constant which is set up in milliseconds. */ class LeakyIntegrator { public: //--------------------------------------------------------------------------------------------- // construction/destruction: /** Constructor. */ LeakyIntegrator(); /** Destructor. */ ~LeakyIntegrator(); //--------------------------------------------------------------------------------------------- // parameter settings: /** Sets the sample-rate. */ void setSampleRate(real_t newSampleRate); /** Sets the time constant (tau), value is expected in milliseconds. */ void setTimeConstant(real_t newTimeConstant); /** Sets the internal state of the filter to the passed value. */ void setState(real_t newState) { y1 = newState; } //--------------------------------------------------------------------------------------------- // inquiry: /** Returns the time constant (tau) in milliseconds. */ real_t getTimeConstant() const { return tau; } /** Returns the normalizer, required to normalize the impulse response of a series connection of two digital RC-type filters with time constants tau1 and tau2 (in milliseconds) to unity at the given samplerate. */ static real_t getNormalizer(real_t tau1, real_t tau2, real_t sampleRate); //--------------------------------------------------------------------------------------------- // audio processing: /** Calculates one sample at a time. */ INLINE real_t getSample(real_t in); //--------------------------------------------------------------------------------------------- // others: /** Resets the internal state of the filter. */ void reset(); //============================================================================================= protected: /** Calculates the filter coefficient. */ void calculateCoefficient(); real_t coeff; // filter coefficient real_t y1; // previous output sample real_t sampleRate; // the samplerate real_t tau; // time constant in milliseconds }; //----------------------------------------------------------------------------------------------- // inlined functions: INLINE real_t LeakyIntegrator::getSample(real_t in) { return y1 = in + coeff*(y1-in); } } // end namespace rosic #endif ================================================ FILE: lib/open303/src/rosic_MidiNoteEvent.cpp ================================================ #include "rosic_MidiNoteEvent.h" using namespace rosic; //------------------------------------------------------------------------------------------------- // construction/destruction: MidiNoteEvent::MidiNoteEvent() { key = 64; vel = 64; detune = 0.0; priority = 0; } MidiNoteEvent::MidiNoteEvent(int initKey, int initVel, int initDetune, int initPriority) { if( initKey >=0 && initKey <= 127) key = initKey; else key = 64; if( initVel >=0 && initVel <= 127) vel = initVel; else vel = 64; if( initPriority >=0 ) priority = initPriority; else priority = 0; detune = initDetune; } MidiNoteEvent::~MidiNoteEvent() { } //------------------------------------------------------------------------------------------------- // parameter settings: void MidiNoteEvent::setKey(int newKey) { if( newKey >=0 && newKey <= 127) key = newKey; } void MidiNoteEvent::setVelocity(int newVelocity) { if( newVelocity >=0 && newVelocity <= 127) vel = newVelocity; } void MidiNoteEvent::setDetune(real_t newDetune) { detune = newDetune; } void MidiNoteEvent::setPriority(int newPriority) { if( newPriority >=0 ) priority = newPriority; } ================================================ FILE: lib/open303/src/rosic_MidiNoteEvent.h ================================================ #ifndef rosic_MidiNoteEvent_h #define rosic_MidiNoteEvent_h #include "GlobalDefinitions.h" namespace rosic { /** This is a class for representing MIDI note-events. */ class MidiNoteEvent { public: //--------------------------------------------------------------------------------------------- // construction/destruction: /** Default constructor. */ MidiNoteEvent(); /** Constructor with initializations. */ MidiNoteEvent(int initKey, int initVel, int initDetune = 0, int initPriority = 0 ); /** Destructor. */ ~MidiNoteEvent(); //--------------------------------------------------------------------------------------------- // parameter settings: /** Sets the key of the note (as MIDI note number between 0...127). */ void setKey(int newKey); /** Sets the velocity of the note (between 0...127). */ void setVelocity(int newVelocity); /** Sets the detuning of the note (in semitones). */ void setDetune(real_t newDetune); /** Sets the priority of the note. */ void setPriority(int newPriority); //--------------------------------------------------------------------------------------------- // inquiry: /** Returns the key of the note (as MIDI note number between 0...127). */ int getKey() const { return key; } /** Returns the velocity of the note (between 0...127). */ int getVelocity() const { return vel; } /** Returns the detuning of the note (in semitones). */ real_t getDetune() const { return detune; } /** Returns the priority of the note. */ int getPriority() const { return priority; } //--------------------------------------------------------------------------------------------- // overloaded operators: /** Note events are interpreted as equal if the have the same key. */ bool operator==(const MidiNoteEvent& note2) const { if( note2.key == key ) return true; else return false; } protected: int key; // key of the note in the range 0...127 int vel; // velocity of the note in the range 0...127 real_t detune; // detuning in cents (for microtuning) int priority; // a priority value }; } // end namespace rosic #endif // MidiNoteEvent_h ================================================ FILE: lib/open303/src/rosic_NumberManipulations.cpp ================================================ #include "rosic_NumberManipulations.h" using namespace rosic; ================================================ FILE: lib/open303/src/rosic_NumberManipulations.h ================================================ #ifndef rosic_NumberManipulations_h #define rosic_NumberManipulations_h // rosic includes: #include "GlobalDefinitions.h" #include namespace rosic { /** \todo: check the linux versions....they have been inserted here sloppily in order to make it compile when porting. */ /** Assuming, that the FPU is in 'to nearest even integer' rounding mode (which is the default), this function rounds to the nearest integer using upward rounding when the argument is exactly halfway between two integers (instead of returning the nearest even integer in this case). Argument x must satify (INT_MIN/2)�1.0 < x < (INT_MAX/2)+1.0. */ INLINE int roundToInt(real_t x) { # if defined _MSC_VER const float round_to_nearest = 0.5f; int i; __asm { fld x; fadd st, st (0); fadd round_to_nearest; fistp i; sar i, 1; } return (i); /* # elif defined __GNUC__ // too many memory references for 'add', too many memory references for 'sar' const float round_to_nearest = 0.5f; int i; asm("fld x"); asm("fadd st, st(0)"); asm("fadd round_to_nearest"); asm("fistp i"); asm("sar i, 1"); return (i); */ # else real_t xFloor = floor(x); real_t xFrac = x-xFloor; if( xFrac >= 0.5 ) return (int) xFloor + 1; else return (int) xFloor; # endif } INLINE int floorInt(real_t x) { # if defined _MSC_VER const float round_towards_m_i = -0.5f; int i; __asm { fld x; fadd st, st (0); fadd round_towards_m_i; fistp i; sar i, 1; } return (i); /* # elif defined __GNUC__ // under Linux, it says: memory input 2 is not directly addressable const float round_towards_m_i = -0.5f; int i; __asm__ __volatile__ ( "fldl %1 \n\t" "fadd %%st(0), %%st \n\t" "fadds %2 \n\t" "fistpl %0 \n\t" "sarl %0 \n\t" : "=m"(i) : "m"(x), "m"(round_towards_m_i) : "memory" ); return (i); # elif defined __GNUC__ // too many memory references for 'add', too many memory references for 'sar' const float round_towards_m_i = -0.5f; int i; asm("fld x"); asm("fadd st, st (0)"); asm("fadd round_towards_m_i"); asm("fistp i"); asm("sar i, 1"); return (i); */ # else return (int) floor(x); # endif } } // end namespace rosic #endif // #ifndef rosic_NumberManipulations_h ================================================ FILE: lib/open303/src/rosic_OnePoleFilter.cpp ================================================ #include "rosic_OnePoleFilter.h" using namespace rosic; //------------------------------------------------------------------------------------------------- // construction/destruction: OnePoleFilter::OnePoleFilter() { shelvingGain = 1.0; setSampleRate(SAMPLE_RATE); // sampleRate = 44100 Hz by default setMode (0); // bypass by default setCutoff (20000.0); // cutoff = 20000 Hz by default reset(); // reset memorized samples to zero } //------------------------------------------------------------------------------------------------- // parameter settings: void OnePoleFilter::setSampleRate(real_t newSampleRate) { if( newSampleRate > 0.0 ) sampleRate = newSampleRate; sampleRateRec = 1.0 / sampleRate; calcCoeffs(); return; } void OnePoleFilter::setMode(int newMode) { mode = newMode; // 0:bypass, 1:Low Pass, 2:High Pass calcCoeffs(); } void OnePoleFilter::setCutoff(real_t newCutoff) { if( (newCutoff>0.0) && (newCutoff<=20000.0) ) cutoff = newCutoff; else cutoff = 20000.0; calcCoeffs(); return; } void OnePoleFilter::setShelvingGain(real_t newGain) { if( newGain > 0.0 ) { shelvingGain = newGain; calcCoeffs(); } else DEBUG_BREAK; // this is a linear gain factor and must be >= 0.0 } void OnePoleFilter::setShelvingGainInDecibels(real_t newGain) { setShelvingGain(dB2amp(newGain)); } void OnePoleFilter::setCoefficients(real_t newB0, real_t newB1, real_t newA1) { b0 = newB0; b1 = newB1; a1 = newA1; } void OnePoleFilter::setInternalState(real_t newX1, real_t newY1) { x1 = newX1; y1 = newY1; } //------------------------------------------------------------------------------------------------- //others: void OnePoleFilter::calcCoeffs() { switch(mode) { case LOWPASS: { // formula from dspguide: real_t x = exp( -2.0 * PI * cutoff * sampleRateRec); b0 = 1-x; b1 = 0.0; a1 = x; } break; case HIGHPASS: { // formula from dspguide: real_t x = exp( -2.0 * PI * cutoff * sampleRateRec); b0 = 0.5*(1+x); b1 = -0.5*(1+x); a1 = x; } break; case LOWSHELV: { // formula from DAFX: real_t c = 0.5*(shelvingGain-1.0); real_t t = tan(PI*cutoff*sampleRateRec); real_t a; if( shelvingGain >= 1.0 ) a = (t-1.0)/(t+1.0); else a = (t-shelvingGain)/(t+shelvingGain); b0 = 1.0 + c + c*a; b1 = c + c*a + a; a1 = -a; } break; case HIGHSHELV: { // formula from DAFX: real_t c = 0.5*(shelvingGain-1.0); real_t t = tan(PI*cutoff*sampleRateRec); real_t a; if( shelvingGain >= 1.0 ) a = (t-1.0)/(t+1.0); else a = (shelvingGain*t-1.0)/(shelvingGain*t+1.0); b0 = 1.0 + c - c*a; b1 = a + c*a - c; a1 = -a; } break; case ALLPASS: { // formula from DAFX: real_t t = tan(PI*cutoff*sampleRateRec); real_t x = (t-1.0) / (t+1.0); b0 = x; b1 = 1.0; a1 = -x; } break; default: // bypass { b0 = 1.0; b1 = 0.0; a1 = 0.0; }break; } } void OnePoleFilter::reset() { x1 = 0.0; y1 = 0.0; } ================================================ FILE: lib/open303/src/rosic_OnePoleFilter.h ================================================ #ifndef rosic_OnePoleFilter_h #define rosic_OnePoleFilter_h // rosic-indcludes: #include "rosic_RealFunctions.h" namespace rosic { /** This is an implementation of a simple one-pole filter unit. */ class OnePoleFilter { public: /** This is an enumeration of the available filter modes. */ enum modes { BYPASS = 0, LOWPASS, HIGHPASS, LOWSHELV, HIGHSHELV, ALLPASS }; // \todo (maybe): let the user choose between LP/HP versions obtained via bilinear trafo and // impulse invariant trafo //--------------------------------------------------------------------------------------------- // construction/destruction: /** Constructor. */ OnePoleFilter(); //--------------------------------------------------------------------------------------------- // parameter settings: /** Sets the sample-rate. */ void setSampleRate(real_t newSampleRate); /** Chooses the filter mode. See the enumeration for available modes. */ void setMode(int newMode); /** Sets the cutoff-frequency for this filter. */ void setCutoff(real_t newCutoff); /** This will set the time constant 'tau' for the case, when lowpass mode is chosen. This is the time, it takes for the impulse response to die away to 1/e = 0.368... or equivalently, the time it takes for the step response to raise to 1-1/e = 0.632... */ void setLowpassTimeConstant(real_t newTimeConstant) { setCutoff(1.0/(2*PI*newTimeConstant)); } /** Sets the gain factor for the shelving modes (this is not in decibels). */ void setShelvingGain(real_t newGain); /** Sets the gain for the shelving modes in decibels. */ void setShelvingGainInDecibels(real_t newGain); /** Sets the filter coefficients manually. */ void setCoefficients(real_t newB0, real_t newB1, real_t newA1); /** Sets up the internal state variables for both channels. */ void setInternalState(real_t newX1, real_t newY1); //--------------------------------------------------------------------------------------------- // inquiry /** Returns the cutoff-frequency. */ real_t getCutoff() const { return cutoff; } //--------------------------------------------------------------------------------------------- // audio processing: /** Calculates a single filtered output-sample. */ INLINE real_t getSample(real_t in); //--------------------------------------------------------------------------------------------- // others: /** Resets the internal buffers (for the \f$ x[n-1], y[n-1] \f$-samples) to zero. */ void reset(); //============================================================================================= protected: // buffering: real_t x1, y1; // filter coefficients: real_t b0; // feedforward coeffs real_t b1; real_t a1; // feedback coeff // filter parameters: real_t cutoff; real_t shelvingGain; int mode; real_t sampleRate; real_t sampleRateRec; // reciprocal of the sampleRate // internal functions: void calcCoeffs(); // calculates filter coefficients from filter parameters }; //----------------------------------------------------------------------------------------------- // inlined functions: INLINE real_t OnePoleFilter::getSample(real_t in) { // calculate the output sample: y1 = b0*in + b1*x1 + a1*y1 + TINY; // update the buffer variables: x1 = in; return y1; } } // end namespace rosic #endif // rosic_OnePoleFilter_h ================================================ FILE: lib/open303/src/rosic_Open303.cpp ================================================ #include "rosic_Open303.h" using namespace rosic; //------------------------------------------------------------------------------------------------- // construction/destruction: Open303::Open303(const rosic::WaveTable *saw, const rosic::WaveTable *square) { tuning = 440.0; ampScaler = 1.0; oscFreq = 440.0; sampleRate = SAMPLE_RATE; level = -12.0; levelByVel = 12.0; accent = 0.0; slideTime = 60.0; cutoff = 1000.0; envUpFraction = 2.0/3.0; normalAttack = 3.0; accentAttack = 3.0; normalDecay = 1000.0; accentDecay = 200.0; normalAmpRelease = 1.0; accentAmpRelease = 50.0; accentGain = 0.0; pitchWheelFactor = 1.0; currentNote = -1; currentVel = 0; noteOffCountDown = 0; slideToNextNote = false; idle = true; setEnvMod(25.0); oscillator.setWaveTables(saw, square); //mainEnv.setNormalizeSum(true); mainEnv.setNormalizeSum(false); ampEnv.setAttack(0.0); ampEnv.setDecay(1230.0); ampEnv.setSustainLevel(0.0); ampEnv.setRelease(0.5); ampEnv.setTauScale(1.0); pitchSlewLimiter.setTimeConstant(60.0); //ampDeClicker.setTimeConstant(2.0); ampDeClicker.setMode(BiquadFilter::LOWPASS12); ampDeClicker.setGain( amp2dB(sqrt(0.5)) ); ampDeClicker.setFrequency(200.0); rc1.setTimeConstant(0.0); rc2.setTimeConstant(15.0); highpass1.setMode(OnePoleFilter::HIGHPASS); highpass2.setMode(OnePoleFilter::HIGHPASS); allpass.setMode(OnePoleFilter::ALLPASS); notch.setMode(BiquadFilter::BANDREJECT); setSampleRate(sampleRate); // tweakables: highpass1.setCutoff(44.486); highpass2.setCutoff(24.167); allpass.setCutoff(14.008); notch.setFrequency(7.5164); notch.setBandwidth(4.7); filter.setFeedbackHighpassCutoff(150.0); } Open303::~Open303() { } //------------------------------------------------------------------------------------------------- // parameter settings: void Open303::setSampleRate(real_t newSampleRate, int oversampling /*= 4*/) { mainEnv.setSampleRate ( newSampleRate); ampEnv.setSampleRate ( newSampleRate); pitchSlewLimiter.setSampleRate((float)newSampleRate); ampDeClicker.setSampleRate( (float)newSampleRate); rc1.setSampleRate( (float)newSampleRate); rc2.setSampleRate( (float)newSampleRate); #ifdef SEQUENCER sequencer.setSampleRate( newSampleRate); #endif highpass2.setSampleRate ( newSampleRate); allpass.setSampleRate ( newSampleRate); notch.setSampleRate ( newSampleRate); highpass1.setSampleRate ( oversampling*newSampleRate); oscillator.setSampleRate ( oversampling*newSampleRate); filter.setSampleRate ( oversampling*newSampleRate); } void Open303::setCutoff(real_t newCutoff) { cutoff = newCutoff; calculateEnvModScalerAndOffset(); } void Open303::setEnvMod(real_t newEnvMod) { envMod = newEnvMod; calculateEnvModScalerAndOffset(); } void Open303::setAccent(real_t newAccent) { accent = 0.01 * newAccent; } void Open303::setVolume(real_t newLevel) { level = newLevel; ampScaler = dB2amp(level); } void Open303::setSlideTime(real_t newSlideTime) { if( newSlideTime >= 0.0 ) { slideTime = newSlideTime; pitchSlewLimiter.setTimeConstant((float)(0.2*slideTime)); // \todo: tweak the scaling constant } } void Open303::setPitchBend(real_t newPitchBend) { pitchWheelFactor = pitchOffsetToFreqFactor(newPitchBend); } //------------------------------------------------------------------------------------------------------------ // others: void Open303::noteOn(int noteNumber, int velocity, real_t detune) { #ifdef SEQUENCER if( sequencer.modeWasChanged() ) allNotesOff(); if( sequencer.getSequencerMode() != AcidSequencer::OFF ) { if( velocity == 0 ) { sequencer.stop(); releaseNote(currentNote); currentNote = -1; currentVel = 0; } else { sequencer.start(); noteOffCountDown = INT32_MAX; slideToNextNote = false; currentNote = noteNumber; currentVel = velocity; } idle = false; return; } #endif if( velocity == 0 ) // velocity zero indicates note-off events { MidiNoteEvent releasedNote(noteNumber, 0); noteList.remove(releasedNote); if( noteList.empty() ) { currentNote = -1; currentVel = 0; } else { currentNote = noteList.front().getKey(); currentVel = noteList.front().getVelocity(); } releaseNote(noteNumber); } else // velocity was not zero, so this is an actual note-on { // check if the note-list is empty (indicating that currently no note is playing) - if so, // trigger a new note, otherwise, slide to the new note: if( noteList.empty() ) triggerNote(noteNumber, velocity >= 100); else slideToNote(noteNumber, velocity >= 100); currentNote = noteNumber; currentVel = 64; // and we need to add the new note to our list, of course: MidiNoteEvent newNote(noteNumber, velocity); noteList.push_front(newNote); } idle = false; } void Open303::allNotesOff() { noteList.clear(); ampEnv.noteOff(); currentNote = -1; currentVel = 0; } void Open303::triggerNote(int noteNumber, bool hasAccent) { // retrigger osc and reset filter buffers only if amplitude is near zero (to avoid clicks): if( idle ) { oscillator.resetPhase(); filter.reset(); highpass1.reset(); highpass2.reset(); allpass.reset(); notch.reset(); antiAliasFilter.reset(); ampDeClicker.reset(); } if( hasAccent ) { accentGain = accent; setMainEnvDecay(accentDecay); ampEnv.setRelease(accentAmpRelease); } else { accentGain = 0.0; setMainEnvDecay(normalDecay); ampEnv.setRelease(normalAmpRelease); } oscFreq = pitchToFreq(noteNumber, tuning); pitchSlewLimiter.setState(oscFreq); mainEnv.trigger(); ampEnv.noteOn(true, noteNumber, 64); idle = false; } void Open303::slideToNote(int noteNumber, bool hasAccent) { oscFreq = pitchToFreq(noteNumber, tuning); if( hasAccent ) { accentGain = accent; setMainEnvDecay(accentDecay); ampEnv.setRelease(accentAmpRelease); } else { accentGain = 0.0; setMainEnvDecay(normalDecay); ampEnv.setRelease(normalAmpRelease); } idle = false; } void Open303::releaseNote(int noteNumber) { // check if the note-list is empty now. if so, trigger a release, otherwise slide to the note // at the beginning of the list (this is the most recent one which is still in the list). this // initiates a slide back to the most recent note that is still being held: if( noteList.empty() ) { //filterEnvelope.noteOff(); ampEnv.noteOff(); } else { // initiate slide back: oscFreq = pitchToFreq(currentNote); } } void Open303::setMainEnvDecay(real_t newDecay) { mainEnv.setDecayTimeConstant(newDecay); updateNormalizer1(); updateNormalizer2(); } void Open303::calculateEnvModScalerAndOffset() { bool useMeasuredMapping = true; // might be shown as user parameter later if( useMeasuredMapping == true ) { // define some constants that arise from the measurements: const real_t c0 = 3.138152786059267e+002; // lowest nominal cutoff const real_t c1 = 2.394411986817546e+003; // highest nominal cutoff const real_t oF = 0.048292930943553; // factor in line equation for offset const real_t oC = 0.294391201442418; // constant in line equation for offset const real_t sLoF = 3.773996325111173; // factor in line eq. for scaler at low cutoff const real_t sLoC = 0.736965594166206; // constant in line eq. for scaler at low cutoff const real_t sHiF = 4.194548788411135; // factor in line eq. for scaler at high cutoff const real_t sHiC = 0.864344900642434; // constant in line eq. for scaler at high cutoff // do the calculation of the scaler and offset: real_t e = linToLin(envMod, 0.0, 100.0, 0.0, 1.0); real_t c = expToLin(cutoff, c0, c1, 0.0, 1.0); real_t sLo = sLoF*e + sLoC; real_t sHi = sHiF*e + sHiC; envScaler = (1-c)*sLo + c*sHi; envOffset = oF*c + oC; } else { real_t upRatio = pitchOffsetToFreqFactor( envUpFraction *envMod); real_t downRatio = pitchOffsetToFreqFactor(-(1.0-envUpFraction)*envMod); envScaler = upRatio - downRatio; if( envScaler != 0.0 ) // avoid division by zero envOffset = - (downRatio - 1.0) / (upRatio - downRatio); else envOffset = 0.0; } } void Open303::updateNormalizer1() { n1 = LeakyIntegrator::getNormalizer(mainEnv.getDecayTimeConstant(), rc1.getTimeConstant(), sampleRate); n1 = 1.0; // test } void Open303::updateNormalizer2() { n2 = LeakyIntegrator::getNormalizer(mainEnv.getDecayTimeConstant(), rc2.getTimeConstant(), sampleRate); n2 = 1.0; // test } ================================================ FILE: lib/open303/src/rosic_Open303.h ================================================ #ifndef rosic_Open303_h #define rosic_Open303_h #include "rosic_MidiNoteEvent.h" #include "rosic_BlendOscillator.h" #include "rosic_BiquadFilter.h" #include "rosic_TeeBeeFilter.h" #include "rosic_AnalogEnvelope.h" #include "rosic_DecayEnvelope.h" #include "rosic_LeakyIntegrator.h" #include "rosic_EllipticQuarterBandFilter.h" #ifdef SEQUENCER #include "rosic_AcidSequencer.h" #endif #define FLASHMEM_WAVETABLE #ifndef FLASHMEM_WAVETABLE #include "wavetable_gen/rosic_MipMappedWaveTable.h" #endif // #include // using namespace std; // for the noteList template struct list { T _front; bool empty() { return _front == T(); } void clear() { _front = T(); } T &front() { return _front; } void push_front(T &e) { _front = e; } void remove(T &e) { if (_front == e) _front = T(); } }; namespace rosic { /** This is a monophonic bass-synth that aims to emulate the sound of the famous Roland TB 303 and goes a bit beyond. */ class Open303 { public: //----------------------------------------------------------------------------------------------- // construction/destruction: /** Constructor. */ Open303(const rosic::WaveTable *saw, const rosic::WaveTable *square); /** Destructor. */ ~Open303(); //----------------------------------------------------------------------------------------------- // parameter settings: /** Sets the sample-rate (in Hz). */ void setSampleRate(real_t newSampleRate, int oversampling = 4); /** Sets up the waveform continuously between saw and square - the input should be in the range 0...1 where 0 means pure saw and 1 means pure square. */ void setWaveform(real_t newWaveform) { oscillator.setBlendFactor(newWaveform); } /** Sets the master tuning frequency for note A4 (usually 440 Hz). */ void setTuning(real_t newTuning) { tuning = newTuning; } /** Sets the filter's nominal cutoff frequency (in Hz). */ void setCutoff(real_t newCutoff); /** Sets the resonance amount for the filter. */ void setResonance(real_t newResonance) { filter.setResonance(newResonance); } /** Sets the modulation depth of the filter's cutoff frequency by the filter-envelope generator (in percent). */ void setEnvMod(real_t newEnvMod); /** Sets the main envelope's decay time for non-accented notes (in milliseconds). Devil Fish provides range of 30...3000 ms for this parameter. On the normal 303, this parameter had a range of 200...2000 ms. */ void setDecay(real_t newDecay) { normalDecay = newDecay; } /** Sets the accent (in percent). */ void setAccent(real_t newAccent); /** Sets the master volume level (in dB). */ void setVolume(real_t newVolume); // from here: parameter settings which were not available to the user in the 303: /** Sets the amplitudes envelope's sustain level in decibels. Devil Fish uses the second half of the range of the (amplitude) decay pot for this and lets the user adjust it between 0 and 100% of the full volume. In the normal 303, this parameter was fixed to zero. */ void setAmpSustain(real_t newAmpSustain) { ampEnv.setSustainInDecibels(newAmpSustain); } /** Sets the cutoff frequency for the highpass before the main filter. */ void setPreFilterHighpass(real_t newCutoff) { highpass1.setCutoff(newCutoff); } /** Sets the cutoff frequency for the highpass inside the feedback loop of the main filter. */ void setFeedbackHighpass(real_t newCutoff) { filter.setFeedbackHighpassCutoff(newCutoff); } /** Sets the cutoff frequency for the highpass after the main filter. */ void setPostFilterHighpass(real_t newCutoff) { highpass2.setCutoff(newCutoff); } /** Sets the slide-time (in ms). The TB-303 had a slide time of 60 ms. */ void setSlideTime(real_t newSlideTime); /** Sets the filter envelope's attack time for non-accented notes (in milliseconds). Devil Fish provides range of 0.3...30 ms for this parameter. */ void setNormalAttack(real_t newNormalAttack) { normalAttack = newNormalAttack; rc1.setTimeConstant(normalAttack); } /** Sets the filter envelope's attack time for accented notes (in milliseconds). In the Devil Fish, accented notes have a fixed attack time of 3 ms. */ void setAccentAttack(real_t newAccentAttack) { accentAttack = newAccentAttack; rc2.setTimeConstant(accentAttack); } /** Sets the filter envelope's decay time for accented notes (in milliseconds). Devil Fish provides range of 30...3000 ms for this parameter. On the normal 303, this parameter was fixed to 200 ms. */ void setAccentDecay(real_t newAccentDecay) { accentDecay = newAccentDecay; } /** Sets the amplitudes envelope's decay time (in milliseconds). Devil Fish provides range of 16...3000 ms for this parameter. On the normal 303, this parameter was fixed to approximately 3-4 seconds. */ void setAmpDecay(real_t newAmpDecay) { ampEnv.setDecay(newAmpDecay); } /** Sets the amplitudes envelope's release time (in milliseconds). On the normal 303, this parameter was fixed to ..... */ void setAmpRelease(real_t newAmpRelease) { normalAmpRelease = newAmpRelease; ampEnv.setRelease(newAmpRelease); } //----------------------------------------------------------------------------------------------- // inquiry: /** Returns the waveform as a continuous value between 0...1 where 0 means pure saw and 1 means pure square. */ real_t getWaveform() const { return oscillator.getBlendFactor(); } /** Sets the master tuning frequency for note A4 (usually 440 Hz). */ real_t getTuning() const { return tuning; } /** Returns the filter's nominal cutoff frequency (in Hz). */ real_t getCutoff() const { return cutoff; } /** Returns the filter's resonance amount (in percent) */ real_t getResonance() const { return filter.getResonance(); } /** Returns the modulation depth of the filter's cutoff frequency by the filter-envelope generator (in percent). */ real_t getEnvMod() const { return envMod; } /** Returns the filter envelope's decay time for non-accented notes (in milliseconds). */ real_t getDecay() const { return normalDecay; } /** Returns the accent (in percent). */ real_t getAccent() const { return 100.0 * accent; } /** Returns the master volume level (in dB). */ real_t getVolume() const { return level; } // from here: parameters which were not available to the user in the 303: /** Returns the amplitudes envelope's sustain level (in dB). */ real_t getAmpSustain() const { return amp2dB(ampEnv.getSustain()); } /** Returns the cutoff frequency for the highpass before the main filter. */ real_t getPreFilterHighpass() const { return highpass1.getCutoff(); } /** Retruns the cutoff frequency for the highpass inside the feedback loop of the main filter. */ real_t getFeedbackHighpass() const { return filter.getFeedbackHighpassCutoff(); } /** Returns the cutoff frequency for the highpass after the main filter. */ real_t getPostFilterHighpass() const { return highpass2.getCutoff(); } /** Returns the slide-time (in ms). */ real_t getSlideTime() const { return slideTime; } /** Returns the filter envelope's attack time for non-accented notes (in milliseconds). */ real_t getNormalAttack() const { return normalAttack; } /** Returns the filter envelope's attack time for non-accented notes (in milliseconds). */ real_t getAccentAttack() const { return accentAttack; } /** Returns the filter envelope's decay time for non-accented notes (in milliseconds). */ real_t getAccentDecay() const { return accentDecay; } /** Returns the amplitudes envelope's decay time (in milliseconds). */ real_t getAmpDecay() const { return ampEnv.getDecay(); } /** Returns the amplitudes envelope's release time (in milliseconds). */ real_t getAmpRelease() const { return normalAmpRelease; } //----------------------------------------------------------------------------------------------- // audio processing: /** Calculates onse output sample at a time. */ INLINE real_t getSample(); //----------------------------------------------------------------------------------------------- // event handling: /** Accepts note-on events (note offs are also handled here as note ons with velocity zero). */ void noteOn(int noteNumber, int velocity, real_t detune); /** Turns all possibly running notes off. */ void allNotesOff(); /** Sets the pitchbend value in semitones. */ void setPitchBend(real_t newPitchBend); //----------------------------------------------------------------------------------------------- // embedded objects: BlendOscillator oscillator; TeeBeeFilter filter; AnalogEnvelope ampEnv; DecayEnvelope mainEnv; LeakyIntegrator pitchSlewLimiter; //LeakyIntegrator ampDeClicker; BiquadFilter ampDeClicker; LeakyIntegrator rc1, rc2; OnePoleFilter highpass1, highpass2, allpass; BiquadFilter notch; EllipticQuarterBandFilter antiAliasFilter; #ifdef SEQUENCER AcidSequencer sequencer; #endif protected: /** Triggers a note (called either directly in noteOn or in getSample when the sequencer is used). */ void triggerNote(int noteNumber, bool hasAccent); /** Slides to a note (called either directly in noteOn or in getSample when the sequencer is used). */ void slideToNote(int noteNumber, bool hasAccent); /** Releases a note (called either directly in noteOn or in getSample when the sequencer is used). */ void releaseNote(int noteNumber); /** Sets the decay-time of the main envelope and updates the normalizers n1, n2 accordingly. */ void setMainEnvDecay(real_t newDecay); void calculateEnvModScalerAndOffset(); /** Updates the normalizer n1 according to the time-constant of rc1 and the decay-time of the main envelope generator. */ void updateNormalizer1(); /** Updates the normalizer n2 according to the time-constant of rc2 and the decay-time of the main envelope generator. */ void updateNormalizer2(); int oversampling = 1; real_t tuning; // master tunung for A4 in Hz real_t ampScaler; // final volume as raw factor real_t oscFreq; // frequecy of the oscillator (without pitchbend) real_t sampleRate; // the (non-oversampled) sample rate real_t level; // master volume level (in dB) real_t levelByVel; // velocity dependence of the level (in dB) real_t accent; // scales all "byVel" parameters real_t slideTime; // the time to slide from one note to another (in ms) real_t cutoff; // nominal cutoff frequency of the filter real_t envMod; // strength of the envelope modulation in percent real_t envUpFraction; // fraction of the envelope that goes upward real_t envOffset; // offset for the normalized envelope ('bipolarity' parameter) real_t envScaler; // scale-factor for the normalized envelope (derived from envMod) real_t normalAttack; // attack time for the filter envelope on non-accented notes real_t accentAttack; // attack time for the filter envelope on accented notes real_t normalDecay; // decay time for the filter envelope on non-accented notes real_t accentDecay; // decay time for the filter envelope on accented notes real_t normalAmpRelease; // amp-env release time for non-accented notes real_t accentAmpRelease; // amp-env release time for accented notes real_t accentGain; // between 0.0...1.0 - to scale the 3rd amp-envelope on accents real_t pitchWheelFactor; // scale factor for oscillator frequency from pitch-wheel real_t n1, n2; // normalizers for the RCs that are driven by the MEG int currentNote; // note which is currently played (-1 if none) int currentVel; // velocity of currently played note int noteOffCountDown; // a countdown variable till next note-off in sequencer mode bool slideToNextNote; // indicate that we need to slide to the next note in sequencer mode bool idle; // flag to indicate that we have currently nothing to do in getSample list noteList; }; //------------------------------------------------------------------------------------------------- // inlined functions: INLINE real_t Open303::getSample() { //if( sequencer.getSequencerMode() == AcidSequencer::OFF && ampEnv.endIsReached() ) // return 0.0; if( idle ) return 0.0; #ifdef SEQUENCER // check the sequencer if we have some note to trigger: if( sequencer.getSequencerMode() != AcidSequencer::OFF ) { noteOffCountDown--; if( noteOffCountDown == 0 || sequencer.isRunning() == false ) releaseNote(currentNote); AcidNote *note = sequencer.getNote(); if( note != NULL ) { if( note->gate == true && currentNote != -1) { int key = note->key + 12*note->octave + currentNote; key = clip(key, 0, 127); if( !slideToNextNote ) triggerNote(key, note->accent); else slideToNote(key, note->accent); AcidNote* nextNote = sequencer.getNextScheduledNote(); if( note->slide && nextNote->gate == true ) { noteOffCountDown = INT32_MAX; slideToNextNote = true; } else { noteOffCountDown = sequencer.getStepLengthInSamples(); slideToNextNote = false; } } } } #endif // calculate instantaneous oscillator frequency and set up the oscillator: const real_t instFreq = pitchSlewLimiter.getSample(oscFreq); // calculate instantaneous cutoff frequency from the nominal cutoff and all its modifiers and // set up the filter: real_t mainEnvOut = mainEnv.getSample(); real_t tmp1 = n1 * rc1.getSample(mainEnvOut); real_t tmp2 = 0.0; if( accentGain > 0.0 ) tmp2 = mainEnvOut; tmp2 = n2 * rc2.getSample(tmp2); tmp1 = envScaler * ( tmp1 - envOffset ); // seems not to work yet tmp2 = accentGain*tmp2; real_t instCutoff = cutoff * pow(2.0, tmp1+tmp2); filter.setCutoff(instCutoff); real_t ampEnvOut = ampEnv.getSample(); //ampEnvOut += 0.45*filterEnvOut + accentGain*6.8*filterEnvOut; if( ampEnv.isNoteOn() ) ampEnvOut += 0.45*mainEnvOut + accentGain*4.0*mainEnvOut; ampEnvOut = ampDeClicker.getSample(ampEnvOut); oscillator.setFrequency(instFreq*pitchWheelFactor); oscillator.calculateIncrement(); // oversampled calculations: real_t tmp; for(int i=1; i<=oversampling; i++) { tmp = -oscillator.getSample(); // the raw oscillator signal tmp = highpass1.getSample(tmp); // pre-filter highpass tmp = filter.getSample(tmp); // now it's filtered //[eh2k] tmp = antiAliasFilter.getSample(tmp); // anti-aliasing filtered } // these filters may actually operate without oversampling (but only if we reset them in // triggerNote - avoid clicks) tmp = allpass.getSample(tmp); tmp = highpass2.getSample(tmp); tmp = notch.getSample(tmp); tmp *= ampEnvOut; // amplified tmp *= ampScaler; // find out whether we may switch ourselves off for the next call: idle = false; //idle = (sequencer.getSequencerMode() == AcidSequencer::OFF && ampEnv.endIsReached() // && fabs(tmp) < 0.000001); // ampEnvOut < 0.000001; return tmp; } } #endif ================================================ FILE: lib/open303/src/rosic_RealFunctions.cpp ================================================ #include "rosic_RealFunctions.h" using namespace rosic; ================================================ FILE: lib/open303/src/rosic_RealFunctions.h ================================================ #ifndef rosic_RealFunctions_h #define rosic_RealFunctions_h // standard library includes: #include #include // rosic includes: #include "GlobalFunctions.h" #include "rosic_NumberManipulations.h" namespace rosic { /** Inverse hyperbolic sine. */ INLINE real_t asinh(real_t x); /** Returns -1.0 if x is below low, 0.0 if x is between low and high and 1.0 if x is above high. */ INLINE real_t belowOrAbove(real_t x, real_t low, real_t high); /** Clips x into the range min...max. */ template INLINE T clip(T x, T min, T max); /** Evaluates the quartic polynomial y = a4*x^4 + a3*x^3 + a2*x^2 + a1*x + a0 at x. */ INLINE real_t evaluateQuartic(real_t x, real_t a0, real_t a1, real_t a2, real_t a3, real_t a4); /** foldover at the specified value */ INLINE real_t foldOver(real_t x, real_t min, real_t max); /** Computes an integer power of x by successively multiplying x with itself. */ INLINE real_t integerPower(real_t x, int exponent); /** Generates a pseudo-random number between min and max. */ INLINE real_t random(real_t min=0.0, real_t max=1.0); /** Generates a 2*pi periodic saw wave. */ INLINE real_t sawWave(real_t x); /** Calculates sine and cosine of x - this is more efficient than calling sin(x) and cos(x) seperately. */ INLINE void sinCos(real_t x, real_t* sinResult, real_t* cosResult); /** Calculates a parabolic approximation of the sine and cosine of x. */ INLINE void sinCosApprox(real_t x, real_t* sinResult, real_t* cosResult); /** Generates a 2*pi periodic square wave. */ INLINE real_t sqrWave(real_t x); /** Rational approximation of the hyperbolic tangent. */ INLINE real_t tanhApprox(real_t x); /** Generates a 2*pi periodic triangle wave. */ INLINE real_t triWave(real_t x); //=============================================================================================== // implementation: INLINE real_t asinh(real_t x) { return log(x + sqrt(x*x+1) ); } INLINE real_t belowOrAbove(real_t x, real_t low, real_t high) { if( x < low ) return -1.0; else if ( x > high ) return 1.0; else return 0.0; } template INLINE T clip(T x, T min, T max) { if( x > max ) return max; else if ( x < min ) return min; else return x; } INLINE real_t evaluateQuartic(real_t x, real_t a0, real_t a1, real_t a2, real_t a3, real_t a4) { real_t x2 = x*x; return x*(a3*x2+a1) + x2*(a4*x2+a2) + a0; } INLINE real_t foldOver(real_t x, real_t min, real_t max) { if( x > max ) return max - (x-max); else if( x < min ) return min - (x-min); else return x; } INLINE real_t integerPower(real_t x, int exponent) { real_t accu = 1.0; for(int i=0; i 2.0*PI ) x -= 2*PI; while( x < 0.0 ) x += 2*PI; if( x < PI/2 ) { real_t tmp1 = x; real_t tmp2 = (2/PI) * tmp1 - 0.5; real_t tmp3 = (2-4*c)*tmp2*tmp2 + c; *sinResult = tmp3 + tmp2; *cosResult = tmp3 - tmp2; } else if( x < PI ) { real_t tmp1 = (x-PI/2); real_t tmp2 = 0.5 - (2/PI) * tmp1; real_t tmp3 = (2-4*c)*tmp2*tmp2 + c; *sinResult = tmp2 + tmp3; *cosResult = tmp2 - tmp3; } else if( x < 1.5*PI ) { real_t tmp1 = (x-PI); real_t tmp2 = (2/PI) * tmp1 - 0.5; real_t tmp3 = (4*c-2)*tmp2*tmp2 - c; *sinResult = tmp3 - tmp2; *cosResult = tmp3 + tmp2; } else { real_t tmp1 = (x-1.5*PI); real_t tmp2 = (2/PI) * tmp1 - 0.5; real_t tmp3 = (2-4*c)*tmp2*tmp2 + c; *sinResult = tmp2 - tmp3; *cosResult = tmp2 + tmp3; } } INLINE real_t sqrWave(real_t x) { real_t tmp = fmod(x, 2*PI); if( tmp < PI ) return 1.0; else return -1.0; } INLINE real_t tanhApprox(real_t x) { real_t a = fabs(2*x); real_t b = 24+a*(12+a*(6+a)); return 2*(x*b)/(a*b+48); } INLINE real_t triWave(real_t x) { real_t tmp = fmod(x, 2*PI); if( tmp < 0.5*PI ) return tmp/(0.5*PI); else if( tmp < 1.5*PI ) return 1.0 - ((tmp-0.5*PI)/(0.5*PI)); else return -1.0 + ((tmp-1.5*PI)/(0.5*PI)); } } // end namespace rosic #endif // #ifndef rosic_RealFunctions_h ================================================ FILE: lib/open303/src/rosic_TeeBeeFilter.cpp ================================================ #include "rosic_TeeBeeFilter.h" using namespace rosic; //------------------------------------------------------------------------------------------------- // construction/destruction: TeeBeeFilter::TeeBeeFilter() { cutoff = 1000.0; drive = 0.0; driveFactor = 1.0; resonanceRaw = 0.0; resonanceSkewed = 0.0; g = 1.0; sampleRate = SAMPLE_RATE; twoPiOverSampleRate = 2.0*PI/sampleRate; feedbackHighpass.setMode(OnePoleFilter::HIGHPASS); feedbackHighpass.setCutoff(150.0); //setMode(LP_18); setMode(TB_303); calculateCoefficientsExact(); reset(); } TeeBeeFilter::~TeeBeeFilter() { } //------------------------------------------------------------------------------------------------- // parameter settings: void TeeBeeFilter::setSampleRate(real_t newSampleRate) { if( newSampleRate > 0.0 ) sampleRate = newSampleRate; twoPiOverSampleRate = 2.0*PI/sampleRate; feedbackHighpass.setSampleRate(newSampleRate); calculateCoefficientsExact(); } void TeeBeeFilter::setDrive(real_t newDrive) { drive = newDrive; driveFactor = dB2amp(drive); } void TeeBeeFilter::setMode(int newMode) { if( newMode >= 0 && newMode < NUM_MODES ) { mode = newMode; switch(mode) { case FLAT: c0 = 1.0; c1 = 0.0; c2 = 0.0; c3 = 0.0; c4 = 0.0; break; case LP_6: c0 = 0.0; c1 = 1.0; c2 = 0.0; c3 = 0.0; c4 = 0.0; break; case LP_12: c0 = 0.0; c1 = 0.0; c2 = 1.0; c3 = 0.0; c4 = 0.0; break; case LP_18: c0 = 0.0; c1 = 0.0; c2 = 0.0; c3 = 1.0; c4 = 0.0; break; case LP_24: c0 = 0.0; c1 = 0.0; c2 = 0.0; c3 = 0.0; c4 = 1.0; break; case HP_6: c0 = 1.0; c1 = -1.0; c2 = 0.0; c3 = 0.0; c4 = 0.0; break; case HP_12: c0 = 1.0; c1 = -2.0; c2 = 1.0; c3 = 0.0; c4 = 0.0; break; case HP_18: c0 = 1.0; c1 = -3.0; c2 = 3.0; c3 = -1.0; c4 = 0.0; break; case HP_24: c0 = 1.0; c1 = -4.0; c2 = 6.0; c3 = -4.0; c4 = 1.0; break; case BP_12_12: c0 = 0.0; c1 = 0.0; c2 = 1.0; c3 = -2.0; c4 = 1.0; break; case BP_6_18: c0 = 0.0; c1 = 0.0; c2 = 0.0; c3 = 1.0; c4 = -1.0; break; case BP_18_6: c0 = 0.0; c1 = 1.0; c2 = -3.0; c3 = 3.0; c4 = -1.0; break; case BP_6_12: c0 = 0.0; c1 = 0.0; c2 = 1.0; c3 = -1.0; c4 = 0.0; break; case BP_12_6: c0 = 0.0; c1 = 1.0; c2 = -2.0; c3 = 1.0; c4 = 0.0; break; case BP_6_6: c0 = 0.0; c1 = 1.0; c2 = -1.0; c3 = 0.0; c4 = 0.0; break; default: c0 = 1.0; c1 = 0.0; c2 = 0.0; c3 = 0.0; c4 = 0.0; // flat } } calculateCoefficientsApprox4(); } //------------------------------------------------------------------------------------------------- // others: void TeeBeeFilter::reset() { feedbackHighpass.reset(); y1 = 0.0; y2 = 0.0; y3 = 0.0; y4 = 0.0; } ================================================ FILE: lib/open303/src/rosic_TeeBeeFilter.h ================================================ #ifndef rosic_TeeBeeFilter_h #define rosic_TeeBeeFilter_h // standard-library includes: #include // for the NULL macro // rosic-indcludes: #include "rosic_OnePoleFilter.h" namespace rosic { /** This class is a filter that aims to emulate the filter in the Roland TB 303. It's a variation of the Moog ladder filter which includes a highpass in the feedback path that reduces the resonance on low cutoff frequencies. Moreover, it has a highpass and an allpass filter in the input path to pre-shape the input signal (important for the sonic character of internal and subsequent nonlinearities). ...18 vs. 24 dB? blah? */ class TeeBeeFilter { public: /** Enumeration of the available filter modes. */ enum modes { FLAT = 0, LP_6, LP_12, LP_18, LP_24, HP_6, HP_12, HP_18, HP_24, BP_12_12, BP_6_18, BP_18_6, BP_6_12, BP_12_6, BP_6_6, TB_303, // ala mystran & kunn (page 40 in the kvr-thread) NUM_MODES }; //--------------------------------------------------------------------------------------------- // construction/destruction: /** Constructor. */ TeeBeeFilter(); /** Destructor. */ ~TeeBeeFilter(); //--------------------------------------------------------------------------------------------- // parameter settings: /** Sets the sample-rate for this filter. */ void setSampleRate(real_t newSampleRate); /** Sets the cutoff frequency for this filter - the actual coefficient calculation may be supressed by passing 'false' as second parameter, in this case, it should be triggered manually later by calling calculateCoefficients. */ INLINE void setCutoff(real_t newCutoff, bool updateCoefficients = true); /** Sets the resonance in percent where 100% is self oscillation. */ INLINE void setResonance(real_t newResonance, bool updateCoefficients = true); /** Sets the input drive in decibels. */ void setDrive(real_t newDrive); /** Sets the mode of the filter, @see: modes */ void setMode(int newMode); /** Sets the cutoff frequency for the highpass filter in the feedback path. */ void setFeedbackHighpassCutoff(real_t newCutoff) { feedbackHighpass.setCutoff(newCutoff); } //--------------------------------------------------------------------------------------------- // inquiry: /** Returns the cutoff frequency of this filter. */ real_t getCutoff() const { return cutoff; } /** Returns the resonance parameter of this filter. */ real_t getResonance() const { return 100.0 * resonanceRaw; } /** Returns the drive parameter in decibels. */ real_t getDrive() const { return drive; } /** Returns the slected filter mode. */ int getMode() const { return mode; } /** Returns the cutoff frequency for the highpass filter in the feedback path. */ real_t getFeedbackHighpassCutoff() const { return feedbackHighpass.getCutoff(); } //--------------------------------------------------------------------------------------------- // audio processing: /** Calculates one output sample at a time. */ INLINE real_t getSample(real_t in); //--------------------------------------------------------------------------------------------- // others: /** Causes the filter to re-calculate the coeffiecients via the exact formulas. */ INLINE void calculateCoefficientsExact(); /** Causes the filter to re-calculate the coeffiecients using an approximation that is valid for normalized radian cutoff frequencies up to pi/4. */ INLINE void calculateCoefficientsApprox4(); /** Implements the waveshaping nonlinearity between the stages. */ INLINE real_t shape(real_t x); /** Resets the internal state variables. */ void reset(); //============================================================================================= protected: real_t b0, a1; // coefficients for the first order sections real_t y1, y2, y3, y4; // output signals of the 4 filter stages real_t c0, c1, c2, c3, c4; // coefficients for combining various ouput stages real_t k; // feedback factor in the loop real_t g; // output gain real_t driveFactor; // filter drive as raw factor real_t cutoff; // cutoff frequency real_t drive; // filter drive in decibels real_t resonanceRaw; // resonance parameter (normalized to 0...1) real_t resonanceSkewed; // mapped resonance parameter to make it behave more musical real_t sampleRate; // the sample rate in Hz real_t twoPiOverSampleRate; // 2*PI/sampleRate int mode; // the selected filter-mode OnePoleFilter feedbackHighpass; }; //----------------------------------------------------------------------------------------------- // inlined functions: INLINE void TeeBeeFilter::setCutoff(real_t newCutoff, bool updateCoefficients) { if( newCutoff != cutoff ) { if( newCutoff < 200.0 ) // an absolute floor for the cutoff frequency - tweakable cutoff = 200.0; else if( newCutoff > 20000.0 ) cutoff = 20000.0; else cutoff = newCutoff; if( updateCoefficients == true ) calculateCoefficientsApprox4(); } } INLINE void TeeBeeFilter::setResonance(real_t newResonance, bool updateCoefficients) { resonanceRaw = 0.01 * newResonance; resonanceSkewed = (1.0-exp(-3.0*resonanceRaw)) / (1.0-exp(-3.0)); if( updateCoefficients == true ) calculateCoefficientsApprox4(); } INLINE void TeeBeeFilter::calculateCoefficientsExact() { // calculate intermediate variables: real_t wc = twoPiOverSampleRate * cutoff; real_t s, c; sinCos(wc, &s, &c); // c = cos(wc); s = sin(wc); real_t t = tan(0.25*(wc-PI)); real_t r = resonanceSkewed; // calculate filter a1-coefficient tuned such the resonance frequency is just right: real_t a1_fullRes = t / (s-c*t); // calculate filter a1-coefficient as if there were no resonance: real_t x = exp(-wc); real_t a1_noRes = -x; // use a weighted sum between the resonance-tuned and no-resonance coefficient: a1 = r*a1_fullRes + (1.0-r)*a1_noRes; // calculate the b0-coefficient from the condition that each stage should be a leaky // integrator: b0 = 1.0+a1; // calculate feedback factor by dividing the resonance parameter by the magnitude at the // resonant frequency: real_t gsq = b0*b0 / (1.0 + a1*a1 + 2.0*a1*c); k = r / (gsq*gsq); if( mode == TB_303 ) k *= (17.0/4.0); } INLINE void TeeBeeFilter::calculateCoefficientsApprox4() { // calculate intermediate variables: real_t wc = twoPiOverSampleRate * cutoff; real_t wc2 = wc*wc; real_t r = resonanceSkewed; real_t tmp; // compute the filter coefficient via a 12th order polynomial approximation (polynomial // evaluation is done with a Horner-rule alike scheme with nested quadratic factors in the hope // for potentially better parallelization compared to Horner's rule as is): const real_t pa12 = -1.341281325101042e-02; const real_t pa11 = 8.168739417977708e-02; const real_t pa10 = -2.365036766021623e-01; const real_t pa09 = 4.439739664918068e-01; const real_t pa08 = -6.297350825423579e-01; const real_t pa07 = 7.529691648678890e-01; const real_t pa06 = -8.249882473764324e-01; const real_t pa05 = 8.736418933533319e-01; const real_t pa04 = -9.164580250284832e-01; const real_t pa03 = 9.583192455599817e-01; const real_t pa02 = -9.999994950291231e-01; const real_t pa01 = 9.999999927726119e-01; const real_t pa00 = -9.999999999857464e-01; tmp = wc2*pa12 + pa11*wc + pa10; tmp = wc2*tmp + pa09*wc + pa08; tmp = wc2*tmp + pa07*wc + pa06; tmp = wc2*tmp + pa05*wc + pa04; tmp = wc2*tmp + pa03*wc + pa02; a1 = wc2*tmp + pa01*wc + pa00; b0 = 1.0 + a1; // compute the scale factor for the resonance parameter (the factor to obtain k from r) via an // 8th order polynomial approximation: const real_t pr8 = -4.554677015609929e-05; const real_t pr7 = -2.022131730719448e-05; const real_t pr6 = 2.784706718370008e-03; const real_t pr5 = 2.079921151733780e-03; const real_t pr4 = -8.333236384240325e-02; const real_t pr3 = -1.666668203490468e-01; const real_t pr2 = 1.000000012124230e+00; const real_t pr1 = 3.999999999650040e+00; const real_t pr0 = 4.000000000000113e+00; tmp = wc2*pr8 + pr7*wc + pr6; tmp = wc2*tmp + pr5*wc + pr4; tmp = wc2*tmp + pr3*wc + pr2; tmp = wc2*tmp + pr1*wc + pr0; // this is now the scale factor k = r * tmp; g = 1.0; if( mode == TB_303 ) { real_t fx = wc * ONE_OVER_SQRT2/(2*PI); b0 = (0.00045522346 + 6.1922189 * fx) / (1.0 + 12.358354 * fx + 4.4156345 * (fx * fx)); k = fx*(fx*(fx*(fx*(fx*(fx+7198.6997)-5837.7917)-476.47308)+614.95611)+213.87126)+16.998792; g = k * 0.058823529411764705882352941176471; // 17 reciprocal g = (g - 1.0) * r + 1.0; // r is 0 to 1.0 g = (g * (1.0 + r)); k = k * r; // k is ready now } } INLINE real_t TeeBeeFilter::shape(real_t x) { // return tanhApprox(x); // \todo: find some more suitable nonlinearity here //return x; // test const real_t r6 = 1.0/6.0; x = clip(x, -SQRT2, SQRT2); return x - r6*x*x*x; //return clip(x, -1.0, 1.0); } INLINE real_t TeeBeeFilter::getSample(real_t in) { real_t y0; if( mode == TB_303 ) { //y0 = in - feedbackHighpass.getSample(k * shape(y4)); y0 = in - feedbackHighpass.getSample(k*y4); //y0 = in - k*shape(y4); //y0 = in-k*y4; y1 += 2*b0*(y0-y1+y2); y2 += b0*(y1-2*y2+y3); y3 += b0*(y2-2*y3+y4); y4 += b0*(y3-2*y4); return 2*g*y4; //return 3*y4; } // apply drive and feedback to obtain the filter's input signal: //real_t y0 = inputFilter.getSample(0.125*driveFactor*in) - feedbackHighpass.getSample(k*y4); y0 = 0.125*driveFactor*in - feedbackHighpass.getSample(k*y4); /* // cascade of four 1st order sections with nonlinearities: y1 = shape(b0*y0 - a1*y1); y2 = shape(b0*y1 - a1*y2); y3 = shape(b0*y2 - a1*y3); y4 = shape(b0*y3 - a1*y4); */ // cascade of four 1st order sections with only 1 nonlinearity: /* y1 = b0*y0 - a1*y1; y2 = b0*y1 - a1*y2; y3 = b0*y2 - a1*y3; y4 = shape(b0*y3 - a1*y4); */ y1 = y0 + a1*(y0-y1); y2 = y1 + a1*(y1-y2); y3 = y2 + a1*(y2-y3); y4 = y3 + a1*(y3-y4); // \todo: performance test both versions of the ladder //y4 = shape(y3 + a1*(y3-y4)); // \todo: performance test both versions of the ladder return 8.0 * (c0*y0 + c1*y1 + c2*y2 + c3*y3 + c4*y4);; } } #endif // rosic_TeeBeeFilter_h ================================================ FILE: lib/open303/src/sequencer/rosic_AcidPattern.cpp ================================================ #include "rosic_AcidPattern.h" using namespace rosic; AcidPattern::AcidPattern() { numSteps = 16; stepLength = 0.5; } //------------------------------------------------------------------------------------------------- // setup: void AcidPattern::clear() { for(int i=0; i 0.0 ) sampleRate = newSampleRate; } void AcidSequencer::setMode(int newMode) { if( newMode >= 0 && newMode < NUM_SEQUENCER_MODES ) { sequencerMode = newMode; modeChanged = true; } } void AcidSequencer::setKeyPermissible(int key, bool shouldBePermissible) { if( key >= 0 && key <= 12 ) keyPermissible[key] = shouldBePermissible; } void AcidSequencer::toggleKeyPermissibility(int key) { if( key >= 0 && key <= 12 ) keyPermissible[key] = !keyPermissible[key]; } //------------------------------------------------------------------------------------------------- // inquiry: AcidPattern* AcidSequencer::getPattern(int index) { if( index < 0 || index >= numPatterns ) return NULL; else return &patterns[index]; } bool AcidSequencer::modeWasChanged() { bool result = modeChanged; modeChanged = false; return result; // mmm...wouldn't we need mutexes here? the mode changes from the GUI and modeWasChanged // is called from the audio-thread - otherwise note-hangs could happen? } bool AcidSequencer::isKeyPermissible(int key) { if( key >= 0 && key <= 12 ) return keyPermissible[key]; else return false; } //------------------------------------------------------------------------------------------------- // event handling: void AcidSequencer::start() { // set up members such that we will trap in the else-branch in the next call to getNote(): running = true; countDown = -1; step = 0; driftError = 0.0; } void AcidSequencer::stop() { running = false; } //------------------------------------------------------------------------------------------------- // others: ================================================ FILE: lib/open303/src/sequencer/rosic_AcidSequencer.h ================================================ #ifndef rosic_AcidSequencer_h #define rosic_AcidSequencer_h // rosic-indcludes: #include "rosic_AcidPattern.h" namespace rosic { /** This is a sequencer for typical acid-lines involving slides and accents. \todo: make the permissibility-thing work correctly */ class AcidSequencer { public: enum sequencerModes { OFF = 0, KEY_SYNC, HOST_SYNC, NUM_SEQUENCER_MODES }; //--------------------------------------------------------------------------------------------- // construction/destruction: /** Constructor. */ AcidSequencer(); //--------------------------------------------------------------------------------------------- // setup: /** Sets the sample-rate. */ void setSampleRate(real_t newSampleRate); /** Sets the tempo in BPM. */ void setTempo(real_t newTempoInBpm) { bpm = newTempoInBpm; } /** Sets the key in one of the patterns for one of the steps (between 0...11, 0 is C). */ void setKey(int pattern, int step, int newKey); /** Sets the octave for one of the steps (0 is the root octave between C2...B2). */ void setOctave(int pattern, int step, int newOctave); /** Sets the accent flag for one of the steps. */ void setAccent(int pattern, int step, bool shouldBeAccented); /** Sets the slide flag for one of the steps. */ void setSlide(int pattern, int step, bool shouldHaveSlide); /** Sets the gate flag for one of the steps. */ void setGate(int pattern, int step, bool shouldBeOpen); /** Selects one of the modes for the sequencer @see sequencerModes. */ void setMode(int newMode); /** Sets the length of one step (the time while gate is open) in units of one step (which is one 16th note). */ void setStepLength(real_t newStepLength) { patterns[activePattern].setStepLength(newStepLength); } /** Circularly shifts the active pattern by the given number of steps. */ void circularShift(int numSteps) { patterns[activePattern].circularShift(numSteps); } /** Marks a key (note value from 0...12, where 0 and 12 is a C) as permissible or not. Whenever the pattern currently played requires a key that is not permissible, the sequencer will play the closest key among the permissible ones (it will select the lower when two permissible keys are at equal distance). */ void setKeyPermissible(int key, bool shouldBePermissible); /** Toggles the permissibility of a key on/off. */ void toggleKeyPermissibility(int key); //--------------------------------------------------------------------------------------------- // inquiry: /** Returns the number of patterns. */ int getNumPatterns() const { return numPatterns; } /** Returns a pointer to the pattern with given index - NULL if index is out of range. */ AcidPattern* getPattern(int index); /** Returns true when the sequencer is running, false otherwise. */ bool isRunning() const { return running; } /** Returns once true, when the mode was changed due to a call to setMode. Thereafter, it will always return false until a new call to setMode happens - whereafter it will again return true once, ...and so on. The idea is that an outlying class may have to become aware of such changes in order to turn off running notes (trigger all-notes-off or something). */ bool modeWasChanged(); /** Returns the length of one step (the time while gate is open) in units of one step (which is one 16th note). */ real_t getStepLength() const { return patterns[activePattern].getStepLength(); } /** Returns the length of one step (the time while gate is open) in samples. */ int getStepLengthInSamples() const { return roundToInt(sampleRate*getStepLength()*beatsToSeconds(0.25, bpm)); } /** Returns the selected sequencer mode @see sequencerModes. */ int getSequencerMode() const { return sequencerMode; } /** Returns, if the given key is among the permissible ones. */ bool isKeyPermissible(int key); //--------------------------------------------------------------------------------------------- // audio processing: /** Returns a pointer to the note that occurs at this sample if any, NULL otherwise. */ INLINE AcidNote* getNote(); /** Returns the next note that will be scheduled - after getNote() has returned a non-NULL pointer, this will be the next non-NULL note that will be returned. So, if an event has occurred at some time instant, you may investigate the next upcoming event beforehand by calling this function. */ INLINE AcidNote* getNextScheduledNote() { AcidNote* note = patterns[activePattern].getNote(step); note->key = getClosestPermissibleKey(note->key); return note; } /** Returns the key among the permissible ones which is closest to the given key - if two keys are at the same distance, it returns the lower of them. If the passed key is itself permissible, it will be returned unchanged. */ INLINE int getClosestPermissibleKey(int key); //--------------------------------------------------------------------------------------------- // event handling: /** Lets the sequencer start playing. */ void start(); /** Lets the sequencer stop playing. */ void stop(); //--------------------------------------------------------------------------------------------- // others: //============================================================================================= protected: static const int numPatterns = 16; AcidPattern patterns[numPatterns]; int activePattern; // the currently selected pattern bool running; // flag to indicate that sequencer is running bool modeChanged; // flag that is set to true in setMode and to false in modeChanged real_t sampleRate; // the sample-rate real_t bpm; // the tempo in bpm int countDown; // a sample-countdown - counts down for the next step to occur int step; // the current step int sequencerMode; // the selected mode for the sequencer real_t driftError; // to keep track and compensate for accumulating timing error bool keyPermissible[13]; // array of flags to indicate if a particular key is permissible }; //----------------------------------------------------------------------------------------------- // from here: definitions of the functions to be inlined, i.e. all functions which are supposed // to be called at audio-rate (they can't be put into the .cpp file): INLINE AcidNote* AcidSequencer::getNote() { if( running == false ) return NULL; if( countDown > 0 ) { countDown--; return NULL; } else { real_t secondsToNextStep = beatsToSeconds(0.25, bpm); real_t samplesToNextStep = secondsToNextStep * sampleRate; countDown = roundToInt(samplesToNextStep); // keep track of accumulating error due to rounding and compensate when the accumulated error // exceeds half a sample: driftError += countDown - samplesToNextStep; if( driftError < -0.5 ) // negative errors indicate that we are too early { driftError += 1.0; countDown += 1; } else if( driftError >= 0.5 ) { driftError -= 1.0; countDown -= 1; } AcidNote* note = patterns[activePattern].getNote(step); note->key = getClosestPermissibleKey(note->key); step = (step+1) % patterns[activePattern].getNumSteps(); return note; } } INLINE int AcidSequencer::getClosestPermissibleKey(int key) { if( key >= 0 && key <= 12 ) { if( keyPermissible[key] ) return key; else { // find the closest lower permissible key: int kLo = key-1; while( kLo >= 0 ) { if( keyPermissible[kLo] ) break; kLo--; } // find the closest higher permissible key: int kHi = key+1; while( kHi < 12 ) { if( keyPermissible[kHi] ) break; kHi++; } // select the closest (subject to the constraint that it must be between 0 and 12): if( (kHi-key) < (kLo-key) && kHi <= 12 ) return kHi; else if( (kLo-key) < (kHi-key) && kLo >= 0 ) return kLo; else if( (kHi-key) == (kLo-key) && kLo >= 0 ) return kLo; else return -1; // none of the keys is permissible } } else return 0; } } // end namespace rosic #endif // rosic_AcidSequencer_h ================================================ FILE: lib/open303/src/wavetable_gen/fft4g.h ================================================ /* Fast Fourier/Cosine/Sine Transform dimension :one data length :power of 2 decimation :frequency radix :4, 2 data :inplace table :use functions cdft: Complex Discrete Fourier Transform rdft: Real Discrete Fourier Transform ddct: Discrete Cosine Transform ddst: Discrete Sine Transform dfct: Cosine Transform of RDFT (Real Symmetric DFT) dfst: Sine Transform of RDFT (Real Anti-symmetric DFT) function prototypes void cdft(int, int, double *, int *, double *); void rdft(int, int, double *, int *, double *); void ddct(int, int, double *, int *, double *); void ddst(int, int, double *, int *, double *); void dfct(int, double *, double *, int *, double *); void dfst(int, double *, double *, int *, double *); -------- Complex DFT (Discrete Fourier Transform) -------- [definition] X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k ip[0] = 0; // first time only cdft(2*n, 1, a, ip, w); ip[0] = 0; // first time only cdft(2*n, -1, a, ip, w); [parameters] 2*n :data length (int) n >= 1, n = power of 2 a[0...2*n-1] :input/output data (double *) input data a[2*j] = Re(x[j]), a[2*j+1] = Im(x[j]), 0<=j= 2+sqrt(n) strictly, length of ip >= 2+(1<<(int)(log(n+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n/2-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of cdft(2*n, -1, a, ip, w); is cdft(2*n, 1, a, ip, w); for (j = 0; j <= 2 * n - 1; j++) { a[j] *= 1.0 / n; } . -------- Real DFT / Inverse of Real DFT -------- [definition] RDFT R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2 I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0 IRDFT (excluding scale) a[k] = (R[0] + R[n/2]*cos(pi*k))/2 + sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) + sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k ip[0] = 0; // first time only rdft(n, 1, a, ip, w); ip[0] = 0; // first time only rdft(n, -1, a, ip, w); [parameters] n :data length (int) n >= 2, n = power of 2 a[0...n-1] :input/output data (double *) output data a[2*k] = R[k], 0<=k input data a[2*j] = R[j], 0<=j= 2+sqrt(n/2) strictly, length of ip >= 2+(1<<(int)(log(n/2+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n/2-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of rdft(n, 1, a, ip, w); is rdft(n, -1, a, ip, w); for (j = 0; j <= n - 1; j++) { a[j] *= 2.0 / n; } . -------- DCT (Discrete Cosine Transform) / Inverse of DCT -------- [definition] IDCT (excluding scale) C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k DCT C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k ip[0] = 0; // first time only ddct(n, 1, a, ip, w); ip[0] = 0; // first time only ddct(n, -1, a, ip, w); [parameters] n :data length (int) n >= 2, n = power of 2 a[0...n-1] :input/output data (double *) output data a[k] = C[k], 0<=k= 2+sqrt(n/2) strictly, length of ip >= 2+(1<<(int)(log(n/2+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n*5/4-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of ddct(n, -1, a, ip, w); is a[0] *= 0.5; ddct(n, 1, a, ip, w); for (j = 0; j <= n - 1; j++) { a[j] *= 2.0 / n; } . -------- DST (Discrete Sine Transform) / Inverse of DST -------- [definition] IDST (excluding scale) S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k DST S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0 ip[0] = 0; // first time only ddst(n, 1, a, ip, w); ip[0] = 0; // first time only ddst(n, -1, a, ip, w); [parameters] n :data length (int) n >= 2, n = power of 2 a[0...n-1] :input/output data (double *) input data a[j] = A[j], 0 output data a[k] = S[k], 0= 2+sqrt(n/2) strictly, length of ip >= 2+(1<<(int)(log(n/2+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n*5/4-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of ddst(n, -1, a, ip, w); is a[0] *= 0.5; ddst(n, 1, a, ip, w); for (j = 0; j <= n - 1; j++) { a[j] *= 2.0 / n; } . -------- Cosine Transform of RDFT (Real Symmetric DFT) -------- [definition] C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n [usage] ip[0] = 0; // first time only dfct(n, a, t, ip, w); [parameters] n :data length - 1 (int) n >= 2, n = power of 2 a[0...n] :input/output data (double *) output data a[k] = C[k], 0<=k<=n t[0...n/2] :work area (double *) ip[0...*] :work area for bit reversal (int *) length of ip >= 2+sqrt(n/4) strictly, length of ip >= 2+(1<<(int)(log(n/4+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n*5/8-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of a[0] *= 0.5; a[n] *= 0.5; dfct(n, a, t, ip, w); is a[0] *= 0.5; a[n] *= 0.5; dfct(n, a, t, ip, w); for (j = 0; j <= n; j++) { a[j] *= 2.0 / n; } . -------- Sine Transform of RDFT (Real Anti-symmetric DFT) -------- [definition] S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0= 2, n = power of 2 a[0...n-1] :input/output data (double *) output data a[k] = S[k], 0= 2+sqrt(n/4) strictly, length of ip >= 2+(1<<(int)(log(n/4+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n*5/8-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of dfst(n, a, t, ip, w); is dfst(n, a, t, ip, w); for (j = 1; j <= n - 1; j++) { a[j] *= 2.0 / n; } . Appendix : The cos/sin table is recalculated when the larger table required. w[] and ip[] are compatible with all routines. */ void cdft(int n, int isgn, real_t *a, int *ip, real_t *w) { void makewt(int nw, int *ip, real_t *w); void bitrv2(int n, int *ip, real_t *a); void bitrv2conj(int n, int *ip, real_t *a); void cftfsub(int n, real_t *a, real_t *w); void cftbsub(int n, real_t *a, real_t *w); if (n > (ip[0] << 2)) { makewt(n >> 2, ip, w); } if (n > 4) { if (isgn >= 0) { bitrv2(n, ip + 2, a); cftfsub(n, a, w); } else { bitrv2conj(n, ip + 2, a); cftbsub(n, a, w); } } else if (n == 4) { cftfsub(n, a, w); } } void rdft(int n, int isgn, real_t *a, int *ip, real_t *w) { void makewt(int nw, int *ip, real_t *w); void makect(int nc, int *ip, real_t *c); void bitrv2(int n, int *ip, real_t *a); void cftfsub(int n, real_t *a, real_t *w); void cftbsub(int n, real_t *a, real_t *w); void rftfsub(int n, real_t *a, int nc, real_t *c); void rftbsub(int n, real_t *a, int nc, real_t *c); int nw, nc; real_t xi; nw = ip[0]; if (n > (nw << 2)) { nw = n >> 2; makewt(nw, ip, w); } nc = ip[1]; if (n > (nc << 2)) { nc = n >> 2; makect(nc, ip, w + nw); } if (isgn >= 0) { if (n > 4) { bitrv2(n, ip + 2, a); cftfsub(n, a, w); rftfsub(n, a, nc, w + nw); } else if (n == 4) { cftfsub(n, a, w); } xi = a[0] - a[1]; a[0] += a[1]; a[1] = xi; } else { a[1] = 0.5 * (a[0] - a[1]); a[0] -= a[1]; if (n > 4) { rftbsub(n, a, nc, w + nw); bitrv2(n, ip + 2, a); cftbsub(n, a, w); } else if (n == 4) { cftfsub(n, a, w); } } } void ddct(int n, int isgn, real_t *a, int *ip, real_t *w) { void makewt(int nw, int *ip, real_t *w); void makect(int nc, int *ip, real_t *c); void bitrv2(int n, int *ip, real_t *a); void cftfsub(int n, real_t *a, real_t *w); void cftbsub(int n, real_t *a, real_t *w); void rftfsub(int n, real_t *a, int nc, real_t *c); void rftbsub(int n, real_t *a, int nc, real_t *c); void dctsub(int n, real_t *a, int nc, real_t *c); int j, nw, nc; real_t xr; nw = ip[0]; if (n > (nw << 2)) { nw = n >> 2; makewt(nw, ip, w); } nc = ip[1]; if (n > nc) { nc = n; makect(nc, ip, w + nw); } if (isgn < 0) { xr = a[n - 1]; for (j = n - 2; j >= 2; j -= 2) { a[j + 1] = a[j] - a[j - 1]; a[j] += a[j - 1]; } a[1] = a[0] - xr; a[0] += xr; if (n > 4) { rftbsub(n, a, nc, w + nw); bitrv2(n, ip + 2, a); cftbsub(n, a, w); } else if (n == 4) { cftfsub(n, a, w); } } dctsub(n, a, nc, w + nw); if (isgn >= 0) { if (n > 4) { bitrv2(n, ip + 2, a); cftfsub(n, a, w); rftfsub(n, a, nc, w + nw); } else if (n == 4) { cftfsub(n, a, w); } xr = a[0] - a[1]; a[0] += a[1]; for (j = 2; j < n; j += 2) { a[j - 1] = a[j] - a[j + 1]; a[j] += a[j + 1]; } a[n - 1] = xr; } } void ddst(int n, int isgn, real_t *a, int *ip, real_t *w) { void makewt(int nw, int *ip, real_t *w); void makect(int nc, int *ip, real_t *c); void bitrv2(int n, int *ip, real_t *a); void cftfsub(int n, real_t *a, real_t *w); void cftbsub(int n, real_t *a, real_t *w); void rftfsub(int n, real_t *a, int nc, real_t *c); void rftbsub(int n, real_t *a, int nc, real_t *c); void dstsub(int n, real_t *a, int nc, real_t *c); int j, nw, nc; real_t xr; nw = ip[0]; if (n > (nw << 2)) { nw = n >> 2; makewt(nw, ip, w); } nc = ip[1]; if (n > nc) { nc = n; makect(nc, ip, w + nw); } if (isgn < 0) { xr = a[n - 1]; for (j = n - 2; j >= 2; j -= 2) { a[j + 1] = -a[j] - a[j - 1]; a[j] -= a[j - 1]; } a[1] = a[0] + xr; a[0] -= xr; if (n > 4) { rftbsub(n, a, nc, w + nw); bitrv2(n, ip + 2, a); cftbsub(n, a, w); } else if (n == 4) { cftfsub(n, a, w); } } dstsub(n, a, nc, w + nw); if (isgn >= 0) { if (n > 4) { bitrv2(n, ip + 2, a); cftfsub(n, a, w); rftfsub(n, a, nc, w + nw); } else if (n == 4) { cftfsub(n, a, w); } xr = a[0] - a[1]; a[0] += a[1]; for (j = 2; j < n; j += 2) { a[j - 1] = -a[j] - a[j + 1]; a[j] -= a[j + 1]; } a[n - 1] = -xr; } } void dfct(int n, real_t *a, real_t *t, int *ip, real_t *w) { void makewt(int nw, int *ip, real_t *w); void makect(int nc, int *ip, real_t *c); void bitrv2(int n, int *ip, real_t *a); void cftfsub(int n, real_t *a, real_t *w); void rftfsub(int n, real_t *a, int nc, real_t *c); void dctsub(int n, real_t *a, int nc, real_t *c); int j, k, l, m, mh, nw, nc; real_t xr, xi, yr, yi; nw = ip[0]; if (n > (nw << 3)) { nw = n >> 3; makewt(nw, ip, w); } nc = ip[1]; if (n > (nc << 1)) { nc = n >> 1; makect(nc, ip, w + nw); } m = n >> 1; yi = a[m]; xi = a[0] + a[n]; a[0] -= a[n]; t[0] = xi - yi; t[m] = xi + yi; if (n > 2) { mh = m >> 1; for (j = 1; j < mh; j++) { k = m - j; xr = a[j] - a[n - j]; xi = a[j] + a[n - j]; yr = a[k] - a[n - k]; yi = a[k] + a[n - k]; a[j] = xr; a[k] = yr; t[j] = xi - yi; t[k] = xi + yi; } t[mh] = a[mh] + a[n - mh]; a[mh] -= a[n - mh]; dctsub(m, a, nc, w + nw); if (m > 4) { bitrv2(m, ip + 2, a); cftfsub(m, a, w); rftfsub(m, a, nc, w + nw); } else if (m == 4) { cftfsub(m, a, w); } a[n - 1] = a[0] - a[1]; a[1] = a[0] + a[1]; for (j = m - 2; j >= 2; j -= 2) { a[2 * j + 1] = a[j] + a[j + 1]; a[2 * j - 1] = a[j] - a[j + 1]; } l = 2; m = mh; while (m >= 2) { dctsub(m, t, nc, w + nw); if (m > 4) { bitrv2(m, ip + 2, t); cftfsub(m, t, w); rftfsub(m, t, nc, w + nw); } else if (m == 4) { cftfsub(m, t, w); } a[n - l] = t[0] - t[1]; a[l] = t[0] + t[1]; k = 0; for (j = 2; j < m; j += 2) { k += l << 2; a[k - l] = t[j] - t[j + 1]; a[k + l] = t[j] + t[j + 1]; } l <<= 1; mh = m >> 1; for (j = 0; j < mh; j++) { k = m - j; t[j] = t[m + k] - t[m + j]; t[k] = t[m + k] + t[m + j]; } t[mh] = t[m + mh]; m = mh; } a[l] = t[0]; a[n] = t[2] - t[1]; a[0] = t[2] + t[1]; } else { a[1] = a[0]; a[2] = t[0]; a[0] = t[1]; } } void dfst(int n, real_t *a, real_t *t, int *ip, real_t *w) { void makewt(int nw, int *ip, real_t *w); void makect(int nc, int *ip, real_t *c); void bitrv2(int n, int *ip, real_t *a); void cftfsub(int n, real_t *a, real_t *w); void rftfsub(int n, real_t *a, int nc, real_t *c); void dstsub(int n, real_t *a, int nc, real_t *c); int j, k, l, m, mh, nw, nc; real_t xr, xi, yr, yi; nw = ip[0]; if (n > (nw << 3)) { nw = n >> 3; makewt(nw, ip, w); } nc = ip[1]; if (n > (nc << 1)) { nc = n >> 1; makect(nc, ip, w + nw); } if (n > 2) { m = n >> 1; mh = m >> 1; for (j = 1; j < mh; j++) { k = m - j; xr = a[j] + a[n - j]; xi = a[j] - a[n - j]; yr = a[k] + a[n - k]; yi = a[k] - a[n - k]; a[j] = xr; a[k] = yr; t[j] = xi + yi; t[k] = xi - yi; } t[0] = a[mh] - a[n - mh]; a[mh] += a[n - mh]; a[0] = a[m]; dstsub(m, a, nc, w + nw); if (m > 4) { bitrv2(m, ip + 2, a); cftfsub(m, a, w); rftfsub(m, a, nc, w + nw); } else if (m == 4) { cftfsub(m, a, w); } a[n - 1] = a[1] - a[0]; a[1] = a[0] + a[1]; for (j = m - 2; j >= 2; j -= 2) { a[2 * j + 1] = a[j] - a[j + 1]; a[2 * j - 1] = -a[j] - a[j + 1]; } l = 2; m = mh; while (m >= 2) { dstsub(m, t, nc, w + nw); if (m > 4) { bitrv2(m, ip + 2, t); cftfsub(m, t, w); rftfsub(m, t, nc, w + nw); } else if (m == 4) { cftfsub(m, t, w); } a[n - l] = t[1] - t[0]; a[l] = t[0] + t[1]; k = 0; for (j = 2; j < m; j += 2) { k += l << 2; a[k - l] = -t[j] - t[j + 1]; a[k + l] = t[j] - t[j + 1]; } l <<= 1; mh = m >> 1; for (j = 1; j < mh; j++) { k = m - j; t[j] = t[m + k] + t[m + j]; t[k] = t[m + k] - t[m + j]; } t[0] = t[m + mh]; m = mh; } a[l] = t[0]; } a[0] = 0; } /* -------- initializing routines -------- */ #include void makewt(int nw, int *ip, real_t *w) { void bitrv2(int n, int *ip, real_t *a); int j, nwh; real_t delta, x, y; ip[0] = nw; ip[1] = 1; if (nw > 2) { nwh = nw >> 1; delta = atan(1.0) / nwh; w[0] = 1; w[1] = 0; w[nwh] = cos(delta * nwh); w[nwh + 1] = w[nwh]; if (nwh > 2) { for (j = 2; j < nwh; j += 2) { x = cos(delta * j); y = sin(delta * j); w[j] = x; w[j + 1] = y; w[nw - j] = y; w[nw - j + 1] = x; } bitrv2(nw, ip + 2, w); } } } void makect(int nc, int *ip, real_t *c) { int j, nch; real_t delta; ip[1] = nc; if (nc > 1) { nch = nc >> 1; delta = atan(1.0) / nch; c[0] = cos(delta * nch); c[nch] = 0.5 * c[0]; for (j = 1; j < nch; j++) { c[j] = 0.5 * cos(delta * j); c[nc - j] = 0.5 * sin(delta * j); } } } /* -------- child routines -------- */ void bitrv2(int n, int *ip, real_t *a) { int j, j1, k, k1, l, m, m2; real_t xr, xi, yr, yi; ip[0] = 0; l = n; m = 1; while ((m << 3) < l) { l >>= 1; for (j = 0; j < m; j++) { ip[m + j] = ip[j] + l; } m <<= 1; } m2 = 2 * m; if ((m << 3) == l) { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 2 * j + ip[k]; k1 = 2 * k + ip[j]; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += 2 * m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 -= m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += 2 * m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } j1 = 2 * k + m2 + ip[k]; k1 = j1 + m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } } else { for (k = 1; k < m; k++) { for (j = 0; j < k; j++) { j1 = 2 * j + ip[k]; k1 = 2 * k + ip[j]; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } } } } void bitrv2conj(int n, int *ip, real_t *a) { int j, j1, k, k1, l, m, m2; real_t xr, xi, yr, yi; ip[0] = 0; l = n; m = 1; while ((m << 3) < l) { l >>= 1; for (j = 0; j < m; j++) { ip[m + j] = ip[j] + l; } m <<= 1; } m2 = 2 * m; if ((m << 3) == l) { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 2 * j + ip[k]; k1 = 2 * k + ip[j]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += 2 * m2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 -= m2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += 2 * m2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 2 * k + ip[k]; a[k1 + 1] = -a[k1 + 1]; j1 = k1 + m2; k1 = j1 + m2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; k1 += m2; a[k1 + 1] = -a[k1 + 1]; } } else { a[1] = -a[1]; a[m2 + 1] = -a[m2 + 1]; for (k = 1; k < m; k++) { for (j = 0; j < k; j++) { j1 = 2 * j + ip[k]; k1 = 2 * k + ip[j]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += m2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 2 * k + ip[k]; a[k1 + 1] = -a[k1 + 1]; a[k1 + m2 + 1] = -a[k1 + m2 + 1]; } } } void cftfsub(int n, real_t *a, real_t *w) { void cft1st(int n, real_t *a, real_t *w); void cftmdl(int n, int l, real_t *a, real_t *w); int j, j1, j2, j3, l; real_t x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; l = 2; if (n > 8) { cft1st(n, a, w); l = 8; while ((l << 2) < n) { cftmdl(n, l, a, w); l <<= 2; } } if ((l << 2) == n) { for (j = 0; j < l; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j2] = x0r - x2r; a[j2 + 1] = x0i - x2i; a[j1] = x1r - x3i; a[j1 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; } } else { for (j = 0; j < l; j += 2) { j1 = j + l; x0r = a[j] - a[j1]; x0i = a[j + 1] - a[j1 + 1]; a[j] += a[j1]; a[j + 1] += a[j1 + 1]; a[j1] = x0r; a[j1 + 1] = x0i; } } } void cftbsub(int n, real_t *a, real_t *w) { void cft1st(int n, real_t *a, real_t *w); void cftmdl(int n, int l, real_t *a, real_t *w); int j, j1, j2, j3, l; real_t x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; l = 2; if (n > 8) { cft1st(n, a, w); l = 8; while ((l << 2) < n) { cftmdl(n, l, a, w); l <<= 2; } } if ((l << 2) == n) { for (j = 0; j < l; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = -a[j + 1] - a[j1 + 1]; x1r = a[j] - a[j1]; x1i = -a[j + 1] + a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i - x2i; a[j2] = x0r - x2r; a[j2 + 1] = x0i + x2i; a[j1] = x1r - x3i; a[j1 + 1] = x1i - x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i + x3r; } } else { for (j = 0; j < l; j += 2) { j1 = j + l; x0r = a[j] - a[j1]; x0i = -a[j + 1] + a[j1 + 1]; a[j] += a[j1]; a[j + 1] = -a[j + 1] - a[j1 + 1]; a[j1] = x0r; a[j1 + 1] = x0i; } } } void cft1st(int n, real_t *a, real_t *w) { int j, k1, k2; real_t wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; real_t x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; x0r = a[0] + a[2]; x0i = a[1] + a[3]; x1r = a[0] - a[2]; x1i = a[1] - a[3]; x2r = a[4] + a[6]; x2i = a[5] + a[7]; x3r = a[4] - a[6]; x3i = a[5] - a[7]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[4] = x0r - x2r; a[5] = x0i - x2i; a[2] = x1r - x3i; a[3] = x1i + x3r; a[6] = x1r + x3i; a[7] = x1i - x3r; wk1r = w[2]; x0r = a[8] + a[10]; x0i = a[9] + a[11]; x1r = a[8] - a[10]; x1i = a[9] - a[11]; x2r = a[12] + a[14]; x2i = a[13] + a[15]; x3r = a[12] - a[14]; x3i = a[13] - a[15]; a[8] = x0r + x2r; a[9] = x0i + x2i; a[12] = x2i - x0i; a[13] = x0r - x2r; x0r = x1r - x3i; x0i = x1i + x3r; a[10] = wk1r * (x0r - x0i); a[11] = wk1r * (x0r + x0i); x0r = x3i + x1r; x0i = x3r - x1i; a[14] = wk1r * (x0i - x0r); a[15] = wk1r * (x0i + x0r); k1 = 0; for (j = 16; j < n; j += 16) { k1 += 2; k2 = 2 * k1; wk2r = w[k1]; wk2i = w[k1 + 1]; wk1r = w[k2]; wk1i = w[k2 + 1]; wk3r = wk1r - 2 * wk2i * wk1i; wk3i = 2 * wk2i * wk1r - wk1i; x0r = a[j] + a[j + 2]; x0i = a[j + 1] + a[j + 3]; x1r = a[j] - a[j + 2]; x1i = a[j + 1] - a[j + 3]; x2r = a[j + 4] + a[j + 6]; x2i = a[j + 5] + a[j + 7]; x3r = a[j + 4] - a[j + 6]; x3i = a[j + 5] - a[j + 7]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j + 4] = wk2r * x0r - wk2i * x0i; a[j + 5] = wk2r * x0i + wk2i * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j + 2] = wk1r * x0r - wk1i * x0i; a[j + 3] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j + 6] = wk3r * x0r - wk3i * x0i; a[j + 7] = wk3r * x0i + wk3i * x0r; wk1r = w[k2 + 2]; wk1i = w[k2 + 3]; wk3r = wk1r - 2 * wk2r * wk1i; wk3i = 2 * wk2r * wk1r - wk1i; x0r = a[j + 8] + a[j + 10]; x0i = a[j + 9] + a[j + 11]; x1r = a[j + 8] - a[j + 10]; x1i = a[j + 9] - a[j + 11]; x2r = a[j + 12] + a[j + 14]; x2i = a[j + 13] + a[j + 15]; x3r = a[j + 12] - a[j + 14]; x3i = a[j + 13] - a[j + 15]; a[j + 8] = x0r + x2r; a[j + 9] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j + 12] = -wk2i * x0r - wk2r * x0i; a[j + 13] = -wk2i * x0i + wk2r * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j + 10] = wk1r * x0r - wk1i * x0i; a[j + 11] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j + 14] = wk3r * x0r - wk3i * x0i; a[j + 15] = wk3r * x0i + wk3i * x0r; } } void cftmdl(int n, int l, real_t *a, real_t *w) { int j, j1, j2, j3, k, k1, k2, m, m2; real_t wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; real_t x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; m = l << 2; for (j = 0; j < l; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j2] = x0r - x2r; a[j2 + 1] = x0i - x2i; a[j1] = x1r - x3i; a[j1 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; } wk1r = w[2]; for (j = m; j < l + m; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j2] = x2i - x0i; a[j2 + 1] = x0r - x2r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * (x0r - x0i); a[j1 + 1] = wk1r * (x0r + x0i); x0r = x3i + x1r; x0i = x3r - x1i; a[j3] = wk1r * (x0i - x0r); a[j3 + 1] = wk1r * (x0i + x0r); } k1 = 0; m2 = 2 * m; for (k = m2; k < n; k += m2) { k1 += 2; k2 = 2 * k1; wk2r = w[k1]; wk2i = w[k1 + 1]; wk1r = w[k2]; wk1i = w[k2 + 1]; wk3r = wk1r - 2 * wk2i * wk1i; wk3i = 2 * wk2i * wk1r - wk1i; for (j = k; j < l + k; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j2] = wk2r * x0r - wk2i * x0i; a[j2 + 1] = wk2r * x0i + wk2i * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * x0r - wk1i * x0i; a[j1 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r - wk3i * x0i; a[j3 + 1] = wk3r * x0i + wk3i * x0r; } wk1r = w[k2 + 2]; wk1i = w[k2 + 3]; wk3r = wk1r - 2 * wk2r * wk1i; wk3i = 2 * wk2r * wk1r - wk1i; for (j = k + m; j < l + (k + m); j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j2] = -wk2i * x0r - wk2r * x0i; a[j2 + 1] = -wk2i * x0i + wk2r * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * x0r - wk1i * x0i; a[j1 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r - wk3i * x0i; a[j3 + 1] = wk3r * x0i + wk3i * x0r; } } } void rftfsub(int n, real_t *a, int nc, real_t *c) { int j, k, kk, ks, m; real_t wkr, wki, xr, xi, yr, yi; m = n >> 1; ks = 2 * nc / m; kk = 0; for (j = 2; j < m; j += 2) { k = n - j; kk += ks; wkr = 0.5 - c[nc - kk]; wki = c[kk]; xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr - wki * xi; yi = wkr * xi + wki * xr; a[j] -= yr; a[j + 1] -= yi; a[k] += yr; a[k + 1] -= yi; } } void rftbsub(int n, real_t *a, int nc, real_t *c) { int j, k, kk, ks, m; real_t wkr, wki, xr, xi, yr, yi; a[1] = -a[1]; m = n >> 1; ks = 2 * nc / m; kk = 0; for (j = 2; j < m; j += 2) { k = n - j; kk += ks; wkr = 0.5 - c[nc - kk]; wki = c[kk]; xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr + wki * xi; yi = wkr * xi - wki * xr; a[j] -= yr; a[j + 1] = yi - a[j + 1]; a[k] += yr; a[k + 1] = yi - a[k + 1]; } a[m + 1] = -a[m + 1]; } void dctsub(int n, real_t *a, int nc, real_t *c) { int j, k, kk, ks, m; real_t wkr, wki, xr; m = n >> 1; ks = nc / n; kk = 0; for (j = 1; j < m; j++) { k = n - j; kk += ks; wkr = c[kk] - c[nc - kk]; wki = c[kk] + c[nc - kk]; xr = wki * a[j] - wkr * a[k]; a[j] = wkr * a[j] + wki * a[k]; a[k] = xr; } a[m] *= c[0]; } void dstsub(int n, real_t *a, int nc, real_t *c) { int j, k, kk, ks, m; real_t wkr, wki, xr; m = n >> 1; ks = nc / n; kk = 0; for (j = 1; j < m; j++) { k = n - j; kk += ks; wkr = c[kk] - c[nc - kk]; wki = c[kk] + c[nc - kk]; xr = wki * a[k] - wkr * a[j]; a[k] = wkr * a[k] + wki * a[j]; a[j] = xr; } a[m] *= c[0]; } ================================================ FILE: lib/open303/src/wavetable_gen/rosic_Complex.cpp ================================================ #include "rosic_Complex.h" using namespace rosic; //------------------------------------------------------------------------------------------------- // construction/destruction: Complex::Complex() { re = im = 0.0; } Complex::Complex(real_t reInit) { re = reInit; im = 0.0; } Complex::Complex(real_t reInit, real_t imInit) { re = reInit; im = imInit; } Complex::~Complex() { } //------------------------------------------------------------------------------------------------- // magnitude, angle, etc. real_t Complex::getRadius() { return sqrt(re*re + im*im); } real_t Complex::getAngle() { if((re==0.0) && (im==0)) return 0.0; else return atan2(im, re); } void Complex::setRadius(real_t newRadius) { real_t phi = getAngle(); sinCos(phi, &im, &re); re *= newRadius; // re = newRadius * cos(phi); im *= newRadius; // im = newRadius * sin(phi); } void Complex::setAngle(real_t newAngle) { real_t r = getRadius(); sinCos(newAngle, &im, &re); re *= r; // re = r * cos(newAngle); im *= r; // im = r * sin(newAngle); } void Complex::setRadiusAndAngle(real_t newRadius, real_t newAngle) { sinCos(newAngle, &im, &re); re *= newRadius; // re = newRadius * cos(newAngle); im *= newRadius; // im = newRadius * sin(newAngle); } Complex Complex::getConjugate() { return Complex(re, -im); } Complex Complex::getReciprocal() { real_t scaler = 1.0 / (re*re + im*im); return Complex(scaler*re, -scaler*im); } bool Complex::isReal() { return (im == 0.0); } bool Complex::isImaginary() { return (re == 0.0); } bool Complex::isInfinite() { if( re == INF || re == NEG_INF || im == INF || im == NEG_INF ) return true; else return false; } ================================================ FILE: lib/open303/src/wavetable_gen/rosic_Complex.h ================================================ #ifndef rosic_Complex_h #define rosic_Complex_h // rosic-indcludes: #include "../rosic_RealFunctions.h" namespace rosic { /** This is a class for complex numbers. It defines the basic arithmetic operations between complex numbers as well as the special cases when one of the operands is real (real_t). ATTENTION: do not define any further member variables, nor switch the ordering of re and im because the FourierTransformer classes rely on the fact that a complex number consists of two doubles re, im and nothing else (the algorithms actually run on buffers of doubles). */ class Complex { public: //--------------------------------------------------------------------------------------------- // public member variables: /** Real part */ real_t re; /** Imaginary part */ real_t im; //--------------------------------------------------------------------------------------------- // construction/destruction: /** Constructor. Initializes real and imaginary part to zero. */ Complex(); /** Constructor. Initializes real part to the argument "reInit" and imaginary part to zero. */ Complex(real_t reInit); /** Constructor. Initializes real and imaginary parts with the parameters. */ Complex(real_t reInit, real_t imInit); /** Destructor. */ ~Complex(); //--------------------------------------------------------------------------------------------- // overloaded operators: /** Compares two complex numbers of equality. */ bool operator==(const Complex& z) const { if( re == z.re && im == z.im ) return true; else return false; } /** Compares two complex numbers of inequality. */ bool operator!=(const Complex& z) const { if( re != z.re || im != z.im ) return true; else return false; } /** Defines the negative of a complex number. */ Complex operator-() { return Complex(-re, -im); } /** Adds another complex number to this complex and returns the result. */ Complex& operator+=(const Complex &z) { this->re += z.re; this->im += z.im; return *this; } /** Adds a real number to this complex and returns the result. */ Complex& operator+=(const real_t &r) { this->re += r; return *this; } /** Subtracts another complex number from this complex and returns the result. */ Complex& operator-=(const Complex &z) { this->re -= z.re; this->im -= z.im; return *this; } /** Subtracts a real number from this complex and returns the result. */ Complex& operator-=(const real_t &r) { this->re -= r; return *this; } /** Multiplies this complex number by another complex number and returns the result. */ Complex& operator*=(const Complex &z) { real_t reNew = re*z.re - im*z.im; real_t imNew = re*z.im + im*z.re; this->re = reNew; this->im = imNew; return *this; } /** Multiplies this complex number by a real number and returns the result. */ Complex& operator*=(const real_t &r) { this->re *= r; this->im *= r; return *this; } /** Divides this complex number by another complex number and returns the result. */ Complex& operator/=(const Complex &z) { real_t scale = 1.0 / (z.re*z.re + z.im*z.im); real_t reNew = scale*( re*z.re + im*z.im ); real_t imNew = scale*( im*z.re - re*z.im ); this->re = reNew; this->im = imNew; return *this; } /** Divides this complex number by a real number and returns the result. */ Complex& operator/=(const real_t &r) { real_t scale = 1.0 / r; this->re *= scale; this->im *= scale; return *this; } //--------------------------------------------------------------------------------------------- // set-functions: /** Adjusts the radius of this complex number leaving the angle unchanged. */ void setRadius(real_t newRadius); /** Adjusts the angle of this complex number leaving the magnitude unchanged. */ void setAngle(real_t newAngle); /** Sets the radius and angle of this complex number. */ void setRadiusAndAngle(real_t newRadius, real_t newAngle); //--------------------------------------------------------------------------------------------- // get-functions: /** Returns the radius of this complex number. */ real_t getRadius(); /** Returns the angle of this complex number. */ real_t getAngle(); /** Returns the complex conjugate of this complex number. */ Complex getConjugate(); /** Returns the reciprocal of this complex number. */ Complex getReciprocal(); /** Returns true, if this complex number is purely real. */ bool isReal(); /** Returns true, if this complex number is purely imaginary. */ bool isImaginary(); /** Returns true if real or imaginary part (or both) are plus or minus infinity, false otherwise. */ bool isInfinite(); }; // end of class Complex // some binary operators are defined outside the class such that the left hand operand does // not necesarrily need to be of class Complex /** Adds two complex numbers. */ INLINE Complex operator+(const Complex &z, const Complex &w) { return Complex(z.re+w.re, z.im+w.im); } /** Adds a complex and a real number. */ INLINE Complex operator+(const Complex &z, const real_t &r) { return Complex(z.re+r, z.im); } /** Adds a real and a complex number. */ INLINE Complex operator+(const real_t &r, const Complex &z) { return Complex(z.re+r, z.im); } /** Subtracts two complex numbers. */ INLINE Complex operator-(const Complex &z, const Complex &w) { return Complex(z.re-w.re, z.im-w.im); } /** Subtracts a real number from a complex number. */ INLINE Complex operator-(const Complex &z, const real_t &r) { return Complex(z.re-r, z.im); } /** Subtracts a complex number from a real number. */ INLINE Complex operator-(const real_t &r, const Complex &z) { return Complex(r-z.re, -z.im); } /** Multiplies two complex numbers. */ INLINE Complex operator*(const Complex &z, const Complex &w) { return Complex(z.re*w.re-z.im*w.im, z.re*w.im+z.im*w.re); } /** Multiplies a complex number and a real number. */ INLINE Complex operator*(const Complex &z, const real_t &r) { return Complex(z.re*r, z.im*r); } /** Multiplies a real number and a complex number. */ INLINE Complex operator*(const real_t &r, const Complex &z) { return Complex(z.re*r, z.im*r); } /** Divides two complex numbers. */ INLINE Complex operator/(const Complex &z, const Complex &w) { real_t scale = 1.0 / (w.re*w.re + w.im*w.im); return Complex( scale*( z.re*w.re + z.im*w.im), // real part scale*( z.im*w.re - z.re*w.im) ); // imaginary part } /** Divides a complex number by a real number. */ INLINE Complex operator/(const Complex &z, const real_t &r) { real_t scale = 1.0 / r; return Complex(scale*z.re, scale*z.im); } /** Divides a real number by a complex number. */ INLINE Complex operator/(const real_t &r, const Complex &z) { real_t scale = r / (z.re*z.re + z.im*z.im); return Complex(scale*z.re, -scale*z.im); } } // end namespace rosic #endif // rosic_Complex_h ================================================ FILE: lib/open303/src/wavetable_gen/rosic_FourierTransformerRadix2.cpp ================================================ #include "rosic_FourierTransformerRadix2.h" namespace rosic { #include "fft4g.h" } using namespace rosic; //------------------------------------------------------------------------------------------------- // construction/destruction: FourierTransformerRadix2::FourierTransformerRadix2() { N = 0; logN = 0; direction = FORWARD; normalizationMode = NORMALIZE_ON_INVERSE_TRAFO; normalizationFactor = 1.0; #ifndef STATIC_N w = NULL; ip = NULL; tmpBuffer = NULL; #endif setBlockSize(256); } FourierTransformerRadix2::~FourierTransformerRadix2() { // free dynamically allocated memory: #ifndef STATIC_N if( w != NULL ) delete[] w; if( ip != NULL ) delete[] ip; if( tmpBuffer != NULL ) delete[] tmpBuffer; #endif } //------------------------------------------------------------------------------------------------- // parameter settings: void FourierTransformerRadix2::setBlockSize(int newBlockSize) { // check new blocksize for validity: if( newBlockSize >= 2 && isPowerOfTwo(newBlockSize) ) { // check, if the new blocksize is actually different from the old one in order to avoid // unnecesarry re-allocations and re-computations: if( newBlockSize != N ) { N = newBlockSize; logN = (int) floor( log2((real_t) N + 0.5 ) ); updateNormalizationFactor(); #ifndef STATIC_N if( w != NULL ) delete[] w; w = new real_t[2*N]; if( ip != NULL ) delete[] ip; ip = new int[(int) ceil(4.0+sqrt((real_t)N))]; ip[0] = 0; // indicate that re-initialization is necesarry if( tmpBuffer != NULL ) delete[] tmpBuffer; tmpBuffer = new Complex[N]; #else ip[0] = 0; #endif } } else if( !isPowerOfTwo(newBlockSize) || newBlockSize <= 1 ) DEBUG_BREAK; // this class can only deal with blocksizes >= 2 that are a power of two } void FourierTransformerRadix2::setDirection(int newDirection) { if( newDirection >= FORWARD && newDirection <= INVERSE ) { // only when the new direction is actually different form the old one, we have to conjugate // all the twiddle-factors, otherwise everything must stay as is: if( newDirection != direction ) { direction = newDirection; updateNormalizationFactor(); } } else DEBUG_BREAK; // passed int-parameter does not correspond to any meaningful enum-field } void FourierTransformerRadix2::setNormalizationMode(int newNormalizationMode) { if( newNormalizationMode >= NORMALIZE_ON_FORWARD_TRAFO && newNormalizationMode <= ORTHONORMAL_TRAFO ) { normalizationMode = newNormalizationMode; updateNormalizationFactor(); } else DEBUG_BREAK; // passed int-parameter does not correspond to any meaningful enum-field } void FourierTransformerRadix2::setRealSignalMode(bool willBeUsedForRealSignals) { ip[0] = 0; // retriggers twiddle-factor computation } //------------------------------------------------------------------------------------------------- // signal processing: void FourierTransformerRadix2::transformComplexBufferInPlace(Complex *buffer) { // retrieve the adresses of the real part of the first array entries in order to treat the // Complex arrays as arrays of two successive real_t-numbers: real_t* d_buffer = &(buffer[0].re); // normalize the FFT-input, if required: if( normalizationFactor != 1.0 ) { for(int n=0; n<2*N; n++) d_buffer[n] *= normalizationFactor; } // use Ooura's routine: int sign; if( direction == FORWARD ) sign = -1; else sign = +1; cdft(2*N, sign, d_buffer, ip, w); } void FourierTransformerRadix2::transformComplexBuffer(Complex *inBuffer, Complex *outBuffer) { // retrieve the adresses of the real part of the first array entries in order to treat the // Complex arrays as arrays of two successive real_t-numbers: real_t* d_inBuffer = &(inBuffer[0].re); real_t* d_outBuffer = &(outBuffer[0].re); // copy the input into the output for the in-place routine (thereby normalize, if necesarry): int n; if( normalizationFactor != 1.0 ) { for(n=0; n<2*N; n++) d_outBuffer[n] = d_inBuffer[n] * normalizationFactor; } else { for(n=0; n<2*N; n++) d_outBuffer[n] = d_inBuffer[n]; } // use Ooura's routine: int sign; if( direction == FORWARD ) sign = -1; else sign = +1; cdft(2*N, sign, d_outBuffer, ip, w); } //------------------------------------------------------------------------------------------------- // convenience functions for real signal: void FourierTransformerRadix2::transformRealSignal(real_t *inSignal, Complex *outSpectrum) { setDirection(FORWARD); // retrieve the adress of the real part of the first array entry of the output array in order to // treat the Complex array as array of two successive real_t-numbers: real_t* d_outBuffer = &(outSpectrum[0].re); // copy the input into the output for the in-place routine (thereby normalize, if necesarry): int n; if( normalizationFactor != 1.0 ) { for(n=0; n // rosic-indcludes: #include "rosic_Complex.h" #include "../rosic_RealFunctions.h" #define STATIC_N 256 //[eh2k] remove this, to use the original implementation (with new/delete) namespace rosic { /** This class performs a fast Fourier Transform on a block of complex numbers (which are of class "Complex"). The length of the block has to be a power of 2. It uses the FFT library by Takuya Ooura which seems to be rather efficient. It handles the conversion between doubles and Complex numbers by means of some hacky pointer trickery which relies on the fact that an object of class Complex can be interpreted as two doubles stored in subsequent memory locations. This is true for the compiler in MSVC 2005 but may or may not be true for other compilers. In case of problems, try the class FourierTransfromerRadix2Clean which goes without such nasty hacks but is vastly inferior efficiency-wise. */ class FourierTransformerRadix2 { public: /** The direction of the transform. */ enum directions { FORWARD, INVERSE }; /** These are the possible normalization modes. */ enum normalizationModes { NORMALIZE_ON_FORWARD_TRAFO, // divide by blockSize on forward FFT NORMALIZE_ON_INVERSE_TRAFO, // divide by blockSize on inverse FFT (default) ORTHONORMAL_TRAFO // divide by sqrt(blockSize) on both transforms }; //--------------------------------------------------------------------------------------------- // construction/destruction: /** Constructor. */ FourierTransformerRadix2(); /** Destructor. */ ~FourierTransformerRadix2(); //--------------------------------------------------------------------------------------------- // parameter settings: /** FFT-size, has to be a power of 2 and >= 2. */ void setBlockSize(int newBlockSize); /** Sets the direction of the transform (@see: directions). This will affect the sign of the exponent (or equivalently: theimaginary part) in the twiddling factors and the normalization constant. */ void setDirection(int newDirection); /** When you switch bewteen usage of this object for real or complex signals, you will need to call this switch-function in between which just triggers a re-computation of the twiddle factors (which must be different for the two cases). */ void setRealSignalMode(bool willBeUsedForRealSignals); /** Sets the mode for normalization of the output (@see: normalizationModes). */ void setNormalizationMode(int newNormalizationMode); //--------------------------------------------------------------------------------------------- // complex Fourier transforms: /** Transforms a buffer of complex numbers into its (forward or inverse) fourier transform. The inBuffer will remain intact. Both, inBuffer and outBuffer must be of the size which was specified when setting up the blockSize with setBlockSize(). */ void transformComplexBuffer(Complex *inBuffer, Complex *outBuffer); /** Does the same thing as transformComplexBuffer but performes in-place calculation (overwrites the input buffer). */ void transformComplexBufferInPlace(Complex *buffer); //--------------------------------------------------------------------------------------------- // some convenience functions for dealing with real signals: /** Transforms a real signal into its corresponding (conjugate symmetric) complex spectrum using an algorithm which exploits the symmetries for more efficiency. When the input array is an array of doubles of length N, the output array will be an array of complex numbers (class Complex) of length N/2 with the (purely real) transform value of bin N/2 stored in the imaginary part of the first array entry (outSpectrum[0].im = real(N/2)). */ void transformRealSignal(real_t *inSignal, Complex *outSpectrum); /** Calculates real and imaginary part of the spectrum as interleaved real_t buffer: buf[2]=re[1], buf[3]=im[1], buf[4]=re[2], buf[5]=im[2],... in general: buf[2*k]=re[k], buf[2k+1]=im[k], k=1,..,(N/2)-1 where N is the FFT-size. The first two elements of the buffer have a special meaning: buf[0] is the (purely real) DC and buf[1] is the (purely real) coefficient for the Nyquist frequency. The other fields contain the real and imaginary parts of the positive frequencies only (interleaved) because the negative frequencies are redundant (they are conjugate symmetric). */ void transformRealSignal(real_t *signal, real_t *reAndIm); /** Calculates spectral magnitudes and phases from a signal, where *signal should be of length N, where N is the block-size as chosen with setBlockSize() *magnitudes and *phases should be of length N/2. */ void getRealSignalMagnitudesAndPhases(real_t *signal, real_t *magnitudes, real_t *phases); /** Calculates the magnitudes only from a signal (useful for analyzer-stuff). */ void getRealSignalMagnitudes(real_t *signal, real_t *magnitudes); /** Transforms a complex conjugate symmetric spectrum (i.e. a spectrum of a real signal) into the corresponding real signal. */ void transformSymmetricSpectrum(Complex *inSpectrum, real_t *outSignal); /** Calculates a time signal from and interleaved buffer containing the real and imaginary parts of the positive frequencies (the negative frequencies are assumed to be conjugate symmetric). */ void transformSymmetricSpectrum(real_t *reAndIm, real_t *signal); /** Calculates a real time signal from its magnitudes and phases, *magnitudes and *phases should be of length N/2, *signal is of length N where N is the block-size as chosen with setBlockSize(). */ void getRealSignalFromMagnitudesAndPhases(real_t *magnitudes, real_t *phases, real_t *signal); //--------------------------------------------------------------------------------------------- // static functions /** Returns the physical frequency in Hz that corresponds to the given 'binIndex' for a given 'fftSize' and 'sampleRate'. */ static real_t binIndexToFrequency(int binIndex, int fftSize, real_t sampleRate) { return binIndex*sampleRate/fftSize; } //============================================================================================= protected: /** Updates the normalizationFactor member variable acording to a new blockSize, direction or normalizationMode. */ void updateNormalizationFactor(); int N; /**< the blocksize of the FFT. */ int logN; /**< Base 2 logarithm of the blocksize. */ int direction; /**< The direction of the transform (@see: directions). */ int normalizationMode; /**< The normalization mode (@see: normalizationModes. */ real_t normalizationFactor; /**< The normalization factor (can be 1, 1/N or 1/sqrt(N)). */ #ifndef STATIC_N // work-area stuff for Ooura's fft-routines: real_t *w; /**< Table of the twiddle-factors. */ int *ip; /**< Work area for bit-reversal (index pointer?). */ // our own temporary storage area: Complex* tmpBuffer; #else real_t w[2*STATIC_N]; int ip[4+16]; //ceil(4.0+sqrt(STATIC_N))]; Complex tmpBuffer[STATIC_N]; #endif }; } // end namespace rosic #endif // rosic_FourierTransformerRadix2_h ================================================ FILE: lib/open303/src/wavetable_gen/rosic_MipMappedWaveTable.cpp ================================================ #include "rosic_MipMappedWaveTable.h" #include using namespace rosic; MipMappedWaveTable::MipMappedWaveTable() { // init member variables: sampleRate = SAMPLE_RATE; waveform = 0; symmetry = 0.5; // initialize internal 'back-panel' parameters tanhShaperFactor = dB2amp(36.9); tanhShaperOffset = 4.37; squarePhaseShift = 180.0; // set up the fourier-transformer: fourierTransformer.setBlockSize(tableLength); // initialize the buffers: initPrototypeTable(); } MipMappedWaveTable::~MipMappedWaveTable() { } //------------------------------------------------------------------------------------------------- // parameter settings: void MipMappedWaveTable::setWaveform(real_t* newWaveForm, int lengthInSamples) { int i; if( lengthInSamples == tableLength ) { // just copy the values into the internal buffer, when the length of the passed table and the // internal table match: for( i=0; i= 0) && (newWaveform != waveform) ) { waveform = newWaveform; renderWaveform(); } } void MipMappedWaveTable::setSymmetry(real_t newSymmetry) { symmetry = newSymmetry; renderWaveform(); } //------------------------------------------------------------------------------------------------- // internal functions: void MipMappedWaveTable::initPrototypeTable() { for(int i=0; i<(tableLength/* [eh2k] +4 */); i++) prototypeTable[i] = 0.0; } void MipMappedWaveTable::removeDC() { // calculate DC-offset (= average value of the table): real_t dcOffset = 0.0; int i; for(i=0; i max) max = fabs(prototypeTable[i]); // normalize to amplitude 1.0: real_t scale = 1.0/max; for(i=0; i saves one if-statement each audio-cycle) ...and a three further addtional // samples for more elaborate interpolations like cubic (not implemented yet, also: // the fillWith...()-functions don't support these samples yet). */ //eh2k real_t tableSet[numTables][tableLength+4]; // The multisample for anti-aliased waveform generation. The 4 additional values are equal // to the first 4 values in the table for easier interpolation. The first index is for the // table-number - index 0 accesses the first version which has full bandwidth, index 1 // accesses the second version which is bandlimited to Nyquist/2, 2->Nyquist/4, // 3->Nyquist/8, etc. */ // embedded objects: FourierTransformerRadix2 fourierTransformer; // internal parameters: real_t tanhShaperFactor, tanhShaperOffset, squarePhaseShift; }; //----------------------------------------------------------------------------------------------- // inlined functions: INLINE real_t MipMappedWaveTable::getValueLinear(const WaveTable& tableSet, int integerPart, real_t fractionalPart, int tableIndex) { // ensure, that the table index is in the valid range: if( tableIndex<=0 ) tableIndex = 0; else if ( tableIndex>numTables ) tableIndex = 11; return (1.0-fractionalPart) * tableSet[tableIndex][integerPart] + fractionalPart * tableSet[tableIndex][integerPart+1]; } INLINE real_t MipMappedWaveTable::getValueLinear(const WaveTable& tableSet, real_t phaseIndex, int tableIndex) { /* // ensure, that the table index is in the valid range: if( tableIndex<=0 ) tableIndex = 0; else if ( tableIndex>numTables ) tableIndex = 11; */ // calculate integer and fractional part of the phaseIndex: int intIndex = floorInt(phaseIndex); real_t frac = phaseIndex - (real_t) intIndex; return getValueLinear(tableSet, intIndex, frac, tableIndex); // lookup value in the table with linear interpolation and return it: //return (1.0-frac)*tableSet[tableIndex][intIndex] + frac*tableSet[tableIndex][intIndex+1]; } } // end namespace rosic #endif // rosic_MipMappedWaveTable_h ================================================ FILE: lib/peaks/drums/bass_drum.cc ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808-style bass drum. #include "peaks/drums/bass_drum.h" #include #include "stmlib/utils/dsp.h" #include "peaks/resources.h" namespace peaks { using namespace stmlib; void BassDrum::Init() { pulse_up_.Init(); pulse_down_.Init(); attack_fm_.Init(); resonator_.Init(); pulse_up_.set_delay(0); pulse_up_.set_decay(3340); pulse_down_.set_delay(1.0e-3 * 48000); pulse_down_.set_decay(3072); attack_fm_.set_delay(4.0e-3 * 48000); attack_fm_.set_decay(4093); resonator_.set_punch(32768); set_frequency(0); set_decay(32768); set_tone(32768); set_punch(65535); lp_state_ = 0; } void BassDrum::Process(const GateFlags* gate_flags, int16_t* out, size_t size) { while (size--) { GateFlags gate_flag = *gate_flags++; if (gate_flag & GATE_FLAG_RISING) { pulse_up_.Trigger(12 * 32768 * 0.7); pulse_down_.Trigger(-19662 * 0.7); attack_fm_.Trigger(18000); } int32_t excitation = 0; excitation += pulse_up_.Process(); excitation += !pulse_down_.done() ? 16384 : 0; excitation += pulse_down_.Process(); attack_fm_.Process(); resonator_.set_frequency(frequency_ + (attack_fm_.done() ? 0 : 17 << 7)); int32_t resonator_output = (excitation >> 4) + \ resonator_.Process(excitation); lp_state_ += (resonator_output - lp_state_) * lp_coefficient_ >> 15; int32_t output = lp_state_; CLIP(output); *out++ = output; } } } // namespace peaks ================================================ FILE: lib/peaks/drums/bass_drum.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808-style bass drum. #ifndef PEAKS_DRUMS_BASS_DRUM_H_ #define PEAKS_DRUMS_BASS_DRUM_H_ #include "stmlib/stmlib.h" #include "peaks/drums/svf.h" #include "peaks/drums/excitation.h" #include "peaks/gate_processor.h" namespace peaks { class BassDrum { public: BassDrum() { } ~BassDrum() { } void Init(); void Process(const GateFlags* gate_flags, int16_t* out, size_t size); void Configure(uint16_t* parameter, ControlMode control_mode) { if (control_mode == CONTROL_MODE_HALF) { set_frequency(0); set_punch(40000); set_tone(8192 + (parameter[0] >> 1)); set_decay(parameter[1]); } else { set_frequency(parameter[0] - 32768); set_punch(parameter[1]); set_tone(parameter[2]); set_decay(parameter[3]); } } void set_frequency(int16_t frequency) { frequency_ = (31 << 7) + (static_cast(frequency) * 896 >> 15); } void set_decay(uint16_t decay) { uint32_t scaled; uint32_t squared; scaled = 65535 - decay; squared = scaled * scaled >> 16; scaled = squared * scaled >> 18; resonator_.set_resonance(32768 - 128 - scaled); } void set_tone(uint16_t tone) { uint32_t coefficient = tone; coefficient = coefficient * coefficient >> 16; lp_coefficient_ = 512 + (coefficient >> 2) * 3; } void set_punch(uint16_t punch) { resonator_.set_punch(punch * punch >> 16); } private: Excitation pulse_up_; Excitation pulse_down_; Excitation attack_fm_; Svf resonator_; int32_t frequency_; int32_t lp_coefficient_; int32_t lp_state_; DISALLOW_COPY_AND_ASSIGN(BassDrum); }; } // namespace peaks #endif // PEAKS_DRUMS_BASS_DRUM_H_ ================================================ FILE: lib/peaks/drums/excitation.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Exponential decay excitation. #ifndef PEAKS_DRUMS_EXCITATION_H_ #define PEAKS_DRUMS_EXCITATION_H_ #include "stmlib/stmlib.h" namespace peaks { class Excitation { public: Excitation() { } ~Excitation() { } void Init() { delay_ = 0; decay_ = 4093; counter_ = 0; state_ = 0; } void set_delay(uint16_t delay) { delay_ = delay; } void set_decay(uint16_t decay) { decay_ = decay; } void Trigger(int32_t level) { level_ = level; counter_ = delay_ + 1; state_ = 0; } bool done() { return counter_ == 0; } inline int32_t Process() { state_ = (state_ * decay_ >> 12); if (counter_ > 0) { --counter_; if (counter_ == 0) { state_ += level_ < 0 ? -level_ : level_; } } return level_ < 0 ? -state_ : state_; } private: uint32_t delay_; uint32_t decay_; int32_t counter_; int32_t state_; int32_t level_; DISALLOW_COPY_AND_ASSIGN(Excitation); }; } // namespace peaks #endif // PEAKS_DRUMS_EXCITATION_H_ ================================================ FILE: lib/peaks/drums/fm_drum.cc ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Sine FM drum - similar to the BD/SD in Anushri. #include "peaks/drums/fm_drum.h" #include #include "stmlib/utils/dsp.h" #include "stmlib/utils/random.h" #include "peaks/resources.h" namespace peaks { using namespace stmlib; void FmDrum::Init() { phase_ = 0; fm_envelope_phase_ = 0xffffffff; am_envelope_phase_ = 0xffffffff; previous_sample_ = 0; } static const uint16_t kHighestNote = 128 * 128; static const uint16_t kPitchTableStart = 116 * 128; static const uint16_t kOctave = 128 * 12; static const uint16_t bd_map[10][4] = { { 4096, 0, 65535, 32768 }, { 8192 + 4096, 0, 65535, 32768 }, { 8192, 4096, 49512, 32768 }, { 8192, 16384, 40960, 32768 }, { 10240, 4096, 24576, 32768 }, { 10240, 16384, 24576, 16384 }, { 8192, 8192, 32768, 16384 }, { 8192, 24576, 49152, 8192 }, { 4096, 16384, 40960, 16384 }, { 8192, 24576, 49152, 0 }, }; static const uint16_t sd_map[10][4] = { { 24576, 0, 24576, 36864 }, { 24576, 0, 16384, 65535 }, { 28672, 0, 16384, 36864 }, { 28672, 0, 16384, 65535 }, { 20488, 0, 32768, 57344 }, { 28672, 0, 24576, 65535 }, { 20488, 0, 24576, 65535 }, { 28672, 0, 32768, 65535 }, { 20488, 65535, 16384, 0 }, { 65535, 0, 8192, 32768 }, }; void FmDrum::Morph(uint16_t x, uint16_t y) { const uint16_t (*map)[4] = sd_range_ ? sd_map : bd_map; uint16_t parameters[4]; for (uint8_t i = 0; i < 4; ++i) { uint16_t x_integral = (x >> 14) << 1; uint16_t x_fractional = x << 2; uint16_t a = map[x_integral][i]; uint16_t b = map[x_integral + 2][i]; uint16_t c = map[x_integral + 1][i]; uint16_t d = map[x_integral + 3][i]; uint16_t e = a + ((b - a) * x_fractional >> 16); uint16_t f = c + ((d - c) * x_fractional >> 16); parameters[i] = e + ((f - e) * y >> 16); } Configure(parameters, CONTROL_MODE_FULL); } uint32_t FmDrum::ComputeEnvelopeIncrement(uint16_t decay) { uint32_t a = lut_env_increments[decay >> 8]; uint32_t b = lut_env_increments[(decay >> 8) + 1]; return a - ((a - b) * (decay & 0xff) >> 8); } uint32_t FmDrum::ComputePhaseIncrement(int16_t midi_pitch) { if (midi_pitch >= kHighestNote) { midi_pitch = kHighestNote - 1; } int32_t ref_pitch = midi_pitch; ref_pitch -= kPitchTableStart; size_t num_shifts = 0; while (ref_pitch < 0) { ref_pitch += kOctave; ++num_shifts; } uint32_t a = lut_oscillator_increments[ref_pitch >> 4]; uint32_t b = lut_oscillator_increments[(ref_pitch >> 4) + 1]; uint32_t phase_increment = a + \ (static_cast(b - a) * (ref_pitch & 0xf) >> 4); phase_increment >>= num_shifts; return phase_increment; } void FmDrum::Process(const GateFlags* gate_flags, int16_t* out, size_t size) { uint32_t am_envelope_increment = ComputeEnvelopeIncrement(am_decay_); uint32_t fm_envelope_increment = ComputeEnvelopeIncrement(fm_decay_); uint32_t phase = phase_; uint32_t fm_envelope_phase = fm_envelope_phase_; uint32_t am_envelope_phase = am_envelope_phase_; uint32_t aux_envelope_phase = aux_envelope_phase_; uint32_t phase_increment = phase_increment_; while (size--) { GateFlags gate_flag = *gate_flags++; if (gate_flag & GATE_FLAG_RISING) { fm_envelope_phase = 0; am_envelope_phase = 0; aux_envelope_phase = 0; phase = 0x3fff * fm_amount_ >> 16; } fm_envelope_phase += fm_envelope_increment; if (fm_envelope_phase < fm_envelope_increment) { fm_envelope_phase = 0xffffffff; } aux_envelope_phase += 4473924; if (aux_envelope_phase < 4473924) { aux_envelope_phase = 0xffffffff; } if ((size & 3) == 0) { uint32_t aux_envelope = 65535 - Interpolate824( lut_env_expo, aux_envelope_phase); uint32_t fm_envelope = 65535 - Interpolate824( lut_env_expo, fm_envelope_phase); phase_increment = ComputePhaseIncrement( frequency_ + \ (fm_envelope * fm_amount_ >> 16) + \ (aux_envelope * aux_envelope_strength_ >> 15) + \ (previous_sample_ >> 6)); } phase += phase_increment; int16_t mix = Interpolate1022(wav_sine, phase); if (noise_) { mix = Mix(mix, Random::GetSample(), noise_); } am_envelope_phase += am_envelope_increment; if (am_envelope_phase < am_envelope_increment) { am_envelope_phase = 0xffffffff; } uint32_t am_envelope = 65535 - Interpolate824( lut_env_expo, am_envelope_phase); mix = mix * am_envelope >> 16; if (overdrive_) { uint32_t phi = (static_cast(mix) << 16) + (1L << 31); int16_t overdriven = Interpolate1022(wav_overdrive, phi); mix = Mix(mix, overdriven, overdrive_); } previous_sample_ = mix; *out++ = mix; } phase_ = phase; fm_envelope_phase_ = fm_envelope_phase; am_envelope_phase_ = am_envelope_phase; aux_envelope_phase_ = aux_envelope_phase; phase_increment_ = phase_increment; } } // namespace peaks ================================================ FILE: lib/peaks/drums/fm_drum.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Sine FM drum - similar to the BD/SD in Anushri. #ifndef PEAKS_DRUMS_FM_DRUM_H_ #define PEAKS_DRUMS_FM_DRUM_H_ #include "stmlib/stmlib.h" #include "peaks/gate_processor.h" namespace peaks { class FmDrum { public: FmDrum() { } ~FmDrum() { } void Init(); void Process(const GateFlags* gate_flags, int16_t* out, size_t size); void Morph(uint16_t x, uint16_t y); void Configure(uint16_t* parameter, ControlMode control_mode) { if (control_mode == CONTROL_MODE_HALF) { Morph(parameter[0], parameter[1]); } else { set_frequency(parameter[0]); set_fm_amount((parameter[1] >> 2) * 3); set_decay(parameter[2]); set_noise(parameter[3]); } } inline void set_sd_range(bool sd_range) { sd_range_ = sd_range; } inline void set_frequency(uint16_t frequency) { if (frequency <= 16384) { aux_envelope_strength_ = 1024; } else if (frequency <= 32768) { aux_envelope_strength_ = 2048 - (frequency >> 4); } else { aux_envelope_strength_ = 0; } frequency_ = (24 << 7) + ((72 << 7) * frequency >> 16); } inline void set_fm_amount(uint16_t fm_amount) { fm_amount_ = fm_amount >> 2; } inline void set_decay(uint16_t decay) { am_decay_ = 16384 + (decay >> 1); fm_decay_ = 8192 + (decay >> 2); } inline void set_noise(uint16_t noise) { uint32_t n = noise; noise_ = noise >= 32768 ? ((n - 32768) * (n - 32768) >> 15) : 0; noise_ = (noise_ >> 2) * 5; overdrive_ = noise <= 32767 ? ((32767 - n) * (32767 - n) >> 14) : 0; } private: bool sd_range_; uint32_t ComputePhaseIncrement(int16_t midi_pitch); uint32_t ComputeEnvelopeIncrement(uint16_t time); uint16_t aux_envelope_strength_; uint16_t frequency_; uint16_t fm_amount_; uint16_t am_decay_; uint16_t fm_decay_; uint16_t noise_; uint16_t overdrive_; int16_t previous_sample_; uint32_t phase_; uint32_t fm_envelope_phase_; uint32_t am_envelope_phase_; uint32_t aux_envelope_phase_; uint32_t phase_increment_; DISALLOW_COPY_AND_ASSIGN(FmDrum); }; } // namespace peaks #endif // PEAKS_DRUMS_FM_DRUM_H_ ================================================ FILE: lib/peaks/drums/high_hat.cc ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808-style HH. #include "peaks/drums/high_hat.h" #include #include "stmlib/utils/dsp.h" #include "stmlib/utils/random.h" #include "peaks/resources.h" namespace peaks { using namespace stmlib; void HighHat::Init() { noise_.Init(); noise_.set_frequency(105 << 7); // 8kHz noise_.set_resonance(24000); vca_coloration_.Init(); vca_coloration_.set_frequency(110 << 7); // 13kHz vca_coloration_.set_resonance(0); vca_envelope_.Init(); vca_envelope_.set_delay(0); vca_envelope_.set_decay(4093); } void HighHat::Process(const GateFlags* gate_flags, int16_t* out, size_t size) { while (size--) { GateFlags gate_flag = *gate_flags++; if (gate_flag & GATE_FLAG_RISING) { vca_envelope_.Trigger(32768 * 15); } phase_[0] += 48318382; phase_[1] += 71582788; phase_[2] += 37044092; phase_[3] += 54313440; phase_[4] += 66214079; phase_[5] += 93952409; int16_t noise = 0; noise += phase_[0] >> 31; noise += phase_[1] >> 31; noise += phase_[2] >> 31; noise += phase_[3] >> 31; noise += phase_[4] >> 31; noise += phase_[5] >> 31; noise <<= 12; // Run the SVF at the double of the original sample rate for stability. int32_t filtered_noise = 0; filtered_noise += noise_.Process(noise); filtered_noise += noise_.Process(noise); // The 808-style VCA amplifies only the positive section of the signal. if (filtered_noise < 0) { filtered_noise = 0; } else if (filtered_noise > 32767) { filtered_noise = 32767; } int32_t envelope = vca_envelope_.Process() >> 4; int32_t vca_noise = envelope * filtered_noise >> 14; CLIP(vca_noise); int32_t hh = 0; hh += vca_coloration_.Process(vca_noise); hh += vca_coloration_.Process(vca_noise); hh <<= 1; CLIP(hh); *out++ = hh; } } } // namespace peaks ================================================ FILE: lib/peaks/drums/high_hat.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808-style HH. #ifndef PEAKS_DRUMS_HIGH_HAT_H_ #define PEAKS_DRUMS_HIGH_HAT_H_ #include "stmlib/stmlib.h" #include "peaks/drums/svf.h" #include "peaks/drums/excitation.h" #include "peaks/gate_processor.h" namespace peaks { class HighHat { public: HighHat() { } ~HighHat() { } void Init(); void Process(const GateFlags* gate_flags, int16_t* out, size_t size); void Configure(uint16_t* parameter, ControlMode control_mode) { vca_envelope_.set_decay(4092 + (parameter[0] >> 14) + 1); } private: Svf noise_; Svf vca_coloration_; Excitation vca_envelope_; uint32_t phase_[6]; DISALLOW_COPY_AND_ASSIGN(HighHat); }; } // namespace peaks #endif // PEAKS_DRUMS_HIGH_HAT_H_ ================================================ FILE: lib/peaks/drums/snare_drum.cc ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808-style snare drum. #include "peaks/drums/snare_drum.h" #include #include "stmlib/utils/dsp.h" #include "stmlib/utils/random.h" #include "peaks/resources.h" namespace peaks { using namespace stmlib; void SnareDrum::Init() { excitation_1_up_.Init(); excitation_1_up_.set_delay(0); excitation_1_up_.set_decay(1536); excitation_1_down_.Init(); excitation_1_down_.set_delay(1e-3 * 48000); excitation_1_down_.set_decay(3072); excitation_2_.Init(); excitation_2_.set_delay(1e-3 * 48000); excitation_2_.set_decay(1200); excitation_noise_.Init(); excitation_noise_.set_delay(0); body_1_.Init(); body_2_.Init(); noise_.Init(); noise_.set_resonance(2000); set_tone(0); set_snappy(32768); set_decay(32768); set_frequency(0); } void SnareDrum::Process( const GateFlags* gate_flags, int16_t* out, size_t size) { while (size--) { GateFlags gate_flag = *gate_flags++; if (gate_flag & GATE_FLAG_RISING) { excitation_1_up_.Trigger(15 * 32768); excitation_1_down_.Trigger(-1 * 32768); excitation_2_.Trigger(13107); excitation_noise_.Trigger(snappy_); } int32_t excitation_1 = 0; excitation_1 += excitation_1_up_.Process(); excitation_1 += excitation_1_down_.Process(); excitation_1 += !excitation_1_down_.done() ? 2621 : 0; int32_t body_1 = body_1_.Process(excitation_1) + (excitation_1 >> 4); int32_t excitation_2 = 0; excitation_2 += excitation_2_.Process(); excitation_2 += !excitation_2_.done() ? 13107 : 0; int32_t body_2 = body_2_.Process(excitation_2) + (excitation_2 >> 4); int32_t noise_sample = Random::GetSample(); int32_t noise = noise_.Process(noise_sample); int32_t noise_envelope = excitation_noise_.Process(); int32_t sd = 0; sd += body_1 * gain_1_ >> 15; sd += body_2 * gain_2_ >> 15; sd += noise_envelope * noise >> 15; CLIP(sd); *out++ = sd; } } } // namespace peaks ================================================ FILE: lib/peaks/drums/snare_drum.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808-style snare drum. #ifndef PEAKS_DRUMS_SNARE_DRUM_H_ #define PEAKS_DRUMS_SNARE_DRUM_H_ #include "stmlib/stmlib.h" #include "peaks/drums/svf.h" #include "peaks/drums/excitation.h" #include #include "peaks/gate_processor.h" namespace peaks { class SnareDrum { public: SnareDrum() { } ~SnareDrum() { } void Init(); void Process(const GateFlags* gate_flags, int16_t* out, size_t size); void Configure(uint16_t* parameter, ControlMode control_mode) { if (control_mode == CONTROL_MODE_HALF) { set_frequency(0); set_decay(32768); set_tone(parameter[0]); set_snappy(parameter[1]); } else { set_frequency(parameter[0] - 32768); set_tone(parameter[1]); set_snappy(parameter[2]); set_decay(parameter[3]); } } void set_tone(uint16_t tone) { gain_1_ = 22000 - (tone >> 2); gain_2_ = 22000 + (tone >> 2); } void set_snappy(uint16_t snappy) { snappy >>= 1; if (snappy >= 28672) { snappy = 28672; } snappy_ = 512 + snappy; } void set_decay(uint16_t decay) { body_1_.set_resonance(29000 + (decay >> 5)); body_2_.set_resonance(26500 + (decay >> 5)); excitation_noise_.set_decay(4092 + (decay >> 14)); } void set_frequency(int16_t frequency) { int16_t base_note = 52 << 7; int32_t transposition = frequency; base_note += transposition * 896 >> 15; body_1_.set_frequency(base_note); body_2_.set_frequency(base_note + (12 << 7)); noise_.set_frequency(base_note + (48 << 7)); } private: Excitation excitation_1_up_; Excitation excitation_1_down_; Excitation excitation_2_; Excitation excitation_noise_; Svf body_1_; Svf body_2_; Svf noise_; int32_t gain_1_; int32_t gain_2_; uint16_t snappy_; DISALLOW_COPY_AND_ASSIGN(SnareDrum); }; } // namespace peaks #endif // PEAKS_DRUMS_SNARE_DRUM_H_ ================================================ FILE: lib/peaks/drums/svf.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // SVF used for modeling the bridged T-networks. #ifndef PEAKS_DRUMS_SVF_H_ #define PEAKS_DRUMS_SVF_H_ #include "stmlib/stmlib.h" #include "stmlib/utils/dsp.h" #include "peaks/resources.h" namespace peaks { enum SvfMode { SVF_MODE_LP, SVF_MODE_BP, SVF_MODE_HP }; class Svf { public: Svf() { } ~Svf() { } inline void Init() { lp_ = 0; bp_ = 0; frequency_ = 33 << 7; resonance_ = 16384; dirty_ = true; punch_ = 0; } inline void set_frequency(int16_t frequency) { dirty_ = dirty_ || (frequency_ != frequency); frequency_ = frequency; } inline void set_resonance(int16_t resonance) { resonance_ = resonance; dirty_ = true; } inline void set_punch(uint16_t punch) { punch_ = (static_cast(punch) * punch) >> 24; } template inline int32_t Process(int32_t in) { if (dirty_) { f_ = stmlib::Interpolate824(lut_svf_cutoff, frequency_ << 17); damp_ = stmlib::Interpolate824(lut_svf_damp, resonance_ << 17); dirty_ = false; } int32_t f = f_; int32_t damp = damp_; if (punch_) { int32_t punch_signal = lp_ > 4096 ? lp_ : 2048; f += ((punch_signal >> 4) * punch_) >> 9; damp += ((punch_signal - 2048) >> 3); } int32_t notch = in - (bp_ * damp >> 15); lp_ += f * bp_ >> 15; CLIP(lp_) int32_t hp = notch - lp_; bp_ += f * hp >> 15; CLIP(bp_) return mode == SVF_MODE_BP ? bp_ : (mode == SVF_MODE_HP ? hp : lp_); } private: bool dirty_; int16_t frequency_; int16_t resonance_; int32_t punch_; int32_t f_; int32_t damp_; int32_t lp_; int32_t bp_; SvfMode mode_; DISALLOW_COPY_AND_ASSIGN(Svf); }; } // namespace peaks #endif // PEAKS_DRUMS_SVF_H_ ================================================ FILE: lib/peaks/gate_processor.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // General declarations used by all trigger/gate processors. #ifndef PEAKS_GATE_PROCESSOR_H_ #define PEAKS_GATE_PROCESSOR_H_ #include "stmlib/stmlib.h" #include "stmlib/utils/ring_buffer.h" namespace peaks { enum ControlMode { CONTROL_MODE_FULL, CONTROL_MODE_HALF }; enum GateFlagsBits { GATE_FLAG_LOW = 0, GATE_FLAG_HIGH = 1, GATE_FLAG_RISING = 2, GATE_FLAG_FALLING = 4, GATE_FLAG_FROM_BUTTON = 8, GATE_FLAG_AUXILIARY_LOW = 0, GATE_FLAG_AUXILIARY_HIGH = 16, GATE_FLAG_AUXILIARY_RISING = 32, GATE_FLAG_AUXILIARY_FALLING = 64, }; typedef uint8_t GateFlags; inline GateFlags ExtractGateFlags(GateFlags previous, bool current) { previous &= GATE_FLAG_HIGH; if (current) { return previous ? GATE_FLAG_HIGH : (GATE_FLAG_RISING | GATE_FLAG_HIGH); } else { return previous ? GATE_FLAG_FALLING : GATE_FLAG_LOW; } } } // namespace peaks #endif // PEAKS_GATE_PROCESSOR_H_ ================================================ FILE: lib/peaks/modulations/bouncing_ball.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Bouncing ball. #ifndef PEAKS_MODULATIONS_BOUNCING_BALL_H_ #define PEAKS_MODULATIONS_BOUNCING_BALL_H_ #include "stmlib/stmlib.h" #include #include "stmlib/utils/dsp.h" #include "peaks/resources.h" #include "peaks/gate_processor.h" namespace peaks { class BouncingBall { public: BouncingBall() { } ~BouncingBall() { } void Init() { initial_amplitude_ = 65535L << 14; gravity_ = 40; bounce_loss_ = 4095; initial_velocity_ = 0; } void Configure(uint16_t* parameter, ControlMode control_mode) { if (control_mode == CONTROL_MODE_HALF) { set_initial_amplitude(65535); set_initial_velocity(0); set_gravity(parameter[0]); set_bounce_loss(parameter[1]); } else { set_gravity(parameter[0]); set_bounce_loss(parameter[1]); set_initial_amplitude(parameter[2]); set_initial_velocity(parameter[3] - 32768); } } void Process(const GateFlags* gate_flags, int16_t* out, size_t size) { while (size--) { GateFlags gate_flag = *gate_flags++; if (gate_flag & GATE_FLAG_RISING) { velocity_ = initial_velocity_; position_ = initial_amplitude_; } velocity_ -= gravity_; position_ += velocity_; if (position_ < 0) { position_ = 0; velocity_ = -(velocity_ >> 12) * bounce_loss_; } if (position_ > (32767L << 15)) { position_ = 32767L << 15; velocity_ = -(velocity_ >> 12) * bounce_loss_; } *out++ = position_ >> 15; } } inline void set_gravity(uint16_t gravity) { gravity_ = stmlib::Interpolate88(lut_gravity, gravity); } inline void set_bounce_loss(uint16_t bounce_loss) { uint32_t b = 65535 - bounce_loss; b = b * b >> 16; bounce_loss_ = 4095 - (b >> 4); } inline void set_initial_amplitude(uint16_t initial_amplitude) { initial_amplitude_ = static_cast(initial_amplitude) << 14; } inline void set_initial_velocity(int16_t initial_velocity) { initial_velocity_ = static_cast(initial_velocity) << 4; } inline bool FillBuffer() const { return true; } private: int32_t gravity_; int32_t bounce_loss_; int32_t initial_amplitude_; int32_t initial_velocity_; int32_t velocity_; int32_t position_; DISALLOW_COPY_AND_ASSIGN(BouncingBall); }; } // namespace peaks #endif // PEAKS_MODULATIONS_BOUNCING_BALL_H_ ================================================ FILE: lib/peaks/modulations/lfo.cc ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // LFO. #include "peaks/modulations/lfo.h" #include #include "stmlib/utils/dsp.h" #include "stmlib/utils/random.h" #include "peaks/resources.h" namespace peaks { const uint16_t kSlopeBits = 12; const uint32_t kSyncCounterMaxTime = 8 * 48000; using namespace stmlib; void Lfo::Init() { rate_ = 0; shape_ = LFO_SHAPE_SQUARE; parameter_ = 0; reset_phase_ = 0; sync_ = false; previous_parameter_ = 32767; sync_counter_ = kSyncCounterMaxTime; level_ = 32767; pattern_predictor_.Init(); } const int16_t presets[7][2] = { { LFO_SHAPE_SINE, 0 }, { LFO_SHAPE_TRIANGLE, 0 }, { LFO_SHAPE_TRIANGLE, 32767 }, { LFO_SHAPE_SQUARE, 0 }, { LFO_SHAPE_STEPS, 0 }, { LFO_SHAPE_NOISE, -32767 }, { LFO_SHAPE_NOISE, 32767 }, }; void Lfo::set_shape_parameter_preset(uint16_t value) { value = (value >> 8) * 7 >> 8; set_shape(static_cast(presets[value][0])); set_parameter(presets[value][1]); } void Lfo::Process(const GateFlags* gate_flags, int16_t* out, size_t size) { if (!sync_) { int32_t a = lut_lfo_increments[rate_ >> 8]; int32_t b = lut_lfo_increments[(rate_ >> 8) + 1]; phase_increment_ = a + (((b - a) >> 1) * (rate_ & 0xff) >> 7); } while (size--) { ++sync_counter_; GateFlags gate_flag = *gate_flags++; if (gate_flag & GATE_FLAG_RISING) { bool reset_phase = true; if (sync_) { if (sync_counter_ < kSyncCounterMaxTime) { uint32_t period = 0; if (gate_flag & GATE_FLAG_FROM_BUTTON) { period = sync_counter_; } else if (sync_counter_ < 1920) { period = (3 * period_ + sync_counter_) >> 2; reset_phase = false; } else { period = pattern_predictor_.Predict(sync_counter_); } if (period != period_) { period_ = period; phase_increment_ = 0xffffffff / period_; } } sync_counter_ = 0; } if (reset_phase) { phase_ = reset_phase_; } } phase_ += phase_increment_; int32_t sample = (this->*compute_sample_fn_table_[shape_])(); *out++ = sample * level_ >> 15; } } int16_t Lfo::ComputeSampleSine() { uint32_t phase = phase_; int16_t sine = Interpolate1022(wav_sine, phase); int16_t sample; if (parameter_ > 0) { int32_t wf_balance = parameter_; int32_t wf_gain = 2048 + \ (static_cast(parameter_) * (65535 - 2048) >> 15); int32_t original = sine; int32_t folded = Interpolate1022( wav_fold_sine, original * wf_gain + (1UL << 31)); sample = original + ((folded - original) * wf_balance >> 15); } else { int32_t wf_balance = -parameter_; int32_t original = sine; phase += 1UL << 30; int32_t tri = phase < (1UL << 31) ? phase << 1 : ~(phase << 1); int32_t folded = Interpolate1022(wav_fold_power, tri); sample = original + ((folded - original) * wf_balance >> 15); } return sample; } int16_t Lfo::ComputeSampleTriangle() { if (parameter_ != previous_parameter_) { uint16_t slope_offset = parameter_ + 32768; if (slope_offset <= 1) { decay_factor_ = 32768 << kSlopeBits; attack_factor_ = 1 << (kSlopeBits - 1); } else { decay_factor_ = (32768 << kSlopeBits) / slope_offset; attack_factor_ = (32768 << kSlopeBits) / (65536 - slope_offset); } end_of_attack_ = (static_cast(slope_offset) << 16); previous_parameter_ = parameter_; } uint32_t phase = phase_; uint32_t skewed_phase = phase; if (phase < end_of_attack_) { skewed_phase = (phase >> kSlopeBits) * decay_factor_; } else { skewed_phase = ((phase - end_of_attack_) >> kSlopeBits) * attack_factor_; skewed_phase += 1L << 31; } return skewed_phase < 1UL << 31 ? -32768 + (skewed_phase >> 15) : 32767 - (skewed_phase >> 15); } int16_t Lfo::ComputeSampleSquare() { uint32_t threshold = static_cast(parameter_ + 32768) << 16; if (threshold < (phase_increment_ << 1)) { threshold = phase_increment_ << 1; } else if (~threshold < (phase_increment_ << 1)) { threshold = ~(phase_increment_ << 1); } return phase_ < threshold ? 32767 : -32767; } int16_t Lfo::ComputeSampleSteps() { uint16_t quantization_levels = 2 + (((parameter_ + 32768) * 15) >> 16); uint16_t scale = 65535 / (quantization_levels - 1); uint32_t phase = phase_; uint32_t tri_phase = phase; uint32_t tri = tri_phase < (1UL << 31) ? tri_phase << 1 : ~(tri_phase << 1); return ((tri >> 16) * quantization_levels >> 16) * scale - 32768; } int16_t Lfo::ComputeSampleNoise() { uint32_t phase = phase_; if (phase < phase_increment_) { value_ = next_value_; next_value_ = Random::GetSample(); } int16_t sample; int32_t linear_interpolation = value_ + \ ((next_value_ - value_) * static_cast(phase >> 17) >> 15); if (parameter_ < 0) { int32_t balance = parameter_ + 32767; sample = value_ + ((linear_interpolation - value_) * balance >> 15); } else { int16_t raised_cosine = Interpolate824(lut_raised_cosine, phase) >> 1; int32_t smooth_interpolation = value_ + \ ((next_value_ - value_) * raised_cosine >> 15); sample = linear_interpolation + \ ((smooth_interpolation - linear_interpolation) * parameter_ >> 15); } return sample; } /* static */ Lfo::ComputeSampleFn Lfo::compute_sample_fn_table_[] = { &Lfo::ComputeSampleSine, &Lfo::ComputeSampleTriangle, &Lfo::ComputeSampleSquare, &Lfo::ComputeSampleSteps, &Lfo::ComputeSampleNoise }; } // namespace peaks ================================================ FILE: lib/peaks/modulations/lfo.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // LFO. #ifndef PEAKS_MODULATIONS_LFO_H_ #define PEAKS_MODULATIONS_LFO_H_ #include "stmlib/stmlib.h" #include "stmlib/algorithms/pattern_predictor.h" #include "peaks/gate_processor.h" namespace peaks { enum LfoShape { LFO_SHAPE_SINE, LFO_SHAPE_TRIANGLE, LFO_SHAPE_SQUARE, LFO_SHAPE_STEPS, LFO_SHAPE_NOISE, LFO_SHAPE_LAST }; class Lfo { public: typedef int16_t (Lfo::*ComputeSampleFn)(); Lfo() { } ~Lfo() { } void Init(); void Process(const GateFlags* gate_flags, int16_t* out, size_t size); void Configure(uint16_t* parameter, ControlMode control_mode) { if (control_mode == CONTROL_MODE_HALF) { if (sync_) { set_shape_integer(parameter[0]); set_parameter(parameter[1] - 32768); } else { set_rate(parameter[0]); set_shape_parameter_preset(parameter[1]); } set_reset_phase(0); set_level(40960); } else { if (sync_) { set_level(parameter[0]); set_shape_integer(parameter[1]); set_parameter(parameter[2] - 32768); set_reset_phase(parameter[3] - 32768); } else { set_level(40960); set_rate(parameter[0]); set_shape_integer(parameter[1]); set_parameter(parameter[2] - 32768); set_reset_phase(parameter[3] - 32768); } } } inline void set_rate(uint16_t rate) { rate_ = rate; } inline void set_shape(LfoShape shape) { shape_ = shape; } inline void set_shape_integer(uint16_t value) { shape_ = static_cast(value * LFO_SHAPE_LAST >> 16); } void set_shape_parameter_preset(uint16_t value); inline void set_parameter(int16_t parameter) { parameter_ = parameter; } inline void set_reset_phase(int16_t reset_phase) { reset_phase_ = static_cast(reset_phase) << 16; } inline void set_sync(bool sync) { if (!sync_ && sync) { pattern_predictor_.Init(); } sync_ = sync; } inline void set_level(uint16_t level) { level_ = level >> 1; } private: int16_t ComputeSampleSine(); int16_t ComputeSampleTriangle(); int16_t ComputeSampleSquare(); int16_t ComputeSampleSteps(); int16_t ComputeSampleNoise(); uint16_t rate_; LfoShape shape_; int16_t parameter_; int32_t reset_phase_; int32_t level_; bool sync_; uint32_t sync_counter_; stmlib::PatternPredictor<32, 8> pattern_predictor_; uint32_t phase_; uint32_t phase_increment_; uint32_t period_; uint32_t end_of_attack_; uint32_t attack_factor_; uint32_t decay_factor_; int16_t previous_parameter_; int32_t value_; int32_t next_value_; static ComputeSampleFn compute_sample_fn_table_[]; DISALLOW_COPY_AND_ASSIGN(Lfo); }; } // namespace peaks #endif // PEAKS_MODULATIONS_LFO_H_ ================================================ FILE: lib/peaks/modulations/mini_sequencer.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Mini sequencer. #ifndef PEAKS_MODULATIONS_MINI_SEQUENCER_H_ #define PEAKS_MODULATIONS_MINI_SEQUENCER_H_ #include "stmlib/stmlib.h" #include #include "peaks/gate_processor.h" namespace peaks { const uint8_t kMaxNumSteps = 4; class MiniSequencer { public: MiniSequencer() { } ~MiniSequencer() { } void Init() { std::fill(&steps_[0], &steps_[kMaxNumSteps], 0); num_steps_ = 4; step_ = 0; reset_at_next_clock_ = false; } inline void set_step(uint8_t index, int16_t value) { int32_t difference = abs(int32_t(steps_[index]) - value); if (difference > 0) { steps_[index] = value; } } inline void set_num_steps(uint8_t num_steps) { num_steps_ = num_steps; } void Configure(uint16_t* parameter, ControlMode control_mode) { if (control_mode == CONTROL_MODE_HALF) { set_step(0, parameter[0] - 32768); set_step(1, parameter[1] - 32768); set_num_steps(2); } else { set_step(0, parameter[0] - 32768); set_step(1, parameter[1] - 32768); set_step(2, parameter[2] - 32768); set_step(3, parameter[3] - 32768); set_num_steps(4); } } void Process(const GateFlags* gate_flags, int16_t* out, size_t size) { while (size--) { GateFlags gate_flag = *gate_flags++; if (gate_flag & GATE_FLAG_RISING) { ++step_; if (reset_at_next_clock_) { reset_at_next_clock_ = false; step_ = 0; } } if (num_steps_ > 2 && gate_flag & GATE_FLAG_AUXILIARY_RISING) { reset_at_next_clock_ = true; } if (step_ >= num_steps_) { step_ = 0; } *out++ = static_cast(steps_[step_]) * 40960 >> 16; } } private: uint8_t num_steps_; uint8_t step_; int16_t steps_[kMaxNumSteps]; bool reset_at_next_clock_; DISALLOW_COPY_AND_ASSIGN(MiniSequencer); }; } // namespace peaks #endif // PEAKS_MODULATIONS_MINI_SEQUENCER_H_ ================================================ FILE: lib/peaks/modulations/multistage_envelope.cc ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Multistage envelope. #include "peaks/modulations/multistage_envelope.h" #include "stmlib/utils/dsp.h" #include "peaks/resources.h" namespace peaks { using namespace stmlib; void MultistageEnvelope::Init() { set_adsr(0, 8192, 16384, 32767); segment_ = num_segments_; phase_ = 0; phase_increment_ = 0; start_value_ = 0; value_ = 0; hard_reset_ = false; } void MultistageEnvelope::Process( const GateFlags* gate_flags, int16_t* out, size_t size) { while (size--) { GateFlags gate_flag = *gate_flags++; if (gate_flag & GATE_FLAG_RISING) { start_value_ = (segment_ == num_segments_ || hard_reset_) ? level_[0] : value_; segment_ = 0; phase_ = 0; } else if (gate_flag & GATE_FLAG_FALLING && sustain_point_) { start_value_ = value_; segment_ = sustain_point_; phase_ = 0; } else if (phase_ < phase_increment_) { start_value_ = level_[segment_ + 1]; ++segment_; phase_ = 0; if (segment_ == loop_end_) { segment_ = loop_start_; } } bool done = segment_ == num_segments_; bool sustained = sustain_point_ && segment_ == sustain_point_ && gate_flag & GATE_FLAG_HIGH; phase_increment_ = sustained || done ? 0 : lut_env_increments[time_[segment_] >> 8]; int32_t a = start_value_; int32_t b = level_[segment_ + 1]; //eh2k >>> const uint16_t * lutt[] = { lut_env_linear, lut_env_expo, lut_env_quartic }; //<<< uint16_t t = Interpolate824(lutt[shape_[segment_]], phase_); value_ = a + ((b - a) * (t >> 1) >> 15); phase_ += phase_increment_; *out++ = value_; } } } // namespace peaks ================================================ FILE: lib/peaks/modulations/multistage_envelope.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Multistage envelope. #ifndef PEAKS_MODULATIONS_MULTISTAGE_ENVELOPE_H_ #define PEAKS_MODULATIONS_MULTISTAGE_ENVELOPE_H_ #include "stmlib/stmlib.h" #include "stmlib/utils/ring_buffer.h" #include "peaks/gate_processor.h" namespace peaks { enum EnvelopeShape { ENV_SHAPE_LINEAR, ENV_SHAPE_EXPONENTIAL, ENV_SHAPE_QUARTIC }; const uint16_t kMaxNumSegments = 8; class MultistageEnvelope { public: MultistageEnvelope() { } ~MultistageEnvelope() { } void Init(); void Process(const GateFlags* gate_flags, int16_t* out, size_t size); void Configure(uint16_t* parameter, ControlMode control_mode) { if (control_mode == CONTROL_MODE_HALF) { set_ad(parameter[0], parameter[1]); } else { set_adsr(parameter[0], parameter[1], parameter[2] >> 1, parameter[3]); } if (segment_ > num_segments_) { segment_ = 0; phase_ = 0; value_ = 0; } } inline void set_time(uint16_t segment, uint16_t time) { time_[segment] = time; } inline void set_level(uint16_t segment, int16_t level) { level_[segment] = level; } inline void set_num_segments(uint16_t num_segments) { num_segments_ = num_segments; } inline void set_sustain_point(uint16_t sustain_point) { sustain_point_ = sustain_point; } inline void set_adsr( uint16_t attack, uint16_t decay, uint16_t sustain, uint16_t release) { num_segments_ = 3; sustain_point_ = 2; level_[0] = 0; level_[1] = 32767; level_[2] = sustain; level_[3] = 0; time_[0] = attack; time_[1] = decay; time_[2] = release; shape_[0] = ENV_SHAPE_QUARTIC; shape_[1] = ENV_SHAPE_EXPONENTIAL; shape_[2] = ENV_SHAPE_EXPONENTIAL; loop_start_ = loop_end_ = 0; } inline void set_ad(uint16_t attack, uint16_t decay) { num_segments_ = 2; sustain_point_ = 0; level_[0] = 0; level_[1] = 32767; level_[2] = 0; time_[0] = attack; time_[1] = decay; shape_[0] = ENV_SHAPE_EXPONENTIAL; shape_[1] = ENV_SHAPE_EXPONENTIAL; loop_start_ = loop_end_ = 0; } inline void set_adr( uint16_t attack, uint16_t decay, uint16_t sustain, uint16_t release) { num_segments_ = 3; sustain_point_ = 0; level_[0] = 0; level_[1] = 32767; level_[2] = sustain; level_[3] = 0; time_[0] = attack; time_[1] = decay; time_[2] = release; shape_[0] = ENV_SHAPE_LINEAR; shape_[1] = ENV_SHAPE_LINEAR; shape_[2] = ENV_SHAPE_LINEAR; loop_start_ = loop_end_ = 0; } inline void set_ar(uint16_t attack, uint16_t decay) { num_segments_ = 2; sustain_point_ = 1; level_[0] = 0; level_[1] = 32767; level_[2] = 0; time_[0] = attack; time_[1] = decay; shape_[0] = ENV_SHAPE_LINEAR; shape_[1] = ENV_SHAPE_LINEAR; loop_start_ = loop_end_ = 0; } inline void set_adsar( uint16_t attack, uint16_t decay, uint16_t sustain, uint16_t release) { num_segments_ = 4; sustain_point_ = 2; level_[0] = 0; level_[1] = 32767; level_[2] = sustain; level_[3] = 32767; level_[4] = 0; time_[0] = attack; time_[1] = decay; time_[2] = attack; time_[3] = release; shape_[0] = ENV_SHAPE_LINEAR; shape_[1] = ENV_SHAPE_LINEAR; shape_[2] = ENV_SHAPE_LINEAR; shape_[3] = ENV_SHAPE_LINEAR; loop_start_ = loop_end_ = 0; } inline void set_adar( uint16_t attack, uint16_t decay, uint16_t sustain, uint16_t release) { num_segments_ = 4; sustain_point_ = 0; level_[0] = 0; level_[1] = 32767; level_[2] = sustain; level_[3] = 32767; level_[4] = 0; time_[0] = attack; time_[1] = decay; time_[2] = attack; time_[3] = release; shape_[0] = ENV_SHAPE_LINEAR; shape_[1] = ENV_SHAPE_LINEAR; shape_[2] = ENV_SHAPE_LINEAR; shape_[3] = ENV_SHAPE_LINEAR; loop_start_ = loop_end_ = 0; } inline void set_ad_loop(uint16_t attack, uint16_t decay) { num_segments_ = 2; sustain_point_ = 0; level_[0] = 0; level_[1] = 32767; level_[2] = 0; time_[0] = attack; time_[1] = decay; shape_[0] = ENV_SHAPE_LINEAR; shape_[1] = ENV_SHAPE_LINEAR; loop_start_ = 0; loop_end_ = 2; } inline void set_adr_loop( uint16_t attack, uint16_t decay, uint16_t sustain, uint16_t release) { num_segments_ = 3; sustain_point_ = 0; level_[0] = 0; level_[1] = 32767; level_[2] = sustain; level_[3] = 0; time_[0] = attack; time_[1] = decay; time_[2] = release; shape_[0] = ENV_SHAPE_LINEAR; shape_[1] = ENV_SHAPE_LINEAR; shape_[2] = ENV_SHAPE_LINEAR; loop_start_ = 0; loop_end_ = 3; } inline void set_adar_loop( uint16_t attack, uint16_t decay, uint16_t sustain, uint16_t release) { num_segments_ = 4; sustain_point_ = 0; level_[0] = 0; level_[1] = 32767; level_[2] = sustain; level_[3] = 32767; level_[4] = 0; time_[0] = attack; time_[1] = decay; time_[2] = attack; time_[3] = release; shape_[0] = ENV_SHAPE_LINEAR; shape_[1] = ENV_SHAPE_LINEAR; shape_[2] = ENV_SHAPE_LINEAR; shape_[3] = ENV_SHAPE_LINEAR; loop_start_ = 0; loop_end_ = 4; } inline void set_hard_reset(bool hard_reset) { hard_reset_ = hard_reset; } private: int16_t level_[kMaxNumSegments]; uint16_t time_[kMaxNumSegments]; EnvelopeShape shape_[kMaxNumSegments]; int16_t segment_; int16_t start_value_; int16_t value_; uint32_t phase_; uint32_t phase_increment_; uint16_t num_segments_; uint16_t sustain_point_; uint16_t loop_start_; uint16_t loop_end_; bool hard_reset_; DISALLOW_COPY_AND_ASSIGN(MultistageEnvelope); }; } // namespace peaks #endif // PEAKS_MODULATIONS_MULTISTAGE_ENVELOPE_H_ ================================================ FILE: lib/peaks/number_station/number_station.cc ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Number station. #include "peaks/number_station/number_station.h" #include "stmlib/utils/dsp.h" #include "stmlib/utils/random.h" #include "peaks/resources.h" namespace peaks { const uint8_t kDownsample = 4; using namespace stmlib; void NumberStation::Init() { tone_amplitude_ = 0; phase_ = 0; lp_.Init(); lp_.set_frequency(120 << 7); lp_.set_resonance(16000); hp_.Init(); hp_.set_frequency(70 << 7); hp_.set_resonance(8000); previous_inner_sample_ = 0; previous_outer_sample_ = 0; } size_t voice_digits[] = { 0, 4913, 7830, 11306, 14601, 18651, 22308, 26438, 30495, 33296, 36801 }; void NumberStation::Process( const GateFlags* gate_flags, int16_t* out, size_t size) { uint32_t phase_increment; if (voice_) { phase_increment = pitch_shift_; } else { uint16_t frequency = tone_; int32_t a = lut_lfo_increments[frequency >> 8]; int32_t b = lut_lfo_increments[(frequency >> 8) + 1]; phase_increment = a + (((b - a) >> 1) * (frequency & 0xff) >> 7); phase_increment <<= 6; phase_increment *= digit_ + 1; } int32_t drift_target = Random::GetSample(); if (drift_target > drift_) { drift_ += (drift_target - drift_) >> 13; } else { drift_ -= (drift_ - drift_target) >> 13; } int32_t slow_noise = drift_ << 5; CLIP(slow_noise); size /= kDownsample; while (size--) { for (uint8_t i = 0; i < kDownsample; ++i) { GateFlags gate_flag = *gate_flags++; if (gate_flag & GATE_FLAG_RISING) { uint16_t random = Random::GetSample(); if (random < transition_probability_) { digit_ = random >> 2; digit_ = voice_ ? digit_ % 10 : digit_ & 3; } if (voice_) { phase_ = voice_digits[digit_] << 16; } } if (gate_flag & GATE_FLAG_HIGH) { tone_amplitude_ += (32767 - tone_amplitude_) >> 6; } else { tone_amplitude_ -= tone_amplitude_ >> 6; if (tone_amplitude_ < 64 && tone_amplitude_) { --tone_amplitude_; } } } // Generate a distorted sine wave with fluctuating frequency. int32_t digit; if (voice_) { uint16_t integral = phase_ >> 16; uint16_t fractional = phase_ & 0xffff; if (integral < voice_digits[digit_ + 1]) { uint8_t mask_a = integral * 53; uint8_t mask_b = mask_a + 53; int32_t a = static_cast(wav_digits[integral] ^ mask_a); int32_t b = static_cast(wav_digits[integral + 1] ^ mask_b); digit = (a << 8) + (((b - a) * fractional) >> 8); digit -= 32768; phase_ += phase_increment; gate_ = true; } else { digit = 0; gate_ = false; } } else { phase_ += phase_increment + (lp_noise_ << 10); digit = Interpolate1022(wav_sine, phase_); digit = digit * tone_amplitude_ >> 16; gate_ = tone_amplitude_ > 0; } digit = digit + ((digit - ((digit + 4096) ^ 0x055a)) * distortion_ >> 15); // Generate narrow-band noise. int32_t random_sample = Random::GetSample(); lp_noise_ += (random_sample - lp_noise_) >> 6; noise_phase_ += 238370685; int32_t noise = lp_noise_ * Interpolate1022(wav_sine, noise_phase_) >> 12; // Generate an interference tone. interference_phase_ += 710101260; noise += distortion_ * wav_sine[interference_phase_ >> 22] >> 18; // Mix signal and noise. int32_t inner_sample = digit + ((noise - digit) * noise_ >> 15); if (random_sample >= 32767 - (noise_ >> 7)) { inner_sample = 0; } // Final ringmod. ringmod_phase_ += 38654706 + (38654706 * drift_ >> 10); int32_t ringmod = Interpolate1022(wav_sine, ringmod_phase_) >> 1; ringmod = ringmod * inner_sample >> 15; inner_sample += ringmod * distortion_ >> 15; CLIP(inner_sample) // And a pass of wavefolding... inner_sample = Interpolate1022( wav_fold_sine, inner_sample * 8192 + (1UL << 31)); int32_t outer_sample ; outer_sample = lp_.Process( hp_.Process((inner_sample + previous_inner_sample_) >> 1)); *out++ = (previous_outer_sample_ + outer_sample) >> 1; *out++ = outer_sample; previous_outer_sample_ = outer_sample; outer_sample = lp_.Process( hp_.Process(inner_sample)); *out++ = (previous_outer_sample_ + outer_sample) >> 1; *out++ = outer_sample; previous_outer_sample_ = outer_sample; previous_inner_sample_ = inner_sample; } } } // namespace peaks ================================================ FILE: lib/peaks/number_station/number_station.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Number station. #ifndef PEAKS_NUMBER_STATION_NUMBER_STATION_H_ #define PEAKS_NUMBER_STATION_NUMBER_STATION_H_ #include "stmlib/stmlib.h" #include "peaks/drums/svf.h" #include "peaks/gate_processor.h" namespace peaks { class NumberStation { public: NumberStation() { } ~NumberStation() { } void Init(); void Process(const GateFlags* gate_flags, int16_t* out, size_t size); void Configure(uint16_t* parameter, ControlMode control_mode) { if (control_mode == CONTROL_MODE_HALF) { set_tone(parameter[0]); set_transition_probability(parameter[1]); set_noise(32768); set_distortion(32768); } else { set_tone(parameter[0]); set_transition_probability(parameter[1]); set_noise(parameter[2]); set_distortion(parameter[3]); } } inline void set_tone(uint16_t tone) { tone_ = (tone >> 2) + 32768 + 8192; pitch_shift_ = (tone < 32768) ? (24576 + (tone >> 2)) : 16384 + (tone >> 1); } inline void set_transition_probability(uint16_t transition_probability) { transition_probability_ = transition_probability; } inline void set_distortion(uint16_t distortion) { distortion_ = 8192; distortion_ += ((32767 - 8192) * static_cast(distortion) >> 16); } inline void set_noise(uint16_t noise) { noise_ = 256 + (noise >> 3); } inline void set_voice(bool voice) { voice_ = voice; } inline uint8_t digit() const { return digit_; } inline bool gate() const { return gate_; } private: uint16_t tone_; uint16_t pitch_shift_; uint16_t transition_probability_; int32_t distortion_; int32_t noise_; uint8_t digit_; int32_t drift_; uint32_t phase_; uint32_t noise_phase_; uint32_t ringmod_phase_; uint32_t interference_phase_; int16_t tone_amplitude_; int32_t lp_noise_; int32_t previous_inner_sample_; int32_t previous_outer_sample_; bool voice_; bool gate_; Svf lp_; Svf hp_; DISALLOW_COPY_AND_ASSIGN(NumberStation); }; } // namespace peaks #endif // PEAKS_NUMBER_STATION_NUMBER_STATION_H_ ================================================ FILE: lib/peaks/pulse_processor/pulse_randomizer.cc ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Create random repetitions of a pulse. #include "peaks/pulse_processor/pulse_randomizer.h" #include #include "stmlib/utils/dsp.h" #include "stmlib/utils/random.h" #include "peaks/resources.h" namespace peaks { using namespace stmlib; void PulseRandomizer::Init() { repetition_probability_ = 32767; acceptance_probability_ = 65535; delay_average_ = 32767; delay_randomness_ = 0; std::fill( &delay_counter_[0], &delay_counter_[kTriggerPulseBufferSize], 0xffff); num_pulses_ = 0; retrig_counter_ = 0; } inline uint16_t PulseRandomizer::delay() const { int32_t delay = delay_average_; delay += delay_average_ + (Random::GetSample() * delay_randomness_ >> 16); if (delay < 0) { delay = 0; } else if (delay > 0xffff) { delay = 0xffff; } return Interpolate88(lut_delay_times, delay); } void PulseRandomizer::Process( const GateFlags* gate_flags, int16_t* out, size_t size) { bool new_pulse = false; for (size_t i = 0; i < size; ++i) { new_pulse |= gate_flags[i] & GATE_FLAG_RISING; } if ((Random::GetWord() >> 16) > acceptance_probability_) { // Randomly ignore incoming pulses. new_pulse = false; } if (new_pulse) { ++num_pulses_; } for (uint8_t i = 0; i < kTriggerPulseBufferSize; ++i) { if (delay_counter_[i] == 0xffff) { if (new_pulse) { delay_counter_[i] = delay(); new_pulse = false; } } else if (delay_counter_[i]) { --delay_counter_[i]; } else { if ((Random::GetWord() >> 16) < repetition_probability_) { ++num_pulses_; delay_counter_[i] = delay(); } else { delay_counter_[i] = 0xffff; } } } if (retrig_counter_) { --retrig_counter_; } else { if (num_pulses_) { retrig_counter_ = 12; --num_pulses_; } } int16_t output = retrig_counter_ > 6 ? 20480 : 0; std::fill(&out[0], &out[size], output); } } // namespace peaks ================================================ FILE: lib/peaks/pulse_processor/pulse_randomizer.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Create random repetitions of a pulse. #ifndef PEAKS_PULSE_PROCESSOR_PULSE_RANDOMIZER_H_ #define PEAKS_PULSE_PROCESSOR_PULSE_RANDOMIZER_H_ #include "stmlib/stmlib.h" #include "stmlib/utils/ring_buffer.h" #include "peaks/gate_processor.h" namespace peaks { struct TriggerPulse { uint32_t delay_counter; }; static const uint8_t kTriggerPulseBufferSize = 32; class PulseRandomizer { public: PulseRandomizer() { } ~PulseRandomizer() { } void Init(); void Process(const GateFlags* gate_flags, int16_t* out, size_t size); void Configure(uint16_t* parameter, ControlMode control_mode) { if (control_mode == CONTROL_MODE_HALF) { set_acceptance_probability(65535); set_repetition_probability(parameter[0]); set_delay_average(parameter[1]); set_delay_randomness(0); } else { set_acceptance_probability(parameter[0]); set_repetition_probability(parameter[1]); set_delay_average(parameter[2]); set_delay_randomness(parameter[3]); } } inline void set_repetition_probability(uint16_t repetition_probability) { repetition_probability_ = repetition_probability; } inline void set_acceptance_probability(uint16_t acceptance_probability) { acceptance_probability_ = acceptance_probability; } inline void set_delay_average(uint16_t delay_average) { delay_average_ = delay_average >> 1; } inline void set_delay_randomness(uint16_t delay_randomness) { delay_randomness_ = delay_randomness; } private: uint16_t delay() const; uint16_t repetition_probability_; uint16_t acceptance_probability_; uint16_t delay_average_; uint16_t delay_randomness_; uint16_t num_pulses_; uint16_t retrig_counter_; uint16_t delay_counter_[kTriggerPulseBufferSize]; DISALLOW_COPY_AND_ASSIGN(PulseRandomizer); }; } // namespace peaks #endif // PEAKS_PULSE_PROCESSOR_PULSE_RANDOMIZER_H_ ================================================ FILE: lib/peaks/pulse_processor/pulse_shaper.cc ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Trigger to gate converter with pre-delay, duration, and repetitions. #include "peaks/pulse_processor/pulse_shaper.h" #include #include "stmlib/utils/dsp.h" #include "peaks/resources.h" namespace peaks { using namespace stmlib; void PulseShaper::Init() { initial_delay_ = 0; duration_ = 0; delay_ = 0; num_repetitions_ = 0; Pulse p; p.initial_delay_counter = 0; p.duration_counter = 0; p.delay_counter = 0; p.repetition_counter = 0; std::fill(&pulse_buffer_[0], &pulse_buffer_[kPulseBufferSize], p); previous_num_pulses_ = 0; retrig_counter_ = 0; } inline uint16_t PulseShaper::delay() const { return Interpolate88(lut_delay_times, delay_) - 1; } inline uint16_t PulseShaper::duration() const { return Interpolate88(lut_delay_times, duration_); } inline uint16_t PulseShaper::initial_delay() const { return Interpolate88(lut_delay_times, initial_delay_); } void PulseShaper::Process( const GateFlags* gate_flags, int16_t* out, size_t size) { bool new_pulse = false; for (size_t i = 0; i < size; ++i) { new_pulse |= gate_flags[i] & GATE_FLAG_RISING; } uint8_t num_pulses = 0; for (uint8_t i = 0; i < kPulseBufferSize; ++i) { Pulse& p = pulse_buffer_[i]; if (p.repetition_counter) { // Handle the case when the duration of the pulse is larger than the // delay time. In this case, set the duration to just a sample below // the delay time. if (p.delay_counter < p.duration_counter && p.repetition_counter > 1) { p.duration_counter = p.delay_counter; } if (p.initial_delay_counter == 0) { if (p.duration_counter) { // ON --p.duration_counter; ++num_pulses; } if (p.delay_counter) { --p.delay_counter; } else { // Retrigger --p.repetition_counter; p.duration_counter = duration(); p.delay_counter = delay(); } } else { // Still in pre-delay phase... --p.initial_delay_counter; } } else { if (new_pulse) { p.repetition_counter = num_repetitions_ + 1; p.initial_delay_counter = initial_delay(); p.duration_counter = duration(); p.delay_counter = delay(); new_pulse = false; num_pulses += p.initial_delay_counter ? 0 : 1; } } } // The output is already high, but a new pulse is arriving. Create // a short dip in the output to retrigger. if (previous_num_pulses_ && num_pulses > previous_num_pulses_) { retrig_counter_ = 6; } previous_num_pulses_ = num_pulses; if (retrig_counter_) { --retrig_counter_; } int16_t output = num_pulses > 0 && !retrig_counter_ ? 20480 : 0; std::fill(&out[0], &out[size], output); } } // namespace peaks ================================================ FILE: lib/peaks/pulse_processor/pulse_shaper.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Trigger to gate converter with pre-delay, duration, and repetitions. #ifndef PEAKS_PULSE_PROCESSOR_PULSE_SHAPER_H_ #define PEAKS_PULSE_PROCESSOR_PULSE_SHAPER_H_ #include "stmlib/stmlib.h" #include "stmlib/utils/ring_buffer.h" #include "peaks/gate_processor.h" namespace peaks { struct Pulse { uint16_t initial_delay_counter; uint16_t duration_counter; uint16_t delay_counter; uint16_t repetition_counter; }; static const uint8_t kPulseBufferSize = 32; class PulseShaper { public: PulseShaper() { } ~PulseShaper() { } void Init(); void Process(const GateFlags* gate_flags, int16_t* out, size_t size); void Configure(uint16_t* parameter, ControlMode control_mode) { if (control_mode == CONTROL_MODE_HALF) { set_initial_delay(0); set_duration(parameter[0] >> 1); set_delay((parameter[0] >> 1) + 2048); set_num_repetitions(parameter[1]); } else { set_initial_delay(parameter[0]); set_duration(parameter[1] >> 1); set_delay(parameter[2] >> 1); set_num_repetitions(parameter[3]); } } inline void set_initial_delay(uint16_t initial_delay) { initial_delay_ = initial_delay; } inline void set_duration(uint16_t duration) { duration_ = duration; } inline void set_delay(uint16_t delay) { delay_ = delay; } inline void set_num_repetitions(uint16_t num_repetitions) { num_repetitions_ = num_repetitions >> 13; } private: uint16_t delay() const; uint16_t duration() const; uint16_t initial_delay() const; uint16_t initial_delay_; uint16_t duration_; uint16_t delay_; uint16_t num_repetitions_; uint16_t previous_num_pulses_; uint16_t retrig_counter_; Pulse pulse_buffer_[kPulseBufferSize]; DISALLOW_COPY_AND_ASSIGN(PulseShaper); }; } // namespace peaks #endif // PEAKS_PULSE_PROCESSOR_PULSE_SHAPER_H_ ================================================ FILE: lib/peaks/resources.cc ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resources definitions. // // Automatically generated with: // make resources #include "peaks/resources.h" #ifndef FLASHMEM #include "pgmspace.h" #endif namespace peaks { static const char str_dummy[] = "dummy"; const char* string_table[] = { str_dummy, }; const uint16_t FLASHMEM lut_delay_times[] = { 5, 7, 8, 10, 12, 14, 16, 18, 21, 24, 27, 31, 34, 39, 43, 48, 53, 59, 65, 71, 78, 85, 93, 101, 109, 118, 128, 138, 149, 160, 172, 185, 198, 212, 226, 241, 257, 273, 290, 308, 327, 347, 367, 388, 410, 433, 456, 481, 506, 533, 560, 588, 617, 648, 679, 711, 745, 779, 815, 851, 889, 928, 968, 1009, 1052, 1096, 1141, 1187, 1235, 1284, 1334, 1386, 1439, 1493, 1549, 1607, 1666, 1726, 1788, 1851, 1916, 1982, 2050, 2120, 2192, 2265, 2339, 2416, 2494, 2574, 2655, 2739, 2824, 2911, 3000, 3091, 3184, 3278, 3375, 3474, 3574, 3677, 3782, 3888, 3997, 4108, 4221, 4337, 4454, 4574, 4696, 4820, 4946, 5075, 5206, 5340, 5475, 5614, 5754, 5897, 6043, 6191, 6341, 6494, 6650, 6808, 6969, 7133, 7299, 7468, 7639, 7814, 7991, 8171, 8353, 8539, 8727, 8919, 9113, 9310, 9510, 9713, 9920, 10129, 10341, 10556, 10775, 10996, 11221, 11449, 11680, 11915, 12152, 12393, 12638, 12885, 13137, 13391, 13649, 13910, 14175, 14444, 14715, 14991, 15270, 15553, 15839, 16129, 16423, 16720, 17021, 17326, 17635, 17947, 18264, 18584, 18908, 19236, 19568, 19905, 20245, 20589, 20937, 21289, 21646, 22007, 22371, 22740, 23114, 23491, 23873, 24259, 24650, 25045, 25444, 25848, 26256, 26668, 27086, 27507, 27934, 28365, 28800, 29240, 29685, 30135, 30589, 31049, 31512, 31981, 32455, 32933, 33417, 33905, 34399, 34897, 35400, 35909, 36422, 36941, 37465, 37994, 38528, 39068, 39612, 40162, 40718, 41278, 41844, 42416, 42993, 43575, 44163, 44756, 45355, 45960, 46570, 47186, 47807, 48435, 49068, 49706, 50351, 51001, 51657, 52319, 52987, 53661, 54341, 55027, 55719, 56417, 57121, 57832, 58548, 59271, 60000, }; const uint16_t FLASHMEM lut_gravity[] = { 33140, 31065, 29132, 27330, 25650, 24084, 22621, 21256, 19981, 18790, 17676, 16634, 15660, 14748, 13894, 13094, 12344, 11642, 10983, 10365, 9785, 9240, 8729, 8249, 7797, 7373, 6973, 6598, 6244, 5912, 5598, 5303, 5025, 4763, 4516, 4283, 4063, 3855, 3659, 3474, 3299, 3134, 2978, 2830, 2690, 2558, 2433, 2315, 2203, 2097, 1996, 1901, 1811, 1725, 1644, 1567, 1494, 1425, 1359, 1297, 1237, 1181, 1127, 1077, 1028, 982, 938, 897, 857, 820, 784, 750, 717, 686, 657, 629, 602, 576, 552, 529, 506, 485, 465, 446, 427, 410, 393, 377, 362, 347, 333, 320, 307, 295, 283, 272, 261, 251, 241, 232, 223, 214, 206, 198, 191, 183, 176, 170, 163, 157, 151, 146, 140, 135, 130, 125, 121, 116, 112, 108, 104, 100, 97, 93, 90, 87, 84, 81, 78, 75, 73, 70, 68, 65, 63, 61, 59, 57, 55, 53, 51, 50, 48, 46, 45, 43, 42, 40, 39, 38, 37, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 25, 24, 23, 22, 22, 21, 20, 20, 19, 19, 18, 17, 17, 16, 16, 15, 15, 14, 14, 14, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, }; const uint16_t FLASHMEM lut_env_linear[] = { 0, 257, 514, 771, 1028, 1285, 1542, 1799, 2056, 2313, 2570, 2827, 3084, 3341, 3598, 3855, 4112, 4369, 4626, 4883, 5140, 5397, 5654, 5911, 6168, 6425, 6682, 6939, 7196, 7453, 7710, 7967, 8224, 8481, 8738, 8995, 9252, 9509, 9766, 10023, 10280, 10537, 10794, 11051, 11308, 11565, 11822, 12079, 12336, 12593, 12850, 13107, 13364, 13621, 13878, 14135, 14392, 14649, 14906, 15163, 15420, 15677, 15934, 16191, 16448, 16705, 16962, 17219, 17476, 17733, 17990, 18247, 18504, 18761, 19018, 19275, 19532, 19789, 20046, 20303, 20560, 20817, 21074, 21331, 21588, 21845, 22102, 22359, 22616, 22873, 23130, 23387, 23644, 23901, 24158, 24415, 24672, 24929, 25186, 25443, 25700, 25957, 26214, 26471, 26728, 26985, 27242, 27499, 27756, 28013, 28270, 28527, 28784, 29041, 29298, 29555, 29812, 30069, 30326, 30583, 30840, 31097, 31354, 31611, 31868, 32125, 32382, 32639, 32896, 33153, 33410, 33667, 33924, 34181, 34438, 34695, 34952, 35209, 35466, 35723, 35980, 36237, 36494, 36751, 37008, 37265, 37522, 37779, 38036, 38293, 38550, 38807, 39064, 39321, 39578, 39835, 40092, 40349, 40606, 40863, 41120, 41377, 41634, 41891, 42148, 42405, 42662, 42919, 43176, 43433, 43690, 43947, 44204, 44461, 44718, 44975, 45232, 45489, 45746, 46003, 46260, 46517, 46774, 47031, 47288, 47545, 47802, 48059, 48316, 48573, 48830, 49087, 49344, 49601, 49858, 50115, 50372, 50629, 50886, 51143, 51400, 51657, 51914, 52171, 52428, 52685, 52942, 53199, 53456, 53713, 53970, 54227, 54484, 54741, 54998, 55255, 55512, 55769, 56026, 56283, 56540, 56797, 57054, 57311, 57568, 57825, 58082, 58339, 58596, 58853, 59110, 59367, 59624, 59881, 60138, 60395, 60652, 60909, 61166, 61423, 61680, 61937, 62194, 62451, 62708, 62965, 63222, 63479, 63736, 63993, 64250, 64507, 64764, 65021, 65278, 65535, 65535, }; const uint16_t FLASHMEM lut_env_expo[] = { 0, 1035, 2054, 3057, 4045, 5018, 5975, 6918, 7846, 8760, 9659, 10545, 11416, 12275, 13120, 13952, 14771, 15577, 16371, 17152, 17921, 18679, 19425, 20159, 20881, 21593, 22294, 22983, 23662, 24331, 24989, 25637, 26274, 26902, 27520, 28129, 28728, 29318, 29899, 30471, 31034, 31588, 32133, 32670, 33199, 33720, 34232, 34737, 35233, 35722, 36204, 36678, 37145, 37604, 38056, 38502, 38940, 39371, 39796, 40215, 40626, 41032, 41431, 41824, 42211, 42592, 42967, 43336, 43699, 44057, 44409, 44756, 45097, 45434, 45764, 46090, 46411, 46727, 47037, 47344, 47645, 47941, 48233, 48521, 48804, 49083, 49357, 49627, 49893, 50155, 50412, 50666, 50916, 51162, 51404, 51642, 51877, 52108, 52335, 52559, 52780, 52997, 53210, 53421, 53628, 53831, 54032, 54230, 54424, 54616, 54804, 54990, 55173, 55353, 55530, 55704, 55876, 56045, 56211, 56375, 56536, 56695, 56851, 57005, 57157, 57306, 57453, 57597, 57740, 57880, 58018, 58153, 58287, 58419, 58548, 58676, 58801, 58925, 59047, 59167, 59285, 59401, 59515, 59628, 59739, 59848, 59955, 60061, 60165, 60267, 60368, 60468, 60566, 60662, 60757, 60850, 60942, 61032, 61121, 61209, 61295, 61380, 61464, 61546, 61628, 61707, 61786, 61863, 61939, 62014, 62088, 62161, 62233, 62303, 62372, 62441, 62508, 62574, 62639, 62703, 62767, 62829, 62890, 62950, 63010, 63068, 63125, 63182, 63238, 63293, 63347, 63400, 63452, 63504, 63554, 63604, 63654, 63702, 63750, 63797, 63843, 63888, 63933, 63977, 64021, 64063, 64105, 64147, 64188, 64228, 64267, 64306, 64344, 64382, 64419, 64456, 64492, 64527, 64562, 64596, 64630, 64664, 64696, 64729, 64760, 64792, 64822, 64853, 64883, 64912, 64941, 64969, 64997, 65025, 65052, 65079, 65105, 65131, 65157, 65182, 65206, 65231, 65255, 65278, 65302, 65324, 65347, 65369, 65391, 65412, 65434, 65454, 65475, 65495, 65515, 65535, 65535, }; const uint16_t FLASHMEM lut_env_quartic[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 9, 11, 14, 16, 19, 22, 25, 29, 33, 37, 42, 48, 53, 59, 66, 73, 81, 89, 98, 107, 117, 128, 139, 151, 164, 177, 191, 206, 222, 238, 256, 274, 293, 313, 334, 355, 378, 402, 427, 453, 480, 508, 537, 567, 599, 631, 665, 700, 737, 775, 814, 854, 896, 939, 984, 1030, 1077, 1127, 1177, 1230, 1283, 1339, 1396, 1455, 1515, 1577, 1641, 1707, 1775, 1844, 1916, 1989, 2064, 2141, 2220, 2302, 2385, 2470, 2557, 2647, 2739, 2833, 2929, 3027, 3128, 3231, 3336, 3444, 3554, 3667, 3782, 3899, 4019, 4142, 4267, 4395, 4525, 4658, 4794, 4933, 5074, 5218, 5365, 5515, 5668, 5824, 5983, 6144, 6309, 6477, 6648, 6822, 6999, 7179, 7363, 7550, 7740, 7933, 8130, 8330, 8534, 8741, 8951, 9165, 9383, 9604, 9829, 10057, 10289, 10525, 10765, 11008, 11255, 11507, 11761, 12020, 12283, 12550, 12821, 13096, 13375, 13658, 13945, 14237, 14532, 14832, 15137, 15445, 15758, 16076, 16397, 16724, 17054, 17390, 17730, 18074, 18423, 18777, 19136, 19499, 19868, 20241, 20618, 21001, 21389, 21781, 22179, 22582, 22990, 23403, 23821, 24244, 24672, 25106, 25545, 25990, 26440, 26895, 27355, 27821, 28293, 28770, 29253, 29742, 30236, 30735, 31241, 31752, 32270, 32793, 33321, 33856, 34397, 34944, 35497, 36056, 36621, 37192, 37769, 38353, 38943, 39539, 40142, 40751, 41366, 41988, 42617, 43251, 43893, 44541, 45196, 45857, 46526, 47201, 47882, 48571, 49267, 49969, 50678, 51395, 52118, 52849, 53587, 54332, 55084, 55843, 56610, 57384, 58165, 58954, 59750, 60553, 61364, 62183, 63010, 63843, 64685, 65535, 65535, }; const uint16_t FLASHMEM lut_raised_cosine[] = { 0, 2, 9, 22, 39, 61, 88, 120, 157, 199, 246, 298, 354, 416, 482, 553, 629, 710, 796, 886, 982, 1082, 1186, 1296, 1410, 1530, 1653, 1782, 1915, 2053, 2195, 2342, 2494, 2650, 2811, 2976, 3146, 3320, 3498, 3681, 3869, 4060, 4256, 4457, 4661, 4870, 5083, 5300, 5522, 5747, 5977, 6210, 6448, 6689, 6935, 7184, 7437, 7694, 7955, 8220, 8488, 8760, 9035, 9314, 9597, 9883, 10172, 10465, 10762, 11061, 11364, 11670, 11980, 12292, 12607, 12926, 13247, 13572, 13899, 14229, 14562, 14898, 15236, 15578, 15921, 16267, 16616, 16967, 17321, 17676, 18034, 18395, 18757, 19122, 19488, 19857, 20227, 20600, 20974, 21350, 21728, 22107, 22488, 22871, 23255, 23641, 24027, 24416, 24805, 25196, 25588, 25980, 26374, 26769, 27165, 27562, 27959, 28357, 28756, 29155, 29555, 29956, 30356, 30758, 31159, 31561, 31963, 32365, 32767, 33169, 33571, 33973, 34375, 34776, 35178, 35578, 35979, 36379, 36778, 37177, 37575, 37972, 38369, 38765, 39160, 39554, 39946, 40338, 40729, 41118, 41507, 41893, 42279, 42663, 43046, 43427, 43806, 44184, 44560, 44934, 45307, 45677, 46046, 46412, 46777, 47139, 47500, 47858, 48213, 48567, 48918, 49267, 49613, 49956, 50298, 50636, 50972, 51305, 51635, 51962, 52287, 52608, 52927, 53242, 53554, 53864, 54170, 54473, 54772, 55069, 55362, 55651, 55937, 56220, 56499, 56774, 57046, 57314, 57579, 57840, 58097, 58350, 58599, 58845, 59086, 59324, 59557, 59787, 60012, 60234, 60451, 60664, 60873, 61077, 61278, 61474, 61665, 61853, 62036, 62214, 62388, 62558, 62723, 62884, 63040, 63192, 63339, 63481, 63619, 63752, 63881, 64004, 64124, 64238, 64348, 64452, 64552, 64648, 64738, 64824, 64905, 64981, 65052, 65118, 65180, 65236, 65288, 65335, 65377, 65414, 65446, 65473, 65495, 65512, 65525, 65532, 65532, }; const uint16_t FLASHMEM lut_svf_cutoff[] = { 35, 37, 39, 41, 44, 46, 49, 52, 55, 58, 62, 66, 70, 74, 78, 83, 88, 93, 99, 105, 111, 117, 124, 132, 140, 148, 157, 166, 176, 187, 198, 210, 222, 235, 249, 264, 280, 297, 314, 333, 353, 374, 396, 420, 445, 471, 499, 529, 561, 594, 629, 667, 706, 748, 793, 840, 890, 943, 999, 1059, 1122, 1188, 1259, 1334, 1413, 1497, 1586, 1681, 1781, 1886, 1999, 2117, 2243, 2377, 2518, 2668, 2826, 2994, 3172, 3361, 3560, 3772, 3996, 4233, 4485, 4751, 5033, 5332, 5648, 5983, 6337, 6713, 7111, 7532, 7978, 8449, 8949, 9477, 10037, 10628, 11254, 11916, 12616, 13356, 14138, 14964, 15837, 16758, 17730, 18756, 19837, 20975, 22174, 23435, 24761, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, }; const uint16_t FLASHMEM lut_svf_damp[] = { 65534, 49166, 46069, 43993, 42386, 41058, 39917, 38910, 38007, 37184, 36427, 35726, 35070, 34454, 33873, 33322, 32798, 32299, 31820, 31361, 30920, 30496, 30086, 29690, 29306, 28935, 28574, 28224, 27883, 27551, 27228, 26912, 26605, 26304, 26010, 25723, 25441, 25166, 24896, 24631, 24371, 24116, 23866, 23620, 23379, 23141, 22908, 22678, 22452, 22229, 22010, 21794, 21581, 21371, 21164, 20960, 20759, 20560, 20365, 20171, 19980, 19791, 19605, 19421, 19239, 19059, 18882, 18706, 18532, 18360, 18190, 18022, 17856, 17691, 17528, 17367, 17207, 17049, 16892, 16737, 16583, 16431, 16280, 16131, 15982, 15836, 15690, 15546, 15403, 15261, 15120, 14981, 14843, 14705, 14569, 14434, 14300, 14167, 14036, 13905, 13775, 13646, 13518, 13391, 13265, 13140, 13015, 12892, 12769, 12648, 12527, 12407, 12287, 12169, 12051, 11934, 11818, 11703, 11588, 11474, 11361, 11249, 11137, 11026, 10915, 10805, 10696, 10588, 10480, 10373, 10266, 10160, 10055, 9950, 9846, 9742, 9639, 9537, 9435, 9333, 9233, 9132, 9033, 8933, 8835, 8737, 8639, 8542, 8445, 8349, 8253, 8158, 8063, 7969, 7875, 7782, 7689, 7596, 7504, 7413, 7321, 7231, 7140, 7050, 6961, 6872, 6783, 6695, 6607, 6519, 6432, 6346, 6259, 6173, 6088, 6003, 5918, 5833, 5749, 5665, 5582, 5499, 5416, 5334, 5251, 5170, 5088, 5007, 4926, 4846, 4766, 4686, 4607, 4527, 4449, 4370, 4292, 4214, 4136, 4059, 3982, 3905, 3828, 3752, 3676, 3601, 3525, 3450, 3375, 3301, 3226, 3152, 3078, 3005, 2932, 2859, 2786, 2713, 2641, 2569, 2497, 2426, 2355, 2284, 2213, 2142, 2072, 2002, 1932, 1862, 1793, 1724, 1655, 1586, 1518, 1449, 1381, 1313, 1246, 1178, 1111, 1044, 977, 911, 844, 778, 712, 647, 581, 516, 450, 385, 321, 256, 192, 127, 63, }; const uint16_t FLASHMEM lut_svf_scale[] = { 32767, 28381, 27473, 26846, 26352, 25936, 25573, 25248, 24953, 24682, 24429, 24193, 23970, 23759, 23557, 23365, 23181, 23003, 22832, 22667, 22507, 22352, 22201, 22055, 21912, 21772, 21636, 21503, 21373, 21245, 21120, 20998, 20877, 20759, 20643, 20528, 20416, 20305, 20196, 20088, 19982, 19877, 19774, 19672, 19571, 19471, 19373, 19275, 19179, 19083, 18989, 18896, 18803, 18712, 18621, 18531, 18442, 18353, 18266, 18179, 18092, 18007, 17922, 17837, 17754, 17671, 17588, 17506, 17424, 17343, 17263, 17183, 17103, 17024, 16946, 16868, 16790, 16713, 16636, 16559, 16483, 16407, 16331, 16256, 16181, 16107, 16033, 15959, 15885, 15812, 15739, 15666, 15594, 15522, 15450, 15378, 15306, 15235, 15164, 15093, 15022, 14952, 14882, 14812, 14742, 14672, 14602, 14533, 14464, 14395, 14326, 14257, 14188, 14120, 14051, 13983, 13915, 13847, 13779, 13711, 13643, 13575, 13508, 13440, 13372, 13305, 13238, 13170, 13103, 13036, 12969, 12902, 12835, 12768, 12701, 12634, 12567, 12500, 12433, 12366, 12299, 12232, 12165, 12098, 12031, 11964, 11897, 11830, 11762, 11695, 11628, 11561, 11493, 11426, 11359, 11291, 11223, 11156, 11088, 11020, 10952, 10884, 10816, 10747, 10679, 10610, 10542, 10473, 10404, 10335, 10266, 10196, 10127, 10057, 9987, 9917, 9846, 9776, 9705, 9634, 9563, 9491, 9420, 9348, 9276, 9203, 9130, 9057, 8984, 8910, 8836, 8762, 8687, 8613, 8537, 8461, 8385, 8309, 8232, 8155, 8077, 7998, 7920, 7841, 7761, 7680, 7600, 7518, 7436, 7354, 7270, 7187, 7102, 7017, 6931, 6844, 6756, 6668, 6578, 6488, 6397, 6305, 6211, 6117, 6021, 5925, 5827, 5727, 5626, 5524, 5420, 5315, 5207, 5098, 4987, 4873, 4758, 4639, 4518, 4394, 4267, 4137, 4002, 3864, 3720, 3571, 3417, 3255, 3086, 2907, 2717, 2514, 2293, 2049, 1774, 1447, 1022, }; const uint16_t* lookup_table_table[] = { lut_delay_times, lut_gravity, lut_env_linear, lut_env_expo, lut_env_quartic, lut_raised_cosine, lut_svf_cutoff, lut_svf_damp, lut_svf_scale, }; const uint32_t FLASHMEM lut_lfo_increments[] = { 2796, 2891, 2989, 3090, 3195, 3303, 3415, 3531, 3651, 3775, 3903, 4036, 4172, 4314, 4460, 4612, 4768, 4930, 5097, 5270, 5449, 5634, 5825, 6023, 6227, 6438, 6657, 6883, 7116, 7357, 7607, 7865, 8132, 8408, 8693, 8988, 9293, 9608, 9934, 10271, 10620, 10980, 11353, 11738, 12136, 12548, 12974, 13414, 13869, 14339, 14826, 15329, 15849, 16387, 16943, 17517, 18112, 18726, 19361, 20018, 20698, 21400, 22126, 22876, 23652, 24455, 25285, 26142, 27029, 27946, 28894, 29875, 30888, 31936, 33020, 34140, 35298, 36496, 37734, 39014, 40338, 41706, 43121, 44584, 46097, 47660, 49277, 50949, 52678, 54465, 56313, 58223, 60198, 62241, 64352, 66535, 68793, 71126, 73539, 76034, 78614, 81281, 84039, 86890, 89837, 92885, 96036, 99295, 102663, 106146, 109747, 113471, 117320, 121300, 125415, 129670, 134069, 138618, 143321, 148183, 153210, 158408, 163782, 169338, 175083, 181023, 187165, 193514, 200079, 206867, 213885, 221142, 228644, 236401, 244421, 252713, 261287, 270151, 279316, 288792, 298590, 308720, 319193, 330022, 341218, 352794, 364763, 377138, 389933, 403162, 416839, 430981, 445602, 460719, 476350, 492510, 509219, 526495, 544356, 562824, 581918, 601660, 622072, 643176, 664997, 687557, 710883, 735000, 759936, 785717, 812373, 839933, 868429, 897891, 928352, 959847, 992411, 1026079, 1060890, 1096881, 1134094, 1172569, 1212349, 1253479, 1296004, 1339972, 1385431, 1432433, 1481029, 1531274, 1583224, 1636936, 1692470, 1749888, 1809255, 1870635, 1934097, 1999713, 2067555, 2137698, 2210221, 2285204, 2362732, 2442889, 2525766, 2611454, 2700050, 2791651, 2886359, 2984281, 3085525, 3190204, 3298434, 3410335, 3526034, 3645657, 3769338, 3897216, 4029432, 4166133, 4307472, 4453606, 4604698, 4760916, 4922433, 5089430, 5262093, 5440613, 5625190, 5816028, 6013341, 6217348, 6428276, 6646360, 6871842, 7104975, 7346016, 7595235, 7852908, 8119324, 8394778, 8679577, 8974038, 9278488, 9593267, 9918726, 10255226, 10603142, 10962861, 11334784, 11719324, 12116911, 12527986, 12953006, 13392446, 13846795, 14316557, }; const uint32_t FLASHMEM lut_env_increments[] = { 178956970, 162203921, 147263779, 133914742, 121965179, 111249129, 101622525, 92960022, 85152324, 78103929, 71731214, 65960813, 60728233, 55976673, 51656020, 47721976, 44135321, 40861270, 37868923, 35130786, 32622357, 30321772, 28209484, 26268003, 24481648, 22836346, 21319451, 19919582, 18626484, 17430905, 16324491, 15299685, 14349647, 13468178, 12649652, 11888959, 11181454, 10522909, 9909470, 9337624, 8804164, 8306157, 7840925, 7406012, 6999170, 6618338, 6261623, 5927288, 5613733, 5319488, 5043200, 4783621, 4539601, 4310076, 4094068, 3890668, 3699040, 3518407, 3348049, 3187303, 3035548, 2892213, 2756766, 2628711, 2507588, 2392971, 2284460, 2181685, 2084301, 1991984, 1904435, 1821372, 1742534, 1667676, 1596567, 1528995, 1464759, 1403670, 1345553, 1290243, 1237585, 1187435, 1139655, 1094119, 1050706, 1009303, 969803, 932108, 896122, 861758, 828932, 797565, 767584, 738918, 711503, 685274, 660174, 636148, 613143, 591109, 569999, 549770, 530379, 511787, 493956, 476850, 460436, 444683, 429558, 415035, 401085, 387683, 374804, 362424, 350523, 339078, 328069, 317479, 307287, 297478, 288035, 278942, 270184, 261748, 253620, 245786, 238236, 230956, 223936, 217166, 210635, 204334, 198253, 192383, 186717, 181245, 175961, 170858, 165927, 161162, 156558, 152107, 147805, 143644, 139621, 135729, 131964, 128321, 124796, 121384, 118081, 114883, 111787, 108788, 105883, 103069, 100343, 97700, 95139, 92657, 90250, 87917, 85654, 83459, 81330, 79265, 77261, 75316, 73428, 71596, 69817, 68090, 66413, 64784, 63202, 61666, 60173, 58722, 57312, 55942, 54610, 53315, 52056, 50832, 49641, 48484, 47357, 46262, 45196, 44159, 43149, 42167, 41211, 40280, 39374, 38492, 37632, 36796, 35981, 35187, 34414, 33660, 32926, 32211, 31513, 30834, 30172, 29526, 28896, 28282, 27684, 27100, 26531, 25975, 25434, 24905, 24390, 23886, 23395, 22916, 22449, 21992, 21546, 21111, 20687, 20272, 19867, 19471, 19085, 18708, 18339, 17979, 17627, 17283, 16947, 16619, 16298, 15985, 15678, 15378, 15085, 14799, 14519, 14245, 13977, 13716, 13459, 13209, 12964, 12724, 12490, 12260, 12036, 11816, 11601, 11390, 11184, }; const uint32_t FLASHMEM lut_oscillator_increments[] = { 594570139, 598878640, 603218361, 607589530, 611992374, 616427123, 620894008, 625393262, 629925120, 634489817, 639087591, 643718683, 648383334, 653081787, 657814287, 662581081, 667382416, 672218544, 677089717, 681996188, 686938214, 691916051, 696929960, 701980202, 707067040, 712190739, 717351567, 722549792, 727785686, 733059521, 738371572, 743722117, 749111434, 754539804, 760007511, 765514839, 771062075, 776649508, 782277431, 787946136, 793655918, 799407076, 805199909, 811034720, 816911812, 822831491, 828794068, 834799851, 840849155, 846942294, 853079587, 859261354, 865487916, 871759598, 878076727, 884439633, 890848647, 897304104, 903806339, 910355693, 916952505, 923597121, 930289887, 937031151, 943821265, 950660583, 957549461, 964488259, 971477339, 978517064, 985607802, 992749922, 999943798, 1007189803, 1014488315, 1021839716, 1029244387, 1036702717, 1044215092, 1051781905, 1059403550, 1067080425, 1074812930, 1082601467, 1090446444, 1098348268, 1106307352, 1114324111, 1122398963, 1130532329, 1138724632, 1146976300, 1155287763, 1163659455, 1172091811, 1180585271, 1189140279, }; const uint32_t* lookup_table_32_table[] = { lut_lfo_increments, lut_env_increments, lut_oscillator_increments, }; const uint8_t FLASHMEM wav_digits[] = { 127, 74, 21, 224, 171, 118, 65, 12, 215, 162, 109, 56, 252, 49, 102, 155, 208, 5, 58, 111, 164, 217, 14, 67, 120, 173, 29, 232, 179, 126, 73, 20, 223, 170, 138, 191, 244, 214, 94, 147, 200, 2, 205, 103, 156, 209, 6, 59, 112, 90, 218, 240, 187, 134, 81, 28, 231, 77, 125, 72, 19, 222, 86, 116, 63, 245, 42, 95, 148, 201, 254, 51, 151, 98, 45, 248, 60, 142, 166, 219, 239, 69, 122, 175, 27, 25, 78, 131, 184, 237, 34, 87, 140, 193, 246, 43, 96, 149, 202, 0, 203, 150, 97, 44, 247, 194, 141, 88, 35, 238, 185, 132, 79, 26, 229, 176, 123, 185, 238, 35, 88, 114, 194, 8, 211, 158, 105, 52, 0, 202, 149, 159, 43, 9, 62, 140, 87, 221, 237, 71, 124, 78, 230, 27, 80, 133, 69, 239, 36, 166, 142, 60, 248, 210, 98, 104, 51, 1, 201, 107, 95, 213, 10, 192, 116, 86, 222, 236, 183, 125, 77, 231, 227, 81, 134, 68, 240, 218, 90, 112, 196, 249, 209, 99, 103, 205, 253, 55, 147, 161, 41, 244, 64, 138, 85, 223, 235, 182, 129, 76, 232, 226, 82, 120, 188, 14, 217, 164, 111, 58, 5, 47, 155, 153, 49, 3, 56, 146, 162, 215, 243, 65, 137, 84, 224, 21, 74, 128, 180, 22, 30, 172, 119, 189, 13, 216, 92, 110, 57, 251, 207, 101, 154, 48, 251, 57, 145, 92, 216, 242, 66, 136, 83, 225, 233, 75, 127, 181, 234, 224, 84, 118, 190, 12, 40, 93, 108, 198, 3, 206, 103, 101, 208, 5, 197, 111, 164, 38, 15, 188, 135, 172, 29, 232, 77, 127, 182, 234, 221, 87, 116, 64, 245, 215, 94, 108, 55, 253, 205, 152, 157, 44, 7, 196, 143, 165, 37, 240, 68, 121, 81, 227, 24, 178, 131, 72, 18, 35, 171, 139, 193, 11, 40, 161, 148, 201, 0, 50, 151, 157, 210, 249, 60, 113, 89, 36, 16, 69, 132, 173, 26, 230, 79, 125, 184, 236, 223, 86, 115, 63, 247, 213, 97, 104, 203, 0, 201, 106, 98, 209, 247, 194, 115, 90, 221, 239, 70, 123, 78, 228, 229, 176, 133, 71, 239, 220, 167, 143, 63, 245, 211, 159, 148, 54, 1, 202, 149, 159, 42, 11, 195, 114, 87, 34, 16, 186, 124, 176, 27, 25, 80, 120, 184, 17, 36, 166, 143, 62, 249, 210, 156, 149, 49, 1, 54, 148, 160, 42, 245, 63, 138, 168, 32, 18, 183, 130, 178, 24, 29, 172, 132, 70, 241, 37, 164, 142, 59, 249, 209, 98, 102, 205, 2, 200, 147, 160, 41, 244, 65, 139, 170, 32, 21, 183, 127, 179, 21, 28, 82, 121, 190, 15, 217, 90, 110, 196, 5, 47, 155, 153, 49, 252, 57, 144, 160, 40, 242, 66, 138, 170, 225, 233, 73, 129, 75, 233, 30, 172, 137, 189, 12, 37, 161, 144, 57, 4, 48, 154, 154, 207, 249, 56, 145, 92, 217, 243, 67, 136, 83, 224, 233, 75, 127, 181, 21, 31, 84, 118, 191, 12, 40, 93, 108, 199, 252, 207, 100, 101, 47, 5, 196, 110, 91, 216, 241, 188, 121, 83, 226, 23, 179, 126, 183, 21, 223, 84, 116, 191, 244, 212, 95, 108, 54, 255, 204, 152, 157, 46, 6, 59, 112, 91, 218, 15, 185, 123, 80, 28, 26, 176, 131, 72, 19, 33, 169, 139, 63, 245, 212, 94, 148, 52, 253, 205, 150, 159, 47, 7, 60, 142, 89, 219, 239, 186, 122, 80, 27, 25, 78, 124, 71, 237, 221, 168, 141, 63, 246, 43, 157, 151, 53, 1, 54, 151, 97, 210, 245, 61, 114, 90, 222, 239, 185, 122, 78, 228, 231, 77, 123, 70, 239, 220, 88, 115, 193, 10, 44, 96, 107, 202, 255, 202, 106, 159, 42, 9, 193, 115, 86, 221, 18, 185, 124, 177, 24, 27, 80, 120, 184, 18, 219, 91, 115, 60, 250, 209, 99, 151, 49, 3, 201, 148, 161, 42, 245, 63, 116, 169, 32, 17, 182, 125, 178, 24, 28, 81, 134, 68, 240, 218, 90, 113, 196, 6, 209, 99, 103, 50, 2, 55, 146, 160, 214, 245, 65, 117, 84, 222, 235, 73, 129, 179, 23, 29, 173, 120, 67, 14, 38, 164, 144, 59, 248, 211, 102, 102, 48, 2, 198, 108, 92, 213, 242, 65, 118, 84, 224, 235, 72, 129, 181, 23, 31, 173, 137, 67, 13, 37, 160, 146, 56, 251, 48, 154, 154, 48, 251, 198, 111, 93, 39, 12, 188, 119, 83, 30, 23, 181, 129, 75, 234, 31, 171, 136, 65, 242, 214, 92, 146, 58, 254, 207, 153, 153, 44, 7, 197, 144, 164, 38, 14, 189, 121, 82, 227, 233, 77, 127, 182, 20, 32, 170, 117, 190, 9, 40, 163, 145, 53, 253, 50, 153, 157, 47, 6, 58, 142, 164, 37, 240, 69, 135, 172, 30, 26, 179, 131, 72, 19, 32, 168, 138, 63, 245, 213, 95, 106, 203, 3, 50, 104, 99, 211, 249, 62, 141, 165, 37, 16, 69, 122, 81, 228, 25, 179, 128, 70, 19, 35, 87, 112, 194, 8, 212, 98, 107, 203, 0, 53, 148, 159, 211, 245, 62, 142, 165, 35, 239, 68, 134, 178, 27, 27, 176, 123, 184, 19, 34, 167, 114, 194, 8, 44, 158, 150, 203, 253, 54, 145, 157, 212, 247, 63, 140, 168, 35, 17, 187, 127, 79, 230, 228, 80, 122, 69, 236, 223, 90, 115, 194, 6, 47, 156, 104, 206, 253, 52, 149, 161, 43, 11, 192, 139, 169, 33, 19, 183, 124, 76, 230, 226, 81, 135, 70, 241, 218, 90, 112, 197, 249, 208, 97, 101, 205, 2, 55, 145, 163, 40, 244, 66, 137, 169, 34, 22, 181, 122, 72, 234, 29, 169, 131, 65, 241, 38, 91, 110, 196, 250, 209, 101, 102, 49, 2, 198, 111, 92, 40, 12, 65, 137, 171, 225, 232, 75, 128, 73, 235, 225, 173, 138, 64, 243, 39, 92, 110, 198, 4, 206, 97, 96, 203, 249, 198, 108, 95, 220, 240, 64, 138, 174, 28, 20, 75, 124, 182, 20, 226, 87, 118, 67, 247, 212, 95, 108, 198, 0, 50, 152, 101, 210, 251, 59, 146, 167, 36, 12, 189, 120, 173, 29, 232, 179, 128, 75, 234, 222, 84, 117, 64, 246, 212, 95, 108, 55, 252, 206, 100, 97, 46, 5, 192, 115, 90, 37, 240, 69, 135, 81, 225, 227, 79, 130, 74, 237, 32, 170, 136, 192, 9, 40, 160, 106, 200, 1, 205, 105, 98, 44, 6, 60, 142, 89, 219, 239, 186, 132, 174, 26, 231, 76, 126, 185, 19, 35, 169, 115, 195, 10, 40, 157, 151, 52, 255, 53, 149, 157, 44, 246, 63, 140, 88, 222, 236, 71, 123, 78, 229, 26, 176, 122, 187, 19, 35, 167, 115, 195, 9, 45, 158, 105, 203, 255, 202, 149, 159, 42, 11, 194, 114, 168, 35, 19, 71, 131, 78, 231, 231, 83, 121, 187, 239, 219, 167, 143, 193, 3, 41, 159, 151, 51, 1, 54, 149, 161, 43, 245, 63, 139, 169, 33, 19, 72, 128, 177, 27, 29, 174, 121, 187, 15, 37, 164, 141, 56, 250, 210, 99, 153, 48, 2, 52, 145, 95, 210, 247, 64, 118, 86, 223, 16, 176, 122, 76, 21, 28, 173, 134, 65, 245, 221, 88, 110, 57, 253, 216, 96, 103, 48, 1, 197, 110, 94, 211, 242, 191, 114, 82, 227, 234, 182, 123, 72, 235, 227, 82, 136, 67, 246, 221, 88, 108, 56, 249, 48, 154, 100, 204, 248, 56, 111, 93, 216, 12, 190, 118, 173, 29, 21, 180, 126, 180, 234, 226, 80, 116, 67, 246, 210, 162, 149, 61, 2, 57, 144, 155, 214, 252, 59, 106, 92, 216, 8, 182, 126, 175, 26, 19, 79, 120, 180, 238, 215, 81, 142, 71, 246, 45, 166, 147, 206, 7, 205, 100, 96, 46, 4, 197, 142, 161, 38, 240, 71, 130, 174, 225, 230, 178, 128, 74, 19, 35, 168, 117, 193, 10, 42, 160, 105, 202, 2, 51, 105, 98, 45, 6, 195, 143, 164, 38, 239, 71, 133, 82, 230, 24, 181, 130, 188, 17, 221, 82, 112, 60, 243, 214, 157, 145, 52, 3, 54, 150, 96, 210, 9, 193, 112, 89, 32, 23, 186, 134, 179, 229, 227, 77, 129, 78, 236, 38, 161, 114, 196, 12, 208, 105, 107, 50, 6, 55, 146, 157, 209, 243, 193, 119, 87, 32, 16, 71, 128, 179, 25, 229, 80, 133, 71, 239, 38, 165, 142, 199, 7, 45, 102, 151, 50, 3, 54, 150, 95, 46, 241, 196, 141, 84, 34, 237, 183, 126, 182, 225, 21, 89, 131, 191, 243, 219, 163, 114, 62, 10, 214, 159, 100, 52, 3, 51, 146, 165, 220, 14, 65, 125, 175, 32, 21, 73, 130, 74, 19, 224, 171, 123, 190, 241, 217, 90, 110, 197, 249, 210, 155, 152, 50, 253, 58, 109, 94, 40, 12, 65, 119, 173, 233, 28, 67, 119, 182, 21, 234, 191, 123, 79, 2, 208, 163, 144, 195, 244, 60, 108, 156, 206, 6, 56, 144, 161, 222, 12, 64, 113, 80, 23, 231, 164, 116, 67, 19, 226, 83, 133, 178, 252, 37, 85, 111, 60, 0, 205, 157, 100, 213, 1, 57, 108, 91, 45, 252, 182, 142, 90, 21, 233, 75, 136, 189, 231, 41, 86, 119, 65, 9, 215, 94, 151, 192, 250, 55, 152, 100, 33, 246, 207, 131, 82, 38, 11, 72, 118, 162, 239, 17, 177, 117, 75, 23, 220, 87, 131, 204, 252, 46, 163, 103, 36, 14, 195, 154, 101, 211, 14, 50, 96, 168, 209, 238, 191, 130, 88, 31, 230, 72, 143, 182, 228, 35, 160, 124, 49, 7, 218, 146, 105, 205, 241, 36, 102, 148, 209, 243, 197, 138, 93, 35, 23, 75, 117, 186, 224, 227, 161, 107, 72, 0, 204, 174, 143, 206, 231, 35, 109, 144, 52, 251, 205, 145, 96, 209, 5, 49, 126, 160, 33, 226, 171, 147, 92, 9, 239, 173, 142, 169, 253, 41, 80, 142, 58, 0, 219, 152, 150, 196, 12, 59, 98, 161, 35, 231, 208, 155, 89, 45, 233, 78, 109, 161, 233, 21, 80, 124, 67, 6, 220, 91, 133, 212, 232, 33, 101, 99, 34, 232, 218, 130, 81, 32, 11, 75, 97, 190, 211, 23, 178, 134, 68, 31, 230, 86, 137, 174, 254, 47, 164, 98, 47, 16, 194, 149, 108, 50, 10, 43, 123, 178, 208, 247, 183, 128, 94, 26, 23, 70, 108, 160, 231, 26, 169, 100, 91, 27, 201, 175, 105, 197, 247, 38, 115, 150, 206, 243, 204, 154, 84, 37, 10, 80, 97, 191, 234, 22, 185, 101, 80, 3, 240, 160, 117, 184, 225, 49, 79, 154, 59, 9, 196, 145, 98, 210, 11, 47, 121, 180, 223, 244, 175, 155, 73, 9, 229, 180, 128, 189, 252, 56, 69, 137, 70, 1, 220, 166, 110, 192, 236, 36, 116, 151, 46, 245, 222, 144, 66, 52, 249, 185, 126, 191, 249, 14, 65, 130, 65, 24, 215, 175, 138, 203, 230, 63, 79, 147, 50, 19, 210, 138, 116, 32, 255, 61, 125, 179, 194, 3, 77, 135, 90, 23, 238, 179, 133, 183, 249, 48, 90, 143, 55, 17, 246, 131, 121, 63, 4, 49, 121, 137, 203, 7, 56, 136, 83, 47, 233, 70, 114, 161, 241, 21, 70, 123, 75, 13, 252, 191, 127, 59, 8, 37, 115, 129, 223, 11, 53, 159, 109, 32, 240, 60, 126, 188, 201, 28, 66, 128, 92, 6, 249, 189, 115, 71, 235, 41, 74, 155, 205, 253, 215, 144, 101, 58, 255, 62, 120, 182, 199, 0, 62, 128, 76, 0, 245, 186, 134, 179, 237, 14, 69, 151, 178, 240, 208, 171, 125, 61, 251, 32, 117, 141, 194, 10, 203, 128, 65, 52, 231, 181, 136, 175, 208, 7, 90, 115, 182, 18, 236, 162, 116, 64, 246, 55, 77, 133, 203, 255, 216, 131, 123, 41, 238, 206, 147, 170, 216, 30, 81, 125, 168, 23, 231, 184, 135, 180, 227, 15, 71, 155, 176, 247, 222, 176, 120, 46, 19, 223, 156, 155, 201, 8, 52, 101, 167, 36, 246, 188, 117, 164, 238, 5, 89, 141, 176, 17, 241, 178, 109, 89, 28, 223, 162, 150, 207, 247, 60, 111, 154, 41, 252, 197, 109, 173, 201, 26, 83, 117, 170, 29, 230, 164, 102, 93, 26, 214, 168, 117, 188, 243, 35, 91, 110, 63, 5, 205, 98, 146, 196, 31, 47, 98, 170, 216, 254, 166, 152, 74, 8, 233, 181, 121, 183, 233, 43, 92, 143, 62, 8, 47, 86, 132, 218, 235, 60, 102, 144, 209, 243, 217, 148, 64, 48, 254, 176, 131, 83, 231, 19, 64, 133, 71, 17, 39, 93, 131, 211, 229, 36, 110, 155, 206, 9, 220, 143, 120, 58, 228, 207, 135, 95, 220, 24, 86, 115, 177, 27, 29, 68, 138, 171, 250, 50, 87, 156, 197, 15, 196, 133, 114, 44, 235, 196, 159, 104, 213, 3, 47, 122, 169, 34, 20, 77, 112, 160, 245, 10, 94, 151, 179, 20, 206, 189, 109, 38, 17, 221, 145, 98, 204, 11, 38, 98, 162, 213, 9, 55, 120, 186, 202, 0, 71, 105, 190, 26, 240, 178, 100, 88, 25, 203, 168, 123, 59, 240, 35, 106, 157, 204, 0, 63, 98, 180, 195, 31, 81, 97, 167, 33, 250, 171, 161, 83, 15, 241, 163, 115, 66, 249, 43, 86, 151, 199, 250, 39, 106, 141, 218, 21, 43, 126, 173, 215, 252, 162, 150, 116, 6, 254, 187, 140, 79, 236, 21, 95, 143, 188, 12, 32, 81, 130, 211, 236, 36, 113, 138, 204, 240, 220, 142, 67, 62, 230, 178, 133, 85, 226, 31, 70, 136, 183, 21, 23, 91, 157, 171, 228, 61, 78, 130, 195, 10, 214, 135, 122, 55, 238, 213, 157, 92, 216, 6, 79, 127, 173, 31, 16, 65, 147, 160, 252, 53, 70, 155, 185, 12, 193, 188, 114, 47, 23, 220, 151, 105, 47, 0, 48, 119, 167, 37, 8, 73, 106, 185, 251, 14, 89, 145, 176, 22, 203, 183, 107, 38, 29, 198, 175, 96, 52, 251, 57, 111, 159, 45, 1, 48, 98, 190, 204, 6, 80, 104, 167, 24, 242, 173, 97, 94, 5, 207, 184, 126, 61, 242, 34, 103, 150, 202, 248, 57, 122, 136, 196, 29, 46, 99, 175, 33, 252, 163, 152, 87, 15, 247, 160, 118, 66, 237, 42, 95, 137, 195, 241, 32, 115, 128, 221, 21, 38, 120, 150, 42, 231, 216, 150, 64, 55, 254, 169, 141, 72, 231, 28, 86, 134, 187, 233, 40, 75, 152, 213, 237, 62, 115, 158, 50, 238, 209, 141, 72, 63, 231, 207, 134, 80, 223, 20, 79, 121, 176, 225, 16, 64, 147, 174, 228, 55, 75, 134, 58, 9, 199, 132, 113, 38, 238, 217, 156, 89, 214, 13, 70, 118, 171, 217, 24, 88, 106, 167, 251, 15, 67, 142, 66, 1, 207, 188, 121, 46, 23, 192, 149, 96, 207, 4, 62, 111, 163, 209, 0, 80, 98, 190, 244, 6, 91, 118, 73, 25, 244, 187, 98, 81, 31, 200, 174, 104, 199, 254, 52, 100, 155, 201, 15, 41, 122, 182, 203, 30, 82, 127, 80, 17, 253, 161, 107, 88, 5, 239, 167, 112, 190, 247, 43, 93, 144, 193, 247, 33, 114, 143, 194, 23, 52, 106, 93, 54, 229, 169, 148, 67, 18, 229, 185, 123, 182, 232, 33, 170, 136, 184, 248, 56, 74, 134, 219, 239, 63, 99, 100, 62, 234, 215, 158, 85, 40, 253, 178, 133, 175, 225, 231, 179, 131, 176, 224, 48, 66, 159, 211, 231, 38, 93, 98, 38, 19, 221, 135, 108, 33, 244, 203, 141, 166, 36, 237, 184, 120, 168, 232, 11, 90, 144, 170, 253, 43, 168, 120, 46, 25, 219, 146, 97, 63, 9, 206, 151, 158, 45, 244, 192, 112, 175, 209, 3, 82, 104, 162, 235, 29, 179, 118, 86, 30, 210, 171, 120, 55, 1, 215, 158, 150, 54, 252, 203, 105, 150, 216, 25, 46, 124, 167, 214, 17, 190, 143, 67, 19, 236, 170, 126, 64, 21, 216, 164, 117, 53, 13, 215, 99, 158, 193, 19, 36, 122, 174, 220, 245, 202, 133, 91, 40, 234, 181, 131, 76, 25, 226, 172, 127, 78, 5, 220, 91, 134, 202, 235, 60, 115, 147, 207, 250, 196, 157, 85, 46, 246, 65, 119, 174, 221, 20, 181, 139, 71, 28, 230, 80, 143, 178, 254, 40, 80, 148, 57, 13, 218, 147, 99, 206, 0, 61, 107, 166, 215, 240, 180, 133, 89, 23, 235, 78, 115, 185, 231, 21, 80, 117, 74, 7, 223, 166, 145, 195, 252, 59, 109, 158, 49, 241, 200, 129, 80, 34, 243, 74, 124, 161, 237, 21, 181, 120, 64, 19, 228, 86, 142, 183, 253, 35, 85, 147, 49, 14, 223, 151, 108, 43, 1, 61, 100, 174, 219, 243, 186, 142, 84, 25, 20, 68, 139, 185, 230, 42, 86, 114, 75, 27, 216, 168, 106, 201, 249, 58, 111, 156, 44, 255, 194, 140, 88, 223, 7, 79, 118, 162, 239, 26, 180, 119, 88, 24, 213, 161, 117, 63, 240, 40, 163, 105, 49, 5, 205, 151, 154, 213, 10, 51, 122, 170, 218, 235, 178, 137, 86, 18, 227, 176, 125, 187, 16, 216, 171, 116, 63, 8, 40, 106, 157, 197, 242, 56, 99, 97, 46, 254, 203, 136, 80, 32, 234, 186, 132, 70, 28, 224, 182, 133, 71, 233, 43, 80, 131, 202, 252, 41, 156, 104, 60, 252, 201, 144, 96, 46, 244, 199, 135, 84, 42, 237, 69, 125, 187, 224, 23, 90, 141, 179, 16, 36, 164, 114, 195, 4, 208, 158, 109, 55, 243, 193, 145, 89, 214, 10, 56, 114, 175, 215, 22, 78, 124, 178, 24, 226, 83, 135, 70, 14, 223, 161, 123, 55, 5, 215, 103, 155, 200, 5, 52, 105, 162, 210, 10, 191, 117, 85, 220, 16, 182, 129, 73, 17, 235, 160, 122, 71, 245, 32, 95, 152, 199, 251, 208, 100, 103, 49, 3, 58, 105, 164, 214, 243, 187, 129, 94, 16, 234, 181, 121, 191, 239, 25, 82, 118, 64, 15, 222, 162, 145, 197, 253, 56, 103, 101, 52, 241, 205, 158, 163, 218, 4, 82, 127, 171, 224, 236, 177, 122, 67, 20, 225, 87, 129, 183, 240, 215, 164, 102, 53, 13, 50, 99, 144, 194, 15, 60, 110, 83, 32, 246, 183, 133, 80, 226, 16, 68, 128, 73, 28, 210, 165, 124, 185, 253, 57, 77, 153, 205, 252, 197, 155, 100, 36, 251, 199, 143, 173, 222, 241, 185, 141, 92, 19, 230, 71, 143, 163, 252, 38, 84, 117, 56, 9, 211, 168, 104, 53, 3, 53, 150, 103, 43, 247, 211, 134, 175, 213, 4, 81, 118, 172, 228, 228, 178, 127, 67, 16, 222, 170, 140, 193, 1, 221, 145, 126, 36, 251, 58, 123, 135, 220, 14, 194, 141, 90, 33, 236, 187, 133, 76, 27, 27, 183, 114, 75, 4, 202, 163, 157, 210, 239, 57, 102, 148, 202, 0, 54, 107, 98, 212, 244, 197, 112, 83, 40, 230, 174, 153, 68, 237, 21, 67, 150, 179, 238, 38, 95, 140, 197, 249, 209, 157, 108, 51, 254, 195, 159, 77, 55, 249, 53, 125, 166, 209, 17, 183, 127, 186, 237, 21, 86, 134, 69, 14, 216, 164, 119, 53, 23, 202, 151, 149, 202, 9, 59, 151, 88, 210, 12, 76, 101, 162, 221, 20, 73, 126, 79, 17, 238, 186, 96, 66, 248, 35, 81, 146, 54, 12, 43, 99, 149, 223, 4, 57, 111, 161, 210, 12, 186, 131, 76, 16, 19, 79, 125, 176, 17, 245, 171, 143, 187, 252, 40, 92, 110, 197, 253, 56, 102, 154, 59, 233, 60, 102, 93, 218, 246, 171, 154, 172, 231, 31, 70, 133, 77, 23, 28, 81, 128, 185, 13, 220, 88, 131, 196, 1, 202, 140, 121, 41, 3, 57, 99, 173, 44, 251, 188, 121, 168, 235, 19, 180, 134, 170, 230, 223, 84, 100, 98, 0, 47, 93, 148, 207, 8, 220, 159, 156, 208, 3, 49, 137, 162, 254, 28, 71, 122, 90, 60, 247, 70, 135, 181, 235, 211, 179, 127, 62, 14, 47, 86, 108, 193, 218, 39, 105, 153, 40, 228, 200, 99, 172, 216, 19, 181, 155, 67, 24, 229, 79, 137, 70, 225, 3, 88, 113, 62, 14, 195, 157, 128, 216, 246, 53, 153, 127, 52, 254, 196, 114, 165, 217, 10, 95, 125, 76, 19, 247, 191, 130, 175, 248, 47, 166, 127, 43, 27, 218, 152, 109, 55, 20, 20, 100, 159, 46, 228, 216, 142, 185, 205, 29, 79, 138, 92, 21, 236, 167, 120, 66, 239, 5, 67, 142, 58, 12, 207, 142, 156, 221, 12, 63, 144, 80, 36, 242, 192, 118, 168, 220, 9, 106, 119, 74, 19, 250, 179, 121, 168, 254, 32, 160, 96, 40, 8, 212, 97, 155, 201, 29, 27, 126, 95, 45, 227, 156, 140, 164, 213, 22, 177, 146, 90, 6, 235, 174, 121, 184, 210, 23, 66, 149, 199, 9, 204, 157, 136, 196, 249, 202, 135, 64, 60, 251, 182, 133, 170, 196, 59, 82, 118, 178, 30, 240, 86, 158, 173, 9, 202, 180, 113, 34, 8, 199, 137, 102, 233, 35, 52, 105, 166, 43, 248, 86, 86, 184, 225, 230, 162, 98, 80, 31, 234, 178, 116, 155, 238, 41, 95, 147, 41, 11, 40, 68, 139, 47, 253, 213, 136, 74, 34, 252, 170, 115, 139, 236, 239, 178, 116, 92, 20, 61, 74, 141, 71, 13, 218, 181, 107, 203, 9, 197, 124, 188, 211, 243, 194, 157, 78, 221, 20, 84, 130, 86, 26, 246, 163, 125, 183, 27, 42, 119, 157, 63, 14, 209, 178, 100, 194, 236, 204, 158, 99, 37, 237, 210, 139, 93, 221, 14, 103, 106, 80, 31, 225, 189, 124, 180, 239, 212, 174, 112, 53, 24, 196, 144, 149, 211, 226, 37, 97, 159, 43, 242, 62, 119, 91, 40, 233, 184, 134, 73, 22, 241, 185, 138, 160, 254, 43, 94, 140, 62, 245, 37, 156, 123, 58, 251, 200, 106, 99, 37, 243, 48, 97, 162, 217, 17, 69, 120, 183, 226, 231, 161, 110, 74, 21, 39, 167, 125, 62, 232, 57, 104, 147, 207, 0, 50, 98, 165, 44, 255, 206, 153, 93, 220, 237, 186, 131, 188, 232, 17, 91, 130, 186, 249, 44, 167, 125, 50, 12, 220, 152, 152, 58, 240, 200, 101, 168, 223, 0, 70, 119, 163, 211, 233, 162, 144, 68, 16, 227, 90, 120, 73, 241, 33, 90, 145, 201, 247, 40, 111, 146, 55, 234, 210, 157, 90, 212, 5, 67, 119, 173, 227, 238, 183, 120, 191, 231, 17, 80, 123, 87, 21, 203, 166, 151, 192, 248, 57, 110, 152, 52, 4, 62, 98, 177, 213, 246, 169, 145, 74, 14, 232, 76, 135, 190, 225, 26, 169, 117, 191, 249, 62, 72, 149, 48, 21, 209, 131, 105, 44, 3, 42, 124, 175, 216, 244, 187, 120, 189, 247, 25, 74, 121, 82, 10, 204, 167, 114, 184, 236, 60, 88, 108, 54, 3, 55, 106, 144, 213, 251, 201, 154, 78, 53, 250, 69, 107, 184, 238, 27, 177, 121, 181, 224, 47, 83, 126, 46, 5, 196, 178, 109, 197, 237, 61, 97, 159, 40, 253, 57, 126, 171, 218, 229, 181, 138, 64, 21, 229, 69, 146, 182, 234, 221, 173, 112, 199, 253, 45, 157, 98, 60, 11, 197, 157, 159, 217, 3, 52, 117, 166, 32, 16, 78, 127, 74, 29, 225, 181, 115, 64, 16, 33, 91, 139, 196, 244, 44, 98, 144, 201, 252, 204, 145, 101, 34, 241, 63, 118, 172, 216, 23, 68, 125, 179, 229, 25, 173, 115, 77, 16, 218, 161, 114, 199, 252, 47, 103, 144, 205, 1, 50, 111, 93, 32, 252, 196, 137, 87, 221, 21, 75, 130, 178, 228, 30, 80, 130, 189, 240, 210, 174, 119, 60, 0, 47, 105, 148, 202, 3, 55, 147, 92, 40, 8, 68, 136, 93, 39, 236, 189, 137, 183, 230, 16, 91, 143, 191, 13, 218, 91, 144, 62, 13, 212, 152, 110, 58, 255, 63, 100, 171, 219, 7, 69, 136, 85, 30, 238, 188, 135, 72, 16, 232, 168, 137, 190, 246, 47, 80, 152, 194, 249, 48, 159, 111, 56, 248, 197, 151, 88, 218, 14, 66, 118, 169, 233, 17, 77, 134, 180, 18, 234, 172, 112, 70, 15, 44, 85, 150, 199, 253, 51, 103, 152, 214, 1, 199, 151, 93, 33, 250, 181, 135, 165, 232, 16, 73, 130, 73, 22, 32, 81, 138, 67, 9, 212, 171, 96, 50, 255, 52, 111, 150, 217, 5, 198, 139, 88, 36, 240, 70, 122, 82, 21, 239, 176, 130, 180, 235, 43, 95, 136, 62, 14, 210, 168, 104, 203, 255, 206, 149, 98, 44, 249, 62, 119, 160, 223, 19, 69, 128, 87, 24, 230, 179, 127, 70, 239, 32, 85, 143, 197, 242, 42, 158, 149, 53, 1, 203, 105, 101, 43, 242, 192, 114, 164, 217, 22, 67, 123, 76, 31, 224, 177, 128, 190, 239, 217, 175, 116, 63, 244, 36, 104, 145, 202, 250, 195, 156, 100, 214, 15, 56, 114, 83, 36, 233, 184, 127, 184, 236, 29, 174, 124, 77, 22, 217, 91, 138, 194, 6, 208, 159, 104, 206, 7, 48, 111, 95, 41, 246, 193, 116, 169, 32, 239, 178, 134, 79, 230, 24, 84, 131, 191, 15, 223, 161, 112, 199, 250, 47, 157, 98, 53, 248, 201, 110, 164, 209, 14, 64, 137, 86, 33, 21, 74, 122, 179, 20, 231, 168, 124, 66, 243, 35, 93, 148, 197, 6, 210, 100, 152, 204, 1, 57, 144, 88, 44, 240, 188, 119, 175, 227, 20, 181, 128, 75, 22, 30, 82, 136, 189, 13, 218, 160, 108, 57, 250, 49, 100, 155, 205, 5, 57, 145, 93, 38, 242, 189, 136, 82, 30, 233, 180, 128, 181, 20, 31, 87, 138, 191, 243, 215, 161, 110, 58, 3, 49, 103, 154, 47, 251, 196, 144, 165, 219, 13, 65, 120, 83, 31, 235, 177, 126, 183, 232, 34, 85, 119, 66, 11, 40, 95, 145, 202, 252, 205, 154, 97, 44, 249, 57, 114, 164, 37, 241, 186, 134, 175, 226, 25, 76, 130, 72, 17, 220, 168, 116, 192, 244, 42, 160, 148, 201, 1, 204, 104, 157, 45, 7, 60, 142, 88, 36, 239, 186, 122, 175, 27, 230, 78, 131, 71, 18, 221, 168, 115, 193, 246, 43, 96, 148, 53, 1, 203, 105, 158, 211, 8, 61, 141, 89, 34, 239, 185, 122, 178, 228, 26, 176, 122, 70, 238, 35, 89, 141, 194, 9, 210, 159, 105, 52, 0, 52, 107, 159, 43, 246, 193, 115, 168, 221, 18, 184, 131, 79, 25, 228, 80, 133, 186, 239, 36, 89, 142, 195, 248, 210, 157, 105, 51, 254, 201, 148, 160, 213, 10, 192, 139, 86, 222, 18, 73, 125, 77, 25, 226, 175, 121, 187, 240, 37, 165, 143, 59, 6, 46, 99, 152, 205, 3, 55, 147, 94, 41, 244, 191, 117, 170, 32, 235, 73, 126, 179, 233, 28, 173, 120, 188, 241, 217, 164, 111, 58, 5, 208, 155, 153, 206, 3, 56, 109, 93, 40, 243, 190, 118, 171, 31, 234, 181, 128, 75, 22, 225, 83, 137, 188, 242, 39, 163, 111, 56, 4, 49, 100, 154, 48, 251, 198, 145, 163, 216, 13, 66, 119, 172, 30, 233, 180, 127, 74, 21, 31, 84, 137, 190, 12, 215, 93, 146, 199, 252, 49, 153, 100, 47, 5, 58, 111, 164, 217, 14, 67, 120, 173, 226, 232, 179, 129, 182, 235, 32, 170, 117, 64, 11, 41, 94, 147, 200, 253, 50, 103, 99, 46, 249, 196, 112, 165, 218, 240, 187, 134, 81, 28, 231, 77, 130, 183, 236, 222, 169, 116, 192, 245, 42, 95, 148, 54, 1, 204, 104, 157, 210, 7, 60, 113, 89, 36, 16, 186, 133, 80, 27, 25, 78, 131, 71, 18, 221, 168, 115, 193, 246, 212, 159, 106, 53, 0, 52, 105, 158, 211, 8, 61, 141, 88, 35, 17, 70, 123, 176, 229, 229, 176, 123, 70, 17, 35, 88, 141, 194, 8, 211, 158, 105, 52, 0, 53, 106, 159, 43, 246, 193, 140, 87, 221, 18, 71, 131, 78, 25, 228, 175, 122, 69, 239, 36, 89, 142, 60, 7, 45, 98, 151, 204, 1, 54, 148, 95, 213, 245, 192, 139, 86, 222, 19, 72, 125, 178, 24, 227, 174, 121, 68, 240, 37, 90, 143, 59, 6, 209, 156, 103, 205, 2, 55, 108, 94, 41, 244, 191, 117, 170, 223, 20, 73, 129, 76, 23, 226, 173, 135, 188, 241, 217, 164, 111, 58, 5, 47, 100, 153, 206, 3, 56, 146, 93, 40, 243, 65, 118, 171, 224, 234, 181, 128, 75, 233, 30, 83, 136, 66, 13, 216, 163, 110, 198, 251, 48, 101, 101, 48, 251, 198, 145, 92, 216, 13, 66, 136, 83, 30, 233, 180, 127, 181, 234, 31, 171, 118, 65, 243, 40, 162, 146, 56, 252, 49, 102, 155, 208, 5, 58, 111, 164, 217, 14, 67, 135, 173, 226, 23, 76, 129, 182, 20, 223, 170, 117, 64, 11, 214, 94, 147, 200, 2, 205, 152, 99, 46, 249, 59, 143, 165, 218, 15, 68, 121, 81, 28, 231, 77, 130, 183, 236, 33, 86, 139, 192, 245, 213, 160, 148, 54, 1, 204, 151, 98, 45, 7, 60, 113, 166, 219, 16, 186, 133, 80, 27, 230, 78, 124, 184, 237, 34, 87, 115, 62, 9, 212, 159, 106, 53, 255, 52, 105, 158, 211, 8, 194, 141, 88, 35, 238, 70, 123, 79, 229, 26, 176, 123, 185, 238, 35, 167, 114, 61, 8, 211, 97, 105, 203, 255, 53, 107, 96, 215, 246, 61, 113, 87, 223, 239, 71, 128, 76, 26, 230, 173, 120, 68, 19, 217, 175, 140, 60, 250, 39, 97, 157, 200, 4, 50, 144, 160, 35, 245, 195, 138, 160, 222, 26, 76, 124, 76, 8, 236, 164, 114, 69, 242, 32, 80, 135, 207, 250, 46, 152, 105, 56, 246, 204, 102, 168, 192, 25, 78, 124, 93, 43, 241, 151, 152, 94, 17, 23, 65, 154, 166, 230, 41, 164, 104, 45, 18, 195, 150, 159, 195, 27, 34, 124, 174, 45, 252, 163, 151, 67, 12, 234, 68, 108, 169, 245, 12, 88, 113, 82, 17, 193, 177, 106, 202, 234, 44, 115, 150, 202, 244, 220, 177, 124, 48, 249, 70, 102, 182, 254, 15, 90, 130, 67, 5, 243, 187, 117, 187, 253, 62, 77, 157, 57, 10, 215, 133, 114, 56, 249, 63, 127, 191, 193, 27, 72, 134, 94, 11, 248, 189, 127, 185, 251, 59, 71, 129, 191, 26, 204, 135, 113, 46, 8, 53, 119, 129, 204, 28, 52, 112, 81, 61, 229, 169, 130, 160, 241, 56, 85, 144, 179, 29, 201, 133, 87, 33, 24, 44, 79, 180, 232, 224, 37, 108, 100, 58, 225, 214, 131, 175, 212, 12, 88, 105, 162, 18, 245, 151, 86, 88, 14, 217, 92, 148, 229, 233, 48, 108, 105, 58, 26, 221, 132, 158, 221, 29, 34, 103, 182, 220, 225, 165, 174, 109, 5, 234, 73, 151, 155, 205, 60, 78, 137, 58, 29, 197, 143, 97, 195, 16, 44, 114, 144, 215, 248, 223, 168, 117, 63, 252, 71, 109, 169, 197, 7, 68, 131, 79, 1, 195, 182, 116, 203, 237, 52, 121, 134, 200, 246, 212, 179, 120, 9, 224, 196, 101, 181, 253, 55, 95, 115, 74, 10, 245, 184, 127, 190, 227, 57, 65, 150, 194, 3, 202, 183, 64, 25, 234, 195, 98, 189, 247, 33, 89, 103, 81, 52, 243, 171, 140, 178, 230, 1, 78, 155, 177, 15, 204, 131, 72, 17, 27, 223, 108, 141, 234, 43, 37, 122, 92, 36, 235, 166, 133, 85, 241, 3, 84, 101, 191, 235, 249, 178, 80, 104, 19, 201, 84, 157, 224, 219, 41, 124, 97, 57, 237, 210, 154, 162, 202, 30, 93, 98, 166, 227, 243, 148, 92, 99, 12, 234, 171, 147, 163, 208, 9, 81, 151, 44, 16, 215, 148, 145, 216, 38, 45, 118, 181, 44, 225, 149, 167, 126, 6, 228, 177, 154, 160, 193, 54, 71, 117, 84, 4, 203, 94, 146, 220, 226, 38, 71, 157, 45, 229, 230, 145, 118, 43, 226, 78, 106, 179, 192, 10, 92, 118, 67, 10, 209, 86, 143, 222, 227, 53, 76, 148, 62, 37, 212, 190, 127, 34, 244, 45, 127, 133, 194, 3, 66, 139, 94, 1, 238, 78, 143, 165, 245, 57, 91, 114, 42, 23, 207, 186, 126, 58, 0, 58, 124, 131, 199, 7, 198, 135, 75, 50, 238, 66, 98, 170, 249, 15, 76, 113, 88, 8, 253, 187, 126, 53, 253, 62, 118, 129, 199, 0, 193, 134, 115, 44, 13, 44, 109, 183, 199, 30, 190, 155, 85, 56, 250, 189, 112, 188, 225, 61, 77, 158, 192, 11, 220, 133, 97, 50, 13, 43, 117, 191, 197, 11, 211, 156, 75, 1, 253, 185, 126, 191, 242, 11, 92, 128, 72, 31, 204, 180, 143, 194, 229, 51, 125, 143, 205, 246, 222, 143, 64, 60, 248, 64, 123, 188, 201, 27, 77, 141, 95, 15, 240, 169, 130, 165, 239, 7, 67, 147, 60, 23, 203, 135, 126, 60, 252, 54, 122, 181, 196, 8, 183, 157, 77, 12, 225, 78, 109, 175, 246, 11, 86, 136, 78, 27, 206, 187, 98, 59, 246, 34, 118, 137, 48, 253, 210, 134, 83, 42, 8, 78, 111, 182, 237, 26, 75, 118, 68, 2, 240, 166, 137, 179, 254, 63, 84, 145, 63, 22, 193, 138, 99, 208, 2, 44, 100, 170, 215, 240, 188, 138, 66, 19, 227, 72, 133, 185, 224, 39, 82, 114, 69, 6, 218, 164, 107, 206, 255, 55, 118, 154, 219, 6, 193, 138, 87, 36, 245, 65, 122, 175, 232, 231, 75, 124, 77, 23, 210, 173, 122, 58, 253, 40, 78, 147, 206, 253, 201, 104, 105, 44, 242, 198, 117, 88, 203, 23, 77, 126, 87, 31, 241, 186, 120, 64, 224, 39, 88, 135, 199, 241, 211, 158, 121, 61, 5, 206, 102, 148, 193, 0, 62, 136, 76, 39, 255, 190, 132, 78, 235, 29, 94, 129, 186, 23, 205, 175, 125, 192, 240, 33, 110, 158, 204, 243, 201, 146, 110, 41, 253, 61, 112, 163, 209, 17, 66, 142, 72, 23, 226, 86, 131, 170, 232, 45, 160, 114, 194, 12, 46, 149, 151, 206, 3, 60, 148, 161, 36, 253, 205, 128, 175, 219, 3, 67, 116, 73, 29, 31, 164, 135, 66, 240, 35, 94, 129, 198, 248, 221, 147, 105, 35, 2, 51, 102, 176, 222, 10, 68, 116, 86, 223, 227, 180, 129, 183, 225, 26, 83, 127, 74, 3, 211, 166, 111, 193, 240, 47, 101, 145, 204, 6, 57, 145, 95, 42, 9, 64, 112, 86, 24, 239, 187, 126, 180, 22, 22, 175, 115, 189, 13, 37, 89, 144, 196, 251, 53, 96, 155, 206, 241, 206, 155, 84, 208, 15, 75, 124, 87, 229, 233, 178, 128, 66, 23, 227, 85, 131, 186, 249, 215, 164, 107, 52, 3, 207, 103, 147, 45, 2, 49, 110, 162, 34, 246, 182, 141, 82, 24, 17, 78, 127, 178, 17, 39, 87, 138, 183, 1, 40, 86, 147, 196, 2, 51, 158, 104, 208, 247, 59, 137, 82, 216, 245, 72, 126, 169, 237, 237, 69, 134, 75, 225, 213, 85, 127, 54, 244, 219, 88, 101, 50, 2, 198, 102, 99, 217, 12, 192, 102, 164, 215, 26, 179, 127, 74, 29, 246, 191, 128, 73, 229, 223, 82, 130, 62, 249, 210, 101, 155, 49, 232, 201, 110, 96, 60, 246, 220, 136, 75, 46, 18, 177, 105, 180, 232, 17, 180, 146, 66, 229, 37, 160, 135, 44, 244, 195, 149, 110, 32, 2, 193, 98, 150, 215, 24, 197, 103, 163, 216, 1, 176, 123, 94, 30, 233, 189, 120, 80, 237, 216, 92, 128, 198, 247, 214, 106, 144, 51, 19, 205, 98, 87, 34, 253, 214, 140, 79, 39, 235, 73, 111, 186, 255, 27, 95, 150, 64, 252, 211, 91, 123, 54, 3, 198, 158, 113, 52, 251, 204, 124, 162, 192, 1, 80, 108, 175, 202, 232, 73, 136, 88, 29, 254, 164, 109, 74, 10, 220, 75, 148, 215, 241, 35, 124, 159, 218, 2, 59, 145, 77, 47, 232, 181, 145, 90, 24, 224, 69, 123, 166, 230, 20, 71, 143, 176, 241, 217, 162, 98, 61, 10, 198, 147, 106, 53, 241, 58, 107, 164, 214, 7, 76, 126, 164, 226, 232, 177, 117, 66, 31, 229, 175, 117, 190, 15, 45, 93, 144, 195, 254, 57, 100, 147, 47, 251, 199, 155, 95, 45, 245, 67, 135, 164, 230, 29, 74, 128, 180, 16, 223, 175, 116, 68, 15, 41, 164, 146, 54, 253, 49, 103, 152, 208, 0, 63, 112, 166, 33, 12, 185, 143, 82, 20, 227, 183, 130, 180, 239, 40, 85, 141, 194, 11, 41, 164, 106, 55, 2, 204, 149, 98, 47, 249, 193, 140, 167, 219, 19, 65, 126, 172, 229, 24, 176, 125, 68, 16, 222, 169, 141, 62, 244, 43, 96, 148, 53, 255, 202, 151, 97, 46, 8, 195, 141, 167, 35, 17, 185, 121, 177, 228, 24, 176, 132, 71, 16, 35, 166, 141, 60, 8, 211, 156, 150, 54, 0, 53, 104, 154, 215, 15, 60, 114, 168, 38, 239, 188, 129, 78, 24, 27, 173, 123, 68, 18, 219, 166, 140, 193, 251, 47, 99, 149, 50, 254, 203, 150, 94, 43, 10, 192, 116, 87, 32, 236, 183, 124, 179, 229, 29, 81, 135, 69, 15, 219, 165, 143, 59, 250, 47, 97, 153, 50, 253, 202, 108, 95, 214, 244, 190, 117, 84, 32, 235, 182, 126, 179, 234, 28, 81, 133, 189, 243, 216, 91, 110, 56, 4, 212, 154, 101, 48, 252, 199, 108, 162, 214, 13, 64, 116, 170, 225, 20, 74, 127, 74, 23, 226, 174, 117, 64, 13, 39, 93, 147, 196, 249, 49, 100, 154, 207, 251, 57, 110, 92, 216, 243, 188, 137, 81, 30, 233, 74, 129, 180, 234, 31, 84, 118, 65, 243, 215, 93, 146, 56, 3, 207, 153, 101, 47, 5, 58, 110, 165, 216, 14, 188, 134, 83, 28, 232, 76, 128, 183, 234, 32, 170, 117, 64, 11, 41, 94, 145, 201, 252, 50, 153, 98, 45, 248, 197, 112, 167, 219, 14, 68, 134, 80, 29, 230, 178, 125, 183, 236, 33, 86, 116, 63, 11, 212, 160, 107, 200, 254, 50, 105, 98, 210, 249, 195, 113, 166, 219, 239, 69, 122, 80, 228, 230, 78, 124, 184, 237, 221, 87, 115, 62, 9, 212, 96, 106, 53, 0, 203, 150, 97, 211, 8, 60, 115, 167, 220, 238, 185, 133, 78, 26, 229, 79, 123, 70, 238, 220, 88, 114, 194, 247, 44, 96, 151, 202, 1, 53, 149, 97, 42, 247, 192, 140, 87, 34, 237, 184, 131, 177, 230, 27, 81, 132, 187, 238, 36, 89, 113, 61, 6, 211, 156, 105, 51, 254, 201, 148, 160, 213, 10, 62, 117, 168, 220, 18, 72, 125, 77, 25, 226, 175, 120, 68, 15, 218, 165, 112, 196, 249, 46, 99, 153, 204, 3, 55, 108, 94, 41, 244, 190, 139, 84, 33, 235, 183, 129, 76, 23, 29, 82, 134, 189, 240, 38, 91, 144, 58, 250, 208, 100, 102, 49, 252, 199, 146, 93, 40, 243, 190, 118, 171, 225, 20, 74, 127, 180, 233, 225, 172, 119, 66, 13, 216, 163, 110, 57, 4, 207, 101, 154, 207, 4, 57, 110, 163, 216, 13, 189, 136, 83, 30, 232, 180, 127, 74, 234, 224, 84, 137, 190, 243, 40, 93, 146, 199, 252, 206, 153, 100, 47, 250, 197, 111, 164, 217, 14, 67, 120, 173, 227, 23, 76, 129, 73, 20, 223, 171, 116, 65, 10, 214, 161, 147, 200, 253, 51, 102, 157, 208, 6, 59, 112, 90, 37, 240, 187, 135, 81, 28, 231, 77, 125, 183, 236, 33, 86, 139, 193, 245, 42, 95, 107, 201, 0, 204, 151, 98, 45, 248, 195, 142, 166, 219, 16, 69, 122, 175, 228, 25, 78, 124, 71, 18, 221, 168, 115, 62, 9, 212, 96, 149, 202, 255, 52, 105, 158, 211, 8, 61, 141, 88, 35, 238, 185, 132, 79, 26, 26, 79, 132, 185, 238, 35, 88, 141, 194, 247, 44, 158, 105, 52, 255, 202, 149, 96, 43, 246, 193, 115, 168, 221, 18, 71, 124, 177, 230, 27, 80, 133, 69, 16, 219, 166, 113, 60, 7, 210, 98, 151, 204, 1, 54, 107, 160, 213, 10, 63, 116, 86, 33, 236, 183, 130, 77, 24, 227, 174, 121, 187, 240, 37, 90, 143, 196, 249, 46, 99, 152, 205, 253, 200, 147, 94, 41, 244, 191, 138, 85, 223, 235, 73, 126, 179, 232, 226, 82, 135, 188, 241, 38, 91, 111, 58, 5, 208, 100, 102, 206, 3, 56, 109, 93, 215, 243, 65, 118, 84, 224, 21, 74, 128, 75, 22, 225, 172, 119, 66, 13, 39, 92, 145, 198, 4, 48, 154, 101, 48, 251, 198, 145, 92, 39, 13, 66, 119, 172, 225, 22, 75, 128, 181, 234, 31, 84, 137, 190, 12, 40, 162, 109, 56, 3, 49, 153, 155, 208, 5, 58, 111, 164, 217, 14, 67, 135, 173, 29, 232, 179, 126, 73, 20, 32, 85, 117, 64, 11, 41, 161, 147, 200, 2, 50, 152, 156, 209, 249, 196, 143, 90, 37, 240, 187, 134, 174, 227, 24, 77, 130, 183, 236, 33, 86, 139, 192, 10, 213, 160, 148, 54, 254, 51, 151, 157, 210, 7, 60, 142, 89, 36, 239, 186, 133, 80, 27, 25, 177, 124, 71, 18, 34, 87, 140, 193, 246, 43, 96, 149, 202, 255, 203, 105, 97, 44, 247, 194, 141, 88, 35, 238, 185, 123, 176, 229, 26, 79, 132, 185, 238, 35, 88, 141, 194, 8, 44, 158, 105, 52, 255, 202, 149, 159, 212, 9, 193, 140, 168, 34, 18, 71, 131, 78, 25, 27, 174, 129, 69, 21, 39, 165, 112, 199, 6, 45, 98, 105, 204, 3, 54, 149, 161, 40, 245, 63, 137, 168, 33, 236, 75, 125, 178, 230, 28, 81, 121, 184, 11, 217, 90, 115, 197, 248, 46, 98, 152, 204, 2, 54, 147, 95, 41, 246, 191, 137, 175, 221, 238, 76, 130, 77, 235, 224, 83, 120, 66, 14, 39, 90, 111, 199, 4, 209, 103, 100, 207, 0, 193, 109, 162, 41, 13, 65, 119, 85, 224, 21, 180, 125, 73, 22, 31, 175, 138, 67, 13, 38, 163, 145, 198, 251, 48, 101, 154, 48, 250, 57, 145, 92, 39, 242, 66, 119, 172, 225, 22, 180, 128, 74, 21, 31, 170, 118, 65, 241, 40, 163, 146, 56, 252, 206, 102, 100, 47, 250, 196, 110, 91, 38, 15, 184, 124, 175, 30, 21, 178, 124, 182, 20, 223, 85, 117, 64, 245, 41, 94, 146, 54, 2, 205, 152, 157, 47, 6, 59, 112, 164, 36, 15, 69, 135, 174, 28, 229, 79, 125, 72, 237, 223, 86, 116, 62, 245, 213, 160, 148, 54, 1, 51, 104, 98, 210, 7, 195, 113, 89, 37, 16, 186, 133, 175, 228, 25, 78, 124, 184, 18, 220, 87, 141, 63, 246, 42, 159, 149, 202, 1, 52, 105, 97, 211, 247, 61, 141, 88, 220, 17, 70, 123, 176, 26, 229, 79, 122, 185, 238, 220, 88, 141, 194, 8, 44, 97, 105, 203, 255, 202, 106, 96, 212, 246, 193, 115, 87, 221, 18, 184, 124, 78, 25, 27, 80, 122, 186, 239, 219, 89, 142, 60, 7, 45, 98, 104, 204, 254, 54, 107, 95, 42, 245, 63, 116, 86, 222, 19, 72, 130, 77, 24, 227, 81, 121, 68, 240, 218, 165, 143, 59, 6, 46, 156, 152, 50, 253, 55, 147, 94, 214, 245, 64, 138, 85, 223, 235, 73, 129, 179, 232, 226, 82, 120, 188, 241, 217, 164, 111, 58, 5, 208, 100, 102, 206, 3, 199, 109, 162, 40, 243, 190, 118, 171, 31, 21, 181, 128, 180, 22, 30, 172, 119, 189, 13, 216, 92, 145, 57, 251, 207, 154, 154, 48, 251, 57, 110, 92, 216, 13, 189, 119, 83, 30, 22, 180, 128, 74, 234, 31, 171, 137, 65, 12, 40, 162, 146, 56, 252, 49, 153, 155, 47, 5, 58, 144, 164, 38, 241, 67, 135, 173, 29, 232, 76, 126, 182, 235, 32, 170, 138, 191, 11, 41, 94, 108, 200, 253, 205, 103, 156, 46, 6, 196, 143, 90, 218, 240, 187, 121, 81, 227, 231, 77, 125, 72, 236, 222, 86, 116, 63, 245, 213, 95, 148, 54, 1, 51, 151, 98, 210, 248, 60, 113, 89, 219, 16, 186, 122, 80, 27, 25, 78, 124, 184, 18, 221, 87, 115, 62, 9, 43, 159, 149, 53, 255, 203, 105, 158, 44, 247, 194, 141, 167, 35, 17, 70, 132, 176, 26, 26, 79, 123, 185, 17, 220, 88, 114, 194, 247, 211, 97, 150, 52, 0, 53, 106, 159, 212, 246, 193, 140, 168, 34, 237, 71, 131, 78, 25, 228, 80, 122, 69, 16, 36, 89, 142, 195, 7, 45, 157, 104, 204, 254, 54, 107, 95, 213, 10, 63, 139, 169, 33, 236, 72, 130, 77, 231, 227, 81, 121, 68, 240, 218, 165, 143, 196, 249, 46, 99, 152, 50, 2, 200, 147, 161, 41, 244, 64, 138, 170, 223, 235, 73, 129, 179, 232, 29, 82, 120, 188, 14, 38, 91, 111, 197, 5, 208, 100, 102, 49, 252, 199, 109, 162, 215, 243, 190, 118, 84, 224, 21, 181, 128, 75, 22, 30, 83, 119, 66, 242, 216, 92, 145, 198, 251, 48, 154, 154, 48, 251, 57, 145, 163, 216, 242, 66, 136, 83, 225, 233, 75, 128, 74, 234, 31, 84, 137, 190, 12, 215, 93, 146, 199, 252, 49, 153, 100, 208, 250, 197, 111, 91, 38, 14, 67, 120, 173, 29, 23, 179, 126, 73, 20, 223, 170, 117, 191, 11, 214, 161, 108, 200, 2, 205, 103, 156, 209, 6, 196, 143, 165, 37, 240, 187, 134, 174, 227, 231, 178, 125, 72, 19, 222, 86, 139, 63, 245, 42, 95, 148, 54, 254, 51, 104, 157, 210, 7, 60, 113, 166, 219, 16, 186, 122, 175, 27, 25, 177, 131, 71, 237, 34, 87, 140, 193, 246, 43, 96, 149, 202, 255, 52, 105, 158, 211, 8, 61, 114, 167, 220, 17, 70, 123, 176, 229, 26, 79, 132, 185, 238, 35, 88, 141, 194, 247, 44, 97, 150, 203, 0, 53, 106, 159, 212, 9, 62, 115, 168, 221, 237, 71, 131, 78, 25, 228, 175, 122, 69, 16, 219, 166, 113, 195, 248, 210, 157, 151, 51, 254, 54, 148, 95, 42, 245, 63, 139, 169, 222, 19, 72, 125, 178, 231, 28, 81, 134, 187, 240, 37, 165, 112, 59, 6, 209, 156, 103, 50, 2, 55, 147, 94, 214, 244, 191, 138, 85, 223, 20, 73, 126, 76, 23, 226, 173, 120, 67, 14, 217, 164, 111, 58, 5, 208, 100, 153, 206, 3, 56, 109, 162, 215, 12, 65, 118, 171, 224, 21, 74, 128, 75, 22, 225, 172, 119, 66, 13, 216, 163, 110, 198, 251, 48, 101, 154, 207, 4, 57, 110, 163, 216, 242, 189, 136, 82, 31, 232, 181, 126, 75, 21, 224, 84, 137, 191, 242, 41, 95, 144, 197, 253, 48, 103, 154, 208, 250, 197, 145, 89, 37, 242, 191, 132, 80, 28, 232, 76, 128, 183, 233, 35, 86, 137, 189, 246, 43, 95, 146, 200, 2, 204, 154, 96, 42, 253, 192, 139, 89, 39, 241, 187, 120, 172, 224, 28, 73, 134, 179, 232, 37, 85, 136, 194, 244, 213, 161, 104, 51, 7, 203, 144, 100, 40, 251, 194, 113, 167, 216, 20, 65, 126, 170, 225, 31, 72, 133, 190, 232, 33, 86, 114, 58, 15, 221, 148, 102, 62, 10, 204, 146, 96, 210, 11, 56, 117, 160, 218, 23, 64, 125, 182, 227, 28, 74, 128, 186, 239, 221, 163, 117, 55, 4, 222, 146, 98, 61, 249, 200, 107, 155, 211, 1, 55, 123, 175, 219, 20, 65, 122, 180, 227, 31, 83, 132, 68, 19, 221, 175, 125, 49, 10, 222, 151, 111, 48, 0, 51, 99, 170, 223, 3, 56, 113, 173, 218, 23, 76, 121, 177, 228, 30, 81, 120, 64, 8, 208, 169, 124, 48, 15, 215, 159, 152, 206, 5, 63, 100, 166, 211, 8, 65, 116, 168, 221, 23, 74, 125, 176, 234, 28, 173, 123, 69, 6, 211, 174, 102, 50, 3, 211, 100, 154, 203, 5, 61, 105, 160, 215, 12, 64, 117, 174, 230, 18, 77, 121, 177, 234, 30, 175, 113, 75, 7, 211, 169, 103, 62, 1, 205, 101, 152, 204, 7, 58, 108, 161, 219, 9, 71, 112, 164, 233, 30, 76, 134, 182, 234, 226, 174, 126, 72, 6, 221, 168, 101, 62, 7, 207, 153, 154, 210, 7, 56, 109, 167, 221, 11, 68, 127, 165, 234, 16, 73, 130, 183, 21, 219, 172, 124, 74, 1, 220, 168, 107, 50, 1, 204, 103, 158, 210, 2, 63, 116, 160, 223, 9, 67, 113, 166, 228, 30, 73, 128, 72, 16, 219, 174, 124, 54, 3, 221, 168, 109, 51, 2, 206, 151, 156, 209, 3, 56, 117, 162, 222, 21, 67, 124, 169, 225, 29, 77, 130, 71, 16, 222, 173, 117, 57, 14, 211, 153, 111, 49, 3, 201, 150, 158, 209, 11, 62, 113, 164, 216, 21, 67, 126, 181, 225, 30, 76, 134, 184, 238, 220, 165, 113, 57, 13, 214, 155, 109, 48, 251, 201, 150, 98, 42, 246, 193, 115, 169, 223, 16, 68, 120, 181, 226, 31, 84, 129, 190, 236, 39, 91, 142, 60, 5, 209, 153, 109, 54, 248, 207, 146, 89, 47, 241, 195, 138, 86, 222, 17, 75, 121, 183, 225, 26, 86, 128, 189, 246, 32, 94, 141, 197, 6, 211, 159, 99, 53, 245, 192, 155, 86, 46, 242, 186, 137, 85, 222, 23, 77, 123, 183, 236, 24, 87, 130, 185, 244, 35, 95, 147, 198, 248, 46, 154, 98, 54, 247, 205, 154, 91, 46, 246, 188, 118, 169, 228, 17, 73, 126, 181, 233, 30, 81, 139, 185, 244, 32, 91, 151, 194, 249, 207, 159, 108, 60, 245, 202, 150, 88, 37, 12, 71, 113, 171, 230, 18, 75, 125, 78, 17, 225, 87, 129, 180, 255, 37, 87, 150, 57, 4, 193, 140, 124, 57, 246, 198, 108, 173, 200, 29, 81, 118, 171, 30, 228, 161, 111, 67, 21, 39, 69, 156, 168, 224, 34, 94, 98, 45, 38, 238, 129, 109, 44, 13, 34, 111, 186, 193, 0, 69, 136, 72, 6, 241, 185, 128, 184, 244, 60, 76, 155, 194, 26, 244, 140, 67, 40, 16, 206, 103, 189, 250, 47, 30, 101, 167, 54, 241, 165, 158, 95, 228, 9, 84, 156, 165, 254, 33, 185, 80, 16, 35, 203, 142, 104, 219, 220, 30, 67, 189, 198, 8, 209, 147, 70, 59, 226, 71, 116, 169, 248, 2, 66, 120, 81, 54, 241, 129, 107, 55, 244, 56, 66, 191, 236, 30, 56, 147, 117, 55, 237, 211, 136, 162, 200, 9, 90, 106, 184, 18, 251, 130, 84, 102, 4, 222, 81, 151, 229, 211, 8, 116, 146, 63, 228, 214, 136, 81, 215, 5, 39, 107, 182, 203, 16, 164, 166, 98, 52, 195, 190, 134, 171, 239, 12, 112, 174, 212, 5, 196, 130, 71, 41, 241, 49, 120, 189, 246, 22, 82, 139, 77, 9, 196, 144, 153, 68, 237, 8, 118, 171, 149, 234, 46, 174, 118, 26, 37, 198, 158, 144, 219, 25, 37, 116, 174, 32, 237, 146, 162, 74, 17, 234, 65, 102, 146, 194, 58, 64, 118, 80, 16, 199, 191, 127, 57, 244, 40, 126, 131, 221, 1, 201, 179, 113, 1, 231, 190, 127, 189, 252, 49, 97, 159, 191, 31, 251, 180, 107, 86, 7, 43, 79, 136, 220, 233, 58, 157, 124, 7, 214, 218, 156, 160, 215, 24, 99, 80, 138, 250, 22, 167, 94, 105, 13, 208, 169, 131, 170, 239, 51, 78, 145, 57, 29, 231, 191, 116, 45, 10, 46, 107, 135, 252, 46, 84, 129, 74, 62, 250, 163, 123, 180, 231, 53, 79, 158, 201, 12, 205, 133, 76, 45, 11, 54, 102, 139, 207, 37, 28, 100, 164, 53, 243, 166, 150, 86, 224, 19, 65, 145, 170, 224, 221, 185, 82, 24, 21, 222, 101, 155, 216, 233, 47, 117, 139, 214, 249, 217, 144, 76, 38, 23, 74, 118, 190, 232, 16, 78, 118, 88, 55, 195, 171, 132, 214, 226, 56, 119, 143, 221, 9, 192, 143, 127, 61, 241, 57, 124, 184, 208, 30, 78, 120, 70, 0, 194, 138, 110, 185, 249, 62, 79, 156, 215, 237, 34, 159, 126, 18, 227, 196, 111, 175, 197, 7, 54, 114, 173, 37, 255, 149, 164, 84, 25, 8, 76, 159, 170, 255, 52, 74, 138, 54, 26, 207, 142, 153, 194, 16, 58, 105, 160, 41, 247, 178, 144, 119, 59, 236, 88, 97, 173, 252, 22, 88, 140, 180, 10, 205, 184, 123, 56, 244, 59, 107, 156, 53, 251, 206, 156, 74, 54, 233, 182, 121, 139, 194, 12, 70, 122, 177, 236, 227, 163, 111, 81, 14, 41, 74, 131, 192, 1, 195, 149, 119, 39, 231, 222, 152, 175, 199, 40, 95, 120, 168, 225, 23, 181, 119, 90, 5, 228, 95, 159, 173, 244, 208, 178, 126, 44, 21, 215, 143, 110, 216, 31, 25, 112, 182, 221, 243, 190, 134, 81, 21, 226, 176, 136, 165, 249, 40, 172, 103, 86, 29, 192, 180, 125, 49, 244, 42, 71, 128, 193, 5, 193, 137, 94, 39, 243, 184, 121, 166, 236, 8, 74, 123, 90, 11, 199, 191, 103, 49, 14, 35, 73, 136, 208, 241, 49, 146, 100, 41, 249, 195, 113, 165, 210, 30, 72, 127, 86, 10, 241, 166, 105, 85, 31, 222, 94, 153, 218, 225, 37, 98, 110, 51, 4, 202, 105, 156, 215, 0, 54, 120, 163, 37, 254, 175, 146, 91, 11, 238, 177, 141, 170, 246, 55, 83, 140, 56, 13, 209, 97, 149, 206, 7, 63, 96, 152, 212, 254, 209, 153, 65, 54, 255, 180, 129, 184, 245, 12, 67, 143, 186, 21, 222, 167, 143, 199, 254, 42, 107, 158, 201, 252, 195, 132, 77, 59, 231, 209, 129, 168, 208, 5, 92, 118, 178, 30, 229, 175, 130, 179, 251, 41, 86, 131, 195, 7, 218, 142, 115, 35, 242, 199, 157, 88, 208, 24, 88, 100, 169, 41, 231, 177, 124, 187, 227, 16, 92, 136, 177, 244, 223, 180, 121, 44, 23, 222, 150, 108, 48, 8, 46, 122, 174, 43, 253, 176, 143, 175, 235, 24, 69, 109, 160, 249, 27, 164, 99, 88, 21, 203, 179, 97, 51, 250, 32, 124, 141, 197, 254, 200, 159, 89, 220, 7, 79, 103, 184, 244, 6, 72, 116, 92, 15, 247, 185, 103, 81, 4, 45, 78, 139, 212, 248, 199, 151, 110, 47, 3, 48, 98, 181, 204, 26, 72, 133, 92, 10, 240, 166, 108, 91, 27, 221, 88, 146, 168, 254, 211, 175, 97, 50, 254, 53, 109, 146, 196, 30, 47, 119, 93, 54, 233, 163, 144, 68, 8, 239, 71, 154, 171, 255, 32, 164, 100, 52, 8, 41, 89, 158, 218, 229, 40, 122, 156, 35, 224, 217, 151, 64, 62, 255, 65, 109, 143, 254, 17, 185, 115, 75, 22, 221, 168, 136, 207, 237, 11, 121, 157, 61, 21, 209, 140, 125, 51, 239, 193, 97, 134, 194, 30, 186, 136, 68, 31, 231, 179, 123, 179, 247, 0, 71, 131, 57, 27, 201, 133, 119, 22, 226, 194, 100, 128, 244, 26, 63, 139, 95, 39, 232, 176, 133, 183, 255, 63, 113, 151, 69, 31, 204, 188, 110, 26, 38, 222, 110, 139, 208, 16, 50, 148, 95, 40, 242, 206, 128, 173, 196, 53, 106, 110, 179, 19, 241, 185, 102, 99, 16, 208, 80, 154, 215, 243, 42, 101, 159, 206, 245, 219, 157, 165, 205, 47, 93, 123, 170, 41, 228, 162, 158, 105, 0, 225, 88, 138, 186, 241, 35, 85, 159, 192, 15, 195, 144, 144, 212, 29, 47, 97, 162, 47, 253, 166, 168, 77, 25, 19, 77, 128, 76, 18, 23, 65, 135, 188, 7, 210, 92, 156, 213, 233, 63, 108, 101, 58, 238, 217, 137, 95, 209, 10, 190, 133, 94, 30, 31, 64, 133, 181, 235, 24, 88, 130, 181, 254, 37, 88, 106, 44, 28, 216, 102, 150, 219, 5, 207, 155, 94, 36, 242, 191, 120, 164, 243, 7, 70, 134, 188, 231, 38, 175, 96, 95, 31, 41, 85, 154, 202, 6, 206, 154, 100, 32, 246, 194, 119, 183, 201, 0, 73, 117, 165, 230, 227, 161, 102, 70, 238, 38, 82, 138, 193, 241, 41, 165, 123, 34, 12, 204, 98, 147, 221, 22, 45, 124, 163, 32, 252, 172, 130, 171, 231, 228, 178, 131, 176, 235, 223, 164, 99, 50, 15, 43, 101, 153, 219, 239, 63, 111, 101, 60, 252, 61, 119, 166, 33, 237, 70, 126, 179, 25, 226, 184, 115, 64, 21, 220, 80, 128, 206, 255, 47, 150, 96, 203, 5, 54, 106, 96, 212, 13, 63, 142, 81, 37, 235, 188, 135, 72, 27, 31, 89, 140, 188, 18, 221, 167, 140, 194, 7, 44, 102, 159, 203, 3, 203, 156, 84, 45, 241, 197, 143, 86, 217, 31, 69, 123, 76, 29, 234, 164, 113, 64, 240, 34, 86, 129, 200, 252, 211, 154, 97, 53, 250, 207, 144, 160, 208, 15, 191, 136, 83, 40, 236, 181, 129, 176, 239, 16, 67, 137, 187, 240, 219, 163, 102, 48, 12, 213, 155, 152, 49, 252, 198, 144, 94, 41, 12, 64, 116, 174, 233, 31, 66, 122, 183, 20, 230, 164, 127, 71, 15, 216, 162, 145, 57, 7, 202, 158, 100, 48, 251, 57, 106, 166, 221, 11, 74, 112, 175, 225, 232, 182, 124, 79, 19, 228, 168, 117, 66, 13, 41, 95, 144, 197, 254, 49, 152, 155, 213, 3, 63, 106, 160, 216, 240, 184, 128, 84, 24, 238, 183, 126, 182, 20, 33, 86, 137, 189, 10, 212, 161, 146, 202, 249, 55, 101, 99, 44, 250, 197, 141, 88, 37, 14, 68, 121, 175, 28, 231, 179, 127, 72, 236, 32, 84, 136, 192, 11, 214, 164, 105, 54, 255, 55, 110, 153, 208, 5, 60, 140, 92, 33, 234, 190, 132, 172, 225, 26, 177, 120, 65, 23, 217, 169, 143, 201, 252, 33, 106, 157, 203, 4, 206, 144, 105, 37, 243, 61, 115, 88, 33, 237, 186, 128, 76, 229, 25, 75, 140, 183, 227, 36, 90, 115, 57, 13, 213, 152, 108, 51, 246, 204, 148, 97, 40, 8, 59, 119, 171, 219, 26, 65, 120, 181, 228, 228, 172, 123, 69, 19, 220, 175, 119, 58, 2, 45, 103, 147, 200, 9, 62, 111, 95, 40, 246, 196, 136, 169, 220, 236, 180, 125, 177, 25, 224, 174, 135, 68, 241, 32, 95, 141, 59, 7, 210, 155, 111, 54, 255, 203, 146, 165, 208, 13, 72, 124, 175, 223, 235, 73, 128, 74, 31, 229, 171, 126, 64, 12, 221, 160, 146, 194, 242, 35, 105, 147, 198, 4, 60, 147, 85, 36, 254, 176, 132, 92, 25, 236, 183, 121, 190, 229, 16, 92, 132, 183, 251, 34, 162, 102, 50, 9, 192, 149, 105, 60, 246, 192, 108, 171, 214, 24, 85, 98, 191, 238, 30, 181, 117, 69, 6, 244, 186, 121, 81, 3, 208, 162, 145, 205, 238, 36, 115, 141, 196, 8, 56, 149, 81, 54, 228, 175, 150, 65, 13, 238, 76, 132, 189, 251, 49, 68, 152, 175, 254, 43, 163, 106, 60, 15, 193, 150, 115, 34, 255, 196, 118, 169, 212, 31, 84, 119, 167, 227, 225, 184, 112, 68, 26, 212, 162, 124, 60, 247, 45, 84, 154, 198, 240, 62, 98, 156, 42, 244, 204, 158, 86, 52, 255, 176, 134, 172, 239, 8, 90, 150, 173, 255, 46, 85, 117, 53, 7, 196, 143, 123, 36, 14, 193, 147, 156, 217, 25, 40, 106, 176, 206, 24, 70, 130, 66, 10, 245, 161, 107, 75, 24, 217, 89, 138, 201, 249, 60, 110, 155, 195, 2, 207, 159, 106, 32, 250, 202, 132, 81, 33, 22, 77, 113, 191, 246, 21, 89, 132, 65, 29, 200, 182, 124, 48, 0, 211, 157, 147, 199, 17, 38, 121, 177, 222, 15, 193, 130, 71, 50, 248, 164, 146, 64, 16, 227, 86, 136, 174, 233, 60, 66, 156, 206, 6, 219, 143, 126, 43, 235, 217, 159, 89, 40, 14, 77, 97, 178, 198, 3, 88, 118, 77, 29, 243, 187, 110, 80, 1, 211, 167, 145, 195, 241, 32, 116, 150, 195, 4, 56, 150, 84, 37, 254, 181, 128, 81, 30, 20, 78, 119, 191, 229, 18, 89, 141, 66, 11, 212, 172, 126, 55, 14, 203, 103, 146, 193, 20, 41, 97, 174, 208, 12, 190, 129, 92, 12, 251, 166, 111, 67, 21, 26, 88, 155, 170, 224, 58, 82, 154, 198, 6, 194, 136, 119, 60, 233, 203, 151, 91, 220, 5, 77, 104, 189, 242, 27, 74, 129, 77, 29, 212, 167, 123, 75, 12, 212, 92, 148, 193, 247, 57, 109, 154, 210, 249, 193, 135, 82, 47, 250, 188, 130, 81, 224, 31, 68, 136, 189, 228, 37, 87, 118, 56, 3, 223, 171, 96, 62, 5, 205, 107, 149, 216, 12, 55, 120, 160, 217, 239, 190, 131, 88, 18, 239, 182, 122, 68, 236, 38, 81, 132, 200, 241, 46, 99, 149, 52, 1, 201, 146, 101, 40, 243, 192, 140, 88, 222, 21, 66, 120, 177, 229, 228, 177, 121, 68, 19, 221, 167, 141, 195, 246, 45, 96, 150, 203, 0, 202, 149, 96, 43, 247, 192, 142, 86, 34, 18, 70, 126, 179, 228, 26, 81, 122, 69, 16, 219, 166, 142, 60, 7, 210, 157, 104, 51, 254, 200, 149, 94, 42, 245, 63, 117, 168, 220, 17, 74, 127, 179, 230, 28, 175, 123, 64, 11, 222, 166, 114, 58, 249, 47, 96, 156, 200, 7, 51, 111, 160, 214, 245, 189, 137, 81, 36, 239, 181, 131, 77, 232, 28, 80, 132, 184, 242, 36, 90, 144, 58, 4, 209, 153, 100, 51, 253, 199, 109, 162, 214, 14, 67, 116, 170, 224, 234, 180, 129, 74, 23, 224, 173, 119, 189, 243, 38, 94, 147, 196, 250, 49, 101, 101, 49, 249, 197, 147, 94, 38, 242, 66, 119, 173, 227, 20, 73, 129, 180, 21, 224, 170, 116, 67, 14, 214, 162, 146, 199, 253, 48, 103, 155, 208, 5, 197, 144, 164, 217, 14, 67, 120, 82, 29, 232, 179, 129, 182, 235, 32, 170, 117, 65, 11, 214, 161, 108, 55, 2, 205, 103, 156, 208, 7, 58, 113, 164, 218, 240, 186, 135, 80, 29, 230, 179, 124, 72, 19, 222, 86, 138, 193, 244, 43, 94, 148, 54, 1, 204, 151, 98, 45, 7, 195, 142, 89, 36, 239, 69, 122, 175, 228, 25, 78, 131, 71, 18, 221, 168, 115, 62, 9, 212, 159, 106, 53, 0, 203, 150, 97, 44, 8, 61, 114, 167, 220, 17, 70, 123, 79, 26, 229, 176, 122, 71, 17, 220, 167, 141, 195, 246, 45, 96, 151, 203, 0, 53, 149, 97, 42, 247, 192, 141, 86, 34, 18, 70, 126, 179, 228, 26, 81, 133, 186, 16, 219, 167, 115, 62, 6, 211, 156, 104, 204, 1, 55, 106, 161, 212, 11, 63, 139, 86, 32, 237, 182, 128, 76, 25, 227, 81, 135, 185, 242, 39, 88, 141, 197, 249, 209, 157, 101, 48, 255, 202, 146, 95, 41, 11, 65, 116, 171, 222, 21, 72, 126, 179, 23, 227, 172, 121, 65, 15, 216, 165, 111, 197, 251, 45, 102, 155, 204, 2, 56, 146, 92, 41, 242, 188, 136, 85, 31, 21, 74, 126, 181, 232, 31, 83, 136, 189, 242, 216, 163, 110, 57, 4, 206, 154, 101, 48, 251, 57, 110, 163, 216, 13, 66, 136, 83, 30, 233, 180, 127, 74, 21, 224, 84, 137, 190, 243, 40, 93, 146, 56, 3, 206, 153, 100, 47, 250, 197, 111, 164, 217, 14, 67, 120, 173, 226, 23, 76, 126, 73, 20, 223, 171, 116, 65, 11, 214, 94, 147, 200, 252, 51, 103, 156, 209, 249, 196, 143, 90, 36, 240, 187, 134, 81, 28, 24, 77, 130, 183, 236, 33, 86, 139, 192, 10, 213, 160, 107, 54, 1, 204, 151, 98, 45, 248, 60, 113, 166, 219, 16, 69, 122, 175, 228, 230, 177, 124, 71, 18, 221, 168, 115, 62, 9, 212, 96, 149, 202, 255, 203, 150, 97, 44, 247, 194, 141, 88, 35, 238, 185, 123, 176, 229, 26, 79, 132, 185, 238, 35, 167, 114, 61, 8, 211, 158, 105, 52, 255, 202, 149, 159, 212, 9, 62, 115, 168, 221, 237, 184, 131, 78, 25, 228, 175, 122, 69, 239, 36, 89, 142, 195, 248, 45, 98, 151, 204, 254, 201, 148, 95, 42, 245, 192, 116, 169, 222, 19, 72, 125, 178, 231, 227, 174, 121, 68, 15, 218, 165, 112, 59, 249, 46, 99, 152, 205, 2, 55, 108, 94, 41, 244, 191, 138, 85, 32, 235, 73, 126, 179, 232, 29, 82, 135, 67, 14, 217, 164, 111, 58, 5, 208, 155, 153, 206, 3, 56, 109, 162, 215, 12, 65, 118, 84, 31, 234, 181, 128, 75, 22, 30, 83, 136, 189, 242, 39, 163, 110, 57, 4, 207, 154, 101, 48, 251, 57, 110, 163, 216, 13, 66, 119, 172, 225, 22, 75, 127, 74, 21, 224, 171, 118, 65, 243, 215, 93, 146, 199, 252, 49, 102, 155, 208, 5, 197, 144, 91, 38, 241, 188, 135, 173, 226, 23, 76, 129, 182, 20, 32, 85, 117, 191, 244, 41, 161, 108, 55, 2, 205, 152, 99, 46, 249, 59, 112, 165, 218, 15, 68, 134, 81, 28, 24, 77, 125, 183, 236, 33, 86, 139, 192, 245, 42, 95, 148, 201, 254, 51, 151, 98, 45, 248, 195, 142, 89, 36, 239, 186, 133, 80, 27, 230, 78, 131, 184, 237, 34, 168, 115, 62, 9, 212, 159, 106, 53, 255, 52, 105, 158, 211, 8, 61, 114, 167, 220, 17, 70, 123, 176, 26, 229, 176, 132, 185, 238, 35, 88, 141, 194, 247, 44, 158, 150, 203, 255, 202, 149, 96, 43, 246, 193, 140, 87, 34, 237, 184, 131, 78, 25, 228, 80, 133, 186, 239, 36, 89, 142, 195, 248, 45, 98, 151, 204, 1, 54, 107, 160, 213, 10, 63, 116, 86, 33, 236, 183, 130, 77, 24, 227, 81, 134, 68, 15, 218, 165, 112, 59, 6, 209, 156, 103, 50, 253, 200, 108, 161, 214, 11, 64, 117, 170, 223, 20, 73, 126, 179, 232, 226, 82, 120, 67, 241, 217, 164, 111, 58, 5, 208, 155, 102, 49, 3, 56, 109, 162, 40, 12, 190, 137, 84, 31, 234, 181, 128, 75, 233, 225, 172, 136, 66, 242, 216, 92, 145, 198, 251, 48, 101, 154, 207, 4, 198, 110, 92, 216, 13, 189, 136, 83, 30, 233, 75, 127, 74, 21, 31, 84, 137, 65, 12, 215, 162, 109, 56, 252, 49, 102, 155, 208, 5, 58, 111, 164, 217, 14, 67, 120, 82, 29, 232, 179, 129, 73, 20, 32, 85, 138, 191, 244, 41, 94, 147, 55, 2, 205, 152, 156, 209, 6, 59, 112, 90, 37, 240, 187, 134, 81, 28, 24, 77, 125, 72, 236, 222, 169, 116, 63, 245, 42, 160, 107, 54, 254, 51, 151, 98, 210, 248, 60, 142, 166, 37, 16, 64, 132, 82, 25, 26, 79, 127, 71, 19, 221, 169, 141, 195, 8, 212, 96, 149, 200, 250, 53, 147, 103, 47, 247, 194, 141, 164, 223, 16, 185, 121, 178, 229, 25, 176, 127, 67, 18, 221, 167, 140, 195, 246, 45, 96, 149, 201, 0, 202, 148, 97, 43, 246, 193, 140, 168, 34, 237, 71, 125, 177, 25, 228, 80, 133, 69, 16, 36, 89, 142, 60, 7, 45, 157, 104, 50, 254, 200, 148, 160, 213, 11, 63, 116, 169, 222, 18, 183, 128, 76, 24, 226, 174, 121, 187, 241, 36, 91, 143, 59, 249, 46, 99, 103, 50, 252, 201, 146, 94, 41, 11, 65, 117, 171, 222, 235, 182, 129, 77, 23, 227, 172, 135, 188, 240, 38, 91, 145, 197, 250, 209, 155, 153, 206, 252, 199, 146, 162, 215, 12, 65, 118, 84, 31, 234, 181, 128, 180, 233, 225, 83, 136, 66, 13, 216, 92, 145, 198, 251, 48, 154, 154, 48, 251, 198, 145, 163, 39, 242, 189, 136, 172, 225, 22, 75, 128, 74, 234, 224, 171, 118, 65, 12, 215, 162, 146, 199, 252, 49, 102, 155, 208, 5, 59, 110, 165, 216, 15, 67, 120, 83, 31, 234, 176, 122, 77, 23, 221, 170, 138, 188, 241, 46, 86, 155, 207, 248, 48, 152, 103, 38, 240, 205, 134, 93, 32, 244, 68, 123, 173, 228, 30, 75, 132, 180, 238, 32, 169, 116, 59, 14, 214, 162, 148, 203, 251, 49, 104, 96, 46, 248, 199, 141, 91, 32, 238, 186, 122, 173, 229, 25, 179, 124, 71, 239, 37, 95, 129, 207, 253, 34, 99, 111, 57, 13, 223, 130, 113, 35, 241, 63, 117, 169, 204, 30, 77, 125, 178, 229, 228, 179, 132, 186, 234, 38, 90, 141, 62, 3, 219, 145, 120, 57, 241, 207, 107, 151, 196, 6, 49, 121, 172, 220, 239, 71, 130, 78, 226, 31, 86, 134, 186, 21, 211, 175, 97, 50, 9, 222, 158, 150, 196, 13, 58, 96, 167, 208, 8, 60, 112, 171, 217, 21, 78, 121, 76, 30, 232, 165, 104, 86, 1, 215, 160, 143, 194, 245, 34, 111, 145, 197, 5, 50, 107, 164, 208, 12, 68, 119, 81, 43, 231, 185, 146, 92, 24, 233, 169, 134, 180, 253, 43, 80, 150, 192, 249, 43, 99, 159, 196, 10, 63, 104, 92, 33, 254, 174, 156, 71, 13, 228, 179, 127, 189, 231, 17, 94, 129, 186, 246, 34, 91, 151, 204, 242, 56, 96, 103, 58, 244, 212, 135, 73, 53, 252, 184, 117, 166, 241, 7, 68, 137, 176, 235, 31, 87, 139, 185, 251, 32, 85, 147, 60, 9, 195, 141, 112, 59, 235, 204, 145, 163, 212, 1, 76, 113, 170, 225, 20, 74, 133, 191, 224, 42, 92, 136, 68, 0, 217, 180, 123, 33, 22, 193, 156, 152, 220, 22, 43, 124, 173, 223, 11, 67, 124, 167, 232, 17, 71, 134, 74, 25, 208, 189, 99, 41, 28, 218, 167, 149, 195, 241, 60, 101, 151, 212, 1, 52, 118, 172, 215, 27, 78, 127, 80, 18, 233, 162, 101, 94, 10, 201, 162, 113, 198, 248, 59, 111, 153, 195, 248, 61, 96, 151, 216, 2, 55, 119, 88, 36, 224, 168, 156, 86, 13, 240, 188, 127, 188, 224, 51, 87, 128, 200, 255, 37, 104, 159, 192, 11, 63, 109, 157, 40, 251, 209, 152, 77, 53, 245, 169, 139, 78, 236, 21, 64, 138, 177, 231, 35, 81, 134, 202, 243, 39, 107, 145, 205, 249, 199, 133, 69, 48, 236, 214, 135, 82, 216, 30, 71, 109, 190, 236, 20, 89, 140, 179, 252, 46, 80, 134, 199, 7, 218, 140, 114, 46, 228, 209, 129, 87, 41, 0, 78, 100, 186, 211, 31, 78, 117, 186, 224, 17, 90, 142, 185, 241, 220, 180, 126, 32, 24, 201, 131, 107, 52, 7, 55, 124, 182, 199, 1, 74, 127, 160, 233, 30, 65, 119, 189, 235, 224, 160, 99, 84, 18, 196, 185, 120, 48, 5, 58, 116, 137, 219, 20, 52, 103, 170, 210, 10, 72, 126, 164, 231, 22, 176, 111, 94, 12, 255, 178, 110, 78, 9, 42, 83, 128, 210, 232, 33, 107, 146, 218, 12, 60, 102, 163, 222, 10, 189, 143, 65, 8, 244, 174, 102, 94, 31, 221, 83, 155, 172, 226, 61, 78, 159, 207, 247, 52, 97, 148, 212, 0, 59, 139, 87, 50, 231, 165, 156, 71, 14, 226, 76, 137, 163, 249, 54, 68, 132, 202, 253, 32, 90, 156, 193, 251, 53, 150, 100, 60, 224, 218, 145, 64, 49, 224, 185, 120, 161, 240, 15, 89, 146, 182, 229, 42, 95, 136, 201, 240, 46, 98, 111, 60, 21, 211, 140, 127, 58, 228, 200, 114, 160, 206, 4, 81, 109, 191, 233, 28, 71, 131, 189, 231, 38, 93, 140, 59, 4, 202, 137, 114, 40, 236, 216, 147, 158, 221, 29, 45, 100, 187, 211, 25, 66, 118, 183, 224, 17, 84, 128, 71, 24, 212, 188, 102, 33, 30, 192, 141, 107, 206, 13, 34, 127, 184, 199, 4, 54, 114, 163, 219, 27, 65, 121, 177, 29, 233, 186, 99, 92, 18, 204, 180, 124, 59, 252, 33, 119, 142, 219, 13, 58, 106, 166, 223, 15, 74, 115, 174, 222, 227, 189, 150, 85, 15, 255, 190, 105, 75, 240, 33, 73, 131, 211, 238, 34, 104, 159, 199, 11, 63, 102, 167, 211, 242, 183, 135, 78, 8, 240, 172, 145, 68, 18, 28, 88, 155, 169, 228, 54, 81, 152, 195, 242, 54, 109, 147, 204, 7, 195, 155, 79, 62, 228, 161, 157, 66, 18, 233, 79, 142, 161, 255, 9, 91, 133, 182, 244, 34, 91, 152, 192, 248, 48, 145, 105, 56, 226, 221, 138, 73, 54, 249, 67, 127, 188, 241, 2, 94, 141, 188, 237, 41, 93, 141, 181, 241, 45, 163, 101, 38, 26, 218, 131, 116, 60, 244, 198, 115, 168, 200, 28, 80, 119, 165, 235, 31, 71, 133, 188, 229, 39, 85, 113, 51, 28, 194, 186, 112, 34, 19, 196, 151, 154, 195, 20, 41, 99, 170, 210, 22, 76, 114, 167, 239, 30, 72, 125, 64, 3, 202, 176, 109, 38, 28, 218, 156, 151, 196, 236, 32, 125, 144, 216, 15, 53, 123, 175, 208, 24, 78, 120, 76, 17, 243, 165, 103, 93, 7, 201, 175, 115, 197, 230, 62, 116, 134, 199, 8, 51, 99, 151, 222, 2, 55, 116, 168, 36, 255, 173, 154, 80, 14, 243, 161, 126, 184, 225, 54, 77, 156, 206, 242, 43, 107, 159, 197, 13, 60, 97, 163, 40, 249, 212, 157, 73, 58, 244, 163, 133, 77, 237, 13, 66, 149, 181, 252, 34, 82, 134, 204, 244, 36, 105, 158, 50, 245, 218, 135, 66, 52, 237, 169, 128, 87, 216, 27, 88, 109, 189, 229, 21, 85, 140, 180, 252, 42, 81, 153, 199, 1, 223, 136, 125, 47, 230, 222, 157, 91, 213, 1, 81, 101, 164, 236, 31, 77, 117, 188, 226, 19, 89, 131, 185, 12, 212, 178, 118, 39, 31, 213, 136, 109, 207, 15, 54, 127, 172, 211, 7, 69, 125, 165, 234, 25, 71, 140, 178, 234, 233, 164, 99, 92, 16, 203, 183, 102, 58, 244, 63, 119, 148, 219, 15, 61, 100, 174, 210, 1, 79, 116, 165, 227, 239, 190, 109, 85, 8, 194, 188, 123, 69, 241, 37, 78, 156, 195, 244, 53, 108, 151, 221, 22, 53, 125, 172, 222, 245, 177, 151, 75, 6, 249, 165, 114, 79, 233, 42, 89, 134, 201, 253, 46, 86, 158, 194, 238, 61, 102, 151, 214, 252, 201, 158, 64, 62, 241, 162, 138, 87, 231, 19, 64, 142, 177, 234, 38, 94, 128, 204, 228, 59, 111, 158, 207, 4, 195, 135, 121, 53, 233, 213, 157, 80, 222, 25, 75, 113, 183, 227, 24, 70, 142, 180, 252, 51, 72, 129, 198, 11, 212, 143, 127, 44, 226, 220, 133, 104, 214, 14, 50, 122, 174, 217, 19, 79, 118, 191, 245, 10, 65, 136, 190, 18, 221, 183, 101, 36, 28, 198, 141, 110, 206, 7, 60, 110, 163, 212, 10, 55, 126, 185, 202, 0, 90, 113, 182, 27, 228, 191, 106, 83, 22, 200, 171, 116, 198, 255, 38, 96, 152, 51, 2, 48, 102, 179, 195, 31, 83, 121, 168, 35, 226, 164, 146, 91, 2, 242, 161, 121, 191, 247, 33, 91, 109, 57, 5, 40, 110, 138, 219, 23, 44, 103, 162, 42, 255, 175, 155, 67, 13, 228, 188, 128, 183, 236, 28, 175, 115, 70, 243, 32, 80, 132, 211, 238, 34, 98, 154, 52, 246, 201, 128, 79, 41, 248, 185, 119, 175, 227, 235, 179, 120, 73, 233, 22, 68, 156, 168, 230, 39, 89, 108, 48, 13, 193, 137, 106, 37, 255, 196, 110, 165, 36, 246, 183, 143, 81, 225, 28, 94, 151, 160, 248, 43, 87, 113, 74, 5, 217, 172, 102, 50, 3, 51, 100, 99, 43, 240, 207, 136, 90, 223, 1, 87, 108, 187, 236, 30, 179, 122, 68, 30, 211, 163, 114, 61, 245, 40, 94, 111, 63, 12, 192, 146, 156, 219, 22, 40, 100, 181, 208, 19, 185, 140, 92, 22, 236, 183, 125, 186, 238, 38, 169, 123, 51, 6, 223, 155, 151, 198, 238, 32, 124, 142, 219, 8, 196, 135, 85, 47, 230, 189, 123, 178, 230, 27, 181, 112, 73, 30, 212, 166, 139, 210, 227, 59, 121, 135, 195, 253, 195, 152, 112, 38, 255, 196, 115, 171, 216, 16, 188, 137, 64, 18, 225, 80, 140, 170, 253, 49, 75, 133, 194, 0, 217, 147, 102, 56, 248, 201, 104, 165, 208, 10, 198, 135, 89, 42, 233, 73, 119, 162, 244, 9, 64, 141, 187, 8, 209, 171, 125, 51, 2, 46, 96, 157, 201, 252, 207, 156, 81, 32, 247, 68, 120, 184, 203, 1, 89, 118, 79, 30, 239, 189, 117, 75, 13, 38, 95, 149, 198, 4, 216, 149, 106, 54, 253, 62, 96, 179, 196, 30, 76, 115, 80, 22, 230, 184, 138, 77, 20, 31, 87, 140, 191, 14, 210, 173, 100, 60, 251, 56, 107, 138, 221, 20, 51, 111, 90, 46, 254, 182, 128, 87, 30, 20, 79, 132, 181, 19, 236, 166, 126, 69, 241, 33, 83, 130, 215, 241, 54, 152, 98, 38, 240, 204, 149, 89, 216, 10, 71, 123, 80, 20, 228, 185, 121, 75, 239, 43, 91, 154, 177, 252, 43, 162, 106, 48, 5, 200, 154, 156, 213, 2, 56, 142, 82, 46, 251, 178, 131, 174, 229, 19, 67, 143, 191, 238, 223, 173, 113, 59, 9, 213, 94, 144, 205, 252, 207, 159, 105, 39, 241, 197, 143, 165, 211, 28, 78, 125, 173, 27, 228, 178, 126, 70, 237, 33, 82, 138, 194, 11, 211, 150, 99, 61, 6, 200, 105, 154, 212, 14, 62, 115, 167, 35, 17, 71, 121, 179, 227, 29, 74, 134, 69, 22, 212, 175, 122, 59, 12, 210, 96, 148, 201, 1, 53, 106, 158, 214, 13, 59, 116, 160, 213, 20, 70, 128, 72, 17, 237, 167, 114, 66, 21, 216, 167, 142, 193, 250, 46, 102, 145, 203, 9, 62, 108, 165, 214, 245, 193, 136, 83, 38, 229, 189, 137, 68, 30, 225, 174, 132, 190, 247, 44, 80, 133, 204, 255, 44, 99, 152, 205, 253, 202, 151, 86, 37, 249, 180, 130, 80, 33, 22, 79, 116, 191, 227, 20, 86, 135, 66, 14, 38, 90, 145, 58, 6, 215, 147, 111, 57, 251, 195, 146, 161, 208, 6, 74, 113, 170, 29, 233, 180, 128, 181, 235, 30, 172, 118, 67, 15, 219, 167, 109, 56, 249, 54, 98, 159, 206, 249, 194, 148, 89, 36, 243, 188, 136, 172, 226, 21, 73, 129, 180, 235, 29, 80, 140, 189, 13, 211, 164, 107, 62, 6, 202, 157, 96, 46, 7, 63, 106, 161, 220, 11, 69, 127, 170, 230, 233, 182, 120, 79, 19, 217, 172, 115, 70, 8, 41, 92, 144, 205, 251, 53, 111, 148, 214, 5, 197, 138, 92, 34, 247, 189, 131, 84, 24, 230, 76, 128, 180, 239, 37, 83, 141, 199, 240, 43, 162, 111, 51, 4, 201, 146, 103, 41, 249, 63, 119, 161, 221, 22, 64, 127, 172, 228, 228, 183, 123, 64, 20, 219, 174, 117, 58, 8, 40, 103, 156, 192, 244, 63, 99, 153, 208, 245, 202, 129, 86, 46, 226, 179, 141, 72, 25, 24, 72, 143, 181, 224, 44, 87, 128, 203, 244, 208, 151, 100, 58, 240, 197, 154, 109, 35, 244, 58, 122, 165, 205, 3, 85, 108, 189, 227, 229, 168, 113, 72, 29, 214, 168, 124, 54, 2, 210, 97, 159, 192, 14, 39, 123, 173, 221, 10, 197, 130, 93, 45, 225, 186, 137, 74, 25, 30, 87, 143, 176, 253, 40, 86, 134, 199, 5, 214, 150, 108, 57, 241, 196, 153, 91, 214, 14, 72, 126, 167, 208, 27, 69, 121, 179, 17, 233, 160, 118, 77, 0, 213, 172, 110, 193, 243, 35, 106, 150, 193, 13, 51, 104, 93, 46, 249, 178, 132, 90, 16, 231, 188, 131, 183, 224, 19, 67, 153, 173, 255, 47, 93, 107, 48, 15, 195, 150, 105, 60, 242, 195, 145, 167, 208, 6, 79, 121, 160, 235, 19, 181, 121, 67, 31, 235, 160, 125, 73, 15, 40, 88, 155, 204, 241, 60, 109, 156, 209, 254, 204, 154, 80, 44, 248, 180, 130, 82, 225, 17, 70, 141, 184, 229, 44, 82, 139, 70, 6, 198, 176, 124, 57, 9, 203, 103, 155, 220, 23, 40, 98, 181, 214, 9, 187, 143, 65, 8, 243, 163, 115, 66, 21, 222, 80, 135, 209, 230, 57, 78, 153, 206, 1, 196, 154, 115, 60, 232, 206, 132, 92, 36, 21, 79, 116, 160, 235, 23, 68, 135, 69, 26, 214, 165, 126, 50, 3, 211, 156, 148, 205, 245, 57, 100, 146, 218, 12, 192, 133, 84, 46, 226, 179, 131, 76, 229, 30, 71, 143, 181, 226, 47, 82, 139, 195, 13, 217, 144, 121, 59, 243, 194, 150, 157, 211, 2, 48, 124, 166, 209, 26, 68, 129, 73, 18, 233, 161, 119, 79, 23, 216, 89, 139, 203, 243, 33, 110, 156, 196, 2, 200, 146, 86, 33, 249, 203, 130, 80, 32, 17, 78, 116, 185, 236, 22, 89, 131, 186, 12, 220, 173, 121, 50, 14, 215, 159, 103, 206, 4, 63, 101, 168, 222, 14, 66, 139, 81, 39, 226, 191, 137, 75, 19, 227, 83, 131, 187, 248, 47, 82, 151, 193, 251, 210, 159, 97, 57, 244, 192, 148, 94, 41, 13, 66, 112, 172, 232, 18, 76, 124, 180, 20, 229, 170, 127, 74, 10, 221, 161, 110, 199, 248, 52, 99, 156, 201, 1, 58, 111, 93, 36, 246, 184, 141, 86, 29, 232, 75, 129, 182, 233, 27, 80, 141, 189, 241, 40, 162, 111, 59, 7, 202, 157, 102, 46, 5, 59, 109, 167, 218, 13, 65, 120, 82, 28, 234, 176, 125, 74, 22, 222, 170, 138, 189, 247, 45, 90, 151, 203, 252, 205, 153, 97, 45, 253, 192, 140, 88, 36, 15, 69, 123, 173, 224, 28, 73, 129, 181, 236, 222, 171, 119, 59, 14, 209, 163, 105, 55, 254, 50, 106, 158, 214, 3, 63, 115, 167, 219, 238, 184, 134, 83, 24, 229, 179, 124, 184, 236, 32, 85, 143, 194, 244, 42, 96, 106, 52, 1, 201, 148, 99, 45, 247, 194, 114, 166, 222, 19, 68, 122, 177, 229, 229, 177, 122, 68, 19, 222, 165, 115, 61, 247, 45, 99, 148, 201, 2, 55, 107, 159, 212, 246, 192, 142, 85, 32, 239, 186, 130, 78, 230, 26, 81, 135, 184, 237, 37, 88, 142, 60, 7, 210, 156, 105, 50, 255, 200, 149, 95, 42, 10, 63, 117, 168, 223, 18, 73, 125, 178, 24, 227, 174, 121, 68, 15, 218, 165, 112, 59, 6, 46, 99, 152, 205, 2, 200, 147, 94, 41, 244, 191, 138, 85, 32, 235, 182, 129, 76, 232, 29, 82, 135, 188, 241, 217, 164, 111, 58, 5, 208, 100, 153, 206, 3, 56, 109, 162, 215, 12, 190, 137, 84, 31, 234, 181, 128, 75, 22, 225, 172, 119, 66, 13, 39, 92, 145, 198, 251, 207, 154, 101, 48, 4, 57, 110, 163, 217, 13, 66, 119, 172, 225, 233, 180, 127, 74, 21, 224, 171, 118, 65, 243, 40, 93, 146, 199, 252, 49, 102, 155, 47, 250, 197, 144, 90, 39, 240, 189, 135, 82, 226, 23, 77, 128, 183, 234, 33, 85, 138, 64, 11, 214, 160, 109, 54, 2, 205, 152, 156, 209, 7, 58, 113, 164, 219, 15, 68, 134, 81, 29, 230, 179, 124, 73, 18, 222, 86, 138, 193, 244, 43, 94, 148, 54, 1, 204, 150, 99, 44, 249, 195, 142, 89, 219, 16, 68, 123, 174, 229, 24, 79, 131, 184, 18, 221, 169, 114, 63, 8, 213, 159, 106, 202, 255, 53, 104, 159, 210, 9, 60, 114, 167, 35, 238, 184, 133, 78, 27, 228, 176, 123, 185, 238, 35, 88, 141, 194, 247, 44, 97, 105, 52, 255, 202, 149, 96, 43, 246, 193, 115, 168, 221, 18, 71, 124, 177, 230, 27, 175, 122, 69, 16, 219, 89, 142, 195, 248, 45, 98, 151, 204, 1, 54, 107, 95, 42, 245, 192, 139, 86, 33, 236, 183, 125, 178, 231, 28, 81, 134, 187, 240, 218, 165, 112, 59, 6, 209, 156, 103, 50, 253, 55, 108, 161, 214, 11, 64, 117, 170, 223, 235, 182, 129, 76, 23, 29, 82, 135, 188, 241, 38, 91, 144, 197, 5, 208, 155, 102, 49, 252, 199, 146, 93, 40, 243, 190, 118, 171, 224, 21, 74, 127, 180, 22, 225, 172, 119, 66, 13, 216, 163, 110, 57, 251, 48, 101, 154, 207, 4, 57, 110, 92, 39, 242, 189, 136, 83, 30, 233, 75, 128, 181, 234, 31, 84, 137, 190, 243, 40, 93, 109, 56, 3, 206, 153, 100, 47, 250, 197, 111, 164, 217, 14, 67, 120, 173, 226, 232, 179, 126, 73, 20, 223, 170, 117, 191, 244, 41, 94, 147, 200, 253, 50, 103, 156, 46, 249, 196, 143, 90, 37, 240, 187, 134, 81, 227, 24, 77, 130, 183, 236, 33, 86, 139, 63, 10, 213, 160, 107, 54, 254, 51, 104, 157, 210, 7, 60, 113, 166, 219, 16, 69, 122, 175, 228, 230, 177, 124, 71, 18, 221, 168, 115, 193, 246, 43, 96, 149, 202, 0, 203, 150, 158, 44, 247, 194, 141, 88, 35, 17, 70, 123, 79, 26, 229, 176, 123, 70, 17, 220, 167, 141, 194, 247, 44, 97, 150, 203, 0, 53, 149, 96, 212, 9, 193, 140, 168, 221, 18, 184, 131, 78, 25, 27, 80, 133, 186, 239, 36, 166, 113, 60, 248, 210, 157, 151, 204, 1, 54, 148, 160, 213, 10, 192, 139, 86, 33, 236, 72, 125, 178, 231, 227, 174, 121, 187, 240, 37, 90, 143, 196, 249, 46, 156, 103, 50, 253, 200, 108, 161, 214, 11, 64, 117, 170, 223, 20, 73, 126, 76, 232, 226, 173, 120, 67, 14, 217, 91, 144, 197, 250, 208, 155, 102, 49, 252, 199, 146, 93, 215, 12, 65, 118, 171, 31, 234, 181, 128, 180, 233, 30, 83, 136, 189, 242, 216, 163, 110, 198, 4, 48, 154, 154, 207, 4, 57, 110, 163, 216, 13, 66, 119, 172, 30, 233, 180, 127, 181, 21, 224, 84, 137, 65, 12, 215, 162, 109, 199, 252, 49, 102, 100, 208, 5, 197, 111, 164, 217, 14, 188, 135, 82, 29, 232, 179, 126, 73, 235, 32, 85, 138, 191, 244, 41, 94, 108, 200, 2, 50, 103, 99, 46, 249, 196, 143, 90, 37, 240, 187, 121, 174, 28, 24, 178, 130, 72, 19, 222, 86, 116, 63, 10, 42, 95, 148, 201, 1, 51, 104, 157, 210, 248, 60, 142, 166, 37, 16, 68, 135, 175, 228, 230, 78, 131, 71, 18, 34, 168, 140, 193, 9, 43, 159, 106, 202, 0, 52, 150, 97, 211, 8, 195, 114, 164, 35, 236, 184, 123, 176, 229, 26, 177, 123, 70, 17, 34, 88, 114, 61, 8, 211, 97, 150, 203, 255, 202, 106, 159, 212, 246, 62, 115, 87, 221, 18, 71, 124, 78, 25, 228, 80, 122, 69, 16, 219, 89, 113, 195, 248, 210, 98, 104, 51, 1, 54, 148, 95, 213, 10, 63, 116, 169, 222, 236, 72, 130, 178, 231, 28, 174, 134, 187, 240, 218, 165, 143, 59, 249, 46, 156, 152, 50, 2, 200, 147, 161, 41, 11, 191, 138, 85, 32, 235, 182, 126, 76, 23, 29, 173, 135, 67, 241, 217, 91, 144, 58, 250, 208, 100, 153, 206, 3, 56, 146, 162, 215, 243, 190, 118, 171, 224, 21, 181, 127, 180, 22, 30, 172, 119, 189, 13, 39, 92, 110, 57, 251, 207, 154, 154, 48, 251, 57, 145, 92, 216, 242, 189, 119, 83, 30, 22, 180, 127, 181, 21, 31, 171, 137, 65, 243, 215, 93, 146, 56, 3, 206, 102, 100, 208, 250, 58, 144, 164, 217, 241, 67, 135, 82, 227, 23, 177, 129, 183, 20, 32, 170, 117, 191, 11, 214, 94, 147, 200, 253, 50, 153, 157, 46, 249, 58, 142, 165, 218, 240, 187, 121, 81, 227, 24, 178, 130, 183, 19, 33, 86, 116, 192, 10, 213, 95, 107, 54, 254, 51, 151, 157, 210, 248, 60, 113, 88, 219, 16, 186, 123, 80, 27, 25, 177, 131, 184, 18, 221, 86, 115, 63, 247, 212, 159, 149, 53, 0, 52, 105, 97, 210, 247, 195, 114, 167, 35, 17, 184, 123, 176, 229, 229, 176, 132, 70, 17, 35, 88, 141, 194, 8, 44, 97, 105, 203, 0, 202, 149, 158, 43, 246, 193, 115, 168, 34, 18, 71, 131, 78, 25, 27, 175, 122, 186, 16, 36, 166, 113, 195, 7, 210, 98, 151, 51, 254, 201, 107, 94, 212, 10, 193, 116, 87, 222, 18, 183, 125, 178, 25, 227, 174, 134, 186, 240, 219, 165, 142, 59, 249, 46, 156, 102, 205, 2, 201, 108, 161, 41, 244, 64, 138, 85, 222, 234, 182, 127, 77, 233, 29, 173, 135, 188, 14, 39, 164, 110, 196, 5, 208, 101, 103, 49, 2, 198, 146, 163, 40, 243, 64, 136, 84, 224, 234, 181, 127, 75, 22, 30, 173, 119, 188, 13, 216, 92, 111, 198, 251, 206, 101, 154, 49, 251, 57, 145, 163, 216, 242, 189, 136, 172, 225, 22, 180, 127, 74, 21, 31, 84, 118, 190, 12, 215, 93, 146, 199, 252, 206, 153, 155, 47, 5, 58, 144, 164, 38, 241, 67, 120, 173, 29, 232, 179, 126, 182, 20, 32, 170, 117, 191, 11, 41, 94, 108, 200, 253, 205, 103, 156, 46, 249, 59, 143, 90, 218, 240, 68, 121, 81, 28, 24, 178, 130, 183, 19, 222, 86, 116, 63, 245, 213, 160, 148, 54, 1, 51, 150, 98, 210, 248, 60, 112, 166, 218, 17, 186, 123, 174, 228, 25, 78, 124, 71, 18, 217, 172, 119, 54, 13, 43, 97, 147, 193, 244, 63, 98, 154, 211, 246, 203, 132, 80, 43, 230, 191, 132, 76, 26, 229, 79, 136, 181, 231, 41, 92, 115, 56, 9, 218, 144, 105, 62, 246, 63, 102, 157, 222, 14, 205, 139, 81, 37, 23, 78, 126, 185, 226, 226, 171, 125, 73, 26, 221, 89, 134, 205, 239, 61, 104, 148, 52, 237, 222, 156, 92, 213, 2, 52, 112, 168, 221, 234, 189, 134, 79, 229, 23, 65, 149, 182, 243, 216, 170, 104, 36, 26, 209, 100, 139, 210, 19, 53, 111, 88, 50, 230, 186, 131, 172, 199, 1, 90, 114, 77, 29, 243, 183, 92, 86, 249, 48, 65, 139, 213, 1, 219, 148, 117, 60, 245, 57, 125, 182, 196, 29, 73, 143, 92, 21, 252, 149, 148, 186, 241, 11, 69, 129, 73, 31, 211, 168, 100, 56, 4, 61, 117, 150, 192, 12, 198, 147, 94, 55, 232, 160, 138, 181, 241, 24, 69, 127, 69, 29, 226, 172, 114, 67, 9, 42, 90, 157, 214, 243, 61, 101, 111, 53, 216, 229, 107, 179, 213, 5, 79, 131, 94, 224, 21, 182, 123, 64, 27, 217, 94, 144, 164, 239, 38, 166, 116, 22, 47, 215, 113, 128, 193, 22, 51, 158, 85, 218, 241, 190, 131, 87, 26, 26, 84, 168, 149, 255, 33, 176, 93, 24, 39, 219, 119, 179, 216, 245, 201, 139, 108, 211, 6, 60, 136, 92, 219, 20, 94, 85, 180, 231, 234, 146, 81, 88, 50, 217, 96, 161, 203, 247, 218, 190, 101, 204, 250, 54, 144, 107, 45, 14, 32, 65, 187, 37, 248, 156, 162, 91, 12, 227, 125, 180, 187, 28, 204, 188, 99, 204, 230, 37, 150, 123, 202, 14, 41, 69, 130, 36, 212, 223, 149, 89, 41, 231, 90, 76, 185, 13, 244, 191, 105, 179, 247, 40, 170, 102, 62, 245, 52, 73, 137, 34, 218, 211, 159, 92, 42, 249, 192, 82, 188, 55, 251, 176, 140, 79, 242, 14, 166, 98, 64, 232, 60, 71, 146, 50, 47, 203, 102, 157, 49, 244, 209, 110, 133, 208, 238, 180, 142, 89, 215, 13, 78, 149, 67, 253, 63, 64, 136, 184, 20, 199, 92, 133, 62, 9, 207, 190, 142, 227, 248, 208, 147, 87, 34, 25, 88, 136, 71, 31, 14, 91, 127, 189, 23, 251, 164, 147, 183, 30, 197, 146, 127, 242, 222, 222, 149, 102, 33, 251, 37, 126, 85, 41, 5, 90, 113, 82, 228, 235, 190, 139, 172, 18, 193, 136, 91, 67, 179, 15, 182, 123, 53, 19, 55, 122, 148, 42, 240, 57, 124, 165, 35, 1, 69, 142, 165, 240, 253, 153, 96, 109, 224, 109, 114, 107, 99, 5, 223, 86, 136, 219, 2, 221, 103, 142, 45, 5, 33, 121, 93, 220, 10, 155, 172, 74, 2, 0, 0, 149, 102, 63, 210, 169, 132, 223, 237, 215, 184, 105, 221, 252, 59, 114, 145, 36, 254, 195, 145, 124, 43, 244, 85, 49, 183, 46, 215, 179, 137, 172, 207, 55, 171, 111, 53, 229, 38, 111, 130, 192, 16, 219, 147, 125, 55, 240, 216, 114, 231, 255, 194, 139, 133, 190, 234, 1, 85, 129, 91, 5, 52, 66, 134, 205, 240, 202, 131, 108, 56, 239, 203, 132, 113, 243, 39, 215, 185, 92, 200, 1, 81, 96, 186, 2, 250, 64, 158, 188, 229, 45, 183, 110, 52, 248, 214, 98, 103, 27, 251, 4, 124, 123, 61, 30, 43, 125, 189, 204, 224, 148, 132, 145, 255, 29, 81, 112, 93, 2, 44, 92, 117, 43, 45, 241, 68, 163, 50, 225, 55, 102, 94, 222, 24, 74, 154, 68, 208, 6, 76, 129, 69, 4, 236, 81, 137, 185, 1, 251, 142, 147, 133, 211, 223, 129, 109, 54, 3, 32, 76, 168, 48, 226, 76, 124, 82, 21, 238, 176, 130, 191, 227, 231, 181, 81, 88, 238, 28, 79, 115, 27, 14, 52, 124, 177, 239, 242, 239, 156, 179, 217, 255, 64, 103, 172, 28, 30, 77, 109, 111, 49, 236, 122, 179, 190, 39, 202, 89, 129, 227, 219, 55, 176, 73, 209, 23, 56, 106, 181, 223, 253, 191, 113, 87, 6, 202, 170, 139, 143, 194, 202, 154, 101, 175, 232, 13, 72, 124, 3, 23, 42, 118, 99, 214, 23, 192, 157, 91, 210, 248, 160, 157, 67, 244, 33, 94, 88, 109, 238, 53, 77, 149, 196, 21, 241, 161, 135, 194, 249, 56, 107, 112, 38, 10, 55, 131, 66, 56, 224, 96, 67, 173, 48, 253, 71, 150, 162, 255, 222, 180, 105, 199, 249, 41, 99, 153, 48, 19, 52, 121, 156, 58, 234, 223, 137, 149, 236, 226, 146, 137, 191, 244, 12, 95, 124, 90, 4, 32, 84, 128, 201, 244, 216, 148, 156, 198, 248, 208, 139, 124, 196, 54, 35, 172, 127, 33, 29, 81, 107, 184, 21, 251, 161, 140, 180, 229, 44, 166, 125, 63, 243, 39, 149, 117, 18, 242, 17, 89, 95, 3, 233, 54, 97, 190, 205, 16, 162, 161, 68, 244, 10, 88, 120, 67, 7, 32, 84, 139, 41, 39, 240, 96, 174, 232, 234, 228, 155, 179, 194, 24, 76, 130, 75, 52, 19, 93, 111, 182, 17, 235, 174, 143, 183, 13, 192, 130, 120, 228, 192, 39, 188, 123, 200, 18, 42, 127, 164, 38, 238, 181, 100, 177, 231, 226, 188, 133, 183, 226, 26, 160, 87, 107, 12, 29, 112, 124, 18, 10, 62, 113, 136, 196, 249, 210, 133, 163, 204, 30, 66, 130, 87, 31, 23, 78, 125, 83, 63, 243, 115, 177, 186, 36, 204, 91, 129, 214, 240, 54, 147, 120, 35, 17, 39, 105, 87, 33, 242, 67, 125, 173, 17, 200, 145, 143, 138, 244, 194, 130, 112, 173, 224, 36, 82, 147, 32, 23, 57, 120, 145, 39, 244, 195, 142, 167, 216, 246, 162, 163, 175, 208, 61, 162, 88, 69, 230, 48, 88, 134, 197, 27, 194, 93, 143, 216, 7, 193, 145, 98, 45, 250, 192, 128, 120, 47, 56, 108, 129, 112, 8, 26, 94, 146, 182, 229, 209, 190, 114, 217, 228, 215, 148, 108, 54, 3, 206, 149, 107, 50, 252, 25, 87, 93, 63, 229, 64, 112, 187, 232, 22, 183, 109, 66, 249, 54, 164, 124, 59, 8, 208, 150, 111, 60, 231, 195, 72, 190, 33, 235, 198, 122, 161, 216, 24, 74, 133, 90, 26, 2, 68, 127, 85, 23, 36, 165, 123, 54, 15, 197, 154, 179, 237, 242, 214, 144, 175, 217, 9, 56, 120, 87, 48, 238, 95, 110, 78, 8, 234, 81, 134, 72, 30, 214, 181, 138, 226, 225, 197, 131, 102, 220, 12, 52, 111, 166, 43, 255, 66, 96, 187, 34, 251, 186, 129, 178, 24, 246, 189, 113, 169, 212, 33, 184, 119, 193, 233, 32, 96, 154, 206, 250, 199, 98, 172, 211, 242, 183, 132, 81, 224, 231, 173, 152, 178, 199, 3, 185, 82, 69, 252, 53, 86, 146, 198, 12, 202, 107, 143, 203, 254, 199, 148, 81, 33, 241, 178, 151, 71, 194, 35, 73, 84, 80, 230, 11, 89, 140, 186, 9, 219, 90, 143, 214, 4, 197, 152, 103, 39, 242, 204, 133, 123, 209, 58, 94, 158, 122, 26, 6, 89, 136, 181, 23, 209, 168, 144, 162, 247, 217, 170, 110, 53, 5, 193, 138, 127, 47, 42, 36, 158, 121, 44, 8, 73, 118, 165, 30, 242, 186, 158, 145, 230, 211, 165, 114, 60, 9, 221, 180, 74, 53, 204, 23, 129, 75, 41, 22, 54, 114, 173, 211, 248, 175, 99, 128, 244, 247, 190, 121, 67, 20, 219, 185, 86, 59, 194, 13, 136, 71, 50, 236, 37, 104, 156, 213, 229, 214, 102, 137, 200, 224, 170, 130, 78, 31, 224, 162, 89, 189, 192, 59, 190, 82, 60, 249, 39, 97, 147, 52, 235, 207, 74, 184, 211, 248, 204, 139, 86, 33, 232, 163, 150, 171, 249, 237, 178, 120, 181, 229, 39, 162, 114, 53, 13, 34, 74, 139, 53, 234, 198, 145, 165, 209, 251, 223, 115, 129, 220, 198, 175, 104, 174, 234, 230, 164, 107, 94, 243, 8, 116, 136, 40, 16, 194, 148, 145, 199, 238, 194, 114, 174, 1, 223, 72, 107, 179, 212, 233, 162, 166, 66, 201, 46, 79, 135, 82, 18, 192, 160, 157, 197, 254, 48, 107, 65, 9, 244, 35, 77, 180, 210, 253, 151, 149, 190, 208, 10, 77, 133, 90, 12, 245, 171, 119, 166, 223, 46, 136, 93, 55, 244, 40, 124, 139, 58, 208, 220, 123, 134, 194, 4, 184, 135, 67, 18, 250, 191, 163, 131, 239, 210, 129, 114, 178, 225, 59, 86, 120, 30, 6, 42, 124, 139, 213, 243, 203, 148, 93, 59, 242, 119, 82, 75, 41, 230, 71, 139, 191, 251, 32, 140, 85, 180, 214, 52, 80, 102, 45, 4, 61, 145, 120, 197, 62, 48, 190, 124, 222, 29, 87, 107, 175, 60, 195, 182, 147, 161, 247, 45, 191, 107, 193, 250, 217, 92, 190, 208, 27, 231, 133, 153, 202, 38, 50, 146, 115, 46, 25, 67, 106, 184, 27, 253, 165, 131, 186, 255, 0, 88, 103, 35, 4, 211, 105, 181, 210, 15, 232, 155, 150, 217, 13, 198, 135, 89, 218, 232, 182, 109, 150, 230, 253, 189, 122, 66, 228, 59, 82, 102, 40, 246, 39, 107, 147, 59, 224, 198, 120, 148, 214, 29, 51, 157, 65, 221, 20, 66, 119, 187, 230, 235, 164, 129, 182, 230, 219, 183, 110, 44, 255, 62, 125, 133, 33, 224, 192, 104, 168, 195, 4, 200, 159, 80, 208, 1, 65, 130, 66, 1, 242, 174, 140, 155, 237, 211, 135, 103, 56, 241, 55, 119, 98, 43, 236, 48, 124, 181, 198, 240, 163, 151, 93, 213, 48, 106, 130, 83, 13, 232, 82, 149, 165, 251, 205, 186, 110, 212, 247, 39, 97, 108, 36, 242, 57, 113, 188, 209, 225, 165, 152, 171, 239, 26, 73, 143, 88, 23, 19, 89, 136, 70, 4, 208, 167, 155, 216, 234, 199, 148, 111, 55, 6, 42, 98, 84, 51, 227, 191, 122, 188, 226, 229, 187, 119, 182, 244, 6, 163, 123, 72, 28, 223, 70, 136, 49, 13, 198, 158, 102, 214, 9, 59, 155, 86, 37, 6, 79, 116, 174, 21, 227, 177, 135, 179, 234, 32, 168, 114, 71, 8, 47, 87, 108, 48, 252, 63, 97, 100, 38, 251, 192, 137, 163, 220, 246, 188, 134, 83, 26, 16, 70, 127, 74, 235, 44, 95, 142, 62, 27, 205, 172, 145, 192, 248, 50, 157, 114, 42, 14, 51, 118, 165, 220, 28, 76, 114, 172, 23, 243, 188, 131, 70, 16, 34, 172, 127, 55, 241, 59, 104, 145, 205, 245, 63, 96, 97, 38, 250, 204, 134, 93, 222, 23, 66, 129, 65, 30, 25, 77, 142, 173, 254, 43, 91, 116, 51, 5, 212, 155, 108, 53, 255, 206, 156, 159, 217, 14, 193, 115, 173, 215, 1, 84, 130, 95, 11, 234, 166, 122, 178, 233, 222, 168, 118, 203, 241, 41, 101, 154, 199, 6, 51, 107, 88, 38, 250, 204, 143, 170, 217, 23, 178, 139, 73, 24, 27, 64, 138, 190, 247, 38, 162, 121, 62, 0, 217, 155, 99, 205, 2, 203, 108, 164, 210, 15, 69, 114, 162, 215, 17, 182, 136, 67, 27, 228, 83, 129, 190, 8, 213, 162, 148, 204, 243, 36, 98, 154, 198, 4, 198, 149, 87, 35, 251, 187, 118, 173, 225, 237, 188, 130, 181, 238, 18, 90, 128, 180, 246, 218, 166, 107, 59, 6, 205, 101, 100, 54, 242, 194, 111, 160, 221, 9, 66, 119, 171, 230, 22, 182, 124, 79, 16, 224, 87, 141, 190, 4, 208, 166, 108, 194, 246, 55, 103, 154, 44, 255, 198, 147, 88, 217, 12, 64, 125, 82, 25, 22, 72, 131, 180, 233, 32, 86, 137, 66, 14, 208, 167, 104, 53, 253, 51, 100, 158, 209, 2, 61, 115, 167, 217, 14, 187, 134, 82, 25, 229, 177, 117, 79, 19, 35, 84, 142, 193, 10, 41, 93, 151, 207, 252, 205, 147, 102, 46, 248, 194, 139, 93, 37, 239, 70, 127, 172, 27, 231, 176, 130, 189, 239, 32, 84, 113, 59, 11, 213, 158, 149, 200, 1, 202, 104, 96, 210, 12, 194, 140, 89, 34, 239, 71, 120, 177, 228, 24, 177, 127, 71, 236, 220, 166, 141, 194, 8, 208, 156, 151, 202, 255, 53, 106, 159, 214, 13, 63, 141, 86, 35, 236, 185, 131, 179, 230, 224, 173, 133, 68, 16, 37, 88, 143, 192, 249, 45, 99, 104, 50, 1, 55, 148, 94, 42, 247, 193, 117, 169, 35, 237, 183, 125, 179, 229, 28, 174, 121, 69, 15, 36, 88, 143, 58, 249, 47, 157, 102, 207, 0, 201, 145, 94, 214, 11, 65, 116, 84, 35, 233, 73, 124, 177, 232, 226, 172, 135, 189, 241, 36, 90, 110, 57, 7, 208, 100, 102, 206, 3, 198, 144, 92, 215, 14, 64, 119, 171, 31, 21, 75, 126, 180, 22, 227, 175, 118, 189, 13, 217, 163, 110, 57, 4, 48, 100, 154, 207, 6, 58, 110, 163, 216, 240, 191, 136, 172, 30, 22, 74, 128, 74, 234, 224, 171, 118, 190, 242, 215, 93, 147, 56, 2, 207, 102, 155, 208, 5, 56, 109, 91, 39, 241, 189, 134, 83, 29, 23, 77, 128, 182, 20, 221, 168, 116, 191, 246, 43, 95, 147, 55, 3, 204, 152, 156, 209, 249, 197, 142, 165, 219, 240, 186, 135, 81, 227, 25, 79, 128, 183, 19, 223, 171, 116, 192, 10, 42, 94, 107, 55, 1, 50, 105, 156, 210, 248, 194, 142, 167, 218, 16, 186, 132, 81, 27, 24, 78, 131, 71, 19, 221, 87, 115, 193, 247, 212, 158, 106, 53, 1, 52, 104, 158, 44, 247, 61, 114, 167, 220, 238, 185, 123, 176, 229, 26, 79, 123, 71, 17, 220, 167, 114, 61, 247, 44, 97, 150, 203, 0, 202, 149, 96, 212, 9, 62, 114, 168, 35, 236, 184, 131, 78, 230, 26, 81, 133, 69, 16, 219, 89, 142, 195, 248, 45, 157, 104, 51, 254, 201, 148, 95, 43, 10, 63, 116, 169, 33, 236, 72, 124, 178, 231, 28, 174, 121, 187, 15, 219, 165, 112, 59, 249, 47, 99, 103, 50, 2, 55, 109, 161, 41, 244, 191, 138, 84, 223, 20, 182, 129, 76, 23, 29, 82, 135, 188, 14, 217, 164, 144, 58, 250, 47, 155, 103, 48, 252, 56, 109, 162, 215, 12, 190, 118, 171, 224, 21, 75, 126, 75, 22, 225, 172, 136, 188, 242, 216, 162, 111, 57, 250, 49, 101, 154, 48, 250, 198, 110, 163, 216, 13, 189, 137, 82, 225, 22, 180, 127, 74, 21, 224, 84, 137, 65, 12, 40, 93, 146, 56, 3, 49, 102, 100, 47, 5, 197, 145, 91, 38, 241, 67, 120, 82, 29, 23, 76, 126, 182, 234, 32, 170, 138, 191, 11, 214, 161, 147, 200, 253, 50, 152, 99, 209, 6, 196, 112, 165, 37, 241, 187, 134, 81, 28, 24, 178, 125, 183, 237, 33, 169, 139, 192, 10, 213, 95, 148, 201, 254, 204, 151, 98, 45, 248, 195, 113, 166, 36, 239, 69, 122, 175, 27, 230, 78, 131, 71, 18, 221, 168, 140, 193, 9, 212, 159, 106, 53, 255, 52, 105, 158, 44, 247, 61, 114, 88, 220, 17, 70, 132, 79, 26, 26, 79, 123, 70, 238, 35, 88, 141, 194, 247, 44, 97, 105, 52, 255, 202, 149, 159, 212, 246, 193, 140, 168, 221, 237, 184, 131, 78, 230, 27, 175, 122, 186, 16, 219, 89, 142, 60, 7, 45, 157, 104, 204, 1, 201, 107, 160, 42, 245, 63, 116, 169, 222, 236, 183, 130, 77, 24, 28, 81, 121, 68, 15, 218, 165, 143, 196, 6, 46, 99, 103, 50, 2, 55, 147, 161, 41, 244, 191, 117, 170, 223, 235, 182, 129, 179, 232, 29, 173, 120, 67, 14, 38, 91, 111, 58, 250, 208, 155, 153, 206, 3, 56, 109, 93, 40, 243, 65, 118, 171, 224, 234, 181, 128, 180, 233, 30, 172, 119, 66, 242, 39, 92, 145, 57, 4, 207, 101, 101, 48, 251, 57, 110, 92, 39, 242, 189, 119, 172, 30, 233, 180, 127, 181, 234, 31, 84, 137, 65, 12, 40, 93, 109, 199, 252, 206, 153, 155, 208, 250, 58, 111, 164, 38, 14, 67, 120, 173, 226, 23, 179, 126, 73, 235, 223, 170, 117, 64, 11, 214, 94, 108, 55, 253, 50, 152, 99, 209, 249, 196, 143, 90, 37, 240, 68, 134, 81, 227, 24, 178, 125, 183, 19, 222, 169, 116, 63, 10, 42, 95, 107, 54, 254, 51, 104, 157, 210, 7, 60, 113, 166, 219, 16, 69, 133, 80, 228, 25, 177, 124, 184, 18, 221, 87, 115, 62, 246, 43, 96, 149, 202, 255, 52, 105, 158, 211, 8, 61, 114, 167, 35, 238, 70, 132, 79, 26, 229, 176, 123, 70, 17, 220, 167, 114, 61, 8, 211, 158, 150, 203, 255, 202, 149, 96, 43, 246, 62, 115, 87, 34, 18, 71, 131, 177, 230, 228, 175, 133, 186, 239, 36, 89, 142, 195, 248, 45, 98, 151, 204, 1, 201, 148, 95, 42, 245, 63, 116, 169, 33, 236, 72, 125, 178, 231, 28, 81, 121, 68, 15, 218, 165, 112, 59, 6, 209, 156, 103, 50, 253, 200, 147, 161, 214, 244, 64, 138, 85, 32, 235, 182, 129, 179, 232, 29, 82, 120, 188, 241, 38, 91, 144, 197, 250, 47, 100, 153, 206, 3, 56, 109, 93, 40, 12, 65, 118, 171, 224, 21, 74, 127, 180, 22, 225, 83, 119, 66, 13, 216, 163, 110, 57, 4, 207, 154, 154, 207, 4, 57, 110, 92, 216, 13, 66, 119, 172, 225, 22, 75, 128, 181, 234, 31, 84, 137, 190, 243, 40, 93, 109, 199, 252, 49, 153, 100, 47, 250, 197, 144, 91, 38, 241, 188, 135, 82, 29, 232, 179, 129, 73, 20, 223, 170, 117, 64, 11, 214, 161, 108, 200, 253, 50, 103, 156, 209, 6, 59, 112, 165, 218, 15, 68, 121, 174, 28, 231, 178, 130, 183, 19, 33, 86, 139, 63, 10, 42, 95, 107, 54, 1, 204, 151, 98, 45, 248, 195, 142, 89, 36, 239, 69, 122, 175, 27, 230, 177, 124, 71, 237, 34, 168, 115, 193, 246, 212, 159, 149, 202, 255, 52, 105, 158, 44, 8, 194, 141, 88, 35, 17, 70, 132, 79, 229, 26, 79, 132, 185, 238, 35, 88, 141, 194, 247, 44, 158, 105, 52, 255, 202, 149, 96, 43, 246, 193, 115, 168, 221, 18, 71, 124, 177, 230, 27, 80, 133, 69, 16, 219, 166, 113, 60, 248, 45, 157, 104, 204, 254, 201, 148, 95, 42, 245, 192, 139, 86, 33, 236, 183, 130, 77, 24, 227, 174, 121, 68, 15, 218, 90, 143, 196, 249, 46, 99, 152, 205, 2, 55, 108, 161, 214, 11, 64, 138, 170, 223, 20, 73, 126, 179, 232, 29, 82, 135, 188, 241, 38, 91, 144, 197, 250, 208, 155, 102, 49, 252, 199, 109, 93, 40, 243, 190, 137, 84, 31, 234, 181, 128, 75, 22, 225, 172, 119, 66, 13, 216, 163, 145, 198, 251, 48, 101, 101, 48, 4, 57, 110, 163, 216, 13, 66, 119, 172, 225, 22, 75, 128, 181, 21, 224, 84, 137, 190, 12, 215, 162, 109, 56, 3, 206, 102, 155, 208, 250, 58, 111, 91, 38, 241, 188, 135, 82, 29, 232, 179, 126, 73, 20, 223, 170, 117, 64, 244, 41, 94, 147, 200, 253, 205, 152, 99, 46, 249, 59, 112, 165, 218, 240, 187, 121, 81, 28, 231, 77, 130, 183, 236, 33, 169, 116, 192, 245, 213, 160, 107, 54, 1, 204, 151, 157, 210, 7, 60, 113, 166, 219, 16, 186, 133, 80, 27, 25, 78, 131, 184, 237, 34, 87, 115, 62, 9, 43, 96, 149, 202, 255, 52, 105, 97, 44, 247, 194, 114, 167, 220, 17, 70, 123, 176, 229, 26, 79, 132, 185, 238, 35, 88, 141, 61, 8, 211, 158, 105, 52, 255, 53, 106, 159, 212, 9, 62, 115, 87, 34, 237, 184, 131, 78, 25, 228, 175, 122, 69, 239, 36, 89, 142, 195, 248, 210, 157, 104, 51, 254, 201, 148, 95, 213, 10, 192, 116, 169, 33, 236, 72, 125, 178, 231, 28, 81, 134, 68, 15, 218, 165, 112, 59, 6, 209, 99, 152, 205, 2, 55, 108, 161, 214, 11, 64, 117, 170, 223, 20, 182, 129, 76, 23, 226, 82, 135, 188, 241, 217, 164, 111, 58, 5, 208, 155, 102, 49, 252, 199, 146, 93, 40, 243, 190, 137, 84, 224, 21, 74, 127, 180, 233, 30, 83, 136, 189, 242, 39, 92, 145, 198, 251, 48, 101, 101, 207, 4, 57, 110, 163, 39, 13, 189, 136, 172, 225, 22, 180, 128, 181, 21, 31, 84, 137, 190, 12, 215, 162, 146, 56, 3, 206, 153, 100, 47, 5, 59, 111, 164, 38, 241, 188, 134, 82, 28, 233, 179, 129, 183, 234, 34, 84, 139, 190, 244, 41, 161, 108, 54, 0, 204, 153, 98, 47, 249, 58, 115, 161, 222, 11, 71, 120, 174, 28, 230, 179, 124, 74, 16, 221, 163, 121, 51, 3, 222, 86, 186, 226, 244, 221, 133, 119, 62, 253, 44, 105, 161, 35, 229, 189, 122, 161, 246, 28, 160, 102, 97, 14, 57, 104, 174, 46, 20, 206, 137, 111, 197, 232, 55, 157, 103, 215, 6, 43, 104, 169, 35, 224, 161, 155, 85, 58, 242, 98, 200, 162, 13, 198, 183, 99, 193, 233, 13, 153, 78, 59, 11, 32, 116, 130, 215, 215, 220, 128, 87, 34, 224, 157, 128, 137, 204, 236, 184, 124, 84, 26, 52, 66, 114, 26, 20, 58, 70, 183, 221, 248, 214, 129, 166, 223, 240, 216, 160, 127, 253, 93, 107, 150, 83, 6, 195, 89, 182, 146, 7, 255, 175, 131, 200, 236, 62, 153, 115, 201, 9, 205, 136, 118, 5, 252, 10, 56, 85, 26, 193, 160, 126, 128, 172, 11, 156, 56, 77, 229, 6, 127, 159, 52, 16, 44, 108, 110, 47, 216, 225, 105, 233, 238, 225, 138, 146, 95, 243, 85, 126, 145, 12, 60, 18, 74, 150, 157, 246, 199, 180, 156, 214, 13, 236, 182, 77, 212, 83, 19, 177, 112, 55, 247, 93, 74, 181, 50, 161, 160, 164, 150, 240, 19, 179, 92, 185, 216, 34, 188, 64, 9, 24, 112, 60, 145, 19, 209, 205, 99, 151, 238, 245, 248, 191, 188, 218, 8, 68, 112, 106, 1, 8, 99, 118, 120, 55, 227, 170, 203, 171, 3, 134, 179, 96, 194, 49, 8, 128, 16, 11, 20, 99, 115, 171, 22, 249, 178, 187, 148, 50, 157, 145, 81, 226, 132, 20, 146, 58, 46, 245, 27, 43, 190, 0, 171, 218, 88, 184, 209, 23, 176, 146, 187, 215, 25, 139, 65, 109, 30, 109, 60, 139, 105, 52, 47, 65, 175, 255, 9, 133, 211, 149, 231, 22, 58, 134, 67, 42, 61, 111, 145, 14, 46, 197, 85, 232, 251, 37, 135, 177, 150, 239, 206, 53, 179, 62, 43, 48, 5, 123, 99, 61, 237, 50, 67, 164, 14, 214, 146, 147, 242, 140, 18, 247, 69, 182, 202, 20, 117, 117, 116, 78, 33, 34, 176, 207, 232, 214, 158, 130, 241, 255, 238, 187, 115, 199, 113, 124, 181, 4, 30, 60, 119, 161, 176, 34, 156, 173, 186, 226, 251, 195, 133, 105, 217, 38, 50, 140, 117, 27, 247, 22, 62, 117, 110, 253, 93, 99, 151, 241, 244, 145, 97, 157, 208, 45, 167, 120, 44, 247, 10, 104, 113, 19, 205, 208, 46, 245, 45, 181, 158, 126, 185, 254, 52, 181, 175, 84, 255, 0, 90, 118, 76, 24, 37, 64, 155, 43, 17, 230, 141, 164, 136, 244, 253, 131, 165, 222, 24, 94, 118, 114, 9, 25, 94, 140, 179, 24, 248, 170, 159, 189, 28, 216, 138, 102, 133, 206, 237, 182, 152, 217, 4, 43, 119, 94, 57, 245, 91, 117, 169, 230, 229, 166, 131, 165, 24, 197, 164, 109, 170, 189, 61, 156, 68, 219, 236, 49, 110, 150, 35, 232, 42, 108, 164, 34, 241, 178, 136, 164, 237, 250, 151, 107, 189, 210, 17, 183, 73, 51, 237, 51, 80, 151, 56, 18, 55, 76, 136, 37, 242, 196, 135, 92, 203, 238, 147, 182, 89, 161, 93, 161, 66, 94, 235, 50, 116, 153, 45, 46, 223, 69, 184, 207, 19, 219, 146, 99, 213, 9, 212, 185, 123, 231, 67, 187, 198, 83, 239, 19, 87, 164, 70, 59, 195, 71, 182, 211, 26, 198, 147, 104, 219, 3, 211, 163, 123, 234, 73, 208, 188, 93, 222, 17, 82, 104, 77, 58, 243, 118, 176, 177, 2, 212, 169, 123, 206, 244, 207, 160, 156, 135, 16, 255, 131, 184, 210, 14, 50, 116, 67, 61, 27, 120, 88, 77, 8, 242, 162, 121, 70, 10, 193, 181, 162, 218, 32, 247, 105, 151, 193, 22, 201, 183, 124, 217, 37, 92, 115, 170, 42, 255, 176, 121, 73, 52, 229, 107, 153, 117, 57, 50, 120, 153, 203, 252, 242, 169, 157, 246, 39, 62, 146, 81, 60, 251, 190, 142, 91, 242, 62, 181, 178, 96, 23, 4, 116, 168, 75, 59, 246, 91, 191, 230, 246, 48, 151, 107, 55, 242, 220, 111, 227, 245, 213, 131, 152, 173, 234, 49, 106, 111, 102, 26, 17, 95, 133, 168, 243, 198, 94, 159, 26, 47, 24, 44, 159, 26, 218, 192, 108, 190, 197, 224, 145, 142, 178, 244, 19, 177, 109, 92, 232, 1, 86, 111, 179, 232, 223, 191, 106, 202, 248, 42, 118, 123, 5, 245, 44, 100, 172, 220, 247, 174, 141, 168, 29, 9, 107, 138, 87, 9, 220, 174, 128, 230, 228, 207, 131, 99, 199, 236, 53, 134, 122, 47, 31, 53, 138, 178, 201, 249, 154, 125, 160, 224, 30, 178, 109, 77, 234, 51, 92, 113, 49, 16, 201, 156, 131, 238, 215, 202, 191, 123, 212, 4, 44, 102, 93, 58, 253, 71, 107, 161, 233, 230, 167, 103, 75, 22, 48, 99, 144, 30, 56, 221, 109, 136, 232, 8, 235, 186, 100, 242, 19, 195, 134, 69, 55, 231, 79, 88, 170, 18, 249, 185, 115, 180, 241, 55, 164, 104, 33, 248, 13, 117, 110, 34, 240, 197, 145, 185, 253, 14, 216, 152, 68, 51, 0, 100, 119, 80, 3, 228, 88, 145, 174, 14, 198, 189, 143, 231, 222, 210, 135, 115, 62, 254, 36, 123, 91, 60, 248, 184, 138, 161, 210, 18, 176, 145, 68, 244, 60, 83, 119, 73, 2, 209, 75, 157, 61, 15, 213, 156, 96, 202, 5, 194, 151, 164, 194, 24, 65, 134, 65, 21, 29, 65, 126, 181, 20, 241, 160, 137, 187, 250, 35, 166, 110, 201, 234, 53, 152, 111, 34, 247, 56, 107, 162, 218, 240, 179, 128, 165, 234, 20, 77, 145, 164, 224, 224, 160, 103, 79, 11, 215, 93, 107, 49, 9, 202, 110, 156, 47, 6, 42, 117, 179, 220, 253, 179, 137, 90, 226, 22, 180, 115, 89, 30, 35, 95, 130, 184, 243, 32, 81, 157, 203, 6, 196, 147, 105, 40, 4, 57, 131, 87, 37, 12, 68, 126, 186, 242, 28, 177, 121, 76, 23, 222, 87, 114, 50, 6, 221, 161, 147, 196, 246, 50, 106, 149, 219, 1, 61, 138, 81, 47, 227, 176, 131, 172, 231, 229, 183, 125, 190, 228, 40, 90, 135, 195, 10, 213, 97, 105, 60, 10, 204, 147, 102, 41, 14, 55, 118, 88, 220, 21, 77, 119, 181, 24, 226, 186, 115, 68, 17, 217, 160, 115, 196, 240, 42, 103, 104, 60, 251, 48, 99, 152, 212, 240, 203, 135, 94, 33, 18, 68, 122, 184, 225, 24, 81, 123, 186, 231, 44, 167, 121, 53, 12, 216, 154, 106, 200, 9, 62, 98, 168, 215, 11, 60, 118, 169, 222, 239, 179, 129, 72, 31, 233, 166, 123, 191, 247, 32, 94, 142, 196, 253, 42, 156, 101, 205, 0, 205, 152, 86, 45, 246, 67, 115, 168, 32, 20, 75, 127, 178, 238, 27, 173, 123, 188, 240, 219, 167, 110, 57, 1, 45, 108, 159, 204, 252, 196, 148, 95, 211, 8, 191, 139, 84, 31, 234, 180, 127, 183, 237, 31, 173, 117, 67, 243, 38, 161, 104, 61, 4, 50, 102, 154, 51, 248, 198, 106, 164, 222, 12, 189, 136, 172, 30, 235, 176, 121, 79, 21, 30, 170, 119, 191, 243, 213, 93, 148, 193, 255, 50, 98, 154, 44, 254, 193, 147, 90, 217, 243, 184, 134, 82, 29, 21, 72, 129, 73, 234, 34, 87, 136, 188, 11, 213, 162, 111, 53, 255, 49, 153, 103, 46, 4, 57, 112, 165, 218, 241, 186, 120, 175, 29, 229, 178, 125, 183, 239, 34, 168, 118, 192, 244, 43, 94, 149, 52, 2, 205, 151, 98, 45, 249, 193, 113, 165, 217, 16, 69, 123, 175, 228, 25, 78, 131, 185, 237, 222, 173, 112, 192, 245, 41, 96, 107, 52, 255, 53, 107, 156, 210, 8, 61, 140, 90, 220, 16, 186, 129, 78, 231, 24, 76, 135, 70, 18, 221, 90, 143, 195, 245, 211, 157, 107, 203, 0, 53, 106, 96, 42, 247, 62, 113, 170, 34, 236, 184, 124, 177, 231, 228, 173, 121, 68, 239, 38, 91, 142, 61, 6, 211, 157, 151, 205, 1, 201, 107, 161, 40, 241, 193, 117, 168, 223, 18, 73, 130, 76, 24, 28, 81, 135, 185, 241, 218, 164, 114, 57, 5, 208, 98, 153, 205, 2, 54, 109, 160, 214, 244, 191, 116, 168, 222, 20, 183, 131, 78, 22, 226, 82, 135, 188, 14, 217, 91, 145, 197, 250, 47, 100, 153, 206, 3, 198, 147, 93, 215, 12, 190, 137, 84, 31, 21, 181, 128, 180, 232, 31, 83, 118, 64, 12, 39, 92, 145, 199, 251, 206, 155, 154, 207, 4, 57, 110, 92, 39, 13, 67, 118, 172, 28, 234, 180, 129, 180, 232, 29, 84, 116, 66, 13, 41, 92, 146, 57, 3, 206, 153, 101, 47, 5, 58, 111, 165, 216, 241, 188, 120, 173, 29, 23, 77, 128, 73, 21, 223, 170, 117, 64, 244, 41, 94, 147, 55, 3, 204, 153, 99, 208, 4, 59, 141, 91, 36, 240, 68, 121, 80, 28, 25, 79, 130, 73, 18, 220, 169, 137, 194, 245, 42, 160, 106, 55, 254, 51, 104, 156, 211, 7, 195, 143, 89, 36, 16, 186, 122, 175, 27, 230, 78, 131, 71, 237, 34, 86, 141, 193, 9, 213, 157, 107, 202, 255, 52, 150, 96, 45, 247, 61, 114, 167, 220, 17, 71, 123, 79, 26, 229, 177, 123, 185, 238, 35, 88, 114, 60, 8, 211, 97, 151, 202, 0, 202, 149, 97, 42, 246, 62, 115, 168, 221, 237, 184, 124, 176, 230, 228, 175, 133, 186, 238, 37, 166, 112, 61, 6, 210, 98, 150, 204, 254, 200, 148, 95, 213, 11, 63, 116, 169, 33, 237, 183, 125, 77, 24, 28, 81, 121, 69, 240, 37, 165, 112, 196, 249, 46, 99, 152, 50, 253, 55, 147, 94, 41, 11, 191, 138, 170, 32, 235, 182, 126, 179, 232, 28, 82, 121, 66, 14, 38, 91, 144, 58, 5, 208, 155, 153, 206, 252, 199, 146, 162, 215, 12, 190, 137, 84, 31, 21, 74, 128, 75, 22, 225, 83, 136, 188, 242, 216, 163, 145, 198, 251, 48, 154, 101, 48, 251, 57, 110, 163, 39, 242, 66, 119, 83, 30, 22, 75, 128, 74, 21, 224, 171, 137, 190, 243, 215, 93, 109, 56, 3, 207, 101, 100, 46, 5, 196, 144, 91, 217, 241, 67, 120, 83, 227, 23, 179, 129, 73, 235, 32, 170, 117, 64, 244, 41, 94, 108, 55, 253, 50, 103, 99, 209, 6, 59, 143, 90, 37, 15, 68, 134, 174, 227, 24, 178, 125, 183, 236, 33, 169, 116, 192, 245, 213, 95, 148, 54, 1, 51, 151, 157, 210, 248, 195, 113, 89, 36, 239, 69, 122, 175, 228, 230, 177, 124, 184, 237, 221, 168, 115, 62, 9, 43, 96, 106, 202, 0, 203, 105, 158, 211, 8, 61, 141, 88, 220, 17, 185, 132, 176, 26, 229, 79, 132, 185, 17, 220, 167, 114, 194, 247, 44, 97, 105, 52, 0, 53, 149, 96, 212, 9, 193, 115, 168, 34, 237, 184, 131, 177, 230, 228, 175, 122, 69, 239, 36, 166, 113, 60, 7, 45, 98, 151, 51, 254, 201, 148, 160, 213, 10, 192, 139, 86, 222, 19, 72, 125, 77, 24, 28, 81, 134, 68, 15, 218, 165, 143, 196, 249, 209, 156, 152, 205, 2, 55, 108, 161, 41, 244, 191, 138, 170, 223, 20, 73, 129, 76, 232, 29, 173, 120, 67, 241, 217, 91, 144, 197, 5, 208, 100, 153, 49, 252, 199, 109, 162, 215, 12, 190, 137, 171, 224, 21, 74, 128, 75, 233, 30, 83, 136, 66, 13, 39, 92, 145, 57, 4, 207, 154, 101, 207, 5, 198, 147, 92, 217, 13, 66, 136, 83, 30, 233, 75, 128, 181, 21, 224, 84, 137, 190, 12, 215, 162, 109, 199, 252, 206, 153, 155, 208, 5, 197, 144, 164, 38, 241, 67, 120, 82, 226, 232, 179, 129, 182, 20, 32, 170, 117, 191, 244, 41, 161, 108, 55, 253, 50, 103, 99, 46, 6, 59, 112, 165, 37, 15, 187, 121, 174, 227, 231, 178, 125, 183, 236, 222, 169, 139, 63, 10, 213, 95, 148, 54, 254, 204, 104, 157, 45, 6, 195, 142, 166, 219, 16, 186, 133, 175, 228, 230, 78, 124, 184, 237, 34, 168, 115, 193, 246, 43, 159, 106, 202, 255, 203, 105, 97, 44, 8, 194, 141, 165, 35, 239, 70, 122, 79, 229, 27, 176, 122, 185, 238, 35, 88, 114, 61, 247, 45, 158, 105, 203, 254, 53, 106, 96, 43, 9, 193, 140, 168, 34, 237, 71, 131, 78, 230, 27, 175, 133, 186, 16, 219, 89, 143, 195, 7, 210, 157, 151, 51, 254, 55, 107, 94, 42, 11, 192, 116, 168, 33, 236, 183, 130, 178, 231, 28, 174, 121, 68, 15, 36, 90, 112, 59, 249, 209, 99, 103, 50, 2, 55, 147, 94, 214, 11, 191, 138, 85, 223, 20, 182, 129, 76, 232, 29, 173, 120, 188, 241, 217, 91, 111, 197, 5, 208, 155, 153, 207, 3, 199, 109, 93, 215, 243, 65, 118, 84, 31, 21, 181, 127, 181, 22, 225, 83, 119, 66, 243, 216, 163, 145, 57, 251, 48, 101, 101, 48, 4, 198, 145, 163, 216, 242, 66, 136, 172, 225, 22, 75, 127, 74, 234, 30, 171, 119, 191, 243, 214, 93, 146, 56, 3, 48, 153, 100, 209, 5, 197, 145, 91, 216, 14, 189, 135, 173, 29, 23, 179, 129, 182, 21, 223, 85, 117, 191, 244, 214, 160, 147, 200, 2, 50, 103, 98, 209, 6, 196, 143, 90, 218, 240, 68, 120, 80, 28, 24, 77, 125, 72, 236, 222, 86, 139, 63, 245, 213, 94, 148, 201, 254, 204, 151, 98, 211, 7, 195, 142, 166, 36, 16, 69, 133, 175, 27, 230, 177, 131, 184, 18, 221, 168, 140, 193, 9, 212, 96, 149, 53, 0, 203, 150, 158, 44, 8, 194, 141, 166, 220, 238, 185, 123, 79, 26, 26, 176, 132, 70, 238, 35, 88, 114, 194, 247, 211, 97, 150, 52, 255, 202, 106, 96, 212, 9, 193, 115, 87, 221, 237, 71, 124, 177, 230, 27, 80, 122, 186, 16, 219, 89, 113, 195, 248, 210, 157, 104, 204, 1, 54, 148, 160, 42, 245, 192, 139, 169, 33, 236, 72, 130, 77, 231, 28, 175, 134, 68, 15, 37, 164, 143, 196, 6, 46, 156, 103, 204, 2, 201, 147, 161, 214, 244, 64, 117, 85, 32, 20, 72, 129, 76, 232, 29, 82, 135, 188, 14, 217, 91, 111, 58, 250, 47, 155, 102, 49, 252, 56, 146, 93, 215, 243, 190, 137, 171, 31, 21, 74, 128, 75, 233, 225, 83, 119, 66, 242, 216, 163, 110, 198, 4, 207, 101, 101, 207, 251, 198, 110, 163, 39, 242, 189, 136, 83, 225, 22, 180, 127, 181, 234, 224, 84, 137, 65, 12, 214, 93, 146, 56, 252, 206, 153, 100, 209, 5, 58, 144, 91, 217, 241, 67, 120, 82, 29, 232, 179, 129, 182, 20, 32, 170, 116, 191, 245, 214, 94, 108, 55, 253, 50, 152, 99, 46, 249, 59, 143, 90, 37, 14, 68, 121, 81, 28, 24, 178, 130, 183, 19, 222, 86, 139, 63, 245, 213, 95, 148, 201, 1, 204, 104, 157, 210, 7, 194, 142, 166, 36, 16, 69, 132, 80, 27, 230, 79, 124, 184, 237, 220, 168, 140, 192, 9, 43, 159, 107, 202, 255, 52, 105, 97, 44, 8, 61, 141, 167, 35, 238, 185, 123, 176, 229, 26, 176, 123, 185, 238, 220, 167, 141, 194, 8, 211, 158, 150, 52, 255, 53, 106, 159, 43, 246, 193, 140, 169, 221, 237, 184, 131, 177, 231, 27, 175, 133, 186, 16, 36, 89, 113, 60, 7, 45, 98, 104, 51, 0, 55, 107, 95, 42, 10, 63, 139, 86, 33, 19, 183, 125, 178, 24, 28, 81, 121, 69, 240, 36, 164, 143, 196, 249, 46, 99, 103, 50, 2, 55, 147, 161, 214, 244, 64, 138, 170, 223, 235, 182, 129, 179, 232, 226, 82, 120, 67, 14, 216, 91, 146, 197, 4, 208, 100, 153, 49, 3, 199, 109, 162, 40, 243, 190, 118, 171, 224, 234, 181, 127, 180, 233, 30, 83, 136, 66, 242, 39, 162, 145, 198, 4, 48, 154, 101, 48, 4, 198, 145, 163, 39, 13, 189, 136, 172, 225, 233, 75, 128, 74, 234, 224, 171, 137, 191, 12, 214, 162, 146, 199, 252, 49, 152, 155, 208, 250, 197, 110, 164, 217, 241, 188, 121, 82, 226, 232, 179, 129, 182, 235, 32, 85, 116, 64, 245, 41, 161, 108, 55, 253, 50, 103, 99, 46, 6, 196, 112, 165, 218, 240, 187, 134, 81, 28, 24, 178, 130, 183, 19, 222, 169, 139, 192, 10, 42, 161, 107, 54, 1, 51, 104, 157, 45, 248, 195, 113, 89, 36, 16, 69, 133, 175, 228, 230, 78, 131, 71, 237, 34, 87, 115, 62, 246, 212, 96, 149, 202, 255, 203, 150, 97, 44, 8, 61, 141, 88, 35, 238, 70, 123, 79, 26, 229, 176, 132, 185, 17, 220, 88, 114, 194, 247, 211, 97, 150, 52, 0, 53, 149, 159, 212, 9, 62, 140, 87, 221, 237, 184, 125, 78, 25, 26, 175, 133, 186, 16, 36, 89, 113, 60, 248, 210, 98, 104, 51, 1, 54, 148, 95, 213, 245, 192, 116, 86, 33, 236, 72, 130, 178, 24, 227, 81, 120, 68, 241, 218, 165, 143, 59, 6, 46, 156, 103, 205, 253, 55, 108, 94, 214, 11, 191, 117, 170, 223, 235, 73, 129, 179, 232, 29, 82, 120, 67, 241, 38, 164, 144, 58, 5, 208, 100, 102, 206, 3, 199, 109, 162, 40, 12, 65, 136, 171, 31, 234, 74, 127, 75, 233, 30, 172, 136, 66, 13, 39, 163, 145, 198, 4, 207, 101, 101, 207, 4, 57, 110, 163, 216, 242, 66, 119, 83, 30, 233, 180, 128, 181, 21, 31, 171, 118, 190, 12, 215, 93, 146, 56, 252, 49, 153, 155, 208, 250, 58, 144, 91, 217, 241, 188, 120, 173, 29, 23, 179, 126, 182, 20, 223, 85, 117, 64, 244, 214, 161, 147, 55, 2, 50, 152, 99, 209, 249, 59, 112, 90, 218, 15, 187, 134, 174, 28, 231, 77, 125, 72, 236, 222, 169, 139, 63, 10, 42, 160, 107, 201, 1, 51, 104, 98, 210, 7, 195, 142, 166, 219, 239, 69, 133, 80, 228, 230, 177, 131, 71, 18, 221, 168, 115, 193, 9, 212, 96, 149, 53, 0, 203, 150, 158, 211, 247, 61, 114, 167, 220, 17, 70, 123, 79, 26, 26, 176, 132, 185, 238, 35, 88, 141, 194, 8, 211, 158, 105, 52, 255, 53, 106, 96, 212, 9, 62, 140, 87, 34, 237, 184, 131, 78, 25, 228, 80, 133, 186, 239, 219, 89, 142, 60, 248, 45, 157, 104, 51, 254, 201, 148, 95, 213, 10, 63, 116, 86, 33, 19, 72, 125, 178, 231, 227, 81, 134, 68, 240, 37, 165, 112, 59, 6, 46, 99, 103, 50, 253, 200, 147, 161, 214, 11, 64, 138, 170, 32, 235, 182, 129, 76, 232, 29, 82, 135, 188, 14, 38, 91, 111, 58, 5, 208, 155, 153, 49, 252, 56, 146, 162, 215, 243, 65, 118, 171, 224, 21, 74, 127, 75, 22, 30, 172, 136, 189, 13, 216, 163, 110, 57, 251, 48, 101, 154, 207, 4, 57, 145, 92, 39, 242, 189, 136, 83, 30, 22, 180, 127, 181, 234, 31, 84, 118, 190, 243, 40, 93, 146, 199, 252, 49, 102, 155, 208, 5, 197, 144, 164, 217, 14, 188, 135, 82, 29, 232, 76, 129, 182, 235, 223, 170, 117, 64, 244, 214, 161, 108, 200, 2, 205, 152, 99, 46, 249, 196, 143, 90, 218, 15, 68, 134, 81, 28, 24, 77, 130, 183, 236, 33, 86, 139, 192, 245, 42, 95, 148, 201, 254, 51, 104, 157, 210, 7, 60, 113, 166, 219, 239, 69, 133, 175, 228, 230, 177, 124, 71, 18, 221, 168, 115, 62, 246, 212, 159, 106, 53, 0, 203, 150, 97, 211, 247, 61, 114, 167, 220, 238, 185, 123, 79, 26, 26, 79, 132, 185, 17, 220, 167, 114, 194, 247, 44, 97, 150, 52, 255, 202, 149, 96, 43, 9, 62, 140, 87, 221, 237, 184, 131, 78, 230, 27, 80, 133, 186, 239, 36, 166, 113, 195, 248, 45, 98, 151, 204, 1, 201, 148, 95, 42, 10, 192, 116, 169, 33, 19, 72, 130, 77, 24, 227, 174, 121, 68, 15, 218, 165, 112, 59, 6, 46, 99, 152, 205, 2, 55, 108, 161, 214, 11, 64, 117, 170, 223, 20, 73, 126, 76, 23, 226, 173, 120, 67, 241, 217, 91, 144, 197, 250, 208, 155, 102, 49, 252, 199, 146, 93, 40, 12, 190, 137, 84, 31, 234, 181, 128, 75, 233, 225, 83, 136, 189, 242, 39, 92, 145, 198, 251, 48, 101, 154, 207, 4, 57, 110, 163, 216, 13, 66, 119, 172, 30, 22, 75, 128, 181, 234, 224, 84, 118, 65, 12, 215, 162, 109, 56, 3, 49, 102, 155, 208, 5, 197, 144, 91, 38, 241, 188, 135, 82, 226, 23, 76, 126, 73, 20, 223, 170, 138, 191, 244, 41, 94, 147, 200, 2, 205, 152, 156, 209, 6, 59, 112, 165, 218, 15, 68, 121, 174, 227, 231, 178, 130, 72, 19, 222, 169, 116, 192, 245, 213, 160, 107, 54, 1, 204, 151, 98, 45, 7, 60, 113, 166, 219, 16, 186, 133, 80, 27, 25, 78, 131, 184, 237, 34, 87, 140, 62, 246, 43, 159, 149, 202, 255, 52, 105, 97, 44, 247, 194, 114, 88, 35, 17, 185, 132, 176, 26, 229, 79, 123, 185, 238, 220, 88, 141, 194, 8, 44, 158, 105, 203, 255, 53, 106, 96, 212, 9, 193, 115, 168, 221, 18, 71, 124, 177, 230, 228, 80, 133, 69, 239, 219, 166, 142, 60, 7, 45, 157, 104, 204, 254, 201, 107, 95, 213, 10, 192, 116, 169, 33, 236, 183, 130, 77, 24, 227, 81, 134, 187, 240, 37, 165, 143, 196, 249, 46, 99, 152, 205, 253, 200, 147, 161, 41, 244, 64, 138, 170, 32, 235, 182, 129, 76, 23, 29, 173, 135, 188, 241, 217, 91, 144, 58, 250, 208, 155, 153, 49, 252, 199, 109, 93, 40, 243, 190, 137, 84, 224, 21, 74, 127, 180, 233, 30, 83, 136, 66, 242, 39, 163, 110, 198, 4, 48, 101, 101, 48, 4, 57, 110, 163, 216, 13, 189, 136, 172, 225, 233, 75, 128, 74, 21, 224, 171, 137, 65, 12, 40, 162, 109, 199, 3, 206, 102, 155, 47, 5, 58, 111, 164, 38, 14, 67, 120, 173, 226, 232, 76, 129, 73, 20, 32, 85, 138, 191, 11, 214, 94, 108, 55, 253, 50, 103, 156, 46, 249, 59, 143, 90, 218, 240, 187, 121, 81, 28, 24, 178, 125, 183, 19, 222, 86, 116, 192, 245, 213, 95, 148, 54, 1, 51, 151, 98, 210, 248, 60, 113, 89, 219, 16, 186, 122, 175, 27, 230, 78, 124, 184, 237, 221, 168, 140, 62, 246, 43, 159, 106, 202, 0, 203, 150, 158, 44, 247, 61, 141, 88, 220, 238, 185, 123, 79, 26, 26, 176, 123, 70, 238, 35, 88, 114, 194, 247, 211, 158, 150, 52, 0, 53, 149, 159, 212, 246, 62, 115, 87, 221, 237, 184, 124, 78, 25, 27, 175, 122, 186, 239, 219, 166, 113, 60, 248, 45, 157, 151, 204, 254, 54, 107, 95, 213, 10, 192, 116, 169, 33, 19, 72, 130, 178, 231, 227, 81, 134, 68, 15, 37, 165, 112, 59, 249, 46, 99, 152, 50, 2, 200, 108, 161, 214, 11, 64, 117, 170, 32, 235, 73, 129, 76, 232, 226, 82, 135, 67, 14, 38, 164, 111, 197, 5, 208, 155, 102, 49, 3, 56, 146, 162, 40, 243, 190, 137, 84, 224, 234, 74, 128, 75, 233, 30, 172, 136, 189, 13, 216, 92, 110, 198, 251, 207, 101, 154, 207, 4, 57, 110, 92, 39, 242, 66, 119, 83, 225, 22, 180, 128, 181, 21, 224, 84, 118, 65, 243, 215, 162, 146, 199, 3, 49, 102, 100, 208, 250, 58, 111, 91, 217, 14, 67, 120, 173, 226, 232, 76, 129, 73, 20, 32, 85, 117, 64, 11, 214, 161, 147, 200, 2, 205, 103, 99, 209, 249, 196, 112, 90, 218, 15, 187, 134, 174, 28, 231, 77, 125, 183, 19, 33, 86, 116, 63, 245, 213, 95, 148, 201, 1, 204, 104, 157, 45, 248, 60, 142, 89, 219, 16, 186, 122, 175, 27, 25, 177, 124, 184, 18, 221, 87, 140, 193, 246, 43, 159, 106, 53, 255, 52, 150, 97, 44, 247, 61, 114, 88, 220, 17, 70, 132, 176, 26, 26, 79, 132, 185, 17, 220, 88, 114, 61, 247, 211, 97, 105, 52, 0, 53, 149, 159, 212, 246, 193, 115, 87, 34, 18, 184, 131, 177, 25, 228, 80, 133, 69, 239, 36, 167, 142, 195, 7, 210, 98, 104, 204, 1, 54, 107, 95, 213, 10, 192, 116, 86, 33, 19, 183, 130, 178, 231, 227, 174, 134, 187, 15, 37, 165, 112, 196, 6, 209, 99, 152, 50, 2, 55, 108, 161, 214, 244, 191, 117, 85, 32, 235, 182, 126, 179, 23, 29, 82, 120, 67, 241, 217, 91, 144, 58, 5, 47, 100, 153, 49, 3, 56, 146, 162, 215, 243, 190, 118, 84, 31, 20, 181, 128, 180, 233, 225, 83, 119, 66, 242, 39, 163, 145, 198, 251, 48, 101, 154, 48, 4, 57, 145, 163, 216, 13, 189, 136, 172, 30, 22, 75, 127, 181, 21, 225, 85, 137, 65, 243, 40, 162, 109, 199, 252, 49, 102, 100, 47, 5, 197, 144, 164, 217, 241, 188, 135, 173, 226, 232, 76, 129, 182, 20, 223, 85, 138, 64, 244, 214, 161, 147, 55, 253, 50, 103, 156, 46, 249, 196, 112, 90, 37, 15, 187, 134, 174, 227, 231, 77, 130, 72, 236, 33, 86, 117, 63, 244, 213, 95, 148, 201, 1, 204, 104, 98, 45, 7, 60, 142, 89, 219, 16, 186, 122, 80, 27, 25, 176, 131, 184, 18, 34, 87, 115, 62, 9, 212, 159, 149, 202, 255, 203, 150, 158, 44, 8, 61, 141, 88, 35, 17, 185, 132, 177, 26, 229, 79, 132, 70, 238, 34, 167, 141, 61, 8, 44, 158, 105, 52, 0, 202, 106, 159, 43, 9, 193, 140, 87, 221, 237, 184, 124, 78, 25, 26, 175, 122, 186, 16, 219, 166, 142, 195, 248, 210, 98, 151, 51, 1, 54, 148, 160, 42, 245, 63, 116, 86, 222, 19, 183, 130, 179, 24, 227, 80, 121, 68, 240, 218, 165, 112, 59, 4, 208, 157, 102, 51, 253, 200, 108, 163, 215, 10, 67, 118, 169, 220, 21, 73, 129, 77, 22, 227, 175, 126, 69, 10, 222, 163, 108, 59, 252, 33, 105, 149, 194, 6, 197, 150, 84, 35, 251, 184, 141, 169, 228, 23, 76, 127, 66, 29, 229, 85, 128, 182, 249, 34, 167, 106, 62, 10, 196, 146, 99, 203, 11, 43, 120, 179, 216, 240, 183, 146, 79, 11, 232, 71, 144, 167, 248, 29, 161, 126, 76, 28, 213, 88, 149, 210, 235, 33, 104, 152, 35, 246, 208, 180, 122, 40, 3, 89, 99, 181, 236, 238, 190, 118, 71, 25, 219, 87, 131, 177, 251, 38, 87, 145, 54, 5, 221, 130, 120, 59, 3, 35, 100, 183, 209, 246, 180, 129, 89, 23, 230, 77, 129, 167, 254, 48, 69, 130, 61, 14, 217, 128, 74, 45, 18, 34, 74, 133, 198, 12, 205, 157, 95, 42, 226, 69, 120, 163, 252, 1, 87, 146, 184, 26, 205, 182, 91, 33, 17, 40, 73, 177, 223, 239, 204, 183, 117, 43, 251, 60, 127, 168, 203, 9, 82, 106, 177, 16, 244, 168, 100, 91, 2, 208, 78, 160, 213, 255, 210, 131, 77, 60, 2, 48, 120, 141, 219, 6, 50, 124, 164, 39, 226, 173, 153, 83, 13, 235, 80, 173, 159, 232, 36, 168, 82, 47, 242, 33, 111, 135, 201, 8, 58, 96, 181, 208, 230, 214, 159, 65, 54, 226, 190, 107, 157, 246, 225, 171, 100, 88, 244, 55, 85, 133, 196, 5, 40, 108, 131, 218, 244, 209, 138, 75, 56, 251, 174, 114, 128, 207, 227, 182, 145, 81, 234, 11, 89, 129, 68, 7, 40, 67, 143, 228, 1, 243, 131, 104, 58, 240, 211, 143, 162, 254, 23, 71, 116, 65, 63, 235, 83, 111, 75, 19, 31, 92, 144, 163, 224, 204, 189, 101, 58, 13, 219, 185, 65, 222, 48, 33, 103, 95, 5, 237, 73, 97, 160, 237, 224, 181, 152, 175, 252, 21, 189, 106, 191, 243, 192, 189, 71, 28, 224, 15, 70, 156, 62, 209, 219, 126, 133, 206, 11, 181, 135, 191, 244, 24, 78, 105, 89, 227, 222, 177, 89, 112, 43, 13, 14, 184, 49, 36, 226, 132, 129, 224, 28, 49, 159, 72, 211, 21, 82, 127, 94, 8, 230, 182, 96, 109, 49, 199, 116, 193, 229, 1, 242, 143, 114, 233, 204, 44, 99, 122, 58, 12, 37, 101, 173, 40, 249, 190, 140, 112, 57, 250, 164, 156, 254, 242, 204, 129, 95, 48, 221, 19, 121, 157, 35, 32, 53, 73, 190, 218, 249, 216, 130, 83, 53, 246, 169, 139, 161, 208, 0, 189, 90, 100, 25, 5, 106, 151, 61, 23, 203, 111, 139, 211, 11, 219, 181, 110, 44, 226, 213, 133, 95, 222, 48, 94, 137, 108, 13, 23, 78, 173, 167, 22, 198, 172, 128, 215, 239, 38, 135, 76, 61, 249, 207, 157, 92, 47, 243, 49, 102, 84, 52, 235, 66, 109, 170, 243, 28, 189, 116, 179, 230, 55, 94, 99, 26, 19, 211, 103, 101, 50, 245, 216, 107, 179, 215, 250, 67, 126, 163, 203, 26, 182, 140, 72, 229, 9, 66, 133, 84, 40, 205, 88, 154, 199, 6, 213, 138, 110, 199, 9, 57, 110, 164, 214, 5, 73, 112, 168, 224, 18, 71, 121, 66, 2, 249, 190, 139, 173, 248, 221, 169, 126, 46, 251, 32, 108, 152, 202, 3, 198, 104, 172, 211, 12, 64, 125, 83, 21, 228, 164, 115, 179, 254, 25, 160, 120, 78, 24, 212, 77, 153, 195, 249, 53, 155, 159, 223, 14, 57, 110, 160, 35, 253, 180, 129, 86, 230, 25, 77, 112, 70, 29, 211, 166, 143, 174, 243, 45, 91, 111, 53, 241, 36, 98, 99, 209, 254, 195, 141, 165, 45, 242, 77, 125, 88, 12, 237, 184, 126, 178, 228, 38, 87, 116, 60, 243, 39, 83, 146, 202, 250, 202, 159, 102, 46, 253, 193, 117, 89, 34, 230, 184, 122, 87, 27, 29, 181, 120, 177, 230, 32, 85, 132, 200, 240, 41, 158, 98, 63, 3, 54, 106, 156, 47, 254, 199, 113, 164, 33, 233, 187, 132, 75, 229, 30, 74, 142, 183, 238, 216, 94, 136, 56, 11, 44, 150, 108, 200, 253, 193, 106, 153, 45, 244, 61, 142, 95, 33, 18, 185, 121, 190, 237, 231, 174, 135, 184, 237, 32, 167, 120, 63, 248, 46, 159, 111, 205, 4, 54, 149, 162, 41, 255, 196, 143, 83, 220, 31, 66, 131, 76, 26, 30, 86, 128, 71, 2, 222, 89, 138, 199, 2, 213, 103, 159, 206, 253, 204, 149, 88, 43, 247, 188, 113, 163, 217, 20, 182, 133, 79, 234, 30, 82, 123, 66, 240, 39, 90, 144, 59, 249, 39, 101, 96, 57, 250, 196, 108, 94, 47, 9, 73, 141, 80, 224, 20, 72, 121, 179, 21, 227, 81, 140, 64, 13, 44, 88, 111, 197, 249, 200, 158, 155, 53, 252, 196, 149, 89, 216, 241, 185, 117, 164, 231, 22, 180, 127, 183, 235, 31, 82, 140, 188, 241, 214, 160, 147, 197, 7, 205, 154, 110, 40, 255, 194, 144, 161, 217, 14, 70, 125, 172, 230, 22, 178, 130, 177, 232, 222, 87, 136, 191, 244, 41, 95, 105, 62, 7, 202, 147, 103, 216, 251, 206, 117, 175, 218, 241, 76, 121, 82, 230, 17, 79, 126, 180, 228, 35, 170, 117, 193, 11, 208, 169, 108, 50, 3, 206, 146, 157, 211, 5, 63, 117, 164, 218, 22, 64, 121, 174, 228, 27, 76, 131, 70, 18, 221, 168, 112, 57, 13, 208, 152, 110, 202, 0, 207, 104, 155, 209, 247, 195, 116, 175, 216, 238, 70, 121, 178, 227, 27, 181, 120, 185, 19, 216, 161, 122, 57, 12, 211, 159, 106, 52, 6, 60, 107, 158, 214, 11, 61, 116, 174, 33, 236, 67, 127, 77, 26, 228, 174, 121, 67, 21, 223, 163, 118, 62, 252, 47, 157, 145, 203, 255, 200, 109, 166, 214, 9, 62, 136, 86, 219, 236, 177, 130, 179, 30, 233, 171, 125, 67, 12, 33, 93, 138, 198, 6, 209, 97, 145, 196, 3, 201, 110, 160, 43, 11, 65, 117, 84, 37, 237, 178, 132, 69, 18, 30, 90, 130, 188, 241, 38, 91, 144, 195, 253, 46, 153, 152, 205, 3, 199, 146, 93, 43, 245, 183, 129, 93, 22, 28, 94, 123, 64, 30, 23, 93, 142, 67, 15, 217, 93, 154, 207, 6, 201, 159, 154, 49, 243, 204, 152, 83, 40, 1, 89, 112, 67, 16, 28, 88, 135, 73, 21, 226, 173, 143, 177, 244, 212, 164, 110, 59, 9, 197, 159, 104, 62, 15, 27, 104, 67, 40, 28, 95, 125, 89, 30, 20, 178, 132, 185, 236, 217, 172, 139, 68, 26, 217, 164, 126, 56, 235, 19, 157, 125, 41, 16, 27, 123, 86, 41, 241, 66, 119, 191, 230, 224, 187, 127, 75, 3, 205, 164, 97, 59, 232, 61, 178, 119, 201, 228, 19, 100, 104, 34, 251, 48, 105, 183, 218, 234, 188, 128, 82, 17, 243, 164, 106, 71, 241, 45, 186, 105, 60, 229, 11, 115, 96, 39, 3, 38, 112, 143, 214, 244, 203, 135, 92, 37, 254, 163, 155, 177, 197, 23, 166, 98, 71, 252, 3, 77, 123, 40, 11, 59, 65, 135, 206, 252, 193, 158, 99, 47, 249, 221, 147, 168, 195, 25, 160, 154, 78, 244, 0, 68, 121, 81, 24, 51, 124, 155, 198, 4, 222, 146, 106, 205, 241, 214, 182, 95, 202, 7, 214, 150, 83, 206, 9, 95, 125, 94, 21, 9, 122, 159, 191, 11, 209, 169, 112, 199, 8, 241, 189, 100, 212, 15, 217, 138, 88, 220, 30, 85, 119, 69, 45, 4, 97, 96, 181, 17, 233, 167, 135, 190, 0, 199, 134, 105, 220, 234, 194, 133, 110, 197, 27, 44, 109, 76, 38, 29, 106, 105, 168, 23, 226, 179, 124, 180, 25, 250, 179, 116, 166, 253, 204, 130, 100, 200, 237, 63, 99, 98, 35, 7, 21, 70, 165, 45, 251, 187, 137, 175, 23, 242, 146, 111, 162, 240, 231, 180, 100, 187, 226, 62, 80, 100, 32, 254, 29, 79, 156, 36, 243, 193, 110, 162, 33, 234, 159, 150, 189, 251, 233, 168, 104, 183, 248, 49, 88, 116, 87, 3, 14, 111, 153, 58, 8, 201, 153, 152, 47, 239, 227, 150, 181, 198, 242, 166, 148, 171, 242, 21, 70, 134, 71, 27, 1, 102, 133, 52, 3, 214, 162, 150, 55, 19, 236, 138, 156, 196, 1, 209, 157, 90, 209, 0, 75, 126, 92, 23, 14, 97, 148, 79, 25, 223, 171, 140, 195, 7, 203, 191, 109, 223, 241, 197, 129, 103, 217, 5, 51, 122, 80, 46, 30, 104, 102, 77, 16, 225, 180, 122, 186, 24, 192, 133, 125, 205, 228, 213, 134, 101, 205, 14, 62, 111, 159, 46, 12, 31, 80, 174, 43, 233, 186, 134, 176, 29, 242, 142, 97, 185, 249, 35, 180, 97, 195, 240, 38, 105, 146, 52, 254, 42, 78, 170, 45, 246, 195, 142, 170, 32, 248, 170, 158, 73, 244, 17, 163, 108, 71, 252, 43, 95, 143, 59, 251, 56, 64, 137, 55, 251, 201, 151, 95, 214, 251, 163, 169, 91, 203, 0, 188, 155, 74, 228, 18, 91, 120, 71, 241, 50, 127, 134, 56, 15, 213, 153, 157, 204, 236, 220, 137, 87, 217, 1, 180, 159, 80, 237, 24, 78, 127, 181, 232, 19, 114, 147, 191, 4, 221, 167, 110, 198, 15, 215, 187, 117, 192, 20, 205, 136, 90, 215, 29, 69, 137, 84, 26, 6, 109, 155, 181, 30, 232, 169, 141, 190, 7, 195, 187, 103, 203, 251, 192, 136, 101, 221, 20, 62, 152, 94, 218, 28, 99, 98, 174, 21, 238, 182, 126, 73, 29, 202, 180, 112, 172, 240, 207, 185, 145, 219, 234, 52, 137, 119, 208, 24, 19, 103, 91, 43, 252, 187, 127, 82, 22, 243, 162, 139, 184, 28, 253, 165, 132, 218, 231, 211, 182, 101, 195, 225, 19, 122, 99, 39, 240, 193, 140, 95, 46, 251, 189, 105, 165, 6, 206, 181, 149, 167, 254, 208, 137, 124, 212, 222, 53, 105, 109, 56, 3, 54, 146, 107, 60, 245, 42, 98, 67, 12, 252, 72, 101, 168, 26, 255, 172, 135, 152, 206, 44, 90, 116, 58, 9, 213, 146, 103, 48, 20, 44, 146, 80, 8, 9, 41, 110, 162, 48, 205, 177, 101, 147, 244, 25, 168, 121, 185, 21, 209, 169, 113, 223, 239, 223, 186, 114, 48, 17, 35, 111, 80, 57, 241, 45, 110, 164, 223, 238, 75, 117, 72, 10, 240, 81, 166, 167, 0, 241, 178, 141, 215, 236, 215, 130, 112, 200, 24, 32, 106, 86, 33, 3, 77, 117, 68, 52, 4, 99, 115, 111, 48, 228, 67, 144, 180, 26, 248, 182, 156, 219, 239, 46, 151, 111, 196, 8, 196, 135, 86, 200, 38, 191, 167, 116, 225, 2, 106, 121, 107, 61, 238, 65, 148, 174, 12, 202, 165, 153, 207, 3, 223, 105, 185, 223, 236, 217, 154, 165, 207, 21, 189, 151, 115, 28, 2, 91, 133, 79, 18, 30, 80, 118, 81, 15, 8, 125, 100, 29, 12, 52, 117, 141, 208, 237, 221, 145, 169, 208, 243, 179, 128, 170, 238, 22, 163, 131, 168, 248, 208, 177, 114, 185, 250, 57, 93, 126, 46, 3, 42, 104, 106, 54, 246, 62, 124, 162, 46, 245, 93, 99, 87, 1, 232, 72, 145, 164, 237, 205, 188, 117, 211, 231, 214, 181, 122, 51, 246, 52, 108, 146, 220, 240, 212, 141, 172, 216, 16, 70, 123, 87, 19, 31, 67, 133, 65, 28, 212, 172, 141, 192, 240, 61, 109, 121, 46, 253, 38, 100, 156, 35, 226, 198, 124, 181, 212, 231, 169, 131, 76, 27, 24, 69, 147, 168, 31, 253, 168, 129, 208, 252, 40, 147, 117, 63, 23, 44, 104, 109, 38, 241, 194, 140, 174, 202, 8, 69, 152, 87, 25, 15, 69, 120, 93, 6, 218, 73, 129, 61, 9, 215, 157, 104, 49, 6, 45, 113, 91, 53, 230, 56, 96, 166, 34, 251, 173, 132, 166, 255, 231, 184, 116, 68, 245, 39, 95, 153, 210, 0, 202, 147, 147, 209, 13, 199, 143, 75, 43, 26, 81, 142, 71, 48, 232, 64, 111, 166, 231, 227, 163, 117, 69, 253, 59, 80, 124, 33, 9, 40, 107, 157, 55, 241, 214, 155, 170, 192, 26, 68, 130, 88, 28, 21, 76, 116, 177, 31, 243, 161, 118, 181, 245, 216, 169, 97, 196, 230, 42, 157, 115, 52, 2, 61, 107, 167, 37, 248, 181, 138, 175, 231, 233, 179, 123, 181, 225, 11, 93, 122, 83, 5, 214, 91, 153, 193, 5, 222, 150, 100, 222, 9, 196, 153, 94, 223, 26, 82, 134, 64, 12, 237, 73, 134, 183, 17, 214, 160, 113, 183, 249, 46, 94, 110, 201, 240, 32, 100, 104, 32, 242, 194, 114, 162, 216, 244, 177, 139, 82, 234, 18, 72, 134, 179, 232, 40, 92, 139, 51, 4, 221, 94, 146, 201, 11, 193, 144, 159, 219, 3, 198, 141, 174, 202, 2, 66, 130, 91, 30, 25, 79, 124, 68, 21, 213, 160, 117, 195, 254, 42, 157, 150, 204, 246, 56, 97, 96, 37, 254, 192, 117, 175, 221, 231, 168, 137, 176, 238, 18, 179, 125, 186, 231, 36, 91, 142, 195, 11, 213, 155, 150, 207, 2, 200, 159, 104, 214, 15, 63, 140, 169, 222, 20, 66, 124, 77, 25, 26, 80, 121, 64, 20, 218, 162, 119, 61, 252, 46, 157, 149, 202, 7, 50, 107, 95, 42, 246, 194, 118, 170, 37, 225, 187, 134, 182, 228, 226, 174, 130, 189, 245, 45, 93, 141, 59, 6, 208, 157, 102, 48, 249, 207, 153, 88, 41, 10, 190, 138, 175, 214, 28, 76, 125, 176, 233, 28, 86, 131, 64, 5, 213, 172, 110, 199, 5, 213, 158, 153, 202, 6, 59, 110, 166, 212, 15, 66, 116, 84, 29, 238, 176, 134, 72, 233, 225, 174, 117, 66, 243, 36, 93, 145, 196, 248, 51, 102, 153, 205, 249, 192, 148, 92, 218, 242, 191, 137, 172, 224, 20, 180, 124, 75, 233, 29, 85, 137, 65, 13, 213, 162, 144, 197, 3, 204, 152, 100, 208, 7, 59, 146, 95, 39, 15, 64, 121, 83, 25, 235, 77, 130, 180, 234, 33, 85, 117, 191, 245, 43, 161, 110, 51, 0, 50, 102, 157, 47, 251, 199, 142, 165, 216, 11, 71, 123, 175, 227, 25, 76, 125, 75, 23, 220, 86, 116, 61, 8, 215, 161, 148, 203, 255, 204, 104, 159, 214, 3, 60, 141, 91, 219, 16, 186, 132, 81, 27, 230, 176, 126, 184, 238, 32, 87, 115, 62, 247, 41, 97, 106, 52, 0, 53, 104, 97, 46, 245, 194, 114, 88, 33, 236, 185, 121, 177, 26, 229, 78, 134, 185, 16, 220, 89, 143, 194, 10, 209, 97, 148, 202, 253, 207, 150, 158, 215, 11, 193, 143, 84, 221, 22, 67, 126, 78, 24, 228, 80, 133, 186, 238, 219, 165, 114, 61, 248, 45, 156, 105, 51, 0, 54, 107, 161, 215, 11, 192, 139, 169, 223, 19, 183, 130, 77, 24, 227, 81, 134, 187, 15, 219, 164, 143, 198, 251, 209, 157, 103, 204, 0, 53, 108, 95, 43, 244, 191, 138, 84, 33, 234, 180, 129, 179, 23, 227, 173, 135, 188, 241, 38, 90, 144, 197, 250, 47, 100, 153, 206, 3, 199, 147, 93, 40, 243, 190, 137, 84, 224, 20, 72, 126, 180, 22, 225, 83, 136, 188, 243, 216, 162, 110, 57, 5, 206, 154, 154, 48, 250, 199, 111, 160, 217, 243, 191, 137, 173, 227, 23, 180, 126, 75, 21, 31, 84, 119, 64, 12, 40, 93, 109, 56, 252, 49, 102, 155, 47, 250, 58, 110, 165, 217, 240, 189, 120, 172, 226, 232, 179, 129, 182, 20, 223, 85, 138, 64, 11, 214, 161, 108, 200, 253, 50, 152, 99, 209, 6, 59, 112, 90, 37, 240, 187, 121, 174, 28, 230, 178, 130, 183, 19, 222, 86, 138, 192, 10, 213, 95, 148, 201, 1, 205, 151, 157, 211, 7, 195, 142, 89, 36, 16, 69, 133, 80, 27, 25, 78, 131, 71, 18, 34, 87, 140, 62, 9, 212, 159, 149, 202, 0, 203, 150, 97, 44, 8, 60, 114, 88, 35, 238, 70, 122, 176, 26, 229, 79, 132, 185, 17, 220, 167, 114, 61, 8, 211, 97, 150, 52, 255, 53, 106, 159, 212, 9, 62, 140, 87, 34, 237, 184, 131, 79, 25, 27, 81, 133, 69, 16, 219, 89, 142, 195, 248, 45, 157, 105, 51, 1, 54, 107, 95, 43, 245, 63, 116, 169, 33, 19, 72, 125, 178, 24, 227, 81, 134, 68, 15, 218, 90, 143, 59, 6, 209, 99, 152, 205, 2, 55, 108, 161, 214, 244, 191, 138, 85, 32, 20, 73, 129, 77, 23, 29, 82, 120, 67, 14, 38, 91, 144, 197, 5, 47, 100, 153, 49, 3, 56, 146, 93, 215, 12, 190, 137, 171, 224, 21, 181, 128, 180, 233, 30, 172, 119, 66, 242, 39, 163, 111, 57, 251, 48, 154, 100, 48, 4, 57, 110, 92, 39, 242, 189, 119, 172, 225, 22, 180, 127, 74, 234, 31, 84, 137, 65, 12, 215, 162, 146, 199, 252, 206, 153, 155, 208, 5, 58, 144, 91, 38, 14, 67, 120, 82, 29, 23, 76, 129, 73, 20, 223, 85, 117, 64, 11, 41, 94, 108, 55, 2, 50, 103, 156, 46, 249, 196, 112, 165, 218, 240, 187, 134, 174, 227, 24, 178, 125, 72, 236, 33, 86, 139, 63, 245, 42, 95, 148, 201, 254, 51, 151, 98, 45, 7, 60, 142, 89, 36, 239, 69, 122, 175, 228, 230, 78, 131, 184, 237, 221, 168, 115, 62, 246, 212, 159, 106, 53, 0, 52, 105, 158, 44, 247, 194, 114, 167, 220, 17, 185, 132, 176, 229, 26, 79, 123, 70, 17, 220, 88, 141, 194, 247, 211, 158, 105, 203, 0, 53, 149, 96, 43, 9, 62, 115, 87, 34, 237, 184, 124, 177, 230, 228, 175, 122, 186, 239, 36, 166, 113, 60, 7, 210, 98, 104, 51, 254, 54, 107, 160, 213, 10, 63, 116, 169, 222, 19, 72, 130, 77, 24, 28, 81, 121, 187, 240, 218, 165, 112, 196, 249, 46, 156, 103, 50, 2, 55, 147, 94, 41, 244, 64, 117, 170, 32, 235, 73, 126, 179, 232, 29, 173, 120, 67, 14, 38, 91, 144, 58, 5, 208, 100, 153, 49, 252, 199, 146, 162, 215, 12, 65, 118, 171, 31, 234, 74, 127, 180, 22, 225, 172, 136, 189, 242, 216, 163, 110, 57, 251, 48, 154, 154, 207, 4, 198, 145, 163, 216, 13, 66, 119, 83, 30, 22, 75, 128, 181, 234, 31, 84, 137, 190, 243, 215, 162, 109, 56, 252, 49, 153, 100, 47, 250, 197, 144, 91, 38, 241, 188, 135, 173, 29, 232, 179, 129, 182, 20, 223, 170, 138, 191, 244, 41, 94, 147, 200, 253, 50, 103, 99, 46, 249, 196, 143, 90, 37, 15, 187, 134, 81, 28, 231, 178, 125, 72, 19, 222, 169, 116, 63, 10, 42, 160, 107, 201, 1, 204, 151, 157, 210, 7, 60, 113, 166, 219, 16, 69, 122, 175, 228, 25, 78, 131, 184, 237, 34, 87, 140, 193, 246, 43, 96, 149, 202, 0, 203, 150, 97, 44, 247, 194, 141, 88, 35, 238, 185, 132, 176, 229, 229, 79, 132, 185, 238, 35, 88, 141, 194, 8, 44, 97, 105, 203, 0, 202, 106, 159, 43, 9, 62, 140, 168, 221, 237, 71, 124, 78, 230, 27, 175, 133, 186, 16, 36, 89, 113, 195, 248, 210, 98, 151, 51, 1, 201, 148, 160, 213, 245, 63, 116, 86, 222, 19, 183, 125, 178, 24, 28, 81, 121, 187, 240, 218, 90, 143, 59, 249, 46, 156, 152, 205, 253, 55, 108, 94, 214, 244, 191, 117, 85, 32, 235, 182, 129, 179, 23, 226, 82, 120, 188, 241, 217, 164, 144, 58, 250, 47, 155, 153, 206, 252, 56, 109, 93, 40, 12, 190, 137, 171, 31, 234, 74, 128, 75, 233, 30, 172, 136, 189, 13, 39, 92, 110, 198, 251, 207, 101, 154, 48, 4, 57, 145, 163, 216, 242, 66, 119, 172, 30, 22, 180, 127, 181, 21, 224, 84, 118, 65, 243, 40, 162, 109, 199, 3, 49, 153, 155, 208, 250, 58, 144, 91, 217, 241, 67, 135, 173, 226, 23, 76, 126, 182, 20, 223, 85, 117, 64, 244, 214, 161, 147, 55, 2, 50, 152, 99, 46, 249, 196, 112, 165, 37, 15, 68, 134, 81, 227, 231, 178, 125, 72, 19, 33, 86, 116, 63, 245, 213, 160, 148, 54, 254, 51, 151, 157, 210, 248, 60, 113, 89, 36, 16, 186, 133, 175, 27, 25, 78, 124, 184, 237, 221, 87, 140, 62, 9, 43, 159, 106, 202, 0, 203, 105, 97, 44, 8, 194, 141, 167, 35, 238, 70, 132, 79, 229, 229, 79, 132, 70, 17, 35, 167, 114, 194, 8, 44, 97, 105, 203, 0, 202, 106, 159, 43, 9, 62, 140, 87, 221, 237, 71, 124, 78, 25, 27, 175, 133, 69, 16, 36, 166, 113, 60, 7, 210, 98, 151, 204, 1, 201, 107, 95, 42, 10, 63, 139, 169, 222, 236, 72, 125, 77, 231, 28, 174, 121, 187, 15, 218, 90, 112, 59, 249, 209, 156, 103, 50, 253, 200, 108, 94, 41, 11, 191, 117, 170, 32, 235, 73, 129, 76, 232, 226, 173, 135, 67, 241, 38, 91, 144, 197, 5, 208, 100, 102, 206, 3, 56, 146, 162, 215, 12, 65, 118, 171, 31, 234, 74, 127, 180, 22, 225, 83, 119, 189, 242, 216, 163, 145, 57, 251, 48, 154, 101, 48, 251, 198, 110, 163, 39, 13, 189, 136, 83, 30, 233, 180, 128, 74, 21, 31, 84, 137, 190, 243, 215, 162, 146, 56, 3, 49, 102, 100, 208, 5, 197, 111, 164, 38, 14, 67, 135, 173, 226, 233, 76, 129, 72, 235, 32, 171, 138, 191, 10, 41, 94, 108, 200, 253, 204, 103, 156, 46, 6, 196, 143, 165, 37, 240, 68, 121, 81, 227, 24, 178, 130, 183, 19, 222, 86, 116, 63, 245, 213, 160, 148, 54, 254, 51, 104, 98, 45, 248, 195, 113, 89, 219, 239, 186, 133, 80, 228, 230, 177, 124, 71, 237, 34, 168, 115, 193, 9, 212, 96, 149, 53, 255, 203, 150, 158, 44, 8, 61, 141, 88, 220, 17, 185, 123, 176, 26, 26, 176, 132, 185, 17, 220, 88, 141, 61, 247, 211, 158, 150, 203, 255, 202, 106, 159, 43, 246, 62, 115, 87, 34, 18, 71, 131, 78, 230, 27, 175, 133, 69, 16, 36, 89, 113, 60, 7, 45, 98, 104, 51, 1, 201, 148, 160, 42, 245, 62, 116, 86, 222, 19, 183, 125, 77, 231, 28, 81, 121, 68, 241, 218, 165, 143, 59, 249, 209, 156, 103, 205, 253, 200, 147, 94, 214, 244, 64, 117, 85, 32, 235, 73, 126, 179, 23, 226, 82, 120, 67, 241, 38, 164, 144, 58, 5, 47, 100, 102, 206, 252, 199, 109, 93, 215, 12, 190, 136, 171, 224, 234, 74, 127, 75, 233, 30, 172, 119, 189, 13, 39, 92, 111, 198, 251, 207, 154, 154, 48, 4, 56, 144, 92, 217, 242, 189, 119, 83, 30, 23, 180, 127, 180, 21, 224, 84, 118, 190, 243, 215, 162, 146, 199, 3, 49, 153, 155, 208, 251, 58, 144, 164, 38, 14, 67, 135, 173, 226, 232, 76, 126, 73, 235, 223, 85, 138, 64, 11, 41, 161, 147, 200, 2, 50, 103, 99, 46, 7, 59, 142, 165, 37, 15, 68, 121, 174, 28, 231, 178, 131, 72, 19, 32, 168, 139, 192, 11, 42, 95, 107, 54, 254, 204, 151, 157, 45, 248, 60, 143, 167, 219, 238, 68, 133, 81, 229, 25, 177, 131, 71, 18, 35, 168, 114, 192, 246, 212, 96, 106, 53, 255, 203, 150, 158, 45, 8, 61, 140, 167, 221, 238, 185, 123, 79, 26, 27, 176, 123, 185, 17, 221, 89, 141, 60, 246, 210, 158, 151, 52, 0, 53, 149, 96, 212, 246, 193, 114, 87, 34, 19, 184, 124, 177, 25, 228, 80, 133, 68, 239, 36, 166, 142, 195, 7, 210, 98, 104, 204, 1, 201, 107, 95, 42, 10, 63, 116, 86, 222, 236, 183, 125, 77, 24, 227, 174, 134, 68, 15, 37, 90, 143, 59, 6, 209, 99, 103, 50, 2, 201, 108, 161, 41, 244, 64, 138, 85, 223, 235, 182, 126, 179, 23, 29, 82, 120, 188, 241, 38, 91, 111, 197, 250, 208, 100, 153, 49, 3, 199, 146, 162, 40, 12, 65, 118, 84, 31, 21, 181, 128, 180, 22, 225, 83, 136, 66, 13, 216, 92, 110, 57, 4, 48, 101, 101, 207, 4, 57, 110, 92, 216, 13, 189, 136, 172, 225, 233, 75, 127, 74, 234, 224, 84, 118, 65, 243, 215, 162, 146, 199, 3, 49, 153, 100, 208, 5, 197, 111, 164, 38, 241, 67, 135, 82, 226, 23, 179, 129, 73, 235, 32, 85, 117, 191, 244, 214, 94, 108, 55, 252, 204, 103, 156, 46, 249, 59, 143, 90, 218, 240, 68, 121, 81, 227, 24, 178, 125, 183, 236, 33, 169, 116, 193, 10, 213, 95, 107, 201, 1, 204, 151, 157, 45, 248, 60, 142, 89, 219, 239, 186, 122, 80, 27, 25, 78, 124, 184, 237, 221, 87, 140, 62, 246, 43, 159, 106, 202, 255, 203, 105, 97, 44, 8, 61, 141, 88, 220, 17, 185, 123, 176, 229, 229, 79, 123, 185, 238, 220, 167, 141, 61, 247, 44, 158, 105, 203, 0, 202, 106, 159, 43, 246, 62, 140, 168, 34, 237, 71, 131, 78, 230, 228, 175, 122, 187, 16, 36, 89, 113, 195, 7, 45, 157, 151, 204, 254, 201, 107, 160, 42, 10, 63, 139, 86, 33, 236, 72, 125, 77, 24, 28, 174, 134, 68, 15, 218, 90, 112, 59, 248, 209, 156, 152, 50, 253, 55, 108, 94, 41, 11, 191, 117, 170, 223, 235, 182, 126, 179, 232, 226, 82, 120, 188, 241, 38, 91, 111, 58, 5, 208, 155, 102, 49, 252, 56, 146, 162, 214, 13, 65, 119, 169, 224, 21, 74, 128, 74, 23, 226, 170, 114, 68, 10, 220, 93, 148, 206, 246, 32, 105, 157, 204, 255, 204, 154, 81, 44, 249, 181, 138, 83, 28, 22, 89, 151, 187, 228, 20, 169, 122, 70, 0, 199, 169, 107, 58, 255, 59, 111, 156, 209, 255, 200, 156, 162, 215, 3, 77, 116, 80, 16, 227, 160, 104, 68, 22, 40, 68, 157, 166, 230, 45, 160, 100, 47, 38, 220, 107, 147, 220, 20, 60, 159, 72, 46, 224, 177, 125, 191, 245, 15, 84, 143, 73, 20, 213, 186, 111, 29, 47, 214, 127, 138, 210, 228, 48, 131, 114, 39, 247, 203, 143, 162, 203, 2, 84, 117, 170, 25, 231, 184, 101, 89, 13, 216, 72, 147, 210, 229, 213, 131, 121, 49, 9, 206, 107, 157, 223, 4, 49, 98, 170, 223, 16, 186, 146, 108, 60, 239, 81, 153, 182, 255, 222, 185, 98, 193, 13, 215, 158, 106, 206, 12, 32, 75, 134, 208, 254, 210, 170, 123, 7, 237, 104, 86, 160, 234, 239, 140, 104, 186, 21, 222, 165, 112, 201, 234, 51, 74, 130, 54, 234, 232, 190, 121, 49, 30, 126, 83, 168, 37, 240, 154, 142, 188, 239, 30, 173, 117, 71, 232, 11, 119, 152, 50, 32, 248, 131, 125, 38, 17, 11, 115, 81, 57, 225, 157, 137, 183, 203, 233, 164, 147, 76, 244, 36, 107, 140, 92, 32, 240, 189, 100, 54, 5, 7, 67, 99, 33, 250, 212, 159, 179, 192, 240, 163, 145, 168, 250, 39, 115, 117, 96, 58, 244, 168, 139, 65, 28, 35, 121, 157, 43, 3, 202, 137, 100, 214, 14, 208, 136, 168, 199, 20, 104, 107, 116, 50, 21, 66, 120, 67, 2, 198, 93, 186, 172, 0, 222, 173, 117, 194, 227, 53, 129, 107, 196, 36, 43, 115, 161, 8, 233, 90, 107, 95, 9, 205, 130, 145, 245, 245, 212, 177, 86, 88, 230, 2, 78, 98, 33, 2, 47, 125, 136, 212, 238, 203, 104, 190, 54, 192, 141, 181, 190, 177, 41, 160, 83, 106, 27, 61, 102, 155, 40, 46, 211, 120, 139, 194, 251, 216, 134, 133, 242, 224, 245, 168, 114, 35, 66, 15, 144, 17, 59, 24, 89, 173, 152, 29, 246, 188, 146, 233, 250, 212, 149, 103, 193, 235, 219, 166, 67, 55, 226, 9, 36, 160, 98, 222, 187, 105, 150, 205, 26, 149, 89, 180, 223, 58, 166, 113, 55, 4, 41, 100, 114, 20, 248, 216, 157, 166, 231, 215, 128, 129, 179, 203, 15, 95, 142, 99, 10, 52, 124, 135, 68, 24, 198, 170, 129, 61, 16, 216, 152, 77, 48, 66, 42, 166, 123, 196, 26, 50, 84, 165, 60, 206, 88, 81, 189, 28, 235, 191, 105, 179, 255, 222, 171, 121, 27, 53, 57, 40, 147, 28, 238, 39, 100, 180, 245, 12, 159, 151, 189, 251, 234, 185, 141, 94, 16, 15, 70, 124, 84, 22, 242, 191, 170, 130, 13, 229, 144, 149, 201, 35, 29, 150, 113, 38, 45, 81, 152, 90, 26, 239, 65, 101, 178, 15, 254, 183, 92, 182, 168, 23, 142, 93, 198, 252, 36, 74, 131, 45, 200, 58, 75, 160, 54, 247, 189, 136, 163, 237, 231, 148, 106, 93, 7, 38, 26, 114, 9, 41, 35, 74, 185, 224, 7, 251, 188, 143, 202, 250, 195, 108, 89, 39, 1, 68, 136, 72, 15, 247, 176, 198, 128, 48, 224, 171, 151, 162, 208, 57, 131, 83, 58, 219, 42, 152, 156, 47, 243, 56, 127, 165, 48, 228, 175, 166, 182, 175, 9, 136, 88, 167, 248, 58, 75, 114, 9, 35, 63, 120, 153, 54, 255, 197, 144, 150, 216, 241, 213, 158, 121, 42, 44, 127, 147, 101, 29, 22, 94, 152, 182, 8, 241, 170, 169, 216, 242, 214, 145, 120, 203, 244, 54, 153, 113, 63, 233, 37, 54, 183, 12, 241, 64, 113, 165, 249, 25, 147, 98, 170, 242, 36, 167, 122, 41, 14, 33, 109, 109, 59, 240, 238, 152, 166, 225, 226, 240, 128, 172, 209, 50, 80, 146, 106, 28, 12, 64, 135, 68, 29, 215, 93, 130, 193, 11, 221, 188, 124, 231, 52, 203, 179, 77, 42, 1, 33, 105, 85, 62, 226, 68, 115, 183, 227, 228, 160, 120, 179, 245, 208, 171, 105, 45, 216, 0, 98, 120, 61, 248, 55, 119, 190, 211, 238, 168, 115, 165, 213, 30, 179, 149, 73, 225, 224, 160, 126, 86, 26, 3, 112, 102, 36, 1, 47, 152, 141, 213, 0, 210, 158, 171, 223, 4, 78, 141, 66, 28, 29, 185, 149, 75, 29, 236, 117, 171, 85, 47, 47, 87, 109, 202, 233, 207, 138, 99, 199, 0, 62, 127, 95, 48, 246, 79, 152, 77, 28, 239, 76, 165, 185, 55, 250, 68, 153, 183, 251, 42, 170, 100, 205, 243, 206, 96, 151, 39, 239, 58, 99, 65, 2, 253, 86, 73, 163, 61, 201, 76, 143, 167, 253, 32, 191, 100, 180, 212, 37, 169, 145, 200, 18, 199, 109, 102, 13, 209, 57, 48, 128, 5, 219, 186, 115, 169, 251, 10, 190, 99, 75, 200, 60, 169, 115, 60, 13, 211, 92, 108, 45, 36, 200, 92, 191, 59, 219, 197, 118, 171, 206, 26, 176, 156, 85, 196, 57, 73, 116, 74, 28, 35, 95, 122, 32, 45, 56, 83, 107, 28, 8, 58, 148, 150, 192, 11, 209, 159, 172, 249, 8, 70, 131, 64, 23, 26, 78, 124, 100, 22, 19, 75, 90, 30, 241, 34, 121, 128, 61, 224, 220, 96, 186, 203, 3, 195, 156, 71, 221, 19, 177, 153, 176, 207, 17, 134, 91, 178, 233, 40, 70, 131, 33, 42, 218, 74, 184, 217, 250, 223, 155, 94, 43, 241, 208, 121, 143, 33, 197, 147, 133, 190, 198, 1, 173, 90, 109, 12, 3, 122, 156, 206, 22, 201, 151, 152, 57, 1, 4, 117, 118, 6, 252, 183, 139, 130, 251, 227, 145, 159, 78, 254, 59, 73, 117, 84, 240, 47, 177, 117, 237, 205, 214, 176, 113, 60, 241, 32, 72, 94, 9, 226, 70, 124, 165, 242, 226, 160, 131, 160, 233, 245, 75, 169, 75, 18, 210, 160, 102, 213, 227, 195, 185, 116, 201, 3, 45, 114, 94, 4, 235, 75, 124, 187, 202, 31, 145, 98, 72, 29, 26, 117, 153, 87, 17, 219, 93, 153, 215, 248, 192, 151, 159, 210, 2, 27, 117, 74, 6, 240, 65, 122, 191, 225, 253, 189, 127, 73, 224, 43, 163, 110, 90, 8, 56, 121, 184, 193, 28, 238, 146, 153, 200, 31, 199, 155, 79, 42, 10, 83, 116, 85, 8, 253, 163, 139, 148, 200, 45, 185, 111, 42, 241, 48, 73, 156, 35, 39, 199, 125, 137, 212, 255, 223, 154, 191, 254, 22, 189, 130, 64, 8, 29, 88, 136, 79, 25, 212, 163, 140, 202, 255, 212, 154, 158, 211, 243, 201, 159, 115, 62, 245, 63, 140, 164, 35, 225, 168, 130, 180, 233, 13, 109, 157, 184, 26, 208, 183, 124, 62, 246, 210, 153, 102, 56, 248, 200, 99, 136, 202, 18, 49, 137, 68, 48, 231, 187, 134, 69, 21, 227, 171, 127, 186, 253, 63, 64, 150, 207, 14, 198, 146, 98, 57, 246, 195, 154, 83, 38, 240, 49, 105, 182, 197, 0, 78, 138, 95, 9, 235, 175, 123, 73, 27, 202, 175, 142, 213, 239, 58, 114, 147, 51, 246, 205, 146, 84, 36, 253, 186, 140, 81, 215, 25, 78, 121, 185, 227, 17, 88, 123, 82, 26, 201, 171, 104, 58, 7, 208, 99, 158, 202, 13, 47, 98, 161, 214, 241, 176, 153, 83, 26, 225, 190, 134, 75, 234, 27, 85, 128, 183, 248, 46, 88, 144, 57, 1, 197, 147, 96, 53, 253, 197, 110, 163, 220, 4, 75, 114, 174, 224, 232, 177, 124, 183, 232, 229, 160, 122, 71, 246, 37, 80, 149, 198, 0, 202, 152, 154, 212, 6, 199, 153, 86, 33, 10, 73, 127, 172, 30, 237, 183, 126, 181, 238, 33, 171, 116, 190, 246, 41, 162, 108, 204, 249, 205, 157, 103, 42, 253, 197, 114, 166, 219, 15, 68, 123, 172, 30, 230, 72, 132, 181, 17, 218, 170, 118, 192, 244, 212, 162, 107, 55, 3, 50, 109, 153, 209, 6, 192, 137, 95, 36, 19, 65, 126, 80, 24, 229, 176, 135, 189, 238, 35, 169, 112, 61, 11, 215, 158, 150, 201, 1, 201, 151, 96, 209, 14, 58, 119, 167, 32, 237, 70, 132, 76, 24, 231, 180, 120, 71, 238, 34, 93, 138, 196, 243, 45, 156, 109, 55, 253, 203, 149, 96, 42, 244, 196, 137, 87, 219, 27, 79, 122, 176, 29, 227, 172, 135, 190, 238, 217, 163, 118, 56, 7, 47, 103, 144, 202, 1, 203, 148, 94, 40, 244, 192, 117, 168, 32, 238, 181, 125, 179, 229, 29, 81, 135, 185, 240, 217, 161, 114, 196, 6, 209, 156, 102, 51, 0, 49, 106, 162, 215, 244, 188, 136, 84, 33, 234, 183, 131, 72, 19, 226, 81, 132, 189, 243, 39, 91, 144, 199, 255, 43, 100, 98, 52, 255, 197, 147, 93, 214, 14, 66, 119, 86, 28, 232, 180, 127, 182, 234, 31, 172, 117, 64, 13, 37, 95, 148, 194, 5, 203, 155, 101, 50, 250, 56, 111, 92, 37, 241, 191, 119, 175, 229, 18, 72, 129, 72, 17, 227, 171, 136, 188, 243, 213, 166, 110, 57, 253, 53, 101, 155, 47, 5, 197, 146, 91, 217, 241, 188, 121, 172, 226, 22, 78, 129, 72, 21, 223, 85, 136, 189, 11, 213, 165, 110, 55, 252, 48, 101, 99, 209, 7, 58, 113, 164, 37, 242, 185, 121, 81, 28, 231, 179, 124, 73, 236, 32, 87, 138, 193, 245, 213, 95, 148, 55, 0, 205, 150, 96, 47, 248, 61, 112, 166, 218, 17, 69, 120, 173, 229, 25, 177, 125, 70, 19, 221, 168, 115, 193, 9, 212, 96, 106, 53, 254, 54, 104, 96, 45, 246, 195, 140, 166, 221, 17, 70, 122, 176, 26, 26, 78, 132, 70, 17, 220, 165, 113, 60, 247, 211, 158, 150, 201, 1, 52, 106, 96, 212, 11, 60, 114, 168, 35, 233, 188, 130, 177, 230, 25, 81, 123, 71, 239, 37, 88, 142, 194, 249, 45, 157, 105, 49, 255, 54, 107, 160, 42, 10, 63, 139, 86, 222, 236, 183, 125, 179, 24, 226, 175, 120, 68, 240, 39, 88, 143, 58, 6, 46, 98, 152, 50, 253, 200, 147, 94, 41, 244, 191, 138, 85, 32, 20, 72, 124, 177, 232, 227, 172, 120, 188, 241, 38, 164, 111, 59, 7, 209, 155, 152, 204, 3, 199, 147, 92, 40, 12, 65, 119, 170, 224, 235, 180, 128, 180, 233, 30, 172, 119, 189, 13, 217, 163, 145, 198, 4, 48, 101, 154, 207, 4, 198, 145, 163, 217, 13, 188, 137, 83, 225, 22, 75, 127, 74, 234, 31, 84, 118, 65, 13, 215, 93, 146, 56, 3, 49, 102, 155, 208, 5, 58, 111, 164, 217, 14, 67, 120, 82, 29, 23, 76, 126, 73, 235, 32, 85, 138, 191, 11, 214, 94, 147, 200, 2, 205, 152, 99, 46, 249, 196, 143, 90, 37, 240, 68, 121, 174, 227, 24, 77, 125, 72, 19, 222, 169, 139, 193, 245, 42, 95, 148, 54, 1, 51, 104, 157, 210, 7, 195, 142, 89, 36, 239, 69, 122, 80, 27, 25, 78, 131, 184, 237, 34, 168, 115, 62, 246, 212, 159, 106, 53, 255, 52, 105, 158, 44, 8, 61, 114, 88, 35, 238, 185, 123, 176, 26, 228, 176, 132, 185, 238, 34, 88, 114, 61, 247, 44, 97, 150, 203, 255, 202, 149, 96, 43, 9, 193, 140, 87, 221, 18, 71, 124, 177, 25, 228, 175, 122, 186, 239, 219, 166, 142, 195, 248, 210, 98, 104, 51, 1, 54, 107, 95, 42, 245, 192, 139, 169, 33, 236, 183, 125, 178, 231, 29, 175, 133, 184, 11, 218, 164, 113, 59, 6, 209, 156, 103, 205, 0, 49, 111, 92, 43, 247, 190, 138, 84, 33, 235, 72, 129, 176, 236, 28, 80, 120, 64, 15, 216, 165, 110, 59, 5, 46, 100, 102, 204, 2, 198, 146, 162, 40, 12, 190, 137, 171, 225, 234, 74, 127, 75, 22, 225, 173, 119, 189, 13, 216, 163, 110, 198, 251, 207, 101, 155, 207, 251, 199, 145, 92, 39, 13, 66, 118, 172, 30, 233, 75, 128, 74, 21, 31, 171, 119, 65, 12, 215, 93, 146, 198, 252, 49, 103, 100, 208, 5, 196, 145, 91, 38, 241, 67, 120, 82, 226, 22, 76, 129, 73, 20, 222, 171, 117, 64, 244, 41, 95, 146, 200, 252, 205, 152, 99, 47, 249, 196, 143, 90, 37, 15, 68, 121, 174, 28, 24, 178, 125, 183, 237, 33, 86, 139, 63, 245, 42, 161, 107, 201, 1, 51, 105, 98, 210, 7, 195, 142, 166, 36, 239, 69, 133, 80, 228, 230, 78, 124, 184, 237, 221, 168, 115, 193, 246, 43, 96, 106, 53, 0, 203, 150, 158, 211, 247, 194, 114, 167, 220, 17, 70, 132, 176, 26, 229, 79, 123, 185, 238, 220, 167, 141, 194, 8, 44, 97, 150, 203, 255, 203, 107, 159, 42, 9, 62, 140, 168, 221, 236, 184, 124, 78, 230, 27, 175, 122, 69, 16, 219, 89, 113, 60, 248, 210, 157, 104, 204, 1, 201, 107, 160, 42, 10, 63, 139, 169, 222, 236, 72, 125, 77, 24, 28, 174, 121, 187, 240, 37, 90, 112, 59, 249, 208, 156, 152, 50, 253, 55, 108, 94, 215, 244, 191, 116, 85, 32, 20, 182, 129, 179, 232, 226, 82, 120, 66, 241, 217, 164, 145, 58, 4, 47, 100, 102, 206, 3, 199, 109, 162, 40, 12, 65, 137, 171, 224, 234, 74, 127, 75, 233, 30, 172, 119, 189, 13, 216, 92, 110, 57, 4, 48, 154, 154, 207, 251, 198, 110, 92, 39, 13, 189, 137, 172, 30, 233, 75, 128, 74, 234, 31, 171, 137, 65, 12, 40, 93, 109, 56, 3, 206, 102, 155, 47, 250, 58, 111, 91, 217, 14, 188, 120, 82, 29, 23, 76, 126, 73, 235, 223, 170, 117, 64, 244, 41, 161, 108, 200, 2, 205, 103, 99, 46, 6, 196, 143, 165, 37, 240, 68, 134, 81, 227, 231, 178, 130, 72, 19, 222, 86, 139, 63, 245, 42, 160, 148, 201, 254, 51, 151, 98, 210, 248, 60, 113, 166, 36, 16, 186, 122, 175, 27, 230, 177, 124, 71, 237, 34, 168, 115, 62, 9, 43, 96, 106, 53, 255, 203, 105, 158, 44, 8, 61, 141, 88, 220, 17, 185, 132, 79, 26, 229, 79, 123, 70, 238, 220, 167, 114, 61, 8, 44, 158, 105, 203, 255, 202, 106, 159, 43, 9, 193, 140, 87, 34, 237, 71, 124, 177, 230, 27, 175, 133, 186, 16, 36, 89, 113, 195, 248, 210, 157, 151, 51, 254, 54, 148, 160, 213, 245, 192, 116, 169, 33, 236, 183, 130, 77, 231, 227, 81, 134, 68, 15, 37, 165, 112, 59, 6, 209, 99, 103, 205, 2, 200, 108, 161, 41, 244, 191, 138, 85, 223, 20, 182, 126, 179, 23, 29, 82, 135, 188, 241, 217, 164, 144, 197, 250, 47, 100, 153, 206, 3, 56, 146, 93, 40, 243, 190, 118, 84, 31, 21, 181, 128, 180, 22, 225, 83, 136, 66, 242, 39, 92, 145, 198, 4, 48, 154, 101, 48, 251, 198, 145, 163, 39, 13, 66, 136, 172, 225, 233, 75, 128, 74, 234, 31, 84, 137, 190, 12, 215, 93, 146, 199, 252, 49, 102, 100, 47, 250, 197, 111, 91, 38, 241, 188, 120, 173, 226, 232, 179, 129, 73, 235, 223, 85, 117, 64, 11, 41, 161, 108, 200, 2, 205, 152, 156, 209, 6, 59, 112, 165, 218, 15, 68, 121, 174, 28, 231, 178, 125, 72, 19, 222, 169, 116, 63, 10, 42, 95, 148, 201, 254, 51, 104, 157, 210, 7, 195, 142, 166, 36, 239, 186, 133, 80, 27, 230, 177, 124, 71, 18, 221, 168, 140, 193, 246, 43, 96, 149, 53, 0, 52, 150, 97, 211, 8, 194, 114, 167, 220, 17, 70, 132, 79, 26, 229, 176, 123, 185, 238, 35, 88, 114, 61, 8, 211, 158, 105, 52, 255, 202, 149, 96, 43, 246, 193, 115, 168, 221, 18, 71, 124, 177, 230, 27, 80, 133, 186, 239, 36, 89, 142, 60, 7, 45, 157, 104, 51, 254, 201, 107, 95, 42, 245, 192, 139, 86, 33, 236, 183, 130, 77, 24, 227, 174, 121, 187, 15, 218, 165, 143, 196, 249, 46, 99, 152, 205, 2, 55, 108, 161, 214, 11, 64, 117, 170, 223, 20, 182, 129, 179, 232, 29, 82, 120, 67, 14, 217, 164, 111, 58, 5, 208, 100, 153, 206, 252, 199, 109, 162, 40, 12, 65, 118, 171, 224, 234, 181, 128, 75, 22, 30, 172, 119, 189, 242, 39, 92, 145, 198, 251, 48, 101, 101, 207, 4, 198, 145, 92, 216, 13, 189, 119, 172, 225, 22, 180, 128, 74, 21, 224, 171, 118, 65, 12, 215, 162, 109, 56, 3, 206, 153, 100, 47, 5, 58, 144, 164, 217, 14, 67, 120, 82, 29, 23, 76, 126, 73, 235, 32, 85, 138, 191, 244, 214, 161, 147, 55, 253, 50, 152, 156, 209, 6, 196, 112, 90, 37, 241, 71, 114, 84, 23, 31, 68, 113, 68, 232, 37, 173, 113, 192, 243, 215, 167, 150, 203, 236, 33, 129, 67, 212, 39, 59, 134, 90, 216, 17, 190, 124, 164, 30, 238, 180, 123, 79, 18, 215, 180, 151, 133, 255, 144, 179, 136, 226, 248, 197, 158, 109, 56, 0, 19, 111, 86, 52, 17, 76, 126, 180, 30, 240, 165, 118, 67, 24, 205, 120, 177, 198, 54, 244, 118, 179, 218, 250, 204, 155, 119, 211, 34, 32, 136, 69, 36, 16, 79, 123, 72, 15, 251, 167, 117, 168, 172, 42, 140, 89, 62, 242, 11, 113, 113, 39, 247, 55, 97, 177, 247, 25, 222, 149, 164, 204, 235, 186, 137, 81, 56, 250, 112, 218, 182, 62, 249, 163, 158, 239, 216, 240, 174, 119, 209, 30, 55, 120, 182, 49, 233, 77, 108, 83, 54, 247, 175, 160, 79, 175, 54, 168, 103, 105, 31, 23, 28, 105, 7, 41, 60, 64, 100, 196, 37, 197, 183, 90, 195, 5, 182, 154, 119, 0, 225, 89, 66, 168, 2, 195, 182, 154, 137, 224, 253, 176, 146, 40, 7, 26, 79, 98, 18, 6, 44, 151, 85, 221, 227, 141, 146, 175, 250, 56, 81, 101, 127, 16, 48, 118, 124, 88, 0, 223, 162, 135, 209, 247, 50, 158, 98, 46, 6, 58, 159, 68, 61, 255, 67, 83, 130, 29, 205, 168, 137, 170, 255, 222, 166, 110, 85, 225, 0, 87, 101, 203, 245, 48, 158, 102, 40, 234, 209, 128, 87, 37, 44, 109, 134, 115, 15, 12, 108, 139, 92, 6, 218, 85, 130, 210, 231, 41, 174, 107, 217, 253, 221, 141, 112, 33, 232, 196, 105, 130, 211, 244, 163, 113, 176, 232, 239, 161, 114, 66, 229, 49, 70, 132, 192, 244, 44, 98, 102, 59, 14, 197, 131, 112, 194, 44, 40, 130, 70, 35, 14, 85, 128, 68, 8, 233, 69, 157, 182, 239, 221, 92, 139, 192, 11, 222, 137, 120, 58, 235, 50, 77, 139, 57, 239, 193, 97, 165, 219, 18, 169, 144, 182, 243, 23, 84, 129, 184, 235, 34, 166, 96, 43, 8, 219, 145, 147, 236, 21, 198, 128, 93, 220, 25, 50, 138, 88, 44, 17, 68, 114, 188, 224, 224, 169, 133, 188, 6, 198, 189, 122, 56, 240, 52, 115, 104, 33, 255, 63, 99, 177, 43, 226, 177, 112, 167, 212, 31, 78, 128, 78, 238, 30, 162, 100, 91, 0, 221, 74, 136, 212, 250, 219, 148, 108, 193, 42, 33, 141, 113, 43, 17, 90, 124, 85, 23, 232, 76, 128, 68, 0, 244, 186, 117, 159, 208, 223, 129, 101, 210, 236, 54, 152, 97, 56, 252, 61, 100, 165, 219, 12, 66, 114, 170, 25, 254, 173, 110, 67, 250, 62, 88, 103, 83, 243, 34, 82, 131, 193, 18, 220, 111, 143, 216, 254, 192, 148, 167, 215, 9, 176, 158, 72, 11, 23, 104, 165, 79, 55, 207, 92, 154, 178, 254, 214, 176, 98, 193, 229, 56, 144, 104, 45, 14, 50, 141, 84, 54, 228, 169, 115, 134, 250, 247, 146, 122, 166, 250, 47, 84, 122, 40, 9, 62, 70, 156, 63, 17, 201, 97, 149, 41, 236, 219, 156, 166, 192, 15, 69, 156, 64, 226, 8, 94, 143, 70, 10, 200, 81, 148, 208, 247, 216, 147, 106, 205, 254, 198, 128, 114, 42, 28, 28, 122, 76, 55, 238, 87, 99, 160, 30, 243, 161, 129, 182, 229, 37, 163, 121, 63, 241, 46, 150, 125, 35, 241, 38, 67, 142, 60, 235, 194, 124, 189, 207, 21, 182, 148, 75, 233, 8, 86, 114, 74, 21, 33, 90, 120, 45, 21, 220, 110, 182, 217, 247, 220, 152, 162, 199, 18, 48, 131, 67, 39, 24, 71, 116, 75, 11, 232, 82, 133, 78, 28, 201, 172, 159, 219, 246, 221, 142, 98, 200, 9, 38, 97, 90, 36, 244, 74, 124, 175, 33, 225, 186, 135, 79, 29, 239, 161, 120, 165, 235, 218, 177, 106, 205, 242, 38, 110, 155, 55, 3, 51, 103, 163, 40, 245, 181, 142, 87, 18, 242, 166, 132, 163, 204, 22, 181, 97, 190, 253, 40, 86, 110, 53, 1, 32, 112, 159, 48, 251, 207, 158, 89, 216, 224, 156, 158, 160, 202, 12, 186, 100, 77, 227, 16, 70, 131, 74, 25, 44, 127, 132, 62, 10, 206, 154, 104, 38, 247, 210, 140, 94, 252, 43, 187, 166, 89, 233, 25, 92, 143, 72, 0, 216, 78, 170, 183, 12, 209, 169, 102, 49, 11, 219, 184, 111, 242, 33, 193, 175, 86, 221, 5, 74, 119, 175, 19, 225, 90, 157, 188, 23, 218, 174, 127, 55, 1, 193, 128, 98, 236, 225, 221, 138, 156, 222, 1, 52, 118, 95, 52, 20, 103, 100, 169, 28, 224, 183, 121, 66, 24, 202, 139, 142, 230, 251, 201, 136, 156, 219, 241, 50, 145, 115, 37, 28, 25, 101, 165, 37, 230, 190, 128, 74, 19, 253, 160, 157, 174, 7, 254, 167, 131, 207, 248, 47, 138, 117, 207, 41, 17, 99, 99, 44, 251, 201, 141, 168, 49, 245, 85, 92, 65, 55, 239, 64, 148, 172, 230, 194, 142, 119, 231, 212, 58, 102, 98, 32, 246, 203, 148, 86, 45, 28, 44, 158, 121, 50, 25, 81, 95, 190, 3, 211, 189, 154, 151, 235, 45, 163, 126, 48, 15, 214, 150, 148, 230, 12, 235, 190, 77, 43, 29, 106, 100, 78, 8, 230, 88, 98, 170, 229, 228, 167, 124, 71, 27, 201, 125, 160, 61, 43, 203, 145, 101, 211, 31, 215, 181, 80, 198, 24, 78, 113, 93, 17, 22, 88, 129, 85, 225, 51, 88, 104, 84, 8, 209, 77, 143, 48, 47, 216, 106, 140, 222, 16, 197, 138, 82, 200, 3, 173, 123, 132, 227, 203, 167, 123, 66, 252, 63, 163, 94, 90, 241, 36, 83, 156, 56, 19, 194, 110, 153, 213, 34, 32, 134, 68, 34, 244, 188, 109, 167, 14, 255, 177, 134, 176, 239, 217, 190, 101, 178, 231, 41, 72, 178, 62, 35, 206, 98, 99, 195, 11, 209, 145, 95, 214, 29, 73, 129, 78, 56, 238, 92, 150, 159, 200, 208, 130, 102, 199, 237, 8, 92, 74, 40, 4, 60, 113, 146, 36, 227, 218, 134, 90, 223, 59, 96, 137, 116, 8, 228, 89, 160, 178, 8, 251, 164, 148, 227, 253, 216, 132, 113, 49, 245, 47, 75, 159, 56, 236, 206, 121, 188, 211, 229, 160, 159, 177, 253, 10, 176, 112, 84, 26, 35, 68, 160, 193, 16, 220, 149, 101, 199, 31, 55, 137, 125, 45, 24, 46, 119, 87, 54, 246, 184, 76, 134, 231, 242, 187, 117, 66, 251, 58, 165, 106, 38, 12, 45, 101, 156, 51, 247, 219, 104, 141, 206, 246, 204, 135, 68, 222, 10, 67, 136, 94, 22, 225, 83, 130, 187, 4, 200, 82, 160, 220, 4, 218, 138, 124, 205, 24, 60, 111, 86, 59, 228, 187, 127, 187, 215, 228, 75, 88, 188, 18, 224, 163, 91, 68, 227, 221, 161, 144, 51, 21, 46, 98, 152, 204, 13, 17, 116, 93, 44, 255, 160, 135, 166, 22, 228, 183, 139, 95, 21, 21, 86, 141, 185, 229, 14, 74, 152, 60, 28, 215, 153, 152, 52, 255, 212, 138, 81, 39, 14, 77, 125, 190, 193, 4, 76, 125, 66, 7, 234, 169, 126, 68, 1, 195, 171, 108, 199, 244, 62, 120, 187, 223, 252, 213, 158, 81, 220, 9, 188, 136, 115, 11, 237, 72, 147, 164, 249, 55, 67, 131, 72, 7, 221, 162, 109, 49, 13, 214, 136, 98, 208, 1, 48, 96, 190, 248, 30, 179, 146, 70, 21, 30, 79, 117, 80, 4, 213, 175, 130, 210, 239, 52, 77, 150, 51, 3, 196, 157, 101, 37, 245, 213, 130, 93, 33, 19, 72, 96, 141, 196, 23, 180, 104, 83, 20, 216, 174, 120, 43, 27, 222, 96, 146, 193, 235, 47, 126, 144, 217, 240, 208, 128, 81, 42, 227, 181, 139, 66, 25, 30, 65, 147, 161, 252, 47, 90, 118, 56, 1, 217, 146, 100, 58, 243, 200, 105, 153, 211, 0, 49, 98, 162, 223, 18, 190, 138, 74, 28, 237, 168, 126, 71, 16, 219, 91, 138, 202, 244, 38, 103, 107, 59, 245, 204, 149, 92, 43, 247, 195, 118, 173, 221, 16, 76, 121, 179, 230, 30, 80, 123, 66, 6, 214, 163, 141, 192, 248, 47, 98, 156, 202, 4, 49, 111, 160, 215, 245, 183, 130, 86, 35, 235, 183, 132, 77, 233, 28, 82, 134, 190, 242, 35, 94, 148, 58, 6, 208, 155, 103, 206, 253, 194, 148, 94, 42, 242, 64, 119, 171, 225, 21, 74, 126, 182, 236, 22, 84, 137, 71, 5, 222, 160, 111, 198, 5, 206, 101, 155, 206, 5, 57, 111, 162, 219, 15, 189, 138, 82, 29, 237, 183, 127, 180, 233, 28, 85, 118, 190, 241, 41, 162, 109, 56, 1, 202, 154, 100, 47, 250, 196, 110, 162, 223, 11, 65, 135, 80, 29, 22, 77, 125, 79, 18, 221, 171, 117, 65, 8, 43, 86, 148, 204, 255, 50, 156, 96, 209, 6, 59, 112, 88, 44, 248, 184, 120, 171, 234, 16, 79, 124, 73, 18, 223, 86, 137, 63, 9, 215, 163, 111, 55, 255, 204, 105, 155, 213, 4, 60, 143, 93, 39, 238, 68, 123, 80, 31, 226, 178, 131, 188, 235, 38, 87, 140, 62, 11, 214, 96, 149, 53, 2, 202, 151, 97, 44, 247, 60, 115, 166, 223, 21, 71, 133, 77, 24, 231, 178, 122, 185, 238, 35, 89, 141, 60, 10, 44, 99, 149, 207, 3, 202, 150, 98, 41, 244, 193, 113, 171, 222, 19, 185, 135, 74, 27, 26, 82, 135, 187, 239, 218, 164, 112, 61, 248, 46, 102, 149, 204, 255, 202, 144, 94, 212, 8, 63, 116, 87, 36, 232, 183, 126, 182, 226, 31, 174, 123, 70, 14, 218, 90, 143, 196, 6, 208, 158, 101, 50, 3, 54, 109, 162, 213, 244, 189, 137, 87, 33, 21, 74, 127, 77, 20, 227, 82, 134, 190, 240, 38, 164, 111, 59, 4, 208, 155, 102, 48, 252, 57, 108, 162, 214, 13, 65, 119, 171, 31, 234, 181, 129, 74, 23, 224, 173, 119, 188, 243, 38, 93, 145, 57, 251, 48, 154, 101, 48, 251, 198, 145, 92, 39, 243, 189, 118, 173, 224, 20, 74, 127, 74, 20, 226, 168, 119, 191, 242, 40, 163, 109, 199, 253, 48, 102, 154, 210, 4, 58, 145, 88, 37, 242, 189, 120, 172, 226, 23, 179, 129, 183, 233, 34, 86, 136, 64, 10, 212, 163, 110, 53, 3, 205, 103, 99, 46, 249, 59, 112, 167, 217, 12, 70, 121, 81, 30, 227, 177, 125, 183, 236, 32, 169, 117, 63, 245, 43, 93, 150, 203, 255, 204, 149, 96, 47, 249, 195, 112, 167, 219, 239, 187, 132, 80, 229, 27, 76, 131, 71, 19, 223, 170, 114, 62, 246, 42, 97, 149, 53, 1, 203, 105, 156, 210, 8, 194, 114, 88, 34, 238, 185, 133, 79, 229, 27, 79, 132, 70, 17, 35, 88, 143, 61, 243, 46, 152, 151, 55, 0, 202, 104, 154, 45, 247, 192, 114, 169, 35, 19, 185, 124, 79, 230, 228, 172, 133, 69, 16, 37, 91, 113, 195, 7, 210, 99, 104, 204, 254, 201, 107, 160, 212, 245, 63, 139, 86, 223, 19, 74, 131, 76, 231, 226, 81, 135, 185, 240, 219, 91, 112, 59, 7, 211, 99, 101, 50, 3, 200, 147, 94, 214, 246, 67, 138, 85, 220, 238, 182, 127, 179, 22, 31, 173, 121, 191, 14, 39, 90, 111, 58, 5, 47, 155, 155, 49, 253, 57, 109, 162, 40, 14, 191, 119, 171, 31, 20, 181, 127, 75, 232, 224, 83, 137, 64, 13, 217, 162, 110, 198, 4, 207, 154, 101, 48, 6, 57, 110, 163, 39, 243, 189, 137, 82, 225, 232, 180, 128, 74, 235, 29, 84, 118, 190, 12, 41, 92, 146, 56, 3, 206, 102, 155, 209, 4, 197, 144, 91, 38, 14, 67, 120, 173, 29, 232, 76, 126, 73, 235, 222, 171, 138, 65, 244, 40, 161, 108, 201, 3, 205, 103, 98, 209, 249, 196, 112, 90, 36, 15, 68, 134, 174, 227, 24, 77, 131, 72, 19, 222, 169, 139, 192, 244, 42, 161, 106, 201, 254, 51, 105, 157, 45, 249, 195, 112, 88, 218, 16, 184, 122, 175, 26, 25, 177, 124, 186, 18, 221, 87, 115, 62, 247, 43, 159, 149, 52, 0, 52, 150, 159, 211, 246, 61, 141, 89, 222, 17, 184, 123, 78, 26, 26, 176, 133, 184, 16, 220, 89, 112, 194, 245, 211, 97, 105, 52, 0, 202, 149, 158, 212, 246, 63, 115, 87, 34, 18, 184, 131, 177, 230, 27, 174, 122, 187, 17, 36, 88, 113, 194, 7, 211, 98, 104, 204, 0, 54, 148, 160, 43, 244, 63, 139, 168, 223, 236, 72, 130, 76, 231, 29, 175, 135, 186, 14, 36, 90, 113, 196, 249, 208, 99, 103, 50, 2, 55, 147, 94, 41, 245, 65, 117, 85, 222, 234, 183, 126, 76, 232, 29, 173, 135, 67, 14, 217, 91, 111, 197, 251, 209, 100, 153, 49, 3, 199, 109, 162, 215, 13, 65, 136, 85, 30, 235, 74, 126, 180, 233, 225, 173, 136, 66, 13, 39, 163, 110, 198, 251, 207, 154, 154, 48, 251, 57, 145, 163, 39, 242, 66, 136, 83, 225, 233, 180, 127, 74, 21, 224, 84, 118, 190, 243, 215, 162, 109, 199, 252, 49, 102, 100, 208, 250, 197, 144, 91, 38, 14, 67, 120, 173, 29, 232, 179, 126, 73, 235, 32, 85, 138, 64, 11, 214, 161, 108, 200, 253, 50, 152, 99, 46, 249, 59, 112, 165, 37, 15, 68, 134, 174, 28, 24, 77, 130, 183, 236, 222, 169, 116, 63, 245, 42, 160, 148, 201, 1, 51, 104, 98, 45, 7, 195, 113, 166, 36, 239, 69, 133, 175, 228, 230, 78, 131, 71, 237, 34, 168, 140, 62, 9, 43, 96, 106, 202, 0, 203, 105, 97, 211, 8, 194, 141, 167, 35, 17, 70, 132, 79, 26, 229, 176, 132, 70, 17, 220, 167, 141, 194, 8, 44, 158, 105, 52, 0, 53, 106, 159, 43, 9, 193, 140, 168, 221, 18, 71, 131, 78, 230, 27, 175, 133, 186, 16, 36, 89, 113, 195, 7, 210, 98, 104, 51, 1, 54, 148, 160, 213, 245, 192, 139, 86, 222, 236, 183, 130, 77, 24, 227, 81, 121, 187, 240, 218, 90, 143, 196, 249, 46, 156, 103, 205, 2, 55, 108, 161, 41, 11, 64, 117, 170, 223, 235, 182, 129, 76, 232, 29, 173, 135, 188, 14, 38, 164, 111, 58, 250, 47, 155, 153, 49, 252, 199, 146, 162, 40, 243, 65, 137, 84, 224, 234, 181, 127, 75, 233, 30, 172, 119, 189, 13, 216, 92, 145, 198, 251, 207, 154, 154, 207, 4, 57, 110, 92, 216, 13, 189, 119, 172, 225, 22, 75, 128, 74, 234, 224, 84, 137, 190, 12, 215, 162, 109, 56, 3, 49, 153, 100, 47, 250, 58, 111, 164, 38, 241, 188, 135, 82, 29, 23, 76, 126, 73, 235, 32, 85, 138, 64, 11, 214, 161, 147, 200, 2, 50, 103, 99, 209, 249, 196, 143, 90, 37, 15, 68, 121, 174, 28, 231, 77, 125, 183, 236, 222, 169, 116, 63, 10, 42, 160, 148, 201, 1, 204, 151, 98, 210, 248, 195, 142, 89, 219, 16, 186, 133, 175, 228, 25, 78, 131, 184, 18, 221, 87, 140, 193, 246, 43, 96, 149, 53, 255, 52, 105, 158, 211, 8, 194, 141, 88, 35, 238, 185, 132, 79, 229, 26, 79, 123, 70, 17, 220, 88, 141, 194, 247, 44, 97, 105, 52, 255, 53, 149, 96, 43, 246, 193, 140, 168, 221, 18, 71, 131, 78, 25, 27, 175, 133, 186, 239, 36, 89, 142, 195, 248, 45, 157, 151, 204, 254, 201, 148, 95, 42, 245, 192, 139, 86, 33, 19, 72, 125, 178, 231, 28, 81, 134, 187, 240, 37, 90, 112, 59, 249, 46, 99, 152, 205, 2, 55, 108, 161, 41, 244, 191, 138, 85, 32, 235, 182, 129, 76, 23, 29, 82, 135, 67, 241, 38, 91, 144, 197, 5, 208, 155, 102, 49, 3, 56, 109, 162, 215, 12, 65, 137, 84, 31, 234, 181, 128, 75, 22, 225, 172, 119, 66, 13, 216, 163, 145, 198, 251, 48, 101, 101, 48, 251, 198, 145, 92, 216, 13, 66, 119, 83, 30, 233, 180, 127, 74, 234, 31, 84, 137, 190, 243, 40, 93, 146, 56, 252, 49, 153, 100, 47, 250, 197, 144, 91, 38, 241, 188, 135, 82, 29, 23, 76, 129, 182, 235, 32, 85, 138, 191, 244, 214, 161, 108, 55, 2, 205, 152, 99, 46, 6, 59, 112, 165, 218, 15, 68, 121, 174, 227, 24, 77, 125, 72, 19, 222, 169, 116, 63, 10, 213, 160, 107, 201, 254, 51, 104, 156, 211, 6, 61, 112, 166, 219, 16, 186, 133, 81, 26, 231, 179, 125, 70, 19, 221, 87, 140, 192, 244, 41, 98, 151, 200, 253, 53, 105, 97, 45, 245, 192, 142, 91, 32, 237, 187, 133, 79, 229, 27, 77, 134, 186, 237, 33, 90, 140, 195, 247, 211, 158, 104, 53, 253, 200, 151, 98, 41, 247, 192, 140, 168, 220, 19, 69, 126, 179, 231, 26, 81, 132, 187, 238, 36, 89, 142, 60, 6, 208, 159, 107, 48, 252, 203, 149, 95, 213, 11, 62, 118, 171, 220, 17, 74, 126, 177, 228, 31, 80, 134, 69, 12, 223, 163, 118, 62, 2, 210, 158, 103, 205, 3, 53, 110, 162, 213, 15, 68, 112, 172, 218, 17, 74, 127, 77, 20, 228, 165, 113, 75, 9, 223, 160, 109, 58, 251, 44, 103, 154, 205, 0, 59, 104, 164, 208, 11, 70, 112, 175, 225, 232, 178, 138, 70, 27, 237, 166, 112, 70, 12, 38, 88, 148, 195, 255, 52, 97, 156, 199, 14, 51, 100, 171, 222, 15, 188, 142, 88, 16, 230, 187, 114, 64, 18, 227, 84, 138, 184, 244, 47, 90, 149, 207, 245, 56, 111, 146, 215, 0, 56, 145, 93, 45, 255, 172, 150, 66, 16, 226, 181, 127, 181, 236, 42, 94, 129, 180, 254, 35, 84, 154, 192, 250, 54, 102, 97, 41, 245, 203, 158, 75, 53, 253, 177, 128, 80, 224, 16, 70, 142, 187, 231, 43, 92, 130, 200, 242, 47, 92, 149, 52, 7, 198, 153, 114, 61, 247, 207, 135, 95, 38, 18, 66, 112, 163, 232, 18, 69, 137, 177, 229, 37, 82, 143, 192, 8, 209, 150, 103, 37, 17, 219, 152, 109, 36, 243, 61, 119, 174, 208, 29, 74, 119, 187, 238, 16, 70, 131, 188, 236, 220, 163, 123, 48, 24, 194, 142, 102, 56, 246, 207, 149, 155, 220, 2, 51, 126, 165, 209, 25, 77, 117, 182, 227, 25, 175, 121, 66, 28, 212, 180, 96, 44, 9, 217, 154, 106, 206, 9, 58, 101, 174, 216, 6, 52, 126, 161, 216, 23, 74, 125, 79, 30, 233, 160, 104, 86, 31, 212, 174, 119, 56, 248, 41, 104, 150, 194, 12, 59, 103, 171, 222, 13, 68, 119, 170, 33, 239, 190, 141, 67, 6, 243, 162, 117, 74, 11, 216, 95, 153, 200, 245, 32, 106, 149, 196, 11, 62, 105, 160, 215, 243, 188, 140, 93, 18, 250, 167, 145, 69, 26, 233, 168, 137, 187, 254, 40, 77, 129, 200, 240, 57, 99, 158, 205, 5, 198, 144, 95, 33, 248, 179, 152, 66, 17, 228, 190, 121, 75, 233, 22, 90, 152, 175, 252, 36, 84, 148, 195, 253, 49, 153, 101, 46, 249, 195, 153, 86, 41, 254, 178, 140, 90, 25, 23, 73, 138, 185, 250, 48, 88, 128, 184, 241, 43, 94, 108, 54, 3, 204, 155, 101, 36, 244, 203, 129, 86, 47, 246, 184, 120, 168, 232, 22, 66, 140, 189, 235, 36, 85, 138, 192, 10, 213, 95, 107, 52, 4, 197, 155, 108, 32, 244, 201, 137, 93, 219, 21, 78, 116, 160, 233, 19, 73, 134, 187, 239, 35, 87, 140, 192, 246, 213, 155, 99, 56, 15, 197, 155, 106, 36, 243, 61, 119, 172, 211, 30, 75, 113, 183, 227, 30, 76, 134, 185, 16, 34, 88, 113, 58, 5, 193, 138, 100, 60, 251, 52, 108, 151, 223, 6, 51, 123, 172, 34, 239, 184, 125, 179, 228, 26, 175, 122, 70, 24, 213, 180, 103, 44, 248, 42, 105, 135, 220, 6, 62, 99, 160, 46, 247, 195, 137, 174, 212, 27, 79, 121, 79, 31, 239, 187, 99, 93, 29, 37, 86, 129, 213, 233, 40, 103, 144, 204, 253, 52, 109, 165, 221, 1, 71, 113, 87, 40, 231, 162, 155, 85, 14, 235, 89, 136, 173, 229, 44, 164, 149, 192, 4, 43, 98, 155, 198, 8, 63, 107, 162, 32, 254, 174, 144, 78, 9, 251, 76, 108, 165, 248, 15, 172, 112, 187, 13, 219, 86, 155, 192, 244, 32, 109, 158, 51, 246, 212, 134, 65, 62, 229, 186, 102, 184, 240, 7, 66, 121, 78, 232, 225, 87, 133, 179, 253, 38, 80, 149, 58, 10, 193, 140, 127, 50, 224, 209, 108, 177, 203, 1, 77, 122, 88, 28, 18, 76, 134, 166, 250, 46, 91, 134, 189, 12, 220, 174, 122, 43, 30, 214, 139, 148, 198, 23, 54, 124, 88, 41, 14, 67, 122, 165, 247, 10, 64, 142, 189, 17, 213, 162, 122, 41, 17, 207, 187, 123, 199, 228, 34, 101, 151, 43, 245, 61, 121, 162, 208, 5, 87, 115, 167, 237, 226, 186, 123, 77, 7, 192, 179, 111, 46, 230, 54, 113, 156, 204, 9, 218, 150, 148, 212, 5, 43, 97, 175, 219, 27, 184, 141, 74, 18, 241, 174, 96, 90, 30, 54, 71, 157, 197, 244, 223, 141, 105, 198, 12, 58, 126, 141, 210, 11, 57, 141, 93, 37, 229, 172, 162, 81, 2, 239, 71, 167, 175, 232, 218, 169, 98, 60, 246, 63, 112, 131, 220, 7, 55, 104, 95, 45, 243, 201, 152, 118, 62, 246, 190, 103, 148, 254, 26, 170, 104, 81, 12, 40, 79, 157, 203, 242, 45, 159, 103, 204, 249, 206, 153, 76, 55, 235, 166, 130, 182, 246, 14, 76, 135, 93, 2, 230, 92, 157, 174, 251, 44, 90, 104, 57, 254, 209, 159, 97, 62, 230, 218, 138, 85, 202, 37, 91, 117, 94, 14, 255, 176, 113, 169, 250, 25, 84, 119, 74, 8, 35, 92, 106, 49, 20, 213, 129, 114, 57, 24, 21, 114, 163, 42, 226, 169, 143, 160, 254, 0, 79, 132, 183, 16, 230, 86, 139, 66, 6, 199, 181, 117, 46, 10, 45, 72, 134, 208, 246, 200, 128, 83, 209, 19, 85, 123, 83, 29, 234, 181, 124, 73, 21, 215, 184, 98, 84, 25, 221, 72, 191, 232, 252, 195, 148, 104, 40, 5, 35, 104, 163, 38, 243, 186, 130, 84, 24, 230, 182, 109, 94, 1, 209, 175, 156, 233, 234, 43, 175, 101, 49, 2, 50, 121, 136, 217, 251, 197, 141, 89, 32, 230, 191, 129, 92, 12, 242, 188, 130, 163, 201, 59, 87, 125, 49, 15, 212, 100, 154, 219, 243, 54, 146, 101, 211, 245, 200, 133, 94, 41, 251, 175, 138, 186, 196, 5, 64, 120, 77, 28, 217, 89, 138, 207, 250, 38, 98, 107, 54, 1, 206, 158, 107, 34, 251, 215, 148, 93, 200, 55, 94, 120, 73, 16, 237, 173, 134, 176, 228, 46, 80, 139, 195, 6, 210, 155, 99, 62, 242, 217, 130, 72, 213, 40, 24, 123, 80, 43, 235, 180, 131, 183, 236, 22, 89, 129, 190, 242, 36, 166, 121, 54, 9, 195, 139, 124, 60, 23, 28, 114, 160, 37, 254, 187, 139, 170, 215, 30, 66, 116, 187, 237, 24, 80, 125, 79, 1, 200, 189, 112, 34, 243, 7, 76, 150, 59, 242, 192, 147, 95, 213, 5, 74, 122, 161, 230, 16, 78, 130, 64, 25, 240, 187, 86, 99, 9, 6, 112, 136, 56, 10, 197, 155, 100, 48, 1, 50, 126, 179, 209, 9, 65, 119, 91, 16, 249, 167, 98, 111, 5, 8, 120, 169, 184, 5, 221, 166, 105, 59, 253, 57, 119, 143, 222, 1, 59, 144, 89, 44, 224, 169, 157, 112, 8, 28, 104, 163, 189, 19, 214, 168, 119, 71, 14, 44, 74, 138, 217, 245, 51, 155, 101, 39, 247, 208, 147, 69, 40, 4, 93, 97, 164, 30, 227, 178, 124, 78, 24, 222, 67, 171, 215, 252, 40, 163, 98, 56, 16, 222, 142, 120, 43, 8, 40, 120, 89, 37, 21, 67, 132, 88, 21, 224, 94, 161, 167, 252, 33, 173, 121, 46, 28, 204, 133, 101, 205, 238, 56, 151, 107, 40, 3, 45, 113, 84, 50, 235, 73, 101, 175, 242, 16, 180, 116, 80, 9, 193, 188, 112, 219, 238, 46, 140, 124, 50, 14, 33, 98, 107, 57, 245, 47, 104, 179, 203, 30, 184, 147, 82, 56, 198, 189, 136, 152, 244, 217, 186, 111, 59, 247, 57, 103, 98, 59, 7, 36, 127, 180, 198, 7, 62, 155, 118, 11, 200, 178, 96, 154, 244, 238, 140, 101, 65, 253, 43, 165, 119, 197, 235, 56, 115, 147, 198, 9, 54, 156, 125, 4, 236, 76, 82, 136, 217, 252, 148, 149, 76, 224, 28, 171, 120, 172, 237, 62, 86, 149, 192, 255, 210, 136, 78, 21, 249, 37, 69, 177, 36, 236, 166, 128, 170, 27, 231, 178, 115, 169, 246, 11, 91, 137, 188, 12, 210, 184, 113, 50, 234, 18, 126, 154, 41, 224, 203, 145, 95, 40, 226, 64, 109, 136, 250, 28, 180, 125, 78, 30, 246, 188, 126, 179, 239, 63, 89, 98, 46, 18, 201, 159, 106, 61, 252, 42, 78, 134, 203, 12, 185, 129, 89, 11, 251, 179, 149, 170, 255, 33, 167, 122, 74, 13, 223, 176, 127, 62, 244, 40, 121, 137, 217, 250, 207, 155, 66, 40, 8, 93, 103, 188, 31, 247, 191, 120, 75, 25, 205, 186, 115, 200, 227, 50, 79, 145, 55, 8, 216, 128, 110, 216, 26, 28, 96, 88, 41, 227, 189, 128, 90, 10, 233, 180, 132, 169, 255, 41, 85, 118, 51, 6, 223, 157, 159, 223, 233, 57, 104, 100, 41, 242, 202, 128, 86, 41, 238, 78, 112, 184, 231, 231, 184, 112, 65, 239, 43, 82, 133, 196, 241, 41, 98, 104, 50, 246, 192, 157, 99, 213, 13, 58, 113, 85, 42, 228, 186, 122, 189, 237, 31, 173, 121, 69, 234, 34, 88, 116, 58, 3, 45, 98, 106, 54, 251, 205, 144, 92, 212, 2, 51, 127, 172, 34, 229, 191, 128, 176, 228, 29, 80, 133, 190, 245, 218, 173, 127, 52, 1, 42, 110, 150, 199, 7, 54, 146, 93, 47, 252, 182, 143, 168, 215, 30, 64, 120, 178, 17, 237, 185, 118, 189, 254, 48, 74, 149, 63, 13, 214, 159, 97, 59, 246, 197, 106, 172, 217, 4, 191, 128, 91, 16, 226, 75, 114, 162, 252, 20, 174, 126, 72, 5, 208, 169, 103, 59, 253, 61, 107, 146, 49, 246, 210, 158, 94, 211, 24, 87, 121, 169, 30, 236, 189, 115, 71, 30, 231, 170, 140, 178, 254, 32, 161, 124, 45, 13, 206, 104, 140, 198, 8, 62, 145, 95, 33, 250, 178, 138, 85, 227, 31, 71, 136, 181, 18, 210, 166, 112, 187, 249, 56, 81, 153, 204, 2, 206, 159, 104, 35, 242, 193, 113, 163, 221, 12, 191, 141, 90, 24, 29, 64, 143, 190, 233, 34, 84, 139, 60, 13, 220, 168, 110, 55, 255, 48, 106, 97, 36, 241, 193, 121, 182, 202, 27, 65, 133, 81, 26, 228, 181, 123, 79, 23, 220, 85, 136, 192, 15, 216, 148, 111, 207, 240, 39, 121, 151, 209, 244, 199, 136, 93, 36, 230, 191, 135, 176, 230, 24, 179, 115, 79, 20, 32, 84, 130, 207, 254, 41, 98, 151, 53, 249, 192, 153, 105, 40, 11, 58, 114, 84, 36, 235, 185, 120, 185, 239, 19, 86, 134, 184, 237, 37, 166, 114, 52, 12, 218, 158, 151, 205, 254, 202, 151, 160, 208, 13, 59, 118, 169, 223, 23, 77, 124, 79, 29, 229, 170, 120, 68, 13, 217, 164, 143, 198, 250, 45, 97, 153, 205, 2, 200, 147, 94, 214, 244, 189, 142, 87, 223, 22, 74, 124, 178, 232, 28, 83, 120, 65, 12, 38, 88, 146, 59, 0, 215, 156, 101, 206, 1, 59, 104, 165, 222, 4, 69, 136, 83, 22, 236, 181, 124, 182, 233, 226, 170, 113, 70, 15, 216, 95, 153, 205, 247, 59, 98, 155, 53, 242, 206, 148, 94, 39, 242, 191, 142, 85, 26, 233, 73, 134, 189, 227, 23, 81, 136, 64, 8, 211, 160, 111, 59, 6, 198, 145, 98, 44, 250, 57, 102, 170, 201, 2, 70, 132, 91, 22, 239, 178, 129, 73, 22, 218, 172, 113, 66, 11, 40, 91, 159, 217, 236, 57, 101, 101, 37, 245, 207, 134, 93, 35, 245, 184, 135, 174, 224, 16, 65, 143, 187, 228, 34, 169, 118, 61, 9, 211, 170, 102, 56, 10, 203, 149, 158, 216, 8, 46, 96, 171, 221, 239, 185, 129, 84, 31, 224, 185, 119, 74, 30, 213, 170, 142, 198, 253, 39, 107, 156, 205, 250, 55, 105, 99, 42, 253, 207, 131, 83, 36, 238, 67, 114, 186, 237, 31, 77, 123, 70, 236, 37, 95, 137, 60, 15, 217, 149, 96, 55, 2, 51, 109, 152, 208, 9, 195, 143, 85, 34, 237, 186, 135, 75, 27, 26, 86, 140, 178, 234, 38, 167, 117, 58, 1, 209, 98, 150, 51, 248, 194, 154, 85, 43, 0, 43, 99, 189, 211, 17, 177, 137, 70, 31, 224, 172, 124, 78, 1, 215, 163, 140, 200, 232, 60, 109, 144, 207, 252, 201, 147, 161, 41, 241, 179, 152, 70, 46, 239, 79, 113, 161, 248, 20, 83, 123, 64, 14, 36, 95, 145, 62, 9, 192, 149, 96, 202, 15, 55, 97, 167, 42, 245, 186, 137, 168, 227, 21, 177, 137, 71, 28, 229, 86, 133, 175, 226, 47, 162, 105, 49, 2, 205, 155, 103, 53, 242, 205, 152, 93, 223, 29, 87, 100, 166, 225, 238, 190, 118, 77, 19, 231, 163, 126, 70, 14, 44, 87, 157, 215, 241, 55, 153, 98, 38, 243, 204, 152, 93, 34, 241, 71, 113, 161, 238, 30, 72, 127, 79, 30, 211, 161, 125, 66, 246, 46, 87, 154, 192, 251, 49, 103, 97, 43, 241, 205, 133, 83, 35, 241, 64, 115, 163, 238, 18, 73, 124, 77, 27, 215, 161, 114, 59, 11, 40, 90, 147, 193, 246, 54, 107, 98, 46, 253, 197, 136, 95, 32, 237, 69, 121, 170, 227, 30, 72, 128, 71, 17, 217, 173, 119, 61, 11, 214, 158, 106, 203, 253, 55, 106, 156, 211, 245, 193, 143, 88, 223, 21, 66, 121, 79, 24, 231, 177, 123, 70, 17, 220, 166, 115, 60, 247, 46, 98, 149, 201, 0, 203, 151, 98, 41, 244, 192, 141, 168, 220, 19, 69, 126, 179, 231, 27, 175, 120, 70, 19, 216, 164, 112, 60, 249, 46, 103, 146, 201, 2, 55, 149, 92, 46, 241, 196, 136, 87, 33, 18, 74, 126, 182, 228, 30, 80, 134, 69, 12, 217, 166, 113, 196, 248, 47, 99, 103, 50, 253, 55, 109, 160, 214, 244, 189, 142, 86, 33, 21, 77, 123, 183, 233, 227, 169, 125, 71, 12, 38, 89, 146, 199, 251, 47, 100, 152, 204, 1, 57, 146, 95, 44, 247, 188, 137, 169, 227, 22, 72, 126, 75, 23, 224, 172, 119, 66, 12, 217, 162, 110, 198, 250, 50, 103, 155, 207, 250, 196, 147, 94, 37, 243, 189, 118, 174, 227, 20, 73, 129, 74, 20, 225, 170, 118, 65, 12, 215, 163, 109, 199, 253, 50, 101, 153, 208, 251, 198, 147, 89, 39, 241, 67, 120, 173, 29, 232, 76, 128, 180, 232, 33, 170, 119, 68, 15, 213, 161, 146, 202, 255, 51, 152, 98, 47, 249, 59, 114, 167, 219, 240, 186, 135, 80, 227, 25, 79, 131, 183, 18, 220, 171, 117, 192, 244, 40, 94, 148, 54, 1, 204, 104, 156, 210, 248, 194, 140, 91, 38, 239, 69, 123, 174, 229, 25, 78, 124, 71, 18, 221, 168, 115, 62, 9, 43, 97, 148, 200, 254, 52, 150, 99, 46, 245, 192, 140, 88, 220, 17, 70, 122, 178, 231, 25, 76, 134, 185, 16, 223, 164, 113, 63, 9, 211, 97, 150, 202, 1, 52, 107, 158, 213, 9, 192, 142, 84, 33, 239, 184, 125, 179, 228, 26, 80, 122, 69, 239, 36, 88, 143, 195, 7, 211, 156, 104, 204, 3, 52, 105, 160, 43, 247, 195, 137, 87, 33, 18, 73, 124, 178, 231, 227, 174, 121, 68, 14, 219, 167, 114, 58, 6, 46, 97, 155, 206, 0, 55, 147, 92, 43, 245, 191, 138, 170, 223, 235, 73, 126, 178, 234, 30, 80, 134, 67, 12, 218, 167, 110, 197, 251, 45, 102, 152, 206, 252, 199, 146, 93, 40, 243, 190, 136, 85, 30, 234, 74, 126, 181, 232, 30, 172, 118, 67, 12, 217, 162, 110, 57, 251, 48, 100, 155, 206, 5, 56, 110, 92, 38, 243, 188, 137, 83, 225, 22, 74, 129, 180, 234, 31, 84, 137, 190, 12, 215, 163, 108, 57, 3, 206, 102, 154, 209, 4, 58, 111, 91, 39, 240, 189, 135, 173, 226, 22, 77, 128, 183, 235, 32, 170, 117, 65, 10, 215, 161, 108, 55, 253, 50, 102, 157, 209, 6, 59, 143, 90, 37, 240, 187, 134, 174, 227, 24, 77, 130, 183, 236, 222, 169, 116, 63, 10, 213, 160, 148, 201, 255, 50, 105, 157, 210, 248, 195, 143, 88, 37, 238, 186, 133, 175, 228, 24, 79, 131, 184, 237, 34, 168, 115, 62, 8, 213, 159, 106, 202, 255, 52, 104, 158, 211, 8, 61, 141, 88, 35, 238, 185, 132, 79, 229, 26, 79, 132, 185, 238, 35, 167, 114, 61, 8, 211, 158, 105, 52, 255, 53, 106, 159, 212, 9, 62, 140, 87, 34, 237, 184, 131, 177, 230, 27, 80, 133, 186, 239, 219, 166, 113, 60, 7, 210, 157, 151, 204, 1, 54, 107, 160, 213, 10, 63, 139, 86, 33, 236, 183, 130, 178, 231, 28, 81, 134, 187, 240, 218, 165, 112, 59, 6, 209, 156, 152, 205, 2, 55, 108, 161, 214, 244, 191, 138, 85, 32, 235, 182, 126, 179, 232, 29, 82, 135, 188, 241, 217, 164, 111, 58, 5, 208, 155, 102, 49, 3, 56, 109, 162, 215, 12, 190, 137, 84, 31, 234, 181, 127, 180, 233, 30, 83, 136, 189, 13, 216, 163, 110, 57, 251, 48, 101, 154, 207, 4, 57, 110, 163, 216, 13, 66, 119, 83, 30, 233, 180, 127, 181, 234, 31, 84, 137, 190, 12, 215, 162, 109, 56, 3, 206, 153, 100, 208, 5, 58, 111, 164, 217, 241, 188, 135, 82, 29, 23, 76, 129, 182, 235, 32, 85, 138, 191, 244, 41, 161, 108, 55, 2, 205, 152, 156, 209, 6, 59, 112, 90, 37, 240, 187, 134, 81, 28, 231, 178, 125, 183, 236, 33, 86, 139, 192, 10, 213, 160, 107, 54, 1, 204, 151, 157, 210, 7, 60, 113, 166, 219, 239, 186, 133, 80, 27, 230, 177, 131, 184, 237, 34, 87, 140, 193, 246, 43, 159, 106, 53, 0, 203, 150, 97, 211, 8, 61, 114, 167, 35, 238, 185, 132, 79, 26, 229, 176, 132, 185, 238, 35, 88, 141, 194, 247, 211, 158, 105, 52, 255, 202, 106, 159, 212, 9, 62, 115, 168, 221, 18, 184, 124, 177, 25, 27, 80, 133, 186, 239, 36, 89, 142, 60, 7, 210, 157, 104, 204, 1, 54, 107, 95, 42, 10, 63, 116, 169, 33, 236, 183, 130, 77, 24, 227, 81, 134, 187, 240, 37, 165, 112, 59, 6, 209, 99, 152, 205, 253, 55, 108, 161, 214, 11, 64, 117, 85, 32, 235, 182, 129, 76, 23, 29, 82, 135, 188, 241, 38, 91, 144, 197, 5, 208, 155, 102, 49, 252, 199, 146, 162, 215, 12, 65, 137, 84, 31, 234, 181, 128, 75, 22, 30, 83, 136, 189, 242, 39, 92, 145, 198, 251, 48, 101, 154, 207, 4, 57, 110, 163, 216, 13, 66, 136, 83, 30, 233, 180, 127, 74, 21, 224, 171, 118, 65, 12, 215, 162, 109, 56, 252, 49, 102, 155, 208, 5, 58, 111, 164, 217, 14, 67, 120, 173, 29, 232, 179, 126, 73, 20, 223, 85, 138, 191, 244, 41, 94, 147, 55, 2, 205, 152, 99, 46, 249, 196, 143, 90, 37, 15, 68, 121, 174, 227, 24, 77, 125, 72, 19, 222, 86, 139, 63, 10, 213, 160, 107, 54, 254, 51, 104, 98, 210, 7, 60, 113, 166, 219, 16, 69, 122, 175, 228, 25, 78, 131, 184, 18, 221, 168, 115, 62, 9, 212, 159, 149, 202, 255, 52, 150, 97, 44, 8, 61, 114, 167, 220, 17, 70, 132, 79, 26, 229, 176, 123, 70, 238, 35, 88, 141, 194, 247, 44, 97, 105, 52, 255, 202, 106, 159, 212, 9, 62, 115, 168, 221, 18, 71, 124, 177, 230, 228, 175, 122, 69, 239, 36, 89, 142, 195, 7, 210, 157, 104, 51, 254, 201, 148, 95, 42, 245, 192, 139, 86, 33, 236, 72, 125, 178, 231, 28, 81, 134, 68, 15, 37, 90, 143, 196, 249, 46, 99, 152, 205, 253, 200, 147, 94, 41, 244, 191, 117, 170, 223, 20, 73, 126, 179, 232, 29, 173, 120, 188, 14, 217, 164, 111, 58, 5, 208, 155, 102, 49, 252, }; const uint8_t* waveform_8_table[] = { wav_digits, }; const int16_t FLASHMEM wav_sine[] = { 0, 201, 402, 603, 804, 1005, 1206, 1406, 1607, 1808, 2009, 2209, 2410, 2610, 2811, 3011, 3211, 3411, 3611, 3811, 4011, 4210, 4409, 4608, 4807, 5006, 5205, 5403, 5601, 5799, 5997, 6195, 6392, 6589, 6786, 6982, 7179, 7375, 7571, 7766, 7961, 8156, 8351, 8545, 8739, 8932, 9126, 9319, 9511, 9703, 9895, 10087, 10278, 10469, 10659, 10849, 11038, 11227, 11416, 11604, 11792, 11980, 12166, 12353, 12539, 12724, 12909, 13094, 13278, 13462, 13645, 13827, 14009, 14191, 14372, 14552, 14732, 14911, 15090, 15268, 15446, 15623, 15799, 15975, 16150, 16325, 16499, 16672, 16845, 17017, 17189, 17360, 17530, 17699, 17868, 18036, 18204, 18371, 18537, 18702, 18867, 19031, 19194, 19357, 19519, 19680, 19840, 20000, 20159, 20317, 20474, 20631, 20787, 20942, 21096, 21249, 21402, 21554, 21705, 21855, 22004, 22153, 22301, 22448, 22594, 22739, 22883, 23027, 23169, 23311, 23452, 23592, 23731, 23869, 24006, 24143, 24278, 24413, 24546, 24679, 24811, 24942, 25072, 25201, 25329, 25456, 25582, 25707, 25831, 25954, 26077, 26198, 26318, 26437, 26556, 26673, 26789, 26905, 27019, 27132, 27244, 27355, 27466, 27575, 27683, 27790, 27896, 28001, 28105, 28208, 28309, 28410, 28510, 28608, 28706, 28802, 28897, 28992, 29085, 29177, 29268, 29358, 29446, 29534, 29621, 29706, 29790, 29873, 29955, 30036, 30116, 30195, 30272, 30349, 30424, 30498, 30571, 30643, 30713, 30783, 30851, 30918, 30984, 31049, 31113, 31175, 31236, 31297, 31356, 31413, 31470, 31525, 31580, 31633, 31684, 31735, 31785, 31833, 31880, 31926, 31970, 32014, 32056, 32097, 32137, 32176, 32213, 32249, 32284, 32318, 32350, 32382, 32412, 32441, 32468, 32495, 32520, 32544, 32567, 32588, 32609, 32628, 32646, 32662, 32678, 32692, 32705, 32717, 32727, 32736, 32744, 32751, 32757, 32761, 32764, 32766, 32767, 32766, 32764, 32761, 32757, 32751, 32744, 32736, 32727, 32717, 32705, 32692, 32678, 32662, 32646, 32628, 32609, 32588, 32567, 32544, 32520, 32495, 32468, 32441, 32412, 32382, 32350, 32318, 32284, 32249, 32213, 32176, 32137, 32097, 32056, 32014, 31970, 31926, 31880, 31833, 31785, 31735, 31684, 31633, 31580, 31525, 31470, 31413, 31356, 31297, 31236, 31175, 31113, 31049, 30984, 30918, 30851, 30783, 30713, 30643, 30571, 30498, 30424, 30349, 30272, 30195, 30116, 30036, 29955, 29873, 29790, 29706, 29621, 29534, 29446, 29358, 29268, 29177, 29085, 28992, 28897, 28802, 28706, 28608, 28510, 28410, 28309, 28208, 28105, 28001, 27896, 27790, 27683, 27575, 27466, 27355, 27244, 27132, 27019, 26905, 26789, 26673, 26556, 26437, 26318, 26198, 26077, 25954, 25831, 25707, 25582, 25456, 25329, 25201, 25072, 24942, 24811, 24679, 24546, 24413, 24278, 24143, 24006, 23869, 23731, 23592, 23452, 23311, 23169, 23027, 22883, 22739, 22594, 22448, 22301, 22153, 22004, 21855, 21705, 21554, 21402, 21249, 21096, 20942, 20787, 20631, 20474, 20317, 20159, 20000, 19840, 19680, 19519, 19357, 19194, 19031, 18867, 18702, 18537, 18371, 18204, 18036, 17868, 17699, 17530, 17360, 17189, 17017, 16845, 16672, 16499, 16325, 16150, 15975, 15799, 15623, 15446, 15268, 15090, 14911, 14732, 14552, 14372, 14191, 14009, 13827, 13645, 13462, 13278, 13094, 12909, 12724, 12539, 12353, 12166, 11980, 11792, 11604, 11416, 11227, 11038, 10849, 10659, 10469, 10278, 10087, 9895, 9703, 9511, 9319, 9126, 8932, 8739, 8545, 8351, 8156, 7961, 7766, 7571, 7375, 7179, 6982, 6786, 6589, 6392, 6195, 5997, 5799, 5601, 5403, 5205, 5006, 4807, 4608, 4409, 4210, 4011, 3811, 3611, 3411, 3211, 3011, 2811, 2610, 2410, 2209, 2009, 1808, 1607, 1406, 1206, 1005, 804, 603, 402, 201, 0, -201, -402, -603, -804, -1005, -1206, -1406, -1607, -1808, -2009, -2209, -2410, -2610, -2811, -3011, -3211, -3411, -3611, -3811, -4011, -4210, -4409, -4608, -4807, -5006, -5205, -5403, -5601, -5799, -5997, -6195, -6392, -6589, -6786, -6982, -7179, -7375, -7571, -7766, -7961, -8156, -8351, -8545, -8739, -8932, -9126, -9319, -9511, -9703, -9895, -10087, -10278, -10469, -10659, -10849, -11038, -11227, -11416, -11604, -11792, -11980, -12166, -12353, -12539, -12724, -12909, -13094, -13278, -13462, -13645, -13827, -14009, -14191, -14372, -14552, -14732, -14911, -15090, -15268, -15446, -15623, -15799, -15975, -16150, -16325, -16499, -16672, -16845, -17017, -17189, -17360, -17530, -17699, -17868, -18036, -18204, -18371, -18537, -18702, -18867, -19031, -19194, -19357, -19519, -19680, -19840, -20000, -20159, -20317, -20474, -20631, -20787, -20942, -21096, -21249, -21402, -21554, -21705, -21855, -22004, -22153, -22301, -22448, -22594, -22739, -22883, -23027, -23169, -23311, -23452, -23592, -23731, -23869, -24006, -24143, -24278, -24413, -24546, -24679, -24811, -24942, -25072, -25201, -25329, -25456, -25582, -25707, -25831, -25954, -26077, -26198, -26318, -26437, -26556, -26673, -26789, -26905, -27019, -27132, -27244, -27355, -27466, -27575, -27683, -27790, -27896, -28001, -28105, -28208, -28309, -28410, -28510, -28608, -28706, -28802, -28897, -28992, -29085, -29177, -29268, -29358, -29446, -29534, -29621, -29706, -29790, -29873, -29955, -30036, -30116, -30195, -30272, -30349, -30424, -30498, -30571, -30643, -30713, -30783, -30851, -30918, -30984, -31049, -31113, -31175, -31236, -31297, -31356, -31413, -31470, -31525, -31580, -31633, -31684, -31735, -31785, -31833, -31880, -31926, -31970, -32014, -32056, -32097, -32137, -32176, -32213, -32249, -32284, -32318, -32350, -32382, -32412, -32441, -32468, -32495, -32520, -32544, -32567, -32588, -32609, -32628, -32646, -32662, -32678, -32692, -32705, -32717, -32727, -32736, -32744, -32751, -32757, -32761, -32764, -32766, -32767, -32766, -32764, -32761, -32757, -32751, -32744, -32736, -32727, -32717, -32705, -32692, -32678, -32662, -32646, -32628, -32609, -32588, -32567, -32544, -32520, -32495, -32468, -32441, -32412, -32382, -32350, -32318, -32284, -32249, -32213, -32176, -32137, -32097, -32056, -32014, -31970, -31926, -31880, -31833, -31785, -31735, -31684, -31633, -31580, -31525, -31470, -31413, -31356, -31297, -31236, -31175, -31113, -31049, -30984, -30918, -30851, -30783, -30713, -30643, -30571, -30498, -30424, -30349, -30272, -30195, -30116, -30036, -29955, -29873, -29790, -29706, -29621, -29534, -29446, -29358, -29268, -29177, -29085, -28992, -28897, -28802, -28706, -28608, -28510, -28410, -28309, -28208, -28105, -28001, -27896, -27790, -27683, -27575, -27466, -27355, -27244, -27132, -27019, -26905, -26789, -26673, -26556, -26437, -26318, -26198, -26077, -25954, -25831, -25707, -25582, -25456, -25329, -25201, -25072, -24942, -24811, -24679, -24546, -24413, -24278, -24143, -24006, -23869, -23731, -23592, -23452, -23311, -23169, -23027, -22883, -22739, -22594, -22448, -22301, -22153, -22004, -21855, -21705, -21554, -21402, -21249, -21096, -20942, -20787, -20631, -20474, -20317, -20159, -20000, -19840, -19680, -19519, -19357, -19194, -19031, -18867, -18702, -18537, -18371, -18204, -18036, -17868, -17699, -17530, -17360, -17189, -17017, -16845, -16672, -16499, -16325, -16150, -15975, -15799, -15623, -15446, -15268, -15090, -14911, -14732, -14552, -14372, -14191, -14009, -13827, -13645, -13462, -13278, -13094, -12909, -12724, -12539, -12353, -12166, -11980, -11792, -11604, -11416, -11227, -11038, -10849, -10659, -10469, -10278, -10087, -9895, -9703, -9511, -9319, -9126, -8932, -8739, -8545, -8351, -8156, -7961, -7766, -7571, -7375, -7179, -6982, -6786, -6589, -6392, -6195, -5997, -5799, -5601, -5403, -5205, -5006, -4807, -4608, -4409, -4210, -4011, -3811, -3611, -3411, -3211, -3011, -2811, -2610, -2410, -2209, -2009, -1808, -1607, -1406, -1206, -1005, -804, -603, -402, -201, 0, }; const int16_t FLASHMEM wav_fold_power[] = { -32767, -32322, -31881, -31446, -31017, -30592, -30172, -29757, -29347, -28942, -28541, -28146, -27755, -27368, -26987, -26610, -26237, -25869, -25506, -25146, -24791, -24441, -24095, -23752, -23415, -23081, -22751, -22425, -22104, -21786, -21472, -21162, -20856, -20554, -20255, -19961, -19670, -19382, -19098, -18818, -18541, -18268, -17998, -17732, -17469, -17209, -16953, -16700, -16450, -16204, -15960, -15720, -15483, -15249, -15018, -14790, -14565, -14343, -14123, -13907, -13694, -13483, -13275, -13070, -12867, -12668, -12471, -12276, -12084, -11895, -11709, -11524, -11343, -11163, -10987, -10812, -10640, -10471, -10303, -10138, -9975, -9815, -9657, -9501, -9347, -9195, -9045, -8898, -8752, -8609, -8467, -8328, -8190, -8055, -7921, -7789, -7659, -7532, -7405, -7281, -7159, -7038, -6919, -6802, -6686, -6572, -6460, -6349, -6240, -6133, -6027, -5923, -5821, -5719, -5620, -5522, -5425, -5330, -5236, -5144, -5053, -4963, -4875, -4788, -4703, -4619, -4536, -4454, -4374, -4295, -4217, -4140, -4065, -3990, -3917, -3845, -3775, -3705, -3636, -3569, -3502, -3437, -3373, -3309, -3247, -3186, -3125, -3066, -3008, -2950, -2894, -2839, -2784, -2730, -2677, -2626, -2575, -2524, -2475, -2426, -2379, -2332, -2286, -2240, -2196, -2152, -2109, -2067, -2025, -1984, -1944, -1905, -1866, -1828, -1790, -1754, -1718, -1682, -1647, -1613, -1579, -1546, -1514, -1482, -1451, -1420, -1390, -1361, -1332, -1303, -1275, -1248, -1221, -1194, -1168, -1143, -1118, -1093, -1069, -1046, -1022, -1000, -977, -956, -934, -913, -892, -872, -852, -833, -814, -795, -777, -759, -741, -724, -707, -691, -674, -659, -643, -628, -613, -598, -584, -570, -556, -543, -529, -516, -504, -491, -479, -467, -456, -445, -433, -423, -412, -401, -391, -381, -372, -362, -353, -344, -335, -326, -318, -309, -301, -293, -285, -278, -270, -263, -256, -249, -242, -236, -229, -223, -217, -211, -205, -199, -194, -188, -183, -178, -173, -168, -163, -158, -154, -149, -145, -141, -136, -132, -129, -125, -121, -117, -114, -110, -107, -104, -101, -97, -94, -91, -89, -86, -83, -80, -78, -75, -73, -71, -68, -66, -64, -62, -60, -58, -56, -54, -52, -50, -49, -47, -45, -44, -42, -41, -39, -38, -37, -35, -34, -33, -32, -31, -29, -28, -27, -26, -25, -24, -23, -23, -22, -21, -20, -19, -19, -18, -17, -16, -16, -15, -15, -14, -13, -13, -12, -12, -11, -11, -10, -10, -10, -9, -9, -8, -8, -8, -7, -7, -7, -6, -6, -6, -6, -5, -5, -5, -5, -4, -4, -4, -4, -4, -3, -3, -3, -3, -3, -3, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 16, 17, 18, 19, 19, 20, 21, 22, 23, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34, 35, 37, 38, 39, 41, 42, 44, 45, 47, 49, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 71, 73, 75, 78, 80, 83, 86, 89, 91, 94, 97, 101, 104, 107, 110, 114, 117, 121, 125, 129, 132, 136, 141, 145, 149, 154, 158, 163, 168, 173, 178, 183, 188, 194, 199, 205, 211, 217, 223, 229, 236, 242, 249, 256, 263, 270, 278, 285, 293, 301, 309, 318, 326, 335, 344, 353, 362, 372, 381, 391, 401, 412, 423, 433, 445, 456, 467, 479, 491, 504, 516, 529, 543, 556, 570, 584, 598, 613, 628, 643, 659, 674, 691, 707, 724, 741, 759, 777, 795, 814, 833, 852, 872, 892, 913, 934, 956, 977, 1000, 1022, 1046, 1069, 1093, 1118, 1143, 1168, 1194, 1221, 1248, 1275, 1303, 1332, 1361, 1390, 1420, 1451, 1482, 1514, 1546, 1579, 1613, 1647, 1682, 1718, 1754, 1790, 1828, 1866, 1905, 1944, 1984, 2025, 2067, 2109, 2152, 2196, 2240, 2286, 2332, 2379, 2426, 2475, 2524, 2575, 2626, 2677, 2730, 2784, 2839, 2894, 2950, 3008, 3066, 3125, 3186, 3247, 3309, 3373, 3437, 3502, 3569, 3636, 3705, 3775, 3845, 3917, 3990, 4065, 4140, 4217, 4295, 4374, 4454, 4536, 4619, 4703, 4788, 4875, 4963, 5053, 5144, 5236, 5330, 5425, 5522, 5620, 5719, 5821, 5923, 6027, 6133, 6240, 6349, 6460, 6572, 6686, 6802, 6919, 7038, 7159, 7281, 7405, 7532, 7659, 7789, 7921, 8055, 8190, 8328, 8467, 8609, 8752, 8898, 9045, 9195, 9347, 9501, 9657, 9815, 9975, 10138, 10303, 10471, 10640, 10812, 10987, 11163, 11343, 11524, 11709, 11895, 12084, 12276, 12471, 12668, 12867, 13070, 13275, 13483, 13694, 13907, 14123, 14343, 14565, 14790, 15018, 15249, 15483, 15720, 15960, 16204, 16450, 16700, 16953, 17209, 17469, 17732, 17998, 18268, 18541, 18818, 19098, 19382, 19670, 19961, 20255, 20554, 20856, 21162, 21472, 21786, 22104, 22425, 22751, 23081, 23415, 23752, 24095, 24441, 24791, 25146, 25506, 25869, 26237, 26610, 26987, 27368, 27755, 28146, 28541, 28942, 29347, 29757, 30172, 30592, 31017, 31446, 31881, 32322, 32322, }; const int16_t FLASHMEM wav_fold_sine[] = { -32767, -32746, -32726, -32704, -32683, -32662, -32640, -32618, -32596, -32573, -32551, -32528, -32505, -32482, -32458, -32435, -32411, -32387, -32364, -32340, -32316, -32291, -32267, -32243, -32219, -32194, -32170, -32146, -32122, -32097, -32073, -32049, -32025, -32002, -31978, -31955, -31932, -31909, -31886, -31863, -31841, -31819, -31797, -31776, -31755, -31734, -31714, -31694, -31674, -31655, -31636, -31618, -31600, -31582, -31565, -31548, -31532, -31516, -31501, -31486, -31471, -31457, -31443, -31430, -31417, -31404, -31392, -31380, -31368, -31356, -31345, -31334, -31323, -31312, -31302, -31291, -31280, -31269, -31259, -31248, -31236, -31225, -31213, -31201, -31189, -31175, -31162, -31148, -31133, -31117, -31101, -31083, -31065, -31046, -31025, -31003, -30981, -30956, -30931, -30904, -30875, -30845, -30814, -30780, -30745, -30708, -30669, -30628, -30585, -30540, -30494, -30445, -30393, -30340, -30284, -30227, -30167, -30104, -30040, -29973, -29904, -29833, -29759, -29684, -29606, -29526, -29444, -29360, -29274, -29186, -29096, -29005, -28912, -28817, -28721, -28623, -28525, -28425, -28324, -28222, -28119, -28016, -27913, -27809, -27705, -27601, -27497, -27394, -27291, -27189, -27088, -26988, -26889, -26792, -26696, -26602, -26511, -26421, -26334, -26249, -26168, -26089, -26013, -25941, -25872, -25807, -25745, -25687, -25634, -25584, -25539, -25498, -25461, -25430, -25402, -25380, -25362, -25349, -25340, -25337, -25338, -25344, -25354, -25370, -25389, -25414, -25442, -25475, -25512, -25553, -25597, -25645, -25697, -25752, -25809, -25869, -25931, -25996, -26062, -26130, -26198, -26267, -26337, -26407, -26476, -26544, -26611, -26677, -26740, -26801, -26858, -26913, -26963, -27009, -27050, -27086, -27117, -27141, -27158, -27169, -27172, -27167, -27153, -27131, -27100, -27059, -27009, -26948, -26877, -26794, -26701, -26596, -26479, -26351, -26210, -26057, -25892, -25715, -25524, -25322, -25106, -24878, -24638, -24385, -24120, -23843, -23554, -23253, -22941, -22617, -22283, -21939, -21585, -21221, -20849, -20468, -20079, -19683, -19281, -18872, -18458, -18040, -17618, -17193, -16766, -16338, -15909, -15480, -15053, -14628, -14205, -13787, -13374, -12967, -12566, -12173, -11789, -11414, -11050, -10697, -10357, -10030, -9716, -9418, -9135, -8869, -8620, -8389, -8177, -7984, -7810, -7658, -7526, -7416, -7327, -7261, -7218, -7197, -7199, -7224, -7273, -7344, -7439, -7557, -7698, -7861, -8047, -8255, -8484, -8734, -9004, -9294, -9603, -9931, -10275, -10636, -11013, -11404, -11808, -12225, -12652, -13089, -13535, -13988, -14446, -14909, -15374, -15841, -16308, -16773, -17235, -17692, -18142, -18585, -19017, -19439, -19847, -20241, -20619, -20980, -21321, -21642, -21940, -22215, -22465, -22689, -22886, -23053, -23191, -23297, -23372, -23413, -23420, -23393, -23330, -23231, -23095, -22922, -22712, -22463, -22177, -21853, -21491, -21090, -20653, -20178, -19666, -19118, -18534, -17915, -17263, -16578, -15860, -15112, -14335, -13530, -12698, -11841, -10961, -10059, -9137, -8198, -7242, -6273, -5292, -4301, -3303, -2300, -1294, -287, 718, 1719, 2713, 3698, 4672, 5632, 6576, 7502, 8406, 9288, 10143, 10971, 11769, 12535, 13267, 13962, 14620, 15237, 15812, 16345, 16832, 17272, 17665, 18009, 18302, 18545, 18735, 18872, 18956, 18986, 18961, 18882, 18748, 18560, 18317, 18020, 17670, 17267, 16812, 16306, 15749, 15144, 14491, 13793, 13050, 12264, 11437, 10572, 9669, 8733, 7763, 6765, 5738, 4687, 3614, 2521, 1412, 289, -844, -1986, -3132, -4281, -5428, -6571, -7707, -8832, -9945, -11040, -12117, -13171, -14201, -15202, -16173, -17110, -18011, -18874, -19695, -20474, -21206, -21892, -22527, -23111, -23641, -24116, -24536, -24897, -25199, -25442, -25624, -25744, -25803, -25798, -25732, -25603, -25411, -25157, -24841, -24464, -24027, -23530, -22975, -22363, -21695, -20974, -20199, -19375, -18502, -17582, -16619, -15613, -14569, -13488, -12372, -11226, -10051, -8851, -7629, -6387, -5129, -3858, -2578, -1290, 0, 1290, 2578, 3858, 5129, 6387, 7629, 8851, 10051, 11226, 12372, 13488, 14569, 15613, 16619, 17582, 18502, 19375, 20199, 20974, 21695, 22363, 22975, 23530, 24027, 24464, 24841, 25157, 25411, 25603, 25732, 25798, 25803, 25744, 25624, 25442, 25199, 24897, 24536, 24116, 23641, 23111, 22527, 21892, 21206, 20474, 19695, 18874, 18011, 17110, 16173, 15202, 14201, 13171, 12117, 11040, 9945, 8832, 7707, 6571, 5428, 4281, 3132, 1986, 844, -289, -1412, -2521, -3614, -4687, -5738, -6765, -7763, -8733, -9669, -10572, -11437, -12264, -13050, -13793, -14491, -15144, -15749, -16306, -16812, -17267, -17670, -18020, -18317, -18560, -18748, -18882, -18961, -18986, -18956, -18872, -18735, -18545, -18302, -18009, -17665, -17272, -16832, -16345, -15812, -15237, -14620, -13962, -13267, -12535, -11769, -10971, -10143, -9288, -8406, -7502, -6576, -5632, -4672, -3698, -2713, -1719, -718, 287, 1294, 2300, 3303, 4301, 5292, 6273, 7242, 8198, 9137, 10059, 10961, 11841, 12698, 13530, 14335, 15112, 15860, 16578, 17263, 17915, 18534, 19118, 19666, 20178, 20653, 21090, 21491, 21853, 22177, 22463, 22712, 22922, 23095, 23231, 23330, 23393, 23420, 23413, 23372, 23297, 23191, 23053, 22886, 22689, 22465, 22215, 21940, 21642, 21321, 20980, 20619, 20241, 19847, 19439, 19017, 18585, 18142, 17692, 17235, 16773, 16308, 15841, 15374, 14909, 14446, 13988, 13535, 13089, 12652, 12225, 11808, 11404, 11013, 10636, 10275, 9931, 9603, 9294, 9004, 8734, 8484, 8255, 8047, 7861, 7698, 7557, 7439, 7344, 7273, 7224, 7199, 7197, 7218, 7261, 7327, 7416, 7526, 7658, 7810, 7984, 8177, 8389, 8620, 8869, 9135, 9418, 9716, 10030, 10357, 10697, 11050, 11414, 11789, 12173, 12566, 12967, 13374, 13787, 14205, 14628, 15053, 15480, 15909, 16338, 16766, 17193, 17618, 18040, 18458, 18872, 19281, 19683, 20079, 20468, 20849, 21221, 21585, 21939, 22283, 22617, 22941, 23253, 23554, 23843, 24120, 24385, 24638, 24878, 25106, 25322, 25524, 25715, 25892, 26057, 26210, 26351, 26479, 26596, 26701, 26794, 26877, 26948, 27009, 27059, 27100, 27131, 27153, 27167, 27172, 27169, 27158, 27141, 27117, 27086, 27050, 27009, 26963, 26913, 26858, 26801, 26740, 26677, 26611, 26544, 26476, 26407, 26337, 26267, 26198, 26130, 26062, 25996, 25931, 25869, 25809, 25752, 25697, 25645, 25597, 25553, 25512, 25475, 25442, 25414, 25389, 25370, 25354, 25344, 25338, 25337, 25340, 25349, 25362, 25380, 25402, 25430, 25461, 25498, 25539, 25584, 25634, 25687, 25745, 25807, 25872, 25941, 26013, 26089, 26168, 26249, 26334, 26421, 26511, 26602, 26696, 26792, 26889, 26988, 27088, 27189, 27291, 27394, 27497, 27601, 27705, 27809, 27913, 28016, 28119, 28222, 28324, 28425, 28525, 28623, 28721, 28817, 28912, 29005, 29096, 29186, 29274, 29360, 29444, 29526, 29606, 29684, 29759, 29833, 29904, 29973, 30040, 30104, 30167, 30227, 30284, 30340, 30393, 30445, 30494, 30540, 30585, 30628, 30669, 30708, 30745, 30780, 30814, 30845, 30875, 30904, 30931, 30956, 30981, 31003, 31025, 31046, 31065, 31083, 31101, 31117, 31133, 31148, 31162, 31175, 31189, 31201, 31213, 31225, 31236, 31248, 31259, 31269, 31280, 31291, 31302, 31312, 31323, 31334, 31345, 31356, 31368, 31380, 31392, 31404, 31417, 31430, 31443, 31457, 31471, 31486, 31501, 31516, 31532, 31548, 31565, 31582, 31600, 31618, 31636, 31655, 31674, 31694, 31714, 31734, 31755, 31776, 31797, 31819, 31841, 31863, 31886, 31909, 31932, 31955, 31978, 32002, 32025, 32049, 32073, 32097, 32122, 32146, 32170, 32194, 32219, 32243, 32267, 32291, 32316, 32340, 32364, 32387, 32411, 32435, 32458, 32482, 32505, 32528, 32551, 32573, 32596, 32618, 32640, 32662, 32683, 32704, 32726, 32746, 32746, }; const int16_t FLASHMEM wav_overdrive[] = { -32767, -32767, -32767, -32767, -32767, -32767, -32767, -32767, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32765, -32765, -32765, -32765, -32765, -32765, -32765, -32765, -32765, -32765, -32765, -32764, -32764, -32764, -32764, -32764, -32764, -32764, -32764, -32763, -32763, -32763, -32763, -32763, -32763, -32763, -32763, -32762, -32762, -32762, -32762, -32762, -32762, -32761, -32761, -32761, -32761, -32761, -32761, -32760, -32760, -32760, -32760, -32760, -32759, -32759, -32759, -32759, -32759, -32758, -32758, -32758, -32758, -32757, -32757, -32757, -32757, -32756, -32756, -32756, -32756, -32755, -32755, -32755, -32754, -32754, -32754, -32753, -32753, -32753, -32752, -32752, -32752, -32751, -32751, -32751, -32750, -32750, -32749, -32749, -32749, -32748, -32748, -32747, -32747, -32746, -32746, -32745, -32745, -32744, -32744, -32743, -32743, -32742, -32742, -32741, -32741, -32740, -32740, -32739, -32738, -32738, -32737, -32736, -32736, -32735, -32734, -32734, -32733, -32732, -32732, -32731, -32730, -32729, -32728, -32728, -32727, -32726, -32725, -32724, -32723, -32722, -32721, -32720, -32719, -32718, -32717, -32716, -32715, -32714, -32713, -32712, -32711, -32710, -32709, -32707, -32706, -32705, -32704, -32702, -32701, -32700, -32698, -32697, -32695, -32694, -32692, -32691, -32689, -32688, -32686, -32684, -32683, -32681, -32679, -32678, -32676, -32674, -32672, -32670, -32668, -32666, -32664, -32662, -32660, -32658, -32655, -32653, -32651, -32649, -32646, -32644, -32641, -32639, -32636, -32633, -32631, -32628, -32625, -32622, -32619, -32617, -32614, -32610, -32607, -32604, -32601, -32597, -32594, -32591, -32587, -32584, -32580, -32576, -32572, -32568, -32564, -32560, -32556, -32552, -32548, -32543, -32539, -32534, -32530, -32525, -32520, -32515, -32510, -32505, -32500, -32495, -32489, -32484, -32478, -32473, -32467, -32461, -32455, -32448, -32442, -32436, -32429, -32422, -32416, -32409, -32402, -32394, -32387, -32380, -32372, -32364, -32356, -32348, -32340, -32331, -32323, -32314, -32305, -32296, -32287, -32277, -32268, -32258, -32248, -32237, -32227, -32216, -32206, -32195, -32183, -32172, -32160, -32148, -32136, -32124, -32111, -32098, -32085, -32072, -32058, -32044, -32030, -32016, -32001, -31986, -31971, -31955, -31939, -31923, -31907, -31890, -31873, -31855, -31838, -31819, -31801, -31782, -31763, -31743, -31723, -31703, -31682, -31661, -31640, -31618, -31596, -31573, -31550, -31526, -31502, -31478, -31453, -31427, -31401, -31375, -31348, -31320, -31293, -31264, -31235, -31205, -31175, -31145, -31113, -31082, -31049, -31016, -30983, -30948, -30913, -30878, -30842, -30805, -30767, -30729, -30690, -30650, -30610, -30569, -30527, -30484, -30440, -30396, -30351, -30305, -30258, -30211, -30162, -30113, -30063, -30012, -29959, -29906, -29853, -29798, -29742, -29685, -29627, -29568, -29508, -29447, -29385, -29321, -29257, -29191, -29125, -29057, -28988, -28918, -28846, -28774, -28700, -28625, -28548, -28470, -28391, -28311, -28229, -28146, -28061, -27975, -27887, -27798, -27708, -27616, -27522, -27427, -27331, -27232, -27132, -27031, -26928, -26823, -26717, -26609, -26499, -26387, -26274, -26158, -26041, -25923, -25802, -25679, -25555, -25428, -25300, -25170, -25038, -24904, -24767, -24629, -24489, -24346, -24202, -24056, -23907, -23756, -23603, -23448, -23291, -23131, -22970, -22806, -22640, -22471, -22301, -22128, -21952, -21775, -21595, -21413, -21228, -21041, -20852, -20660, -20466, -20270, -20071, -19870, -19666, -19460, -19252, -19041, -18828, -18613, -18395, -18174, -17951, -17726, -17499, -17269, -17036, -16802, -16565, -16325, -16083, -15839, -15593, -15344, -15093, -14840, -14584, -14327, -14067, -13805, -13540, -13274, -13005, -12735, -12462, -12187, -11910, -11632, -11351, -11068, -10784, -10498, -10210, -9920, -9628, -9335, -9040, -8744, -8446, -8146, -7845, -7543, -7239, -6934, -6628, -6320, -6012, -5702, -5391, -5079, -4766, -4453, -4138, -3823, -3507, -3190, -2873, -2555, -2237, -1918, -1599, -1279, -960, -640, -320, 0, 320, 640, 960, 1279, 1599, 1918, 2237, 2555, 2873, 3190, 3507, 3823, 4138, 4453, 4766, 5079, 5391, 5702, 6012, 6320, 6628, 6934, 7239, 7543, 7845, 8146, 8446, 8744, 9040, 9335, 9628, 9920, 10210, 10498, 10784, 11068, 11351, 11632, 11910, 12187, 12462, 12735, 13005, 13274, 13540, 13805, 14067, 14327, 14584, 14840, 15093, 15344, 15593, 15839, 16083, 16325, 16565, 16802, 17036, 17269, 17499, 17726, 17951, 18174, 18395, 18613, 18828, 19041, 19252, 19460, 19666, 19870, 20071, 20270, 20466, 20660, 20852, 21041, 21228, 21413, 21595, 21775, 21952, 22128, 22301, 22471, 22640, 22806, 22970, 23131, 23291, 23448, 23603, 23756, 23907, 24056, 24202, 24346, 24489, 24629, 24767, 24904, 25038, 25170, 25300, 25428, 25555, 25679, 25802, 25923, 26041, 26158, 26274, 26387, 26499, 26609, 26717, 26823, 26928, 27031, 27132, 27232, 27331, 27427, 27522, 27616, 27708, 27798, 27887, 27975, 28061, 28146, 28229, 28311, 28391, 28470, 28548, 28625, 28700, 28774, 28846, 28918, 28988, 29057, 29125, 29191, 29257, 29321, 29385, 29447, 29508, 29568, 29627, 29685, 29742, 29798, 29853, 29906, 29959, 30012, 30063, 30113, 30162, 30211, 30258, 30305, 30351, 30396, 30440, 30484, 30527, 30569, 30610, 30650, 30690, 30729, 30767, 30805, 30842, 30878, 30913, 30948, 30983, 31016, 31049, 31082, 31113, 31145, 31175, 31205, 31235, 31264, 31293, 31320, 31348, 31375, 31401, 31427, 31453, 31478, 31502, 31526, 31550, 31573, 31596, 31618, 31640, 31661, 31682, 31703, 31723, 31743, 31763, 31782, 31801, 31819, 31838, 31855, 31873, 31890, 31907, 31923, 31939, 31955, 31971, 31986, 32001, 32016, 32030, 32044, 32058, 32072, 32085, 32098, 32111, 32124, 32136, 32148, 32160, 32172, 32183, 32195, 32206, 32216, 32227, 32237, 32248, 32258, 32268, 32277, 32287, 32296, 32305, 32314, 32323, 32331, 32340, 32348, 32356, 32364, 32372, 32380, 32387, 32394, 32402, 32409, 32416, 32422, 32429, 32436, 32442, 32448, 32455, 32461, 32467, 32473, 32478, 32484, 32489, 32495, 32500, 32505, 32510, 32515, 32520, 32525, 32530, 32534, 32539, 32543, 32548, 32552, 32556, 32560, 32564, 32568, 32572, 32576, 32580, 32584, 32587, 32591, 32594, 32597, 32601, 32604, 32607, 32610, 32614, 32617, 32619, 32622, 32625, 32628, 32631, 32633, 32636, 32639, 32641, 32644, 32646, 32649, 32651, 32653, 32655, 32658, 32660, 32662, 32664, 32666, 32668, 32670, 32672, 32674, 32676, 32678, 32679, 32681, 32683, 32684, 32686, 32688, 32689, 32691, 32692, 32694, 32695, 32697, 32698, 32700, 32701, 32702, 32704, 32705, 32706, 32707, 32709, 32710, 32711, 32712, 32713, 32714, 32715, 32716, 32717, 32718, 32719, 32720, 32721, 32722, 32723, 32724, 32725, 32726, 32727, 32728, 32728, 32729, 32730, 32731, 32732, 32732, 32733, 32734, 32734, 32735, 32736, 32736, 32737, 32738, 32738, 32739, 32740, 32740, 32741, 32741, 32742, 32742, 32743, 32743, 32744, 32744, 32745, 32745, 32746, 32746, 32747, 32747, 32748, 32748, 32749, 32749, 32749, 32750, 32750, 32751, 32751, 32751, 32752, 32752, 32752, 32753, 32753, 32753, 32754, 32754, 32754, 32755, 32755, 32755, 32756, 32756, 32756, 32756, 32757, 32757, 32757, 32757, 32758, 32758, 32758, 32758, 32759, 32759, 32759, 32759, 32759, 32760, 32760, 32760, 32760, 32760, 32761, 32761, 32761, 32761, 32761, 32761, 32762, 32762, 32762, 32762, 32762, 32762, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, }; const int16_t* waveform_table[] = { wav_sine, wav_fold_power, wav_fold_sine, wav_overdrive, }; } // namespace peaks ================================================ FILE: lib/peaks/resources.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resources definitions. // // Automatically generated with: // make resources #ifndef PEAKS_RESOURCES_H_ #define PEAKS_RESOURCES_H_ #include "stmlib/stmlib.h" namespace peaks { typedef uint8_t ResourceId; extern const char* string_table[]; extern const uint16_t* lookup_table_table[]; extern const uint32_t* lookup_table_32_table[]; extern const uint8_t* waveform_8_table[]; extern const int16_t* waveform_table[]; extern const uint16_t lut_delay_times[]; extern const uint16_t lut_gravity[]; extern const uint16_t lut_env_linear[]; extern const uint16_t lut_env_expo[]; extern const uint16_t lut_env_quartic[]; extern const uint16_t lut_raised_cosine[]; extern const uint16_t lut_svf_cutoff[]; extern const uint16_t lut_svf_damp[]; extern const uint16_t lut_svf_scale[]; extern const uint32_t lut_lfo_increments[]; extern const uint32_t lut_env_increments[]; extern const uint32_t lut_oscillator_increments[]; extern const uint8_t wav_digits[]; extern const int16_t wav_sine[]; extern const int16_t wav_fold_power[]; extern const int16_t wav_fold_sine[]; extern const int16_t wav_overdrive[]; #define STR_DUMMY 0 // dummy #define LUT_DELAY_TIMES 0 #define LUT_DELAY_TIMES_SIZE 257 #define LUT_GRAVITY 1 #define LUT_GRAVITY_SIZE 257 #define LUT_ENV_LINEAR 2 #define LUT_ENV_LINEAR_SIZE 257 const int LUT_ENV_EXPO = 3; #define LUT_ENV_EXPO_SIZE 257 #define LUT_ENV_QUARTIC 4 #define LUT_ENV_QUARTIC_SIZE 257 #define LUT_RAISED_COSINE 5 #define LUT_RAISED_COSINE_SIZE 257 const int LUT_SVF_CUTOFF = 6; #define LUT_SVF_CUTOFF_SIZE 257 const int LUT_SVF_DAMP = 7; #define LUT_SVF_DAMP_SIZE 257 const int LUT_SVF_SCALE = 8; #define LUT_SVF_SCALE_SIZE 257 #define LUT_LFO_INCREMENTS 0 #define LUT_LFO_INCREMENTS_SIZE 257 #define LUT_ENV_INCREMENTS 1 #define LUT_ENV_INCREMENTS_SIZE 257 const int LUT_OSCILLATOR_INCREMENTS = 2; #define LUT_OSCILLATOR_INCREMENTS_SIZE 97 #define WAV_DIGITS 0 #define WAV_DIGITS_SIZE 36824 const int WAV_SINE = 0; const int WAV_SINE_SIZE = 1025; #define WAV_FOLD_POWER 1 #define WAV_FOLD_POWER_SIZE 1025 #define WAV_FOLD_SINE 2 #define WAV_FOLD_SINE_SIZE 1025 #define WAV_OVERDRIVE 3 #define WAV_OVERDRIVE_SIZE 1025 } // namespace peaks #endif // PEAKS_RESOURCES_H_ ================================================ FILE: lib/plaits/dsp/chords/chord_bank.cc ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Chords: wavetable and divide-down organ/string machine. #include "plaits/dsp/chords/chord_bank.h" #include "stmlib/dsp/units.h" #ifndef FLASHMEM #include "pgmspace.h" #endif namespace plaits { using namespace stmlib; #ifdef JON_CHORDS //[eh2k] const char* const chord_names[kChordNumChords] = { "OCT", "Fifth", "min", "min7", "min9", "min11", "Maj", "Maj7", "Maj9", "Sus4", "69", "6th", "10th", "D7", "D7(b9)", "HD", "FD", }; // Alternative chord table by Jon Butler jonbutler88@gmail.com /* static */ const float ChordBank::chords_[kChordNumChords][kChordNumNotes] = { // Fixed Intervals { 0.00f, 0.01f, 11.99f, 12.00f }, // Octave { 0.00f, 7.00f, 7.01f, 12.00f }, // Fifth // Minor { 0.00f, 3.00f, 7.00f, 12.00f }, // Minor { 0.00f, 3.00f, 7.00f, 10.00f }, // Minor 7th { 0.00f, 3.00f, 10.00f, 14.00f }, // Minor 9th { 0.00f, 3.00f, 10.00f, 17.00f }, // Minor 11th // Major { 0.00f, 4.00f, 7.00f, 12.00f }, // Major { 0.00f, 4.00f, 7.00f, 11.00f }, // Major 7th { 0.00f, 4.00f, 11.00f, 14.00f }, // Major 9th // Colour Chords { 0.00f, 5.00f, 7.00f, 12.00f }, // Sus4 { 0.00f, 2.00f, 9.00f, 16.00f }, // 69 { 0.00f, 4.00f, 7.00f, 9.00f }, // 6th { 0.00f, 7.00f, 16.00f, 23.00f }, // 10th (Spread maj7) { 0.00f, 4.00f, 7.00f, 10.00f }, // Dominant 7th { 0.00f, 7.00f, 10.00f, 13.00f }, // Dominant 7th (b9) { 0.00f, 3.00f, 6.00f, 10.00f }, // Half Diminished { 0.00f, 3.00f, 6.00f, 9.00f }, // Fully Diminished }; #else /* static */ const float ChordBank::chords_[kChordNumChords][kChordNumNotes] = { { 0.00f, 0.01f, 11.99f, 12.00f }, // OCT { 0.00f, 7.00f, 7.01f, 12.00f }, // 5 { 0.00f, 5.00f, 7.00f, 12.00f }, // sus4 { 0.00f, 3.00f, 7.00f, 12.00f }, // m { 0.00f, 3.00f, 7.00f, 10.00f }, // m7 { 0.00f, 3.00f, 10.00f, 14.00f }, // m9 { 0.00f, 3.00f, 10.00f, 17.00f }, // m11 { 0.00f, 2.00f, 9.00f, 16.00f }, // 69 { 0.00f, 4.00f, 11.00f, 14.00f }, // M9 { 0.00f, 4.00f, 7.00f, 11.00f }, // M7 { 0.00f, 4.00f, 7.00f, 12.00f }, // M }; #endif // JON_CHORDS void ChordBank::Init(BufferAllocator* allocator) { ratios_ = allocator->Allocate(kChordNumChords * kChordNumNotes); note_count_ = allocator->Allocate(kChordNumChords); sorted_ratios_ = allocator->Allocate(kChordNumNotes); chord_index_quantizer_.Init(kChordNumChords, 0.075f, false); } void ChordBank::Reset() { for (int i = 0; i < kChordNumChords; ++i) { int count = 0; for (int j = 0; j < kChordNumNotes; ++j) { ratios_[i * kChordNumNotes + j] = SemitonesToRatio(chords_[i][j]); if (chords_[i][j] != 0.01f && chords_[i][j] != 7.01f && \ chords_[i][j] != 11.99f && chords_[i][j] != 12.00f) { ++count; } } note_count_[i] = count; } Sort(); } int ChordBank::ComputeChordInversion( float inversion, float* ratios, float* amplitudes) { const float* base_ratio = this->ratios(); inversion = inversion * float(kChordNumNotes * kChordNumVoices); MAKE_INTEGRAL_FRACTIONAL(inversion); int num_rotations = inversion_integral / kChordNumNotes; int rotated_note = inversion_integral % kChordNumNotes; const float kBaseGain = 0.25f; int mask = 0; for (int i = 0; i < kChordNumNotes; ++i) { float transposition = 0.25f * static_cast( 1 << ((kChordNumNotes - 1 + inversion_integral - i) / kChordNumNotes)); int target_voice = (i - num_rotations + kChordNumVoices) % kChordNumVoices; int previous_voice = (target_voice - 1 + kChordNumVoices) % kChordNumVoices; if (i == rotated_note) { ratios[target_voice] = base_ratio[i] * transposition; ratios[previous_voice] = ratios[target_voice] * 2.0f; amplitudes[previous_voice] = kBaseGain * inversion_fractional; amplitudes[target_voice] = kBaseGain * (1.0f - inversion_fractional); } else if (i < rotated_note) { ratios[previous_voice] = base_ratio[i] * transposition; amplitudes[previous_voice] = kBaseGain; } else { ratios[target_voice] = base_ratio[i] * transposition; amplitudes[target_voice] = kBaseGain; } if (i == 0) { if (i >= rotated_note) { mask |= 1 << target_voice; } if (i <= rotated_note) { mask |= 1 << previous_voice; } } } return mask; } } // namespace plaits ================================================ FILE: lib/plaits/dsp/chords/chord_bank.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Chord bank shared by several engines. #ifndef PLAITS_DSP_CHORDS_CHORD_BANK_H_ #define PLAITS_DSP_CHORDS_CHORD_BANK_H_ #include "stmlib/dsp/hysteresis_quantizer.h" #include "stmlib/utils/buffer_allocator.h" #include namespace plaits { const int kChordNumNotes = 4; const int kChordNumVoices = kChordNumNotes + 1; #define JON_CHORDS #ifdef JON_CHORDS const int kChordNumChords = 17; #else const int kChordNumChords = 11; #endif // JON_CHORDS extern const char* const chord_names[kChordNumChords]; class ChordBank { public: ChordBank() { } ~ChordBank() { } void Init(stmlib::BufferAllocator* allocator); void Reset(); int ComputeChordInversion( float inversion, float* ratios, float* amplitudes); inline void Sort() { for (int i = 0; i < kChordNumNotes; ++i) { float r = ratio(i); while (r > 2.0f) { r *= 0.5f; } sorted_ratios_[i] = r; } std::sort(&sorted_ratios_[0], &sorted_ratios_[kChordNumNotes]); } inline void set_chord(float parameter) { chord_index_quantizer_.Process(parameter * 1.02f); } inline int chord_index() const { return chord_index_quantizer_.quantized_value(); } inline const float* ratios() const { return &ratios_[chord_index() * kChordNumNotes]; } inline float ratio(int note) const { return ratios_[chord_index() * kChordNumNotes + note]; } inline float sorted_ratio(int note) const { return sorted_ratios_[note]; } inline int num_notes() const { return note_count_[chord_index()]; } private: stmlib::HysteresisQuantizer2 chord_index_quantizer_; float* ratios_; float* sorted_ratios_; int* note_count_; static const float chords_[kChordNumChords][kChordNumNotes]; DISALLOW_COPY_AND_ASSIGN(ChordBank); }; } // namespace plaits #endif // PLAITS_DSP_CHORDS_CHORD_BANK_H_ ================================================ FILE: lib/plaits/dsp/downsampler/4x_downsampler.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // FIR Downsampler. #ifndef PLAITS_DSP_DOWNSAMPLER_4X_DOWNSAMPLER_H_ #define PLAITS_DSP_DOWNSAMPLER_4X_DOWNSAMPLER_H_ #include "stmlib/stmlib.h" #include "plaits/resources.h" namespace plaits { const size_t kOversampling = 4; class Downsampler { public: Downsampler(float* state) { head_ = *state; tail_ = 0.0f; state_ = state; } ~Downsampler() { *state_ = head_; } inline void Accumulate(int i, float sample) { head_ += sample * lut_4x_downsampler_fir[3 - (i & 3)]; tail_ += sample * lut_4x_downsampler_fir[i & 3]; } inline float Read() { float value = head_; head_ = tail_; tail_ = 0.0f; return value; } private: float head_; float tail_; float* state_; DISALLOW_COPY_AND_ASSIGN(Downsampler); }; } // namespace plaits #endif // PLAITS_DSP_DOWNSAMPLER_4X_DOWNSAMPLER_H_ ================================================ FILE: lib/plaits/dsp/drums/analog_bass_drum.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808 bass drum model, revisited. #ifndef PLAITS_DSP_DRUMS_ANALOG_BASS_DRUM_H_ #define PLAITS_DSP_DRUMS_ANALOG_BASS_DRUM_H_ #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/filter.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/units.h" #include "plaits/dsp/dsp.h" #include "plaits/dsp/oscillator/sine_oscillator.h" namespace plaits { class AnalogBassDrum { public: AnalogBassDrum() { } ~AnalogBassDrum() { } void Init() { pulse_remaining_samples_ = 0; fm_pulse_remaining_samples_ = 0; pulse_ = 0.0f; pulse_height_ = 0.0f; pulse_lp_ = 0.0f; fm_pulse_lp_ = 0.0f; retrig_pulse_ = 0.0f; lp_out_ = 0.0f; tone_lp_ = 0.0f; sustain_gain_ = 0.0f; resonator_.Init(); oscillator_.Init(); } inline float Diode(float x) { if (x >= 0.0f) { return x; } else { x *= 2.0f; return 0.7f * x / (1.0f + fabsf(x)); } } void Render( bool sustain, bool trigger, float accent, float f0, float tone, float decay, float attack_fm_amount, float self_fm_amount, float* out, size_t size) { const int kTriggerPulseDuration = 1.0e-3f * kSampleRate; const int kFMPulseDuration = 6.0e-3f * kSampleRate; const float kPulseDecayTime = 0.2e-3f * kSampleRate; const float kPulseFilterTime = 0.1e-3f * kSampleRate; const float kRetrigPulseDuration = 0.05f * kSampleRate; const float scale = 0.001f / f0; const float q = 1500.0f * stmlib::SemitonesToRatio(decay * 80.0f); const float tone_f = std::min( 4.0f * f0 * stmlib::SemitonesToRatio(tone * 108.0f), 1.0f); const float exciter_leak = 0.08f * (tone + 0.25f); if (trigger) { pulse_remaining_samples_ = kTriggerPulseDuration; fm_pulse_remaining_samples_ = kFMPulseDuration; pulse_height_ = 3.0f + 7.0f * accent; lp_out_ = 0.0f; } stmlib::ParameterInterpolator sustain_gain( &sustain_gain_, accent * decay, size); while (size--) { // Q39 / Q40 float pulse = 0.0f; if (pulse_remaining_samples_) { --pulse_remaining_samples_; pulse = pulse_remaining_samples_ ? pulse_height_ : pulse_height_ - 1.0f; pulse_ = pulse; } else { pulse_ *= 1.0f - 1.0f / kPulseDecayTime; pulse = pulse_; } if (sustain) { pulse = 0.0f; } // C40 / R163 / R162 / D83 ONE_POLE(pulse_lp_, pulse, 1.0f / kPulseFilterTime); pulse = Diode((pulse - pulse_lp_) + pulse * 0.044f); // Q41 / Q42 float fm_pulse = 0.0f; if (fm_pulse_remaining_samples_) { --fm_pulse_remaining_samples_; fm_pulse = 1.0f; // C39 / C52 retrig_pulse_ = fm_pulse_remaining_samples_ ? 0.0f : -0.8f; } else { // C39 / R161 retrig_pulse_ *= 1.0f - 1.0f / kRetrigPulseDuration; } if (sustain) { fm_pulse = 0.0f; } ONE_POLE(fm_pulse_lp_, fm_pulse, 1.0f / kPulseFilterTime); // Q43 and R170 leakage float punch = 0.7f + Diode(10.0f * lp_out_ - 1.0f); // Q43 / R165 float attack_fm = fm_pulse_lp_ * 1.7f * attack_fm_amount; float self_fm = punch * 0.08f * self_fm_amount; float f = f0 * (1.0f + attack_fm + self_fm); CONSTRAIN(f, 0.0f, 0.4f); float resonator_out; if (sustain) { oscillator_.Next(f, sustain_gain.Next(), &resonator_out, &lp_out_); } else { resonator_.set_f_q(f, 1.0f + q * f); resonator_.Process( (pulse - retrig_pulse_ * 0.2f) * scale, &resonator_out, &lp_out_); } ONE_POLE(tone_lp_, pulse * exciter_leak + resonator_out, tone_f); *out++ = tone_lp_; } } private: int pulse_remaining_samples_; int fm_pulse_remaining_samples_; float pulse_; float pulse_height_; float pulse_lp_; float fm_pulse_lp_; float retrig_pulse_; float lp_out_; float tone_lp_; float sustain_gain_; stmlib::Svf resonator_; // Replace the resonator in "free running" (sustain) mode. SineOscillator oscillator_; DISALLOW_COPY_AND_ASSIGN(AnalogBassDrum); }; } // namespace plaits #endif // PLAITS_DSP_DRUMS_ANALOG_BASS_DRUM_H_ ================================================ FILE: lib/plaits/dsp/drums/analog_snare_drum.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808 snare drum model, revisited. #ifndef PLAITS_DSP_DRUMS_ANALOG_SNARE_DRUM_H_ #define PLAITS_DSP_DRUMS_ANALOG_SNARE_DRUM_H_ #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/filter.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/units.h" #include "stmlib/utils/random.h" #include "plaits/dsp/dsp.h" #include "plaits/dsp/oscillator/sine_oscillator.h" namespace plaits { class AnalogSnareDrum { public: AnalogSnareDrum() { } ~AnalogSnareDrum() { } static const int kNumModes = 5; void Init() { pulse_remaining_samples_ = 0; pulse_ = 0.0f; pulse_height_ = 0.0f; pulse_lp_ = 0.0f; noise_envelope_ = 0.0f; sustain_gain_ = 0.0f; for (int i = 0; i < kNumModes; ++i) { resonator_[i].Init(); oscillator_[i].Init(); } noise_filter_.Init(); } void Render( bool sustain, bool trigger, float accent, float f0, float tone, float decay, float snappy, float* out, size_t size) { const float decay_xt = decay * (1.0f + decay * (decay - 1.0f)); const int kTriggerPulseDuration = 1.0e-3f * kSampleRate; const float kPulseDecayTime = 0.1e-3f * kSampleRate; const float q = 2000.0f * stmlib::SemitonesToRatio(decay_xt * 84.0f); const float noise_envelope_decay = 1.0f - 0.0017f * \ stmlib::SemitonesToRatio(-decay * (50.0f + snappy * 10.0f)); const float exciter_leak = snappy * (2.0f - snappy) * 0.1f; snappy = snappy * 1.1f - 0.05f; CONSTRAIN(snappy, 0.0f, 1.0f); if (trigger) { pulse_remaining_samples_ = kTriggerPulseDuration; pulse_height_ = 3.0f + 7.0f * accent; noise_envelope_ = 2.0f; } static const float kModeFrequencies[kNumModes] = { 1.00f, 2.00f, 3.18f, 4.16f, 5.62f}; float f[kNumModes]; float gain[kNumModes]; for (int i = 0; i < kNumModes; ++i) { f[i] = std::min(f0 * kModeFrequencies[i], 0.499f); resonator_[i].set_f_q( f[i], 1.0f + f[i] * (i == 0 ? q : q * 0.25f)); } if (tone < 0.666667f) { // 808-style (2 modes) tone *= 1.5f; gain[0] = 1.5f + (1.0f - tone) * (1.0f - tone) * 4.5f; gain[1] = 2.0f * tone + 0.15f; std::fill(&gain[2], &gain[kNumModes], 0.0f); } else { // What the 808 could have been if there were extra modes! tone = (tone - 0.666667f) * 3.0f; gain[0] = 1.5f - tone * 0.5f; gain[1] = 2.15f - tone * 0.7f; for (int i = 2; i < kNumModes; ++i) { gain[i] = tone; tone *= tone; } } float f_noise = f0 * 16.0f; CONSTRAIN(f_noise, 0.0f, 0.499f); noise_filter_.set_f_q( f_noise, 1.0f + f_noise * 1.5f); stmlib::ParameterInterpolator sustain_gain( &sustain_gain_, accent * decay, size); while (size--) { // Q45 / Q46 float pulse = 0.0f; if (pulse_remaining_samples_) { --pulse_remaining_samples_; pulse = pulse_remaining_samples_ ? pulse_height_ : pulse_height_ - 1.0f; pulse_ = pulse; } else { pulse_ *= 1.0f - 1.0f / kPulseDecayTime; pulse = pulse_; } float sustain_gain_value = sustain_gain.Next(); // R189 / C57 / R190 + C58 / C59 / R197 / R196 / IC14 ONE_POLE(pulse_lp_, pulse, 0.75f); float shell = 0.0f; for (int i = 0; i < kNumModes; ++i) { float excitation = i == 0 ? (pulse - pulse_lp_) + 0.006f * pulse : 0.026f * pulse; shell += gain[i] * (sustain ? oscillator_[i].Next(f[i]) * sustain_gain_value * 0.25f : resonator_[i].Process( excitation) + excitation * exciter_leak); } shell = stmlib::SoftClip(shell); // C56 / R194 / Q48 / C54 / R188 / D54 float noise = 2.0f * stmlib::Random::GetFloat() - 1.0f; if (noise < 0.0f) noise = 0.0f; noise_envelope_ *= noise_envelope_decay; noise *= (sustain ? sustain_gain_value : noise_envelope_) * snappy * 2.0f; // C66 / R201 / C67 / R202 / R203 / Q49 noise = noise_filter_.Process(noise); // IC13 *out++ = noise + shell * (1.0f - snappy); } } private: int pulse_remaining_samples_; float pulse_; float pulse_height_; float pulse_lp_; float noise_envelope_; float sustain_gain_; stmlib::Svf resonator_[kNumModes]; stmlib::Svf noise_filter_; // Replace the resonators in "free running" (sustain) mode. SineOscillator oscillator_[kNumModes]; DISALLOW_COPY_AND_ASSIGN(AnalogSnareDrum); }; } // namespace plaits #endif // PLAITS_DSP_DRUMS_ANALOG_SNARE_DRUM_H_ ================================================ FILE: lib/plaits/dsp/drums/hi_hat.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808 HH, with a few extra parameters to push things to the CY territory... // The template parameter MetallicNoiseSource allows another kind of "metallic // noise" to be used, for results which are more similar to KR-55 or FM hi-hats. #ifndef PLAITS_DSP_DRUMS_HI_HAT_H_ #define PLAITS_DSP_DRUMS_HI_HAT_H_ #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/filter.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/units.h" #include "stmlib/utils/random.h" #include "plaits/dsp/dsp.h" #include "plaits/dsp/oscillator/oscillator.h" namespace plaits { // 808 style "metallic noise" with 6 square oscillators. class SquareNoise { public: SquareNoise() { } ~SquareNoise() { } void Init() { std::fill(&phase_[0], &phase_[6], 0); } void Render(float f0, float* temp_1, float* temp_2, float* out, size_t size) { const float ratios[6] = { // Nominal f0: 414 Hz 1.0f, 1.304f, 1.466f, 1.787f, 1.932f, 2.536f }; uint32_t increment[6]; uint32_t phase[6]; for (int i = 0; i < 6; ++i) { float f = f0 * ratios[i]; if (f >= 0.499f) f = 0.499f; increment[i] = static_cast(f * 4294967296.0f); phase[i] = phase_[i]; } while (size--) { phase[0] += increment[0]; phase[1] += increment[1]; phase[2] += increment[2]; phase[3] += increment[3]; phase[4] += increment[4]; phase[5] += increment[5]; uint32_t noise = 0; noise += (phase[0] >> 31); noise += (phase[1] >> 31); noise += (phase[2] >> 31); noise += (phase[3] >> 31); noise += (phase[4] >> 31); noise += (phase[5] >> 31); *out++ = 0.33f * static_cast(noise) - 1.0f; } for (int i = 0; i < 6; ++i) { phase_[i] = phase[i]; } } private: uint32_t phase_[6]; DISALLOW_COPY_AND_ASSIGN(SquareNoise); }; class RingModNoise { public: RingModNoise() { } ~RingModNoise() { } void Init() { for (int i = 0; i < 6; ++i) { oscillator_[i].Init(); } } void Render(float f0, float* temp_1, float* temp_2, float* out, size_t size) { const float ratio = f0 / (0.01f + f0); const float f1a = 200.0f / kSampleRate * ratio; const float f1b = 7530.0f / kSampleRate * ratio; const float f2a = 510.0f / kSampleRate * ratio; const float f2b = 8075.0f / kSampleRate * ratio; const float f3a = 730.0f / kSampleRate * ratio; const float f3b = 10500.0f / kSampleRate * ratio; const float f[3][2] = { { f1a, f1b }, { f2a, f2b }, { f3a, f3b } }; std::fill(&out[0], &out[size], 0.0f); for (int i = 0; i < 3; ++i) { RenderPair(&oscillator_[2 * i], f[i], temp_1, temp_2, out, size); } } private: void RenderPair( Oscillator* osc, const float* f, float* temp_1, float* temp_2, float* out, size_t size) { osc[0].Render(f[0], 0.5f, temp_1, size); osc[1].Render(f[1], 0.5f, temp_2, size); while (size--) { *out++ += *temp_1++ * *temp_2++; } } Oscillator oscillator_[6]; DISALLOW_COPY_AND_ASSIGN(RingModNoise); }; class SwingVCA { public: float operator()(float s, float gain) { s *= s > 0.0f ? 4.0f : 0.1f; s = s / (1.0f + fabsf(s)); return (s + 0.1f) * gain; } }; class LinearVCA { public: float operator()(float s, float gain) { return s * gain; } }; template< typename MetallicNoiseSource, typename VCA, bool resonance, bool two_stage_envelope> class HiHat { public: HiHat() { } ~HiHat() { } void Init() { envelope_ = 0.0f; noise_clock_ = 0.0f; noise_sample_ = 0.0f; sustain_gain_ = 0.0f; metallic_noise_.Init(); noise_coloration_svf_.Init(); hpf_.Init(); } void Render( bool sustain, bool trigger, float accent, float f0, float tone, float decay, float noisiness, float* temp_1, float* temp_2, float* out, size_t size) { const float envelope_decay = 1.0f - 0.003f * stmlib::SemitonesToRatio( -decay * 84.0f); const float cut_decay = 1.0f - 0.0025f * stmlib::SemitonesToRatio( -decay * 36.0f); if (trigger) { envelope_ = (1.5f + 0.5f * (1.0f - decay)) * (0.3f + 0.7f * accent); } // Render the metallic noise. metallic_noise_.Render(2.0f * f0, temp_1, temp_2, out, size); // Apply BPF on the metallic noise. float cutoff = 150.0f / kSampleRate * stmlib::SemitonesToRatio( tone * 72.0f); CONSTRAIN(cutoff, 0.0f, 16000.0f / kSampleRate); noise_coloration_svf_.set_f_q( cutoff, resonance ? 3.0f + 3.0f * tone : 1.0f); noise_coloration_svf_.Process( out, out, size); // This is not at all part of the 808 circuit! But to add more variety, we // add a variable amount of clocked noise to the output of the 6 schmitt // trigger oscillators. noisiness *= noisiness; float noise_f = f0 * (16.0f + 16.0f * (1.0f - noisiness)); CONSTRAIN(noise_f, 0.0f, 0.5f); for (size_t i = 0; i < size; ++i) { noise_clock_ += noise_f; if (noise_clock_ >= 1.0f) { noise_clock_ -= 1.0f; noise_sample_ = stmlib::Random::GetFloat() - 0.5f; } out[i] += noisiness * (noise_sample_ - out[i]); } // Apply VCA. stmlib::ParameterInterpolator sustain_gain( &sustain_gain_, accent * decay, size); for (size_t i = 0; i < size; ++i) { VCA vca; envelope_ *= envelope_ > 0.5f || !two_stage_envelope ? envelope_decay : cut_decay; out[i] = vca(out[i], sustain ? sustain_gain.Next() : envelope_); } hpf_.set_f_q(cutoff, 0.5f); hpf_.Process(out, out, size); } private: float envelope_; float noise_clock_; float noise_sample_; float sustain_gain_; MetallicNoiseSource metallic_noise_; stmlib::Svf noise_coloration_svf_; stmlib::Svf hpf_; DISALLOW_COPY_AND_ASSIGN(HiHat); }; } // namespace plaits #endif // PLAITS_DSP_DRUMS_HI_HAT_H_ ================================================ FILE: lib/plaits/dsp/drums/synthetic_bass_drum.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Naive bass drum model (modulated oscillator with FM + envelope). // Inadvertently 909-ish. #ifndef PLAITS_DSP_DRUMS_SYNTHETIC_BASS_DRUM_H_ #define PLAITS_DSP_DRUMS_SYNTHETIC_BASS_DRUM_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/units.h" #include "stmlib/utils/random.h" #include "plaits/dsp/dsp.h" #include "plaits/dsp/oscillator/sine_oscillator.h" namespace plaits { class SyntheticBassDrumClick { public: SyntheticBassDrumClick() { } ~SyntheticBassDrumClick() { } void Init() { lp_ = 0.0f; hp_ = 0.0f; filter_.Init(); filter_.set_f_q(5000.0f / kSampleRate, 2.0f); } float Process(float in) { SLOPE(lp_, in, 0.5f, 0.1f); ONE_POLE(hp_, lp_, 0.04f); return filter_.Process(lp_ - hp_); } private: float lp_; float hp_; stmlib::Svf filter_; DISALLOW_COPY_AND_ASSIGN(SyntheticBassDrumClick); }; class SyntheticBassDrumAttackNoise { public: SyntheticBassDrumAttackNoise() { } ~SyntheticBassDrumAttackNoise() { } void Init() { lp_ = 0.0f; hp_ = 0.0f; } float Render() { float sample = stmlib::Random::GetFloat(); ONE_POLE(lp_, sample, 0.05f); ONE_POLE(hp_, lp_, 0.005f); return lp_ - hp_; } private: float lp_; float hp_; DISALLOW_COPY_AND_ASSIGN(SyntheticBassDrumAttackNoise); }; class SyntheticBassDrum { public: SyntheticBassDrum() { } ~SyntheticBassDrum() { } void Init() { phase_ = 0.0f; phase_noise_ = 0.0f; f0_ = 0.0f; fm_ = 0.0f; fm_lp_ = 0.0f; body_env_lp_ = 0.0f; body_env_ = 0.0f; body_env_pulse_width_ = 0; fm_pulse_width_ = 0; tone_lp_ = 0.0f; sustain_gain_ = 0.0f; click_.Init(); noise_.Init(); } inline float DistortedSine(float phase, float phase_noise, float dirtiness) { phase += phase_noise * dirtiness; MAKE_INTEGRAL_FRACTIONAL(phase); phase = phase_fractional; float triangle = (phase < 0.5f ? phase : 1.0f - phase) * 4.0f - 1.0f; float sine = 2.0f * triangle / (1.0f + fabsf(triangle)); float clean_sine = Sine(phase + 0.75f); return sine + (1.0f - dirtiness) * (clean_sine - sine); } inline float TransistorVCA(float s, float gain) { s = (s - 0.6f) * gain; return 3.0f * s / (2.0f + fabsf(s)) + gain * 0.3f; } void Render( bool sustain, bool trigger, float accent, float f0, float tone, float decay, float dirtiness, float fm_envelope_amount, float fm_envelope_decay, float* out, size_t size) { decay *= decay; fm_envelope_decay *= fm_envelope_decay; stmlib::ParameterInterpolator f0_mod(&f0_, f0, size); dirtiness *= std::max(1.0f - 8.0f * f0, 0.0f); const float fm_decay = 1.0f - \ 1.0f / (0.008f * (1.0f + fm_envelope_decay * 4.0f) * kSampleRate); const float body_env_decay = 1.0f - 1.0f / (0.02f * kSampleRate) * \ stmlib::SemitonesToRatio(-decay * 60.0f); const float transient_env_decay = 1.0f - 1.0f / (0.005f * kSampleRate); const float tone_f = std::min( 4.0f * f0 * stmlib::SemitonesToRatio(tone * 108.0f), 1.0f); const float transient_level = tone; if (trigger) { fm_ = 1.0f; body_env_ = transient_env_ = 0.3f + 0.7f * accent; body_env_pulse_width_ = kSampleRate * 0.001f; fm_pulse_width_ = kSampleRate * 0.0013f; } stmlib::ParameterInterpolator sustain_gain( &sustain_gain_, accent * decay, size); while (size--) { ONE_POLE(phase_noise_, stmlib::Random::GetFloat() - 0.5f, 0.002f); float mix = 0.0f; if (sustain) { phase_ += f0_mod.Next(); if (phase_ >= 1.0f) { phase_ -= 1.0f; } float body = DistortedSine(phase_, phase_noise_, dirtiness); mix -= TransistorVCA(body, sustain_gain.Next()); } else { if (fm_pulse_width_) { --fm_pulse_width_; phase_ = 0.25f; } else { fm_ *= fm_decay; float fm = 1.0f + fm_envelope_amount * 3.5f * fm_lp_; phase_ += std::min(f0_mod.Next() * fm, 0.5f); if (phase_ >= 1.0f) { phase_ -= 1.0f; } } if (body_env_pulse_width_) { --body_env_pulse_width_; } else { body_env_ *= body_env_decay; transient_env_ *= transient_env_decay; } const float envelope_lp_f = 0.1f; ONE_POLE(body_env_lp_, body_env_, envelope_lp_f); ONE_POLE(transient_env_lp_, transient_env_, envelope_lp_f); ONE_POLE(fm_lp_, fm_, envelope_lp_f); float body = DistortedSine(phase_, phase_noise_, dirtiness); float transient = click_.Process( body_env_pulse_width_ ? 0.0f : 1.0f) + noise_.Render(); mix -= TransistorVCA(body, body_env_lp_); mix -= transient * transient_env_lp_ * transient_level; } ONE_POLE(tone_lp_, mix, tone_f); *out++ = tone_lp_; } } private: float f0_; float phase_; float phase_noise_; float fm_; float fm_lp_; float body_env_; float body_env_lp_; float transient_env_; float transient_env_lp_; float sustain_gain_; float tone_lp_; SyntheticBassDrumClick click_; SyntheticBassDrumAttackNoise noise_; int body_env_pulse_width_; int fm_pulse_width_; DISALLOW_COPY_AND_ASSIGN(SyntheticBassDrum); }; } // namespace plaits #endif // PLAITS_DSP_DRUMS_SYNTHETIC_BASS_DRUM_H_ ================================================ FILE: lib/plaits/dsp/drums/synthetic_snare_drum.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Naive snare drum model (two modulated oscillators + filtered noise). // Uses a few magic numbers taken from the 909 schematics: // - Ratio between the two modes of the drum set to 1.47. // - Funky coupling between the two modes. // - Noise coloration filters and envelope shapes for the snare. #ifndef PLAITS_DSP_DRUMS_SYNTHETIC_SNARE_DRUM_H_ #define PLAITS_DSP_DRUMS_SYNTHETIC_SNARE_DRUM_H_ #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/units.h" #include "plaits/dsp/dsp.h" namespace plaits { class SyntheticSnareDrum { public: SyntheticSnareDrum() { } ~SyntheticSnareDrum() { } void Init() { phase_[0] = 0.0f; phase_[1] = 0.0f; drum_amplitude_ = 0.0f; snare_amplitude_ = 0.0f; fm_ = 0.0f; hold_counter_ = 0; sustain_gain_ = 0.0f; drum_lp_.Init(); snare_hp_.Init(); snare_lp_.Init(); } inline float DistortedSine(float phase) { float triangle = (phase < 0.5f ? phase : 1.0f - phase) * 4.0f - 1.3f; return 2.0f * triangle / (1.0f + fabsf(triangle)); } void Render( bool sustain, bool trigger, float accent, float f0, float fm_amount, float decay, float snappy, float* out, size_t size) { const float decay_xt = decay * (1.0f + decay * (decay - 1.0f)); fm_amount *= fm_amount; const float drum_decay = 1.0f - 1.0f / (0.015f * kSampleRate) * \ stmlib::SemitonesToRatio( -decay_xt * 72.0f - fm_amount * 12.0f + snappy * 7.0f); const float snare_decay = 1.0f - 1.0f / (0.01f * kSampleRate) * \ stmlib::SemitonesToRatio(-decay * 60.0f - snappy * 7.0f); const float fm_decay = 1.0f - 1.0f / (0.007f * kSampleRate); snappy = snappy * 1.1f - 0.05f; CONSTRAIN(snappy, 0.0f, 1.0f); const float drum_level = stmlib::Sqrt(1.0f - snappy); const float snare_level = stmlib::Sqrt(snappy); const float snare_f_min = std::min(10.0f * f0, 0.5f); const float snare_f_max = std::min(35.0f * f0, 0.5f); snare_hp_.set_f(snare_f_min); snare_lp_.set_f_q(snare_f_max, 0.5f + 2.0f * snappy); drum_lp_.set_f(3.0f * f0); if (trigger) { snare_amplitude_ = drum_amplitude_ = 0.3f + 0.7f * accent; fm_ = 1.0f; phase_[0] = phase_[1] = 0.0f; hold_counter_ = static_cast((0.04f + decay * 0.03f) * kSampleRate); } stmlib::ParameterInterpolator sustain_gain( &sustain_gain_, accent * decay, size); while (size--) { if (sustain) { snare_amplitude_ = sustain_gain.Next(); drum_amplitude_ = snare_amplitude_; fm_ = 0.0f; } else { // Compute all D envelopes. // The envelope for the drum has a very long tail. // The envelope for the snare has a "hold" stage which lasts between // 40 and 70 ms drum_amplitude_ *= (drum_amplitude_ > 0.03f || !(size & 1)) ? drum_decay : 1.0f; if (hold_counter_) { --hold_counter_; } else { snare_amplitude_ *= snare_decay; } fm_ *= fm_decay; } // The 909 circuit has a funny kind of oscillator coupling - the signal // leaving Q40's collector and resetting all oscillators allow some // intermodulation. float reset_noise = 0.0f; float reset_noise_amount = (0.125f - f0) * 8.0f; CONSTRAIN(reset_noise_amount, 0.0f, 1.0f); reset_noise_amount *= reset_noise_amount; reset_noise_amount *= fm_amount; reset_noise += phase_[0] > 0.5f ? -1.0f : 1.0f; reset_noise += phase_[1] > 0.5f ? -1.0f : 1.0f; reset_noise *= reset_noise_amount * 0.025f; float f = f0 * (1.0f + fm_amount * (4.0f * fm_)); phase_[0] += f; phase_[1] += f * 1.47f; if (reset_noise_amount > 0.1f) { if (phase_[0] >= 1.0f + reset_noise) { phase_[0] = 1.0f - phase_[0]; } if (phase_[1] >= 1.0f + reset_noise) { phase_[1] = 1.0f - phase_[1]; } } else { if (phase_[0] >= 1.0f) { phase_[0] -= 1.0f; } if (phase_[1] >= 1.0f) { phase_[1] -= 1.0f; } } float drum = -0.1f; drum += DistortedSine(phase_[0]) * 0.60f; drum += DistortedSine(phase_[1]) * 0.25f; drum *= drum_amplitude_ * drum_level; drum = drum_lp_.Process(drum); float noise = stmlib::Random::GetFloat(); float snare = snare_lp_.Process(noise); snare = snare_hp_.Process(snare); snare = (snare + 0.1f) * (snare_amplitude_ + fm_) * snare_level; *out++ = snare + drum; // It's a snare, it's a drum, it's a snare drum. } } private: float phase_[2]; float drum_amplitude_; float snare_amplitude_; float fm_; float sustain_gain_; int hold_counter_; stmlib::OnePole drum_lp_; stmlib::OnePole snare_hp_; stmlib::Svf snare_lp_; DISALLOW_COPY_AND_ASSIGN(SyntheticSnareDrum); }; } // namespace plaits #endif // PLAITS_DSP_DRUMS_SYNTHETIC_SNARE_DRUM_H_ ================================================ FILE: lib/plaits/dsp/dsp.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Utility DSP routines. #ifndef PLAITS_DSP_DSP_H_ #define PLAITS_DSP_DSP_H_ #include "stmlib/stmlib.h" namespace plaits { static const float kSampleRate = 48000.0f; // There is no proper PLL for I2S, only a divider on the system clock to derive // the bit clock. // The division ratio is set to 47 (23 EVEN, 1 ODD) by the ST libraries. // // Bit clock = 72000000 / 47 = 1531.91 kHz // Frame clock = Bit clock / 32 = 47872.34 Hz // // That's only 4.6 cts of error, but we care! static const float kCorrectedSampleRate = kSampleRate; //[eh2k] 47872.34f; const float a0 = (440.0f / 8.0f) / kCorrectedSampleRate; const size_t kMaxBlockSize = 24; const size_t kBlockSize = 12; } // namespace plaits #endif // PLAITS_DSP_DSP_H_ ================================================ FILE: lib/plaits/dsp/engine/additive_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Additive synthesis with 32 partials. #include "plaits/dsp/engine/additive_engine.h" #include #include "stmlib/dsp/cosine_oscillator.h" #include "plaits/dsp/oscillator/sine_oscillator.h" namespace plaits { using namespace std; using namespace stmlib; void AdditiveEngine::Init(BufferAllocator* allocator) { amplitudes_ = allocator->Allocate(kNumHarmonics); for (int i = 0; i < kNumHarmonicOscillators; ++i) { harmonic_oscillator_[i].Init(); } } void AdditiveEngine::Reset() { fill( &litudes_[0], &litudes_[kNumHarmonics], 0.0f); } void AdditiveEngine::UpdateAmplitudes( float centroid, float slope, float bumps, float* amplitudes, const int* harmonic_indices, size_t num_harmonics) { const float n = (static_cast(num_harmonics) - 1.0f); const float margin = (1.0f / slope - 1.0f) / (1.0f + bumps); const float center = centroid * (n + margin) - 0.5f * margin; float sum = 0.001f; for (size_t i = 0; i < num_harmonics; ++i) { float order = fabsf(static_cast(i) - center) * slope; float gain = 1.0f - order; gain += fabsf(gain); gain *= gain; float b = 0.25f + order * bumps; float bump_factor = 1.0f + Sine(b); gain *= bump_factor; gain *= gain; gain *= gain; int j = harmonic_indices[i]; // Warning about the following line: this is not a proper LP filter because // of the normalization. But in spite of its strange working, this line // turns out to be absolutely essential. // // I have tried both normalizing the LP-ed spectrum, and LP-ing the // normalized spectrum, and both of them cause more annoyances than this // "incorrect" solution. ONE_POLE(amplitudes[j], gain, 0.001f); sum += amplitudes[j]; } sum = 1.0f / sum; for (size_t i = 0; i < num_harmonics; ++i) { amplitudes[harmonic_indices[i]] *= sum; } } inline float Bump(float x, float centroid, float slope) { float d = fabsf(x - centroid); float bump = 1.0f - d * slope; return bump + fabsf(bump); } const int integer_harmonics[24] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }; const int organ_harmonics[8] = { 0, 1, 2, 3, 5, 7, 9, 11 }; void AdditiveEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { const float f0 = NoteToFrequency(parameters.note); const float centroid = parameters.timbre; const float raw_bumps = parameters.harmonics; const float raw_slope = (1.0f - 0.6f * raw_bumps) * parameters.morph; const float slope = 0.01f + 1.99f * raw_slope * raw_slope * raw_slope; const float bumps = 16.0f * raw_bumps * raw_bumps; UpdateAmplitudes( centroid, slope, bumps, &litudes_[0], integer_harmonics, 24); harmonic_oscillator_[0].Render<1>(f0, &litudes_[0], out, size); harmonic_oscillator_[1].Render<13>(f0, &litudes_[12], out, size); UpdateAmplitudes( centroid, slope, bumps, &litudes_[24], organ_harmonics, 8); harmonic_oscillator_[2].Render<1>(f0, &litudes_[24], aux, size); } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/additive_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Additive synthesis with 24+8 partials. #ifndef PLAITS_DSP_ENGINE_ADDITIVE_ENGINE_H_ #define PLAITS_DSP_ENGINE_ADDITIVE_ENGINE_H_ #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/oscillator/harmonic_oscillator.h" namespace plaits { const int kHarmonicBatchSize = 12; const int kNumHarmonics = 36; const int kNumHarmonicOscillators = kNumHarmonics / kHarmonicBatchSize; class AdditiveEngine : public Engine { public: AdditiveEngine() { } ~AdditiveEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: void UpdateAmplitudes( float centroid, float slope, float bumps, float* amplitudes, const int* harmonic_indices, size_t num_harmonics); HarmonicOscillator harmonic_oscillator_[kNumHarmonicOscillators]; float* amplitudes_; DISALLOW_COPY_AND_ASSIGN(AdditiveEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_ADDITIVE_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/bass_drum_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808 and synthetic bass drum generators. #include "plaits/dsp/engine/bass_drum_engine.h" #include namespace plaits { using namespace std; using namespace stmlib; void BassDrumEngine::Init(BufferAllocator* allocator) { analog_bass_drum_.Init(); synthetic_bass_drum_.Init(); overdrive_.Init(); } void BassDrumEngine::Reset() { } void BassDrumEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { const float f0 = NoteToFrequency(parameters.note); const float attack_fm_amount = min(parameters.harmonics * 4.0f, 1.0f); const float self_fm_amount = max(min(parameters.harmonics * 4.0f - 1.0f, 1.0f), 0.0f); const float drive = max(parameters.harmonics * 2.0f - 1.0f, 0.0f) * \ max(1.0f - 16.0f * f0, 0.0f); const bool sustain = parameters.trigger & TRIGGER_UNPATCHED; if(out) { analog_bass_drum_.Render( sustain, parameters.trigger & TRIGGER_RISING_EDGE, parameters.accent, f0, parameters.timbre, parameters.morph, attack_fm_amount, self_fm_amount, out, size); overdrive_.Process( 0.5f + 0.5f * drive, out, size); } if(aux) synthetic_bass_drum_.Render( sustain, parameters.trigger & TRIGGER_RISING_EDGE, parameters.accent, f0, parameters.timbre, parameters.morph, sustain ? parameters.harmonics : 0.4f - 0.25f * parameters.morph * parameters.morph, min(parameters.harmonics * 2.0f, 1.0f), max(parameters.harmonics * 2.0f - 1.0f, 0.0f), aux, size); } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/bass_drum_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808 and synthetic bass drum generators. #ifndef PLAITS_DSP_ENGINE_BASS_DRUM_ENGINE_H_ #define PLAITS_DSP_ENGINE_BASS_DRUM_ENGINE_H_ #include "plaits/dsp/drums/analog_bass_drum.h" #include "plaits/dsp/drums/synthetic_bass_drum.h" #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/fx/overdrive.h" #include "plaits/dsp/fx/sample_rate_reducer.h" namespace plaits { class BassDrumEngine : public Engine { public: BassDrumEngine() { } ~BassDrumEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: AnalogBassDrum analog_bass_drum_; SyntheticBassDrum synthetic_bass_drum_; Overdrive overdrive_; DISALLOW_COPY_AND_ASSIGN(BassDrumEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_BASS_DRUM_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/chord_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Chords: wavetable and divide-down organ/string machine. #include "plaits/dsp/engine/chord_engine.h" #include #include "plaits/resources.h" namespace plaits { using namespace std; using namespace stmlib; void ChordEngine::Init(BufferAllocator* allocator) { for (int i = 0; i < kChordNumVoices; ++i) { divide_down_voice_[i].Init(); wavetable_voice_[i].Init(); } chords_.Init(allocator); morph_lp_ = 0.0f; timbre_lp_ = 0.0f; } void ChordEngine::Reset() { chords_.Reset(); } const float fade_point[kChordNumVoices] = { 0.55f, 0.47f, 0.49f, 0.51f, 0.53f }; const int kRegistrationTableSize = 8; const float registrations[kRegistrationTableSize][kChordNumHarmonics * 2] = { { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f }, // Square { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }, // Saw { 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f }, // Saw + saw { 0.33f, 0.0f, 0.33f, 0.0f, 0.33f, 0.0f }, // Full saw { 0.33f, 0.0f, 0.0f, 0.33f, 0.0f, 0.33f }, // Full saw + square hybrid { 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f }, // Saw + high square harmo { 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f }, // Square + high square harmo { 0.0f, 0.1f, 0.1f, 0.0f, 0.2f, 0.6f }, // // Saw+square + high harmo }; void ChordEngine::ComputeRegistration( float registration, float* amplitudes) { registration *= (kRegistrationTableSize - 1.001f); MAKE_INTEGRAL_FRACTIONAL(registration); for (int i = 0; i < kChordNumHarmonics * 2; ++i) { float a = registrations[registration_integral][i]; float b = registrations[registration_integral + 1][i]; amplitudes[i] = a + (b - a) * registration_fractional; } } #define WAVE(bank, row, column) &wav_integrated_waves[(bank * 64 + row * 8 + column) * 132] const int16_t* const wavetable[] = { WAVE(2, 6, 1), WAVE(2, 6, 6), WAVE(2, 6, 4), WAVE(0, 6, 0), WAVE(0, 6, 1), WAVE(0, 6, 2), WAVE(0, 6, 7), WAVE(2, 4, 7), WAVE(2, 4, 6), WAVE(2, 4, 5), WAVE(2, 4, 4), WAVE(2, 4, 3), WAVE(2, 4, 2), WAVE(2, 4, 1), WAVE(2, 4, 0), }; void ChordEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { ONE_POLE(morph_lp_, parameters.morph, 0.1f); ONE_POLE(timbre_lp_, parameters.timbre, 0.1f); /*[eh2k] Sorry for the hack :-) chords_.set_chord(parameters.harmonics); */ float harmonics[kChordNumHarmonics * 2 + 2]; float note_amplitudes[kChordNumVoices]; float registration = max(1.0f - morph_lp_ * 2.15f, 0.0f); ComputeRegistration(registration, harmonics); harmonics[kChordNumHarmonics * 2] = 0.0f; float ratios[kChordNumVoices]; int aux_note_mask = chords_.ComputeChordInversion( timbre_lp_, ratios, note_amplitudes); fill(&out[0], &out[size], 0.0f); fill(&aux[0], &aux[size], 0.0f); const float f0 = NoteToFrequency(parameters.note) * 0.998f; const float waveform = max((morph_lp_ - 0.535f) * 2.15f, 0.0f); for (int note = 0; note < kChordNumVoices; ++note) { float wavetable_amount = 50.0f * (morph_lp_ - fade_point[note]); CONSTRAIN(wavetable_amount, 0.0f, 1.0f); float divide_down_amount = 1.0f - wavetable_amount; float* destination = (1 << note) & aux_note_mask ? aux : out; const float note_f0 = f0 * ratios[note]; float divide_down_gain = 4.0f - note_f0 * 32.0f; CONSTRAIN(divide_down_gain, 0.0f, 1.0f); divide_down_amount *= divide_down_gain; if (wavetable_amount) { wavetable_voice_[note].Render( note_f0 * 1.004f, note_amplitudes[note] * wavetable_amount, waveform, wavetable, destination, size); } if (divide_down_amount) { divide_down_voice_[note].Render( note_f0, harmonics, note_amplitudes[note] * divide_down_amount, destination, size); } } for (size_t i = 0; i < size; ++i) { out[i] += aux[i]; aux[i] *= 3.0f; } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/chord_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Chords: wavetable and divide-down organ/string machine. #ifndef PLAITS_DSP_ENGINE_CHORD_ENGINE_H_ #define PLAITS_DSP_ENGINE_CHORD_ENGINE_H_ #include "plaits/dsp/chords/chord_bank.h" #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/oscillator/string_synth_oscillator.h" #include "plaits/dsp/oscillator/wavetable_oscillator.h" namespace plaits { const int kChordNumHarmonics = 3; class ChordEngine : public Engine { public: ChordEngine() { } ~ChordEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: void ComputeRegistration(float registration, float* amplitudes); int ComputeChordInversion( float inversion, float* ratios, float* amplitudes); StringSynthOscillator divide_down_voice_[kChordNumVoices]; WavetableOscillator<128, 15> wavetable_voice_[kChordNumVoices]; ChordBank chords_; float morph_lp_; float timbre_lp_; DISALLOW_COPY_AND_ASSIGN(ChordEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_CHORD_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Base class for all engines. #ifndef PLAITS_DSP_ENGINE_ENGINE_H_ #define PLAITS_DSP_ENGINE_ENGINE_H_ #include "plaits/dsp/dsp.h" #include "stmlib/dsp/units.h" #include "stmlib/utils/buffer_allocator.h" namespace plaits { inline float NoteToFrequency(float midi_note) { midi_note -= 9.0f; CONSTRAIN(midi_note, -128.0f, 127.0f); return a0 * 0.25f * stmlib::SemitonesToRatio(midi_note); } enum TriggerState { TRIGGER_LOW = 0, TRIGGER_RISING_EDGE = 1, TRIGGER_UNPATCHED = 2, TRIGGER_HIGH = 4, }; struct EngineParameters { int trigger; float note; float timbre; float morph; float harmonics; float accent; }; struct PostProcessingSettings { // A negative value indicates that a limiter must be used. float out_gain; float aux_gain; // When this flag is set to true, the engine declares that it will // render a signal that already has an envelope (eg: modal drum, 808 kick). // By reporting this information, the synthesis voice upstream will // bypass the internal envelope/LPG. // // This parameter can be changed on a per-call basis when calling Render() // This is used by the speech synthesis engine, which renders either // a continuous vowel sound (which needs to be enveloped by the LPG) // or a word/sentence (which is already enveloped). bool already_enveloped; }; class Engine { public: Engine() { } ~Engine() { } virtual void Init(stmlib::BufferAllocator* allocator) = 0; virtual void Reset() = 0; virtual void LoadUserData(const uint8_t* user_data) = 0; virtual void Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) = 0; PostProcessingSettings post_processing_settings; }; template class EngineRegistry { public: EngineRegistry() { } ~EngineRegistry() { } void Init() { num_engines_ = 0; } inline Engine* get(int index) { return engine_[index]; } void RegisterInstance( Engine* instance, bool already_enveloped, float out_gain, float aux_gain) { if (num_engines_ >= max_size) { return; } engine_[num_engines_] = instance; PostProcessingSettings* s = &instance->post_processing_settings; s->already_enveloped = already_enveloped; s->out_gain = out_gain; s->aux_gain = aux_gain; ++num_engines_; } inline int size() const { return num_engines_; } private: Engine* engine_[max_size]; int num_engines_; }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/fm_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Classic 2-op FM found in Braids, Rings and Elements. #include "plaits/dsp/engine/fm_engine.h" #include "stmlib/dsp/parameter_interpolator.h" #include "plaits/dsp/oscillator/sine_oscillator.h" #include "plaits/dsp/downsampler/4x_downsampler.h" namespace plaits { using namespace stmlib; void FMEngine::Init(BufferAllocator* allocator) { carrier_phase_ = 0; modulator_phase_ = 0; sub_phase_ = 0; previous_carrier_frequency_ = a0; previous_modulator_frequency_ = a0; previous_amount_ = 0.0f; previous_feedback_ = 0.0f; previous_sample_ = 0.0f; } void FMEngine::Reset() { } void FMEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { // 4x oversampling const float note = parameters.note - 24.0f; const float ratio = Interpolate( lut_fm_frequency_quantizer, parameters.harmonics, 128.0f); float modulator_note = note + ratio; float target_modulator_frequency = NoteToFrequency(modulator_note); CONSTRAIN(target_modulator_frequency, 0.0f, 0.5f); // Reduce the maximum FM index for high pitched notes, to prevent aliasing. float hf_taming = 1.0f - (modulator_note - 72.0f) * 0.025f; CONSTRAIN(hf_taming, 0.0f, 1.0f); hf_taming *= hf_taming; ParameterInterpolator carrier_frequency( &previous_carrier_frequency_, NoteToFrequency(note), size); ParameterInterpolator modulator_frequency( &previous_modulator_frequency_, target_modulator_frequency, size); ParameterInterpolator amount_modulation( &previous_amount_, 2.0f * parameters.timbre * parameters.timbre * hf_taming, size); ParameterInterpolator feedback_modulation( &previous_feedback_, 2.0f * parameters.morph - 1.0f, size); Downsampler carrier_downsampler(&carrier_fir_); Downsampler sub_downsampler(&sub_fir_); while (size--) { const float max_uint32 = 4294967296.0f; const float amount = amount_modulation.Next(); const float feedback = feedback_modulation.Next(); float phase_feedback = feedback < 0.0f ? 0.5f * feedback * feedback : 0.0f; const uint32_t carrier_increment = static_cast( max_uint32 * carrier_frequency.Next()); float _modulator_frequency = modulator_frequency.Next(); for (size_t j = 0; j < kOversampling; ++j) { modulator_phase_ += static_cast(max_uint32 * \ _modulator_frequency * (1.0f + previous_sample_ * phase_feedback)); carrier_phase_ += carrier_increment; sub_phase_ += carrier_increment >> 1; float modulator_fb = feedback > 0.0f ? 0.25f * feedback * feedback : 0.0f; float modulator = SinePM( modulator_phase_, modulator_fb * previous_sample_); float carrier = SinePM(carrier_phase_, amount * modulator); float sub = SinePM(sub_phase_, amount * carrier * 0.25f); ONE_POLE(previous_sample_, carrier, 0.05f); carrier_downsampler.Accumulate(j, carrier); sub_downsampler.Accumulate(j, sub); } *out++ = carrier_downsampler.Read(); *aux++ = sub_downsampler.Read(); } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/fm_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Classic 2-op FM, as found in Braids, Rings and Elements. #ifndef PLAITS_DSP_ENGINE_FM_ENGINE_H_ #define PLAITS_DSP_ENGINE_FM_ENGINE_H_ #include "plaits/dsp/engine/engine.h" namespace plaits { class FMEngine : public Engine { public: FMEngine() { } ~FMEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: uint32_t carrier_phase_; uint32_t modulator_phase_; uint32_t sub_phase_; float previous_carrier_frequency_; float previous_modulator_frequency_; float previous_amount_; float previous_feedback_; float previous_sample_; float sub_fir_; float carrier_fir_; DISALLOW_COPY_AND_ASSIGN(FMEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_FM_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/grain_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Windowed sine segments. #include #include "plaits/dsp/engine/grain_engine.h" namespace plaits { using namespace std; using namespace stmlib; void GrainEngine::Init(BufferAllocator* allocator) { grainlet_[0].Init(); grainlet_[1].Init(); // vosim_oscillator_.Init(); z_oscillator_.Init(); dc_blocker_[0].Init(); dc_blocker_[1].Init(); } void GrainEngine::Reset() { } void GrainEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { const float root = parameters.note; const float f0 = NoteToFrequency(root); const float f1 = NoteToFrequency(24.0f + 84.0f * parameters.timbre); const float ratio = SemitonesToRatio(-24.0f + 48.0f * parameters.harmonics); const float carrier_bleed = parameters.harmonics < 0.5f ? 1.0f - 2.0f * parameters.harmonics : 0.0f; const float carrier_bleed_fixed = carrier_bleed * (2.0f - carrier_bleed); const float carrier_shape = 0.33f + (parameters.morph - 0.33f) * \ max(1.0f - f0 * 24.0f, 0.0f); grainlet_[0].Render(f0, f1, carrier_shape, carrier_bleed_fixed, out, size); grainlet_[1].Render(f0, f1 * ratio, carrier_shape, carrier_bleed_fixed, aux, size); dc_blocker_[0].set_f(0.3f * f0); for (size_t i = 0; i < size; ++i) { out[i] = dc_blocker_[0].Process(out[i] + aux[i]); } const float cutoff = NoteToFrequency(root + 96.0f * parameters.timbre); z_oscillator_.Render( f0, cutoff, parameters.morph, parameters.harmonics, aux, size); dc_blocker_[1].set_f(0.3f * f0); dc_blocker_[1].Process(aux, size); } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/grain_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Windowed sine segments. #ifndef PLAITS_DSP_ENGINE_GRAIN_ENGINE_H_ #define PLAITS_DSP_ENGINE_GRAIN_ENGINE_H_ #include "stmlib/dsp/filter.h" #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/oscillator/grainlet_oscillator.h" #include "plaits/dsp/oscillator/vosim_oscillator.h" #include "plaits/dsp/oscillator/z_oscillator.h" namespace plaits { class GrainEngine : public Engine { public: GrainEngine() { } ~GrainEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: GrainletOscillator grainlet_[2]; // VOSIMOscillator vosim_oscillator_; ZOscillator z_oscillator_; stmlib::OnePole dc_blocker_[2]; float grain_balance_; DISALLOW_COPY_AND_ASSIGN(GrainEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_GRAIN_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/hi_hat_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808-style HH with two noise sources - one faithful to the original, the other // more metallic. #include "plaits/dsp/engine/hi_hat_engine.h" namespace plaits { using namespace stmlib; void HiHatEngine::Init(BufferAllocator* allocator) { hi_hat_1_.Init(); hi_hat_2_.Init(); temp_buffer_ = allocator->Allocate(kMaxBlockSize * 2); } void HiHatEngine::Reset() { } void HiHatEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { const float f0 = NoteToFrequency(parameters.note); if(out) hi_hat_1_.Render( parameters.trigger & TRIGGER_UNPATCHED, parameters.trigger & TRIGGER_RISING_EDGE, parameters.accent, f0, parameters.timbre, parameters.morph, parameters.harmonics, temp_buffer_, temp_buffer_ + size, out, size); if(aux) hi_hat_2_.Render( parameters.trigger & TRIGGER_UNPATCHED, parameters.trigger & TRIGGER_RISING_EDGE, parameters.accent, f0, parameters.timbre, parameters.morph, parameters.harmonics, temp_buffer_, temp_buffer_ + size, aux, size); } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/hi_hat_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808-style HH with two noise sources - one faithful to the original, the other // more metallic. #ifndef PLAITS_DSP_ENGINE_HI_HAT_ENGINE_H_ #define PLAITS_DSP_ENGINE_HI_HAT_ENGINE_H_ #include "plaits/dsp/drums/hi_hat.h" #include "plaits/dsp/engine/engine.h" namespace plaits { class HiHatEngine : public Engine { public: HiHatEngine() { } ~HiHatEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: HiHat hi_hat_1_; HiHat hi_hat_2_; float* temp_buffer_; DISALLOW_COPY_AND_ASSIGN(HiHatEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_HI_HAT_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/modal_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // One voice of modal synthesis. #include "plaits/dsp/engine/modal_engine.h" #include namespace plaits { using namespace std; using namespace stmlib; void ModalEngine::Init(BufferAllocator* allocator) { temp_buffer_ = allocator->Allocate(kMaxBlockSize); harmonics_lp_ = 0.0f; Reset(); } void ModalEngine::Reset() { voice_.Init(); } void ModalEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { fill(&out[0], &out[size], 0.0f); fill(&aux[0], &aux[size], 0.0f); ONE_POLE(harmonics_lp_, parameters.harmonics, 0.01f); voice_.Render( parameters.trigger & TRIGGER_UNPATCHED, parameters.trigger & TRIGGER_RISING_EDGE, parameters.accent, NoteToFrequency(parameters.note), harmonics_lp_, parameters.timbre, parameters.morph, temp_buffer_, out, aux, size); } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/modal_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // One voice of modal synthesis. #ifndef PLAITS_DSP_ENGINE_MODAL_ENGINE_H_ #define PLAITS_DSP_ENGINE_MODAL_ENGINE_H_ #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/physical_modelling/modal_voice.h" namespace plaits { class ModalEngine : public Engine { public: ModalEngine() { } ~ModalEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: ModalVoice voice_; float* temp_buffer_; float harmonics_lp_; DISALLOW_COPY_AND_ASSIGN(ModalEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_MODAL_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/noise_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Clocked noise processed by a multimode filter. #include "plaits/dsp/engine/noise_engine.h" #include "stmlib/dsp/parameter_interpolator.h" namespace plaits { using namespace std; using namespace stmlib; void NoiseEngine::Init(BufferAllocator* allocator) { clocked_noise_[0].Init(); clocked_noise_[1].Init(); lp_hp_filter_.Init(); bp_filter_[0].Init(); bp_filter_[1].Init(); previous_f0_ = 0.0f; previous_f1_ = 0.0f; previous_q_ = 0.0f; previous_mode_ = 0.0f; temp_buffer_ = allocator->Allocate(kMaxBlockSize); } void NoiseEngine::Reset() { } void NoiseEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { const float f0 = NoteToFrequency(parameters.note); const float f1 = NoteToFrequency( parameters.note + parameters.harmonics * 48.0f - 24.0f); const float clock_lowest_note = parameters.trigger & TRIGGER_UNPATCHED ? 0.0f : -24.0f; const float clock_f = NoteToFrequency( parameters.timbre * (128.0f - clock_lowest_note) + clock_lowest_note); const float q = 0.5f * SemitonesToRatio(parameters.morph * 120.0f); const bool sync = parameters.trigger & TRIGGER_RISING_EDGE; clocked_noise_[0].Render(sync, clock_f, aux, size); clocked_noise_[1].Render(sync, clock_f * f1 / f0, temp_buffer_, size); ParameterInterpolator f0_modulation(&previous_f0_, f0, size); ParameterInterpolator f1_modulation(&previous_f1_, f1, size); ParameterInterpolator q_modulation(&previous_q_, q, size); ParameterInterpolator mode_modulation( &previous_mode_, parameters.harmonics, size); const float* in_1 = aux; const float* in_2 = temp_buffer_; while (size--) { const float f0 = f0_modulation.Next(); const float f1 = f1_modulation.Next(); const float q = q_modulation.Next(); const float gain = 1.0f / Sqrt((0.5f + q) * 40.0f * f0); lp_hp_filter_.set_f_q(f0, q); bp_filter_[0].set_f_q(f0, q); bp_filter_[1].set_f_q(f1, q); float input_1 = *in_1++ * gain; float input_2 = *in_2++ * gain; lp_hp_filter_.ProcessMultimodeLPtoHP( &input_1, out++, 1, mode_modulation.Next()); *aux++ = bp_filter_[0].Process(input_1) + \ bp_filter_[1].Process(input_2); } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/noise_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Clocked noise processed by a multimode filter. #ifndef PLAITS_DSP_ENGINE_NOISE_ENGINE_H_ #define PLAITS_DSP_ENGINE_NOISE_ENGINE_H_ #include "stmlib/dsp/filter.h" #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/noise/clocked_noise.h" namespace plaits { class NoiseEngine : public Engine { public: NoiseEngine() { } ~NoiseEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: ClockedNoise clocked_noise_[2]; stmlib::Svf lp_hp_filter_; stmlib::Svf bp_filter_[2]; float previous_f0_; float previous_f1_; float previous_q_; float previous_mode_; float* temp_buffer_; DISALLOW_COPY_AND_ASSIGN(NoiseEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_NOISE_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/particle_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Clocked noise processed by a filter. #include "plaits/dsp/engine/particle_engine.h" #include namespace plaits { using namespace std; using namespace stmlib; void ParticleEngine::Init(BufferAllocator* allocator) { for (int i = 0; i < kNumParticles; ++i) { particle_[i].Init(); } diffuser_.Init(allocator->Allocate(8192)); post_filter_.Init(); } void ParticleEngine::Reset() { diffuser_.Reset(); } void ParticleEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { const float f0 = NoteToFrequency(parameters.note); const float density_sqrt = NoteToFrequency( 60.0f + parameters.timbre * parameters.timbre * 72.0f); const float density = density_sqrt * density_sqrt * (1.0f / kNumParticles); const float gain = 1.0f / density; const float q_sqrt = SemitonesToRatio(parameters.morph >= 0.5f ? (parameters.morph - 0.5f) * 120.0f : 0.0f); const float q = 0.5f + q_sqrt * q_sqrt; const float spread = 48.0f * parameters.harmonics * parameters.harmonics; const float raw_diffusion_sqrt = 2.0f * fabsf(parameters.morph - 0.5f); const float raw_diffusion = raw_diffusion_sqrt * raw_diffusion_sqrt; const float diffusion = parameters.morph < 0.5f ? raw_diffusion : 0.0f; const bool sync = parameters.trigger & TRIGGER_RISING_EDGE; fill(&out[0], &out[size], 0.0f); fill(&aux[0], &aux[size], 0.0f); for (int i = 0; i < kNumParticles; ++i) { particle_[i].Render( sync, density, gain, f0, spread, q, out, aux, size); } post_filter_.set_f_q(min(f0, 0.49f), 0.5f); post_filter_.Process(out, out, size); diffuser_.Process( 0.8f * diffusion * diffusion, 0.5f * diffusion + 0.25f, out, size); } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/particle_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Filtered random pulses. #ifndef PLAITS_DSP_ENGINE_PARTICLE_ENGINE_H_ #define PLAITS_DSP_ENGINE_PARTICLE_ENGINE_H_ #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/fx/diffuser.h" #include "plaits/dsp/noise/particle.h" namespace plaits { const int kNumParticles = 6; class ParticleEngine : public Engine { public: ParticleEngine() { } ~ParticleEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: Particle particle_[kNumParticles]; Diffuser diffuser_; stmlib::Svf post_filter_; DISALLOW_COPY_AND_ASSIGN(ParticleEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_PARTICLE_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/snare_drum_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808 and synthetic snare drum generators. #include "plaits/dsp/engine/snare_drum_engine.h" #include namespace plaits { using namespace std; using namespace stmlib; void SnareDrumEngine::Init(BufferAllocator* allocator) { analog_snare_drum_.Init(); synthetic_snare_drum_.Init(); } void SnareDrumEngine::Reset() { } void SnareDrumEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { const float f0 = NoteToFrequency(parameters.note); if(out) analog_snare_drum_.Render( parameters.trigger & TRIGGER_UNPATCHED, parameters.trigger & TRIGGER_RISING_EDGE, parameters.accent, f0, parameters.timbre, parameters.morph, parameters.harmonics, out, size); if(aux) synthetic_snare_drum_.Render( parameters.trigger & TRIGGER_UNPATCHED, parameters.trigger & TRIGGER_RISING_EDGE, parameters.accent, f0, parameters.timbre, parameters.morph, parameters.harmonics, aux, size); } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/snare_drum_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 808 and synthetic snare drum generators. #ifndef PLAITS_DSP_ENGINE_SNARE_DRUM_ENGINE_H_ #define PLAITS_DSP_ENGINE_SNARE_DRUM_ENGINE_H_ #include "plaits/dsp/drums/analog_snare_drum.h" #include "plaits/dsp/drums/synthetic_snare_drum.h" #include "plaits/dsp/engine/engine.h" namespace plaits { class SnareDrumEngine : public Engine { public: SnareDrumEngine() { } ~SnareDrumEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: AnalogSnareDrum analog_snare_drum_; SyntheticSnareDrum synthetic_snare_drum_; DISALLOW_COPY_AND_ASSIGN(SnareDrumEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_SNARE_DRUM_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/speech_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Various flavours of speech synthesis. #include "plaits/dsp/engine/speech_engine.h" #include "plaits/dsp/speech/lpc_speech_synth_words.h" namespace plaits { using namespace std; using namespace stmlib; void SpeechEngine::Init(BufferAllocator* allocator) { sam_speech_synth_.Init(); naive_speech_synth_.Init(); lpc_speech_synth_word_bank_.Init( word_banks_, LPC_SPEECH_SYNTH_NUM_WORD_BANKS, allocator); lpc_speech_synth_controller_.Init(&lpc_speech_synth_word_bank_); word_bank_quantizer_.Init(LPC_SPEECH_SYNTH_NUM_WORD_BANKS + 1, 0.1f, false); temp_buffer_[0] = allocator->Allocate(kMaxBlockSize); temp_buffer_[1] = allocator->Allocate(kMaxBlockSize); prosody_amount_ = 0.0f; speed_ = 0.0f; } void SpeechEngine::Reset() { lpc_speech_synth_word_bank_.Reset(); } void SpeechEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { const float f0 = NoteToFrequency(parameters.note); const float group = parameters.harmonics * 6.0f; // Interpolates between the 3 models: naive, SAM, LPC. if (group <= 2.0f) { *already_enveloped = false; float blend = group; if (group <= 1.0f) { naive_speech_synth_.Render( parameters.trigger == TRIGGER_RISING_EDGE, f0, parameters.morph, parameters.timbre, temp_buffer_[0], aux, out, size); } else { lpc_speech_synth_controller_.Render( parameters.trigger & TRIGGER_UNPATCHED, parameters.trigger & TRIGGER_RISING_EDGE, -1, f0, 0.0f, 0.0f, parameters.morph, parameters.timbre, 1.0f, aux, out, size); blend = 2.0f - blend; } sam_speech_synth_.Render( parameters.trigger == TRIGGER_RISING_EDGE, f0, parameters.morph, parameters.timbre, temp_buffer_[0], temp_buffer_[1], size); blend *= blend * (3.0f - 2.0f * blend); blend *= blend * (3.0f - 2.0f * blend); for (size_t i = 0; i < size; ++i) { aux[i] += (temp_buffer_[0][i] - aux[i]) * blend; out[i] += (temp_buffer_[1][i] - out[i]) * blend; } } else { // Change phonemes/words for LPC. const int word_bank = word_bank_quantizer_.Process( (group - 2.0f) * 0.275f) - 1; const bool replay_prosody = word_bank >= 0 && \ !(parameters.trigger & TRIGGER_UNPATCHED); *already_enveloped = replay_prosody; lpc_speech_synth_controller_.Render( parameters.trigger & TRIGGER_UNPATCHED, parameters.trigger & TRIGGER_RISING_EDGE, word_bank, f0, prosody_amount_, speed_, parameters.morph, parameters.timbre, replay_prosody ? parameters.accent : 1.0f, aux, out, size); } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/speech_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Various flavours of speech synthesis. #ifndef PLAITS_DSP_ENGINE_SPEECH_ENGINE_H_ #define PLAITS_DSP_ENGINE_SPEECH_ENGINE_H_ #include "stmlib/dsp/hysteresis_quantizer.h" #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/speech/lpc_speech_synth_controller.h" #include "plaits/dsp/speech/naive_speech_synth.h" #include "plaits/dsp/speech/sam_speech_synth.h" namespace plaits { class SpeechEngine : public Engine { public: SpeechEngine() { } ~SpeechEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); inline void set_prosody_amount(float prosody_amount) { prosody_amount_ = prosody_amount; } inline void set_speed(float speed) { speed_ = speed; } private: stmlib::HysteresisQuantizer2 word_bank_quantizer_; NaiveSpeechSynth naive_speech_synth_; SAMSpeechSynth sam_speech_synth_; LPCSpeechSynthController lpc_speech_synth_controller_; LPCSpeechSynthWordBank lpc_speech_synth_word_bank_; float* temp_buffer_[2]; float prosody_amount_; float speed_; DISALLOW_COPY_AND_ASSIGN(SpeechEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_SPEECH_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/string_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Three voices of string synthesis. #include "plaits/dsp/engine/string_engine.h" #include namespace plaits { using namespace std; using namespace stmlib; void StringEngine::Init(BufferAllocator* allocator) { temp_buffer_ = allocator->Allocate(kMaxBlockSize); for (int i = 0; i < kNumStrings; ++i) { voice_[i].Init(allocator); f0_[i] = 0.01f; } active_string_ = kNumStrings - 1; f0_delay_.Init(allocator->Allocate(16)); } void StringEngine::Reset() { f0_delay_.Reset(); for (int i = 0; i < kNumStrings; ++i) { voice_[i].Reset(); } } void StringEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { if (parameters.trigger & TRIGGER_RISING_EDGE) { // 8 in original firmware version. // 05.01.18: mic.w: problem with microbrute. f0_[active_string_] = f0_delay_.Read(14); active_string_ = (active_string_ + 1) % kNumStrings; } const float f0 = NoteToFrequency(parameters.note); f0_[active_string_] = f0; f0_delay_.Write(f0); fill(&out[0], &out[size], 0.0f); fill(&aux[0], &aux[size], 0.0f); for (int i = 0; i < kNumStrings; ++i) { voice_[i].Render( parameters.trigger & TRIGGER_UNPATCHED && i == active_string_, parameters.trigger & TRIGGER_RISING_EDGE && i == active_string_, parameters.accent, f0_[i], parameters.harmonics, parameters.timbre * parameters.timbre, parameters.morph, temp_buffer_, out, aux, size); } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/string_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Three voices of string synthesis. #ifndef PLAITS_DSP_ENGINE_STRING_ENGINE_H_ #define PLAITS_DSP_ENGINE_STRING_ENGINE_H_ #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/physical_modelling/string_voice.h" namespace plaits { const int kNumStrings = 3; class StringEngine : public Engine { public: StringEngine() { } ~StringEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: StringVoice voice_[kNumStrings]; float f0_[kNumStrings]; DelayLine f0_delay_; int active_string_; float* temp_buffer_; DISALLOW_COPY_AND_ASSIGN(StringEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_STRING_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/swarm_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Swarm of sawtooths and sines. #include "plaits/dsp/engine/swarm_engine.h" #include namespace plaits { using namespace std; using namespace stmlib; void SwarmEngine::Init(BufferAllocator* allocator) { swarm_voice_ = allocator->Allocate(kNumSwarmVoices); } void SwarmEngine::Reset() { const float n = (kNumSwarmVoices - 1) / 2; for (int i = 0; i < kNumSwarmVoices; ++i) { float rank = (static_cast(i) - n) / n; swarm_voice_[i].Init(rank); } } void SwarmEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { const float f0 = NoteToFrequency(parameters.note); const float control_rate = static_cast(size); const float density = NoteToFrequency(parameters.timbre * 120.0f) * \ 0.025f * control_rate; const float spread = parameters.harmonics * parameters.harmonics * \ parameters.harmonics; float size_ratio = 0.25f * SemitonesToRatio( (1.0f - parameters.morph) * 84.0f); const bool burst_mode = !(parameters.trigger & TRIGGER_UNPATCHED); const bool start_burst = parameters.trigger & TRIGGER_RISING_EDGE; fill(&out[0], &out[size], 0.0f); fill(&aux[0], &aux[size], 0.0f); for (int i = 0; i < kNumSwarmVoices; ++i) { swarm_voice_[i].Render( f0, density, burst_mode, start_burst, spread, size_ratio, out, aux, size); size_ratio *= 0.97f; } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/swarm_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Swarm of sawtooths and sines. #ifndef PLAITS_DSP_ENGINE_SWARM_ENGINE_H_ #define PLAITS_DSP_ENGINE_SWARM_ENGINE_H_ #include "stmlib/dsp/polyblep.h" #include "stmlib/dsp/units.h" #include "stmlib/utils/random.h" #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/oscillator/oscillator.h" #include "plaits/dsp/oscillator/string_synth_oscillator.h" #include "plaits/dsp/oscillator/sine_oscillator.h" #include "plaits/resources.h" namespace plaits { const int kNumSwarmVoices = 8; class GrainEnvelope { public: GrainEnvelope() { } ~GrainEnvelope() { } void Init() { from_ = 0.0f; interval_ = 1.0f; phase_ = 1.0f; fm_ = 0.0f; amplitude_ = 0.5f; previous_size_ratio_ = 0.0f; filter_coefficient_ = 0.0f; } inline void Step(float rate, bool burst_mode, bool start_burst) { bool randomize = false; if (start_burst) { phase_ = 0.5f; fm_ = 16.0f; randomize = true; } else { phase_ += rate * fm_; if (phase_ >= 1.0f) { phase_ -= static_cast(static_cast(phase_)); randomize = true; } } if (randomize) { from_ += interval_; interval_ = stmlib::Random::GetFloat() - from_; // Randomize the duration of the grain. if (burst_mode) { fm_ *= 0.8f + 0.2f * stmlib::Random::GetFloat(); } else { fm_ = 0.5f + 1.5f * stmlib::Random::GetFloat(); } } } inline float frequency(float size_ratio) const { // We approximate two overlapping grains of frequencies f1 and f2 // By a continuous tone ramping from f1 to f2. This allows a continuous // transition between the "grain cloud" and "swarm of glissandi" textures. if (size_ratio < 1.0f) { return 2.0f * (from_ + interval_ * phase_) - 1.0f; } else { return from_; } } inline float amplitude(float size_ratio) { float target_amplitude = 1.0f; if (size_ratio >= 1.0f) { float phase = (phase_ - 0.5f) * size_ratio; CONSTRAIN(phase, -1.0f, 1.0f); float e = Sine(0.5f * phase + 1.25f); target_amplitude = 0.5f * (e + 1.0f); } if ((size_ratio >= 1.0f) ^ (previous_size_ratio_ >= 1.0f)) { filter_coefficient_ = 0.5f; } filter_coefficient_ *= 0.95f; previous_size_ratio_ = size_ratio; ONE_POLE(amplitude_, target_amplitude, 0.5f - filter_coefficient_); return amplitude_; } private: float from_; float interval_; float phase_; float fm_; float amplitude_; float previous_size_ratio_; float filter_coefficient_; DISALLOW_COPY_AND_ASSIGN(GrainEnvelope); }; class AdditiveSawOscillator { public: AdditiveSawOscillator() { } ~AdditiveSawOscillator() { } inline void Init() { phase_ = 0.0f; next_sample_ = 0.0f; frequency_ = 0.01f; gain_ = 0.0f; } inline void Render( float frequency, float level, float* out, size_t size) { if (frequency >= kMaxFrequency) { frequency = kMaxFrequency; } stmlib::ParameterInterpolator fm(&frequency_, frequency, size); stmlib::ParameterInterpolator gain(&gain_, level, size); float next_sample = next_sample_; float phase = phase_; while (size--) { float this_sample = next_sample; next_sample = 0.0f; const float frequency = fm.Next(); phase += frequency; if (phase >= 1.0f) { phase -= 1.0f; float t = phase / frequency; this_sample -= stmlib::ThisBlepSample(t); next_sample -= stmlib::NextBlepSample(t); } next_sample += phase; *out++ += (2.0f * this_sample - 1.0f) * gain.Next(); } phase_ = phase; next_sample_ = next_sample; } private: // Oscillator state. float phase_; float next_sample_; // For interpolation of parameters. float frequency_; float gain_; DISALLOW_COPY_AND_ASSIGN(AdditiveSawOscillator); }; class SwarmVoice { public: SwarmVoice() { } ~SwarmVoice() { } void Init(float rank) { rank_ = rank; envelope_.Init(); saw_.Init(); sine_.Init(); } void Render( float f0, float density, bool burst_mode, bool start_burst, float spread, float size_ratio, float* saw, float* sine, size_t size) { envelope_.Step(density, burst_mode, start_burst); const float scale = 1.0f / kNumSwarmVoices; const float amplitude = envelope_.amplitude(size_ratio) * scale; const float expo_amount = envelope_.frequency(size_ratio); f0 *= stmlib::SemitonesToRatio(48.0f * expo_amount * spread * rank_); const float linear_amount = rank_ * (rank_ + 0.01f) * spread * 0.25f; f0 *= 1.0f + linear_amount; saw_.Render(f0, amplitude, saw, size); sine_.Render(f0, amplitude, sine, size); }; private: float rank_; GrainEnvelope envelope_; AdditiveSawOscillator saw_; FastSineOscillator sine_; }; class SwarmEngine : public Engine { public: SwarmEngine() { } ~SwarmEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: SwarmVoice* swarm_voice_; DISALLOW_COPY_AND_ASSIGN(SwarmEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_SWARM_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/virtual_analog_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 2 variable shape oscillators with sync, FM and crossfading. #include "plaits/dsp/engine/virtual_analog_engine.h" #include #include "stmlib/dsp/parameter_interpolator.h" namespace plaits { using namespace std; using namespace stmlib; void VirtualAnalogEngine::Init(BufferAllocator* allocator) { primary_.Init(); auxiliary_.Init(); auxiliary_.set_master_phase(0.25f); sync_.Init(); variable_saw_.Init(); auxiliary_amount_ = 0.0f; xmod_amount_ = 0.0f; temp_buffer_ = allocator->Allocate(kMaxBlockSize); } void VirtualAnalogEngine::Reset() { } const float intervals[5] = { 0.0f, 7.01f, 12.01f, 19.01f, 24.01f }; inline float Squash(float x) { return x * x * (3.0f - 2.0f * x); } float VirtualAnalogEngine::ComputeDetuning(float detune) const { detune = 2.05f * detune - 1.025f; CONSTRAIN(detune, -1.0f, 1.0f); float sign = detune < 0.0f ? -1.0f : 1.0f; detune = detune * sign * 3.9999f; MAKE_INTEGRAL_FRACTIONAL(detune); float a = intervals[detune_integral]; float b = intervals[detune_integral + 1]; return (a + (b - a) * Squash(Squash(detune_fractional))) * sign; } void VirtualAnalogEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { #if VA_VARIANT == 0 // 1 = variable waveshape controlled by TIMBRE. // 2 = variable waveshape controlled by MORPH, detuned by HARMONICS. // OUT = 1 + 2. // AUX = 1 + sync 2. const float auxiliary_detune = ComputeDetuning(parameters.harmonics); const float primary_f = NoteToFrequency(parameters.note); const float auxiliary_f = NoteToFrequency(parameters.note + auxiliary_detune); const float sync_f = NoteToFrequency( parameters.note + parameters.harmonics * 48.0f); float shape_1 = parameters.timbre * 1.5f; CONSTRAIN(shape_1, 0.0f, 1.0f); float pw_1 = 0.5f + (parameters.timbre - 0.66f) * 1.4f; CONSTRAIN(pw_1, 0.5f, 0.99f); float shape_2 = parameters.morph * 1.5f; CONSTRAIN(shape_2, 0.0f, 1.0f); float pw_2 = 0.5f + (parameters.morph - 0.66f) * 1.4f; CONSTRAIN(pw_2, 0.5f, 0.99f); primary_.Render(primary_f, pw_1, shape_1, temp_buffer_, size); auxiliary_.Render(auxiliary_f, pw_2, shape_2, aux, size); for (size_t i = 0; i < size; ++i) { out[i] = (aux[i] + temp_buffer_[i]) * 0.5f; } sync_.Render(primary_f, sync_f, pw_2, shape_2, aux, size); for (size_t i = 0; i < size; ++i) { aux[i] = (aux[i] + temp_buffer_[i]) * 0.5f; } #elif VA_VARIANT == 1 // 1 = variable waveshape controlled by MORPH. // 2 = variable waveshape controlled by MORPH. // OUT = crossfade between 1 + 2, 1, 1 sync 2 controlled by TIMBRE. // AUX = 2. float auxiliary_amount = max(0.5f - parameters.timbre, 0.0f) * 2.0f; auxiliary_amount *= auxiliary_amount * 0.5f; const float xmod_amount = max(parameters.timbre - 0.5f, 0.0f) * 2.0f; const float squashed_xmod_amount = xmod_amount * (2.0f - xmod_amount); const float auxiliary_detune = ComputeDetuning(parameters.harmonics); const float primary_f = NoteToFrequency(parameters.note); const float auxiliary_f = NoteToFrequency(parameters.note + auxiliary_detune); const float sync_f = primary_f * SemitonesToRatio( xmod_amount * (auxiliary_detune + 36.0f)); float shape = parameters.morph * 1.5f; CONSTRAIN(shape, 0.0f, 1.0f); float pw = 0.5f + (parameters.morph - 0.66f) * 1.4f; CONSTRAIN(pw, 0.5f, 0.99f); primary_.Render(primary_f, pw, shape, out, size); sync_.Render(primary_f, sync_f, pw, shape, aux, size); ParameterInterpolator xmod_amount_modulation( &xmod_amount_, squashed_xmod_amount * (2.0f - squashed_xmod_amount), size); for (size_t i = 0; i < size; ++i) { out[i] += (aux[i] - out[i]) * xmod_amount_modulation.Next(); } auxiliary_.Render(auxiliary_f, pw, shape, aux, size); ParameterInterpolator auxiliary_amount_modulation( &auxiliary_amount_, auxiliary_amount, size); for (size_t i = 0; i < size; ++i) { out[i] += (aux[i] - out[i]) * auxiliary_amount_modulation.Next(); } #elif VA_VARIANT == 2 // 1 = variable square controlled by TIMBRE. // 2 = variable saw controlled by MORPH. // OUT = 1 + 2. // AUX = dual variable waveshape controlled by MORPH, self sync by TIMBRE. const float sync_amount = parameters.timbre * parameters.timbre; const float auxiliary_detune = ComputeDetuning(parameters.harmonics); const float primary_f = NoteToFrequency(parameters.note); const float auxiliary_f = NoteToFrequency(parameters.note + auxiliary_detune); const float primary_sync_f = NoteToFrequency( parameters.note + sync_amount * 48.0f); const float auxiliary_sync_f = NoteToFrequency( parameters.note + auxiliary_detune + sync_amount * 48.0f); float shape = parameters.morph * 1.5f; CONSTRAIN(shape, 0.0f, 1.0f); float pw = 0.5f + (parameters.morph - 0.66f) * 1.46f; CONSTRAIN(pw, 0.5f, 0.995f); // Render monster sync to AUX. primary_.Render(primary_f, primary_sync_f, pw, shape, out, size); auxiliary_.Render(auxiliary_f, auxiliary_sync_f, pw, shape, aux, size); for (size_t i = 0; i < size; ++i) { aux[i] = (aux[i] - out[i]) * 0.5f; } // Render double varishape to OUT. float square_pw = 1.3f * parameters.timbre - 0.15f; CONSTRAIN(square_pw, 0.005f, 0.5f); const float square_sync_ratio = parameters.timbre < 0.5f ? 0.0f : (parameters.timbre - 0.5f) * (parameters.timbre - 0.5f) * 4.0f * 48.0f; const float square_gain = min(parameters.timbre * 8.0f, 1.0f); float saw_pw = parameters.morph < 0.5f ? parameters.morph + 0.5f : 1.0f - (parameters.morph - 0.5f) * 2.0f; saw_pw *= 1.1f; CONSTRAIN(saw_pw, 0.005f, 1.0f); float saw_shape = 10.0f - 21.0f * parameters.morph; CONSTRAIN(saw_shape, 0.0f, 1.0f); float saw_gain = 8.0f * (1.0f - parameters.morph); CONSTRAIN(saw_gain, 0.02f, 1.0f); const float square_sync_f = NoteToFrequency( parameters.note + square_sync_ratio); sync_.Render( primary_f, square_sync_f, square_pw, 1.0f, temp_buffer_, size); variable_saw_.Render(auxiliary_f, saw_pw, saw_shape, out, size); float norm = 1.0f / (std::max(square_gain, saw_gain)); ParameterInterpolator square_gain_modulation( &auxiliary_amount_, square_gain * 0.3f * norm, size); ParameterInterpolator saw_gain_modulation( &xmod_amount_, saw_gain * 0.5f * norm, size); for (size_t i = 0; i < size; ++i) { out[i] = out[i] * saw_gain_modulation.Next() + \ square_gain_modulation.Next() * temp_buffer_[i]; } #endif // VA_VARIANT values } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/virtual_analog_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 2 variable shape oscillators with sync and crossfading. #ifndef PLAITS_DSP_ENGINE_VIRTUAL_ANALOG_ENGINE_H_ #define PLAITS_DSP_ENGINE_VIRTUAL_ANALOG_ENGINE_H_ #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/oscillator/variable_saw_oscillator.h" #include "plaits/dsp/oscillator/variable_shape_oscillator.h" #define VA_VARIANT 2 namespace plaits { class VirtualAnalogEngine : public Engine { public: VirtualAnalogEngine() { } ~VirtualAnalogEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: float ComputeDetuning(float detune) const; VariableShapeOscillator primary_; VariableShapeOscillator auxiliary_; VariableShapeOscillator sync_; VariableSawOscillator variable_saw_; float auxiliary_amount_; float xmod_amount_; float* temp_buffer_; DISALLOW_COPY_AND_ASSIGN(VirtualAnalogEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_VIRTUAL_ANALOG_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/waveshaping_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Slope -> Waveshaper -> Wavefolder. #include "plaits/dsp/engine/waveshaping_engine.h" #include #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/utils/dsp.h" #include "plaits/dsp/oscillator/sine_oscillator.h" #include "plaits/resources.h" namespace plaits { using namespace std; using namespace stmlib; void WaveshapingEngine::Init(BufferAllocator* allocator) { slope_.Init(); triangle_.Init(); previous_shape_ = 0.0f; previous_wavefolder_gain_ = 0.0f; previous_overtone_gain_ = 0.0f; } void WaveshapingEngine::Reset() { } float Tame(float f0, float harmonics, float order) { f0 *= harmonics; float max_f = 0.5f / order; float max_amount = 1.0f - (f0 - max_f) / (0.5f - max_f); CONSTRAIN(max_amount, 0.0f, 1.0f); return max_amount * max_amount * max_amount; } void WaveshapingEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { const float root = parameters.note; const float f0 = NoteToFrequency(root); const float pw = parameters.morph * 0.45f + 0.5f; // Start from bandlimited slope signal. slope_.Render(f0, pw, out, size); triangle_.Render(f0, 0.5f, aux, size); // Try to estimate how rich the spectrum is, and reduce the range of the // waveshaping control accordingly. const float slope = 3.0f + fabsf(parameters.morph - 0.5f) * 5.0f; const float shape_amount = fabsf(parameters.harmonics - 0.5f) * 2.0f; const float shape_amount_attenuation = Tame(f0, slope, 16.0f); const float wavefolder_gain = parameters.timbre; const float wavefolder_gain_attenuation = Tame( f0, slope * (3.0f + shape_amount * shape_amount_attenuation * 5.0f), 12.0f); // Apply waveshaper / wavefolder. ParameterInterpolator shape_modulation( &previous_shape_, 0.5f + (parameters.harmonics - 0.5f) * shape_amount_attenuation, size); ParameterInterpolator wf_gain_modulation( &previous_wavefolder_gain_, 0.03f + 0.46f * wavefolder_gain * wavefolder_gain_attenuation, size); const float overtone_gain = parameters.timbre * (2.0f - parameters.timbre); ParameterInterpolator overtone_gain_modulation( &previous_overtone_gain_, overtone_gain * (2.0f - overtone_gain), size); for (size_t i = 0; i < size; ++i) { float shape = shape_modulation.Next() * 3.9999f; MAKE_INTEGRAL_FRACTIONAL(shape); const int16_t* shape_1 = lookup_table_i16_table[shape_integral]; const int16_t* shape_2 = lookup_table_i16_table[shape_integral + 1]; float ws_index = 127.0f * out[i] + 128.0f; MAKE_INTEGRAL_FRACTIONAL(ws_index) ws_index_integral &= 255; float x0 = static_cast(shape_1[ws_index_integral]) / 32768.0f; float x1 = static_cast(shape_1[ws_index_integral + 1]) / 32768.0f; float x = x0 + (x1 - x0) * ws_index_fractional; float y0 = static_cast(shape_2[ws_index_integral]) / 32768.0f; float y1 = static_cast(shape_2[ws_index_integral + 1]) / 32768.0f; float y = y0 + (y1 - y0) * ws_index_fractional; float mix = x + (y - x) * shape_fractional; float index = mix * wf_gain_modulation.Next() + 0.5f; float fold = InterpolateHermite( lut_fold + 1, index, 512.0f); float fold_2 = -InterpolateHermite( lut_fold_2 + 1, index, 512.0f); float sine = Sine(aux[i] * 0.25f + 0.5f); out[i] = fold; aux[i] = sine + (fold_2 - sine) * overtone_gain_modulation.Next(); } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/waveshaping_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Slope -> Waveshaper -> Wavefolder. #ifndef PLAITS_DSP_ENGINE_WAVESHAPING_ENGINE_H_ #define PLAITS_DSP_ENGINE_WAVESHAPING_ENGINE_H_ #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/oscillator/oscillator.h" namespace plaits { class WaveshapingEngine : public Engine { public: WaveshapingEngine() { } ~WaveshapingEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: Oscillator slope_; Oscillator triangle_; float previous_shape_; float previous_wavefolder_gain_; float previous_overtone_gain_; DISALLOW_COPY_AND_ASSIGN(WaveshapingEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_WAVESHAPING_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine/wavetable_engine.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 8x8x3 wave terrain. #include "plaits/dsp/engine/wavetable_engine.h" #include #include "plaits/resources.h" namespace plaits { using namespace std; using namespace stmlib; const int kNumBanks = 4; const int kNumWavesPerBank = 64; const int kNumWaves = 192; const int kNumCustomWaves = 15; const size_t kTableSize = 128; const float kTableSizeF = float(kTableSize); void WavetableEngine::Init(BufferAllocator* allocator) { phase_ = 0.0f; x_lp_ = 0.0f; y_lp_ = 0.0f; z_lp_ = 0.0f; x_pre_lp_ = 0.0f; y_pre_lp_ = 0.0f; z_pre_lp_ = 0.0f; previous_x_ = 0.0f; previous_y_ = 0.0f; previous_z_ = 0.0f; previous_f0_ = a0; diff_out_.Init(); wave_map_ = allocator->Allocate(kNumWavesPerBank); } void WavetableEngine::Reset() { } void WavetableEngine::LoadUserData(const uint8_t* user_data) { for (int bank = 0; bank < kNumBanks; ++bank) { for (int wave = 0; wave < kNumWavesPerBank; ++wave) { int i = bank * kNumWavesPerBank + wave; int w = i; if (bank == kNumBanks - 1) { w = user_data ? user_data[wave] : (w * 101 % kNumWaves); } const int16_t* base = wav_integrated_waves; if (w >= kNumWaves) { base = (const int16_t*)(user_data + 64); w = min(w - kNumWaves, kNumCustomWaves); } wave_map_[i] = base + size_t(w) * (kTableSize + 4); } } } inline float Clamp(float x, float amount) { x = x - 0.5f; x *= amount; CONSTRAIN(x, -0.5f, 0.5f); x += 0.5f; return x; } inline float WavetableEngine::ReadWave( int x, int y, int z, int phase_integral, float phase_fractional) { return InterpolateWaveHermite( wave_map_[x + y * 8 + z * kNumWavesPerBank], phase_integral, phase_fractional); } void WavetableEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { const float f0 = NoteToFrequency(parameters.note); ONE_POLE(x_pre_lp_, parameters.timbre * 6.9999f, 0.2f); ONE_POLE(y_pre_lp_, parameters.morph * 6.9999f, 0.2f); ONE_POLE(z_pre_lp_, parameters.harmonics * 6.9999f, 0.05f); const float x = x_pre_lp_; const float y = y_pre_lp_; const float z = z_pre_lp_; const float quantization = min(max(z - 3.0f, 0.0f), 1.0f); const float lp_coefficient = min( max(2.0f * f0 * (4.0f - 3.0f * quantization), 0.01f), 0.1f); MAKE_INTEGRAL_FRACTIONAL(x); MAKE_INTEGRAL_FRACTIONAL(y); MAKE_INTEGRAL_FRACTIONAL(z); x_fractional += quantization * (Clamp(x_fractional, 16.0f) - x_fractional); y_fractional += quantization * (Clamp(y_fractional, 16.0f) - y_fractional); z_fractional += quantization * (Clamp(z_fractional, 16.0f) - z_fractional); ParameterInterpolator x_modulation( &previous_x_, static_cast(x_integral) + x_fractional, size); ParameterInterpolator y_modulation( &previous_y_, static_cast(y_integral) + y_fractional, size); ParameterInterpolator z_modulation( &previous_z_, static_cast(z_integral) + z_fractional, size); ParameterInterpolator f0_modulation(&previous_f0_, f0, size); while (size--) { const float f0 = f0_modulation.Next(); const float gain = (1.0f / (f0 * 131072.0f)) * (0.95f - f0); const float cutoff = min(kTableSizeF * f0, 1.0f); ONE_POLE(x_lp_, x_modulation.Next(), lp_coefficient); ONE_POLE(y_lp_, y_modulation.Next(), lp_coefficient); ONE_POLE(z_lp_, z_modulation.Next(), lp_coefficient); const float x = x_lp_; const float y = y_lp_; const float z = z_lp_; MAKE_INTEGRAL_FRACTIONAL(x); MAKE_INTEGRAL_FRACTIONAL(y); MAKE_INTEGRAL_FRACTIONAL(z); phase_ += f0; if (phase_ >= 1.0f) { phase_ -= 1.0f; } const float p = phase_ * kTableSizeF; MAKE_INTEGRAL_FRACTIONAL(p); { int x0 = x_integral; int x1 = x_integral + 1; int y0 = y_integral; int y1 = y_integral + 1; int z0 = z_integral; int z1 = z_integral + 1; if (z0 >= 4) { z0 = 7 - z0; } if (z1 >= 4) { z1 = 7 - z1; } float x0y0z0 = ReadWave(x0, y0, z0, p_integral, p_fractional); float x1y0z0 = ReadWave(x1, y0, z0, p_integral, p_fractional); float xy0z0 = x0y0z0 + (x1y0z0 - x0y0z0) * x_fractional; float x0y1z0 = ReadWave(x0, y1, z0, p_integral, p_fractional); float x1y1z0 = ReadWave(x1, y1, z0, p_integral, p_fractional); float xy1z0 = x0y1z0 + (x1y1z0 - x0y1z0) * x_fractional; float xyz0 = xy0z0 + (xy1z0 - xy0z0) * y_fractional; float x0y0z1 = ReadWave(x0, y0, z1, p_integral, p_fractional); float x1y0z1 = ReadWave(x1, y0, z1, p_integral, p_fractional); float xy0z1 = x0y0z1 + (x1y0z1 - x0y0z1) * x_fractional; float x0y1z1 = ReadWave(x0, y1, z1, p_integral, p_fractional); float x1y1z1 = ReadWave(x1, y1, z1, p_integral, p_fractional); float xy1z1 = x0y1z1 + (x1y1z1 - x0y1z1) * x_fractional; float xyz1 = xy0z1 + (xy1z1 - xy0z1) * y_fractional; float mix = xyz0 + (xyz1 - xyz0) * z_fractional; mix = diff_out_.Process(cutoff, mix) * gain; *out++ = mix; *aux++ = static_cast(static_cast(mix * 32.0f)) / 32.0f; } } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine/wavetable_engine.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 8x8x3 wave terrain. #ifndef PLAITS_DSP_ENGINE_WAVETABLE_ENGINE_H_ #define PLAITS_DSP_ENGINE_WAVETABLE_ENGINE_H_ #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/oscillator/wavetable_oscillator.h" namespace plaits { class WavetableEngine : public Engine { public: WavetableEngine() { } ~WavetableEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data); virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: float ReadWave(int x, int y, int z, int phase_i, float phase_f); float phase_; float x_pre_lp_; float y_pre_lp_; float z_pre_lp_; float x_lp_; float y_lp_; float z_lp_; float previous_x_; float previous_y_; float previous_z_; float previous_f0_; // Maps a (bank, X, Y) coordinate to a waveform index. // This allows all waveforms to be reshuffled by the user to create new maps. const int16_t** wave_map_; Differentiator diff_out_; DISALLOW_COPY_AND_ASSIGN(WavetableEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_WAVETABLE_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine2/arpeggiator.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Arpeggiator. #ifndef PLAITS_DSP_ENGINE_ARPEGGIATOR_H_ #define PLAITS_DSP_ENGINE_ARPEGGIATOR_H_ #include "stmlib/utils/random.h" namespace plaits { enum ArpeggiatorMode { ARPEGGIATOR_MODE_UP, ARPEGGIATOR_MODE_DOWN, ARPEGGIATOR_MODE_UP_DOWN, ARPEGGIATOR_MODE_RANDOM, ARPEGGIATOR_MODE_LAST }; class Arpeggiator{ public: Arpeggiator() { } ~Arpeggiator() { } void Init() { mode_ = ARPEGGIATOR_MODE_UP; Reset(); } void Reset() { note_ = 0; octave_ = 0; direction_ = 1; } void set_mode(ArpeggiatorMode mode) { mode_ = mode; } void set_range(int range) { range_ = range; } inline int note() const { return note_; } inline int octave() const { return octave_; } void Clock(int num_notes) { if (num_notes == 1 && range_ == 1) { note_ = octave_ = 0; return; } if (mode_ == ARPEGGIATOR_MODE_RANDOM) { while (true) { uint32_t w = stmlib::Random::GetWord(); int octave = (w >> 4) % range_; int note = (w >> 20) % num_notes; if (octave != octave_ || note != note_) { octave_ = octave; note_ = note; break; } } return; } if (mode_ == ARPEGGIATOR_MODE_UP) { direction_ = 1; } if (mode_ == ARPEGGIATOR_MODE_DOWN) { direction_ = -1; } note_ += direction_; bool done = false; while (!done) { done = true; if (note_ >= num_notes || note_ < 0) { octave_ += direction_; note_= direction_ > 0 ? 0 : num_notes - 1; } if (octave_ >= range_ || octave_ < 0) { octave_ = direction_ > 0 ? 0 : range_ - 1; if (mode_ == ARPEGGIATOR_MODE_UP_DOWN) { direction_ = -direction_; note_ = direction_ > 0 ? 1 : num_notes - 2; octave_ = direction_ > 0 ? 0 : range_ - 1; done = false; } } } } private: ArpeggiatorMode mode_; int range_; int note_; int octave_; int direction_; DISALLOW_COPY_AND_ASSIGN(Arpeggiator); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_ARPEGGIATOR_H_ ================================================ FILE: lib/plaits/dsp/engine2/chiptune_engine.cc ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Chiptune waveforms with arpeggiator. #include "plaits/dsp/engine2/chiptune_engine.h" #include namespace plaits { using namespace std; using namespace stmlib; void ChiptuneEngine::Init(BufferAllocator* allocator) { bass_.Init(); for (int i = 0; i < kChordNumNotes; ++i) { voice_[i].Init(); } chords_.Init(allocator); arpeggiator_.Init(); arpeggiator_pattern_selector_.Init(12, 0.075f, false); envelope_shape_ = NO_ENVELOPE; envelope_state_ = 0.0f; aux_envelope_amount_ = 0.0f; } void ChiptuneEngine::Reset() { chords_.Reset(); } void ChiptuneEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { const float f0 = NoteToFrequency(parameters.note); const float shape = parameters.morph * 0.995f; const bool clocked = !(parameters.trigger & TRIGGER_UNPATCHED); float root_transposition = 1.0f; *already_enveloped = clocked; if (clocked) { if (parameters.trigger & TRIGGER_RISING_EDGE) { chords_.set_chord(parameters.harmonics); chords_.Sort(); int pattern = arpeggiator_pattern_selector_.Process(parameters.timbre); arpeggiator_.set_mode(ArpeggiatorMode(pattern / 3)); arpeggiator_.set_range(1 << (pattern % 3)); arpeggiator_.Clock(chords_.num_notes()); envelope_state_ = 1.0f; } const float octave = float(1 << arpeggiator_.octave()); const float note_f0 = f0 * chords_.sorted_ratio( arpeggiator_.note()) * octave; root_transposition = octave; voice_[0].Render(note_f0, shape, out, size); } else { float ratios[kChordNumVoices]; float amplitudes[kChordNumVoices]; chords_.set_chord(parameters.harmonics); chords_.ComputeChordInversion(parameters.timbre, ratios, amplitudes); for (int j = 1; j < kChordNumVoices; j += 2) { amplitudes[j] = -amplitudes[j]; } fill(&out[0], &out[size], 0.0f); for (int voice = 0; voice < kChordNumVoices; ++voice) { const float voice_f0 = f0 * ratios[voice]; voice_[voice].Render(voice_f0, shape, aux, size); for (size_t j = 0; j < size; ++j) { out[j] += aux[j] * amplitudes[voice]; } } } // Render bass note. bass_.Render(f0 * 0.5f * root_transposition, aux, size); // Apply envelope if necessary. if (envelope_shape_ != NO_ENVELOPE) { const float shape = fabsf(envelope_shape_); const float decay = 1.0f - \ 2.0f / kSampleRate * SemitonesToRatio(60.0f * shape) * shape; float aux_envelope_amount = envelope_shape_ * 20.0f; CONSTRAIN(aux_envelope_amount, 0.0f, 1.0f); for (size_t i = 0; i < size; ++i) { ONE_POLE(aux_envelope_amount_, aux_envelope_amount, 0.01f); envelope_state_ *= decay; out[i] *= envelope_state_; aux[i] *= 1.0f + aux_envelope_amount_ * (envelope_state_ - 1.0f); } } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine2/chiptune_engine.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Chiptune waveforms with arpeggiator. #ifndef PLAITS_DSP_ENGINE_CHIPTUNE_ENGINE_H_ #define PLAITS_DSP_ENGINE_CHIPTUNE_ENGINE_H_ #include "plaits/dsp/chords/chord_bank.h" #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/engine2/arpeggiator.h" #include "plaits/dsp/oscillator/nes_triangle_oscillator.h" #include "plaits/dsp/oscillator/super_square_oscillator.h" namespace plaits { class ChiptuneEngine : public Engine { public: ChiptuneEngine() { } ~ChiptuneEngine() { } enum { NO_ENVELOPE = 2 }; virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); inline void set_envelope_shape(float envelope_shape) { envelope_shape_ = envelope_shape; } private: SuperSquareOscillator voice_[kChordNumVoices]; NESTriangleOscillator<> bass_; ChordBank chords_; Arpeggiator arpeggiator_; stmlib::HysteresisQuantizer2 arpeggiator_pattern_selector_; float envelope_shape_; float envelope_state_; float aux_envelope_amount_; DISALLOW_COPY_AND_ASSIGN(ChiptuneEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_CHIPTUNE_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine2/phase_distortion_engine.cc ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Phase distortion and phase modulation with an asymmetric triangle as the // modulator. #include "plaits/dsp/engine2/phase_distortion_engine.h" #include #include "stmlib/dsp/parameter_interpolator.h" #include "plaits/dsp/oscillator/sine_oscillator.h" #include "plaits/resources.h" namespace plaits { using namespace std; using namespace stmlib; void PhaseDistortionEngine::Init(BufferAllocator* allocator) { modulator_.Init(); shaper_.Init(); temp_buffer_ = allocator->Allocate(kMaxBlockSize * 4); } void PhaseDistortionEngine::Reset() { } void PhaseDistortionEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { const float f0 = 0.5f * NoteToFrequency(parameters.note); const float modulator_f = min(0.25f, f0 * SemitonesToRatio(Interpolate( lut_fm_frequency_quantizer, parameters.harmonics, 128.0f))); const float pw = 0.5f + parameters.morph * 0.49f; const float amount = 8.0f * parameters.timbre * parameters.timbre * \ (1.0f - modulator_f * 3.8f); // Upsample by 2x float* synced = &temp_buffer_[0]; float* free_running = &temp_buffer_[2 * size]; shaper_.Render( f0, modulator_f, pw, 0.0f, amount, synced, 2 * size); modulator_.Render( f0, modulator_f, pw, 0.0f, amount, free_running, 2 * size); for (size_t i = 0; i < size; ++i) { // Naive 0.5x downsampling. out[i] = 0.5f * Sine(*synced++ + 0.25f); out[i] += 0.5f * Sine(*synced++ + 0.25f); aux[i] = 0.5f * Sine(*free_running++ + 0.25f); aux[i] += 0.5f * Sine(*free_running++ + 0.25f); } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine2/phase_distortion_engine.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Phase distortion and phase modulation with an asymmetric triangle as the // modulator. #ifndef PLAITS_DSP_ENGINE_PHASE_DISTORTION_ENGINE_H_ #define PLAITS_DSP_ENGINE_PHASE_DISTORTION_ENGINE_H_ #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/oscillator/variable_shape_oscillator.h" namespace plaits { class PhaseDistortionEngine : public Engine { public: PhaseDistortionEngine() { } ~PhaseDistortionEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: VariableShapeOscillator shaper_; VariableShapeOscillator modulator_; float* temp_buffer_; DISALLOW_COPY_AND_ASSIGN(PhaseDistortionEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_PHASE_DISTORTION_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine2/six_op_engine.cc ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 6-operator FM synth. #include "plaits/dsp/engine2/six_op_engine.h" #include #include "plaits/resources.h" namespace plaits { using namespace fm; using namespace std; using namespace stmlib; void FMVoice::Init(fm::Algorithms<6>* algorithms, float sample_rate) { voice_.Init(algorithms, sample_rate); lfo_.Init(sample_rate); parameters_.sustain = false; parameters_.gate = false; parameters_.note = 48.0f; parameters_.velocity = 0.5f; parameters_.brightness = 0.5f; parameters_.envelope_control = 0.5f; parameters_.pitch_mod = 0.0f; parameters_.amp_mod = 0.0f; patch_ = NULL; } void FMVoice::Render(float* buffer, size_t size) { if (!patch_) { return; } voice_.Render(parameters_, buffer, size); } void FMVoice::LoadPatch(const fm::Patch* patch) { if (patch == patch_) { return; } patch_ = patch; voice_.SetPatch(patch_); lfo_.Set(patch_->modulations); } const int kNumPatchesPerBank = 96; void SixOpEngine::Init(BufferAllocator* allocator) { patch_index_quantizer_.Init(kNumPatchesPerBank, 0.005f, false); algorithms_.Init(); for (int i = 0; i < kNumSixOpVoices; ++i) { voice_[i].Init(&algorithms_, kCorrectedSampleRate); } temp_buffer_ = allocator->Allocate(kMaxBlockSize * 4); acc_buffer_ = allocator->Allocate(kMaxBlockSize * kNumSixOpVoices); patches_ = allocator->Allocate(kNumPatchesPerBank); active_voice_ = kNumSixOpVoices - 1; rendered_voice_ = 0; } void SixOpEngine::Reset() { } void SixOpEngine::LoadUserData(const uint8_t* user_data) { for (int i = 0; i < kNumPatchesPerBank; ++i) { patches_[i].Unpack(user_data + i * fm::Patch::SYX_SIZE); } for (int i = 0; i < kNumSixOpVoices; ++i) { voice_[i].UnloadPatch(); } } void SixOpEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { /*[eh2k] Sorry for the hack :-) int patch_index = patch_index_quantizer_.Process( parameters.harmonics * 1.02f); */ if (parameters.trigger & TRIGGER_UNPATCHED) { const float t = parameters.morph; voice_[0].mutable_lfo()->Scrub(2.0f * kCorrectedSampleRate * t); for (int i = 0; i < kNumSixOpVoices; ++i) { voice_[i].LoadPatch(&patches_[patch_index]); Voice<6>::Parameters* p = voice_[i].mutable_parameters(); p->sustain = i == 0 ? true : false; p->gate = false; p->note = parameters.note; p->velocity = parameters.accent; p->brightness = parameters.timbre; p->envelope_control = t; voice_[i].set_modulations(voice_[0].lfo()); } } else { if (parameters.trigger & TRIGGER_RISING_EDGE) { active_voice_ = (active_voice_ + 1) % kNumSixOpVoices; voice_[active_voice_].LoadPatch(&patches_[patch_index]); voice_[active_voice_].mutable_lfo()->Reset(); } Voice<6>::Parameters* p = voice_[active_voice_].mutable_parameters(); p->note = parameters.note; p->velocity = parameters.accent; p->envelope_control = parameters.morph; voice_[active_voice_].mutable_lfo()->Step(float(size)); for (int i = 0; i < kNumSixOpVoices; ++i) { Voice<6>::Parameters* p = voice_[i].mutable_parameters(); p->brightness = parameters.timbre; p->sustain = false; p->gate = (parameters.trigger & TRIGGER_HIGH) && (i == active_voice_); if (voice_[i].patch() != voice_[active_voice_].patch()) { voice_[i].mutable_lfo()->Step(float(size)); voice_[i].set_modulations(voice_[i].lfo()); } else { voice_[i].set_modulations(voice_[active_voice_].lfo()); } } } // Naive block rendering. // fill(temp_buffer_[0], temp_buffer_[size], 0.0f); // for (int i = 0; i < kNumSixOpVoices; ++i) { // voice_[i].Render(temp_buffer_, size); // } // Staggered rendering. copy( &acc_buffer_[0], &acc_buffer_[(kNumSixOpVoices - 1) * size], &temp_buffer_[0]); fill( &temp_buffer_[(kNumSixOpVoices - 1) * size], &temp_buffer_[kNumSixOpVoices * size], 0.0f); rendered_voice_ = (rendered_voice_ + 1) % kNumSixOpVoices; voice_[rendered_voice_].Render(temp_buffer_, size * kNumSixOpVoices); for (size_t i = 0; i < size; ++i) { aux[i] = out[i] = SoftClip(temp_buffer_[i] * 0.25f); } copy( &temp_buffer_[size], &temp_buffer_[kNumSixOpVoices * size], &acc_buffer_[0]); } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine2/six_op_engine.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // 6-operator FM synth. #ifndef PLAITS_DSP_ENGINE_SIX_OP_ENGINE_H_ #define PLAITS_DSP_ENGINE_SIX_OP_ENGINE_H_ #include "stmlib/dsp/hysteresis_quantizer.h" #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/fm/algorithms.h" #include "plaits/dsp/fm/lfo.h" #include "plaits/dsp/fm/voice.h" #include "plaits/dsp/fm/patch.h" namespace plaits { const int kNumSixOpVoices = 2; class FMVoice { public: FMVoice() { } ~FMVoice() { } void Init(fm::Algorithms<6>* algorithms, float sample_rate); void LoadPatch(const fm::Patch* patch); void Render(float* buffer, size_t size); inline void UnloadPatch() { patch_ = NULL; } inline const fm::Patch* patch() const { return patch_; } inline fm::Voice<6>::Parameters* mutable_parameters() { return ¶meters_; } inline fm::Lfo* mutable_lfo() { return &lfo_; } inline const fm::Lfo& lfo() const { return lfo_; } inline void set_modulations(const fm::Lfo& lfo) { parameters_.pitch_mod = lfo.pitch_mod(); parameters_.amp_mod = lfo.amp_mod(); } private: const fm::Patch* patch_; fm::Lfo lfo_; fm::Voice<6> voice_; fm::Voice<6>::Parameters parameters_; DISALLOW_COPY_AND_ASSIGN(FMVoice); }; class SixOpEngine : public Engine { public: SixOpEngine() { } ~SixOpEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data); virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); void LoadBank(int bank); uint8_t patch_index = 0; //[eh2k] private: stmlib::HysteresisQuantizer2 patch_index_quantizer_; fm::Algorithms<6> algorithms_; fm::Patch* patches_; FMVoice voice_[kNumSixOpVoices]; float* temp_buffer_; float* acc_buffer_; int active_voice_; int rendered_voice_; DISALLOW_COPY_AND_ASSIGN(SixOpEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_SIX_OP_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine2/string_machine_engine.cc ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // String machine emulation with filter and chorus. #include "plaits/dsp/engine2/string_machine_engine.h" #include #include "plaits/resources.h" namespace plaits { using namespace std; using namespace stmlib; void StringMachineEngine::Init(BufferAllocator* allocator) { for (int i = 0; i < kChordNumNotes; ++i) { divide_down_voice_[i].Init(); } chords_.Init(allocator); morph_lp_ = 0.0f; timbre_lp_ = 0.0f; svf_[0].Init(); svf_[1].Init(); ensemble_.Init(allocator->Allocate(1024)); } void StringMachineEngine::Reset() { chords_.Reset(); ensemble_.Reset(); } const int kRegistrationTableSize = 11; const float registrations[kRegistrationTableSize][kChordNumHarmonics * 2] = { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }, // Saw { 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f }, // Saw + saw { 0.4f, 0.0f, 0.2f, 0.0f, 0.4f, 0.0f }, // Full saw { 0.3f, 0.0f, 0.0f, 0.3f, 0.0f, 0.4f }, // Full saw + square hybrid { 0.3f, 0.0f, 0.0f, 0.0f, 0.0f, 0.7f }, // Saw + high square harmo { 0.2f, 0.0f, 0.0f, 0.2f, 0.0f, 0.6f }, // Weird hybrid { 0.0f, 0.2f, 0.1f, 0.0f, 0.2f, 0.5f }, // Sawsquare high harmo { 0.0f, 0.3f, 0.0f, 0.3f, 0.0f, 0.4f }, // Square high armo { 0.0f, 0.4f, 0.0f, 0.3f, 0.0f, 0.3f }, // Full square { 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f }, // Square + Square { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f }, // Square }; void StringMachineEngine::ComputeRegistration( float registration, float* amplitudes) { registration *= (kRegistrationTableSize - 1.001f); MAKE_INTEGRAL_FRACTIONAL(registration); for (int i = 0; i < kChordNumHarmonics * 2; ++i) { float a = registrations[registration_integral][i]; float b = registrations[registration_integral + 1][i]; amplitudes[i] = a + (b - a) * registration_fractional; } } void StringMachineEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { ONE_POLE(morph_lp_, parameters.morph, 0.1f); ONE_POLE(timbre_lp_, parameters.timbre, 0.1f); chords_.set_chord(parameters.harmonics); float harmonics[kChordNumHarmonics * 2 + 2]; float registration = max(morph_lp_, 0.0f); ComputeRegistration(registration, harmonics); harmonics[kChordNumHarmonics * 2] = 0.0f; // Render string/organ sound. fill(&out[0], &out[size], 0.0f); fill(&aux[0], &aux[size], 0.0f); const float f0 = NoteToFrequency(parameters.note) * 0.998f; for (int note = 0; note < kChordNumNotes; ++note) { const float note_f0 = f0 * chords_.ratio(note); float divide_down_gain = 4.0f - note_f0 * 32.0f; CONSTRAIN(divide_down_gain, 0.0f, 1.0f); divide_down_voice_[note].Render( note_f0, harmonics, 0.25f * divide_down_gain, note & 1 ? aux : out, size); } // Pass through VCF. const float cutoff = 2.2f * f0 * SemitonesToRatio(120.0f * parameters.timbre); svf_[0].set_f_q(cutoff, 1.0f); svf_[1].set_f_q(cutoff * 1.5f, 1.0f); // Mixdown. for (size_t i = 0; i < size; ++i) { const float l = svf_[0].Process(out[i]); const float r = svf_[1].Process(aux[i]); out[i] = 0.66f * l + 0.33f * r; aux[i] = 0.66f * r + 0.33f * l; } // Ensemble FX. const float amount = fabsf(parameters.timbre - 0.5f) * 2.0f; const float depth = 0.35f + 0.65f * parameters.timbre; ensemble_.set_amount(amount); ensemble_.set_depth(depth); ensemble_.Process(out, aux, size); } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine2/string_machine_engine.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // String machine emulation with filter and chorus. #ifndef PLAITS_DSP_ENGINE_STRING_MACHINE_ENGINE_H_ #define PLAITS_DSP_ENGINE_STRING_MACHINE_ENGINE_H_ #include "plaits/dsp/chords/chord_bank.h" #include "plaits/dsp/engine/chord_engine.h" #include "stmlib/dsp/filter.h" #include "plaits/dsp/fx/ensemble.h" namespace plaits { class StringMachineEngine : public Engine { public: StringMachineEngine() { } ~StringMachineEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: void ComputeRegistration(float registration, float* amplitudes); ChordBank chords_; Ensemble ensemble_; StringSynthOscillator divide_down_voice_[kChordNumNotes]; stmlib::NaiveSvf svf_[2]; float morph_lp_; float timbre_lp_; DISALLOW_COPY_AND_ASSIGN(StringMachineEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_STRING_MACHINE_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine2/virtual_analog_vcf_engine.cc ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Virtual analog with VCF. #include "plaits/dsp/engine2/virtual_analog_vcf_engine.h" #include #include "stmlib/dsp/parameter_interpolator.h" using namespace std; namespace plaits { using namespace std; using namespace stmlib; void VirtualAnalogVCFEngine::Init(BufferAllocator* allocator) { oscillator_.Init(); sub_oscillator_.Init(); svf_[0].Init(); svf_[1].Init(); previous_sub_gain_ = 0.0f; previous_cutoff_ = 0.0f; previous_stage2_gain_ = 0.0f; previous_q_ = 0.0f; previous_gain_ = 0.0f; } void VirtualAnalogVCFEngine::Reset() { } void VirtualAnalogVCFEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { // VA Oscillator (saw or PW square) + sub const float f0 = NoteToFrequency(parameters.note); float shape = (parameters.morph - 0.25f) * 2.0f + 0.5f; CONSTRAIN(shape, 0.5f, 1.0f); float pw = (parameters.morph - 0.5f) * 2.0f + 0.5f; if (parameters.morph > 0.75f) { pw = 2.5f - parameters.morph * 2.0f; } CONSTRAIN(pw, 0.5f, 0.98f); float sub_gain = max(fabsf(parameters.morph - 0.5f) - 0.3f, 0.0f) * 5.0f; oscillator_.Render(f0, pw, shape, out, size); sub_oscillator_.Render(f0 * 0.501f, 0.5f, 1.0f, aux, size); const float cutoff = f0 * SemitonesToRatio( (parameters.timbre - 0.2f) * 120.0f); float stage2_gain = 1.0f - (parameters.harmonics - 0.4f) * 4.0f; CONSTRAIN(stage2_gain, 0.0f, 1.0f); const float resonance = 2.667f * \ max(fabsf(parameters.harmonics - 0.5f) - 0.125f, 0.0f); const float resonance_sqr = resonance * resonance; const float q = resonance_sqr * resonance_sqr * 48.0f; float gain = (parameters.harmonics - 0.7f) + 0.85f; CONSTRAIN(gain, 0.7f - resonance_sqr * 0.3f, 1.0f); ParameterInterpolator sub_gain_modulation( &previous_sub_gain_, sub_gain, size); ParameterInterpolator cutoff_modulation( &previous_cutoff_, cutoff, size); ParameterInterpolator stage2_gain_modulation( &previous_stage2_gain_, stage2_gain, size); ParameterInterpolator q_modulation( &previous_q_, q, size); ParameterInterpolator gain_modulation(&previous_gain_, gain, size); for (size_t i = 0; i < size; ++i) { const float cutoff = min(cutoff_modulation.Next(), 0.25f); const float q = q_modulation.Next(); const float stage2_gain = stage2_gain_modulation.Next(); svf_[0].set_f_q(cutoff, 0.5f + q); svf_[1].set_f_q(cutoff, 0.5f + 0.025f * q); const float gain = gain_modulation.Next(); const float input = SoftClip( (out[i] + aux[i] * sub_gain_modulation.Next()) * gain); float lp, hp; svf_[0].Process( input, &lp, &hp); lp = SoftClip(lp * gain); lp += stage2_gain * \ (SoftClip(svf_[1].Process(lp)) - lp); out[i] = lp; aux[i] = SoftClip(hp * gain); } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine2/virtual_analog_vcf_engine.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Virtual analog oscillator with VCF. #ifndef PLAITS_DSP_ENGINE_VIRTUAL_ANALOG_VCF_ENGINE_H_ #define PLAITS_DSP_ENGINE_VIRTUAL_ANALOG_VCF_ENGINE_H_ #include "stmlib/dsp/filter.h" #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/oscillator/variable_saw_oscillator.h" #include "plaits/dsp/oscillator/variable_shape_oscillator.h" namespace plaits { class VirtualAnalogVCFEngine : public Engine { public: VirtualAnalogVCFEngine() { } ~VirtualAnalogVCFEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: stmlib::Svf svf_[2]; VariableShapeOscillator oscillator_; VariableShapeOscillator sub_oscillator_; float previous_cutoff_; float previous_stage2_gain_; float previous_q_; float previous_gain_; float previous_sub_gain_; DISALLOW_COPY_AND_ASSIGN(VirtualAnalogVCFEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_VIRTUAL_ANALOG_VCF_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/engine2/wave_terrain_engine.cc ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Wave terrain synthesis. #include "plaits/dsp/engine2/wave_terrain_engine.h" #include #include #include "plaits/dsp/oscillator/wavetable_oscillator.h" namespace plaits { using namespace std; using namespace stmlib; void WaveTerrainEngine::Init(BufferAllocator* allocator) { path_.Init(); offset_ = 0.0f; terrain_ = 0.0f; temp_buffer_ = allocator->Allocate(kMaxBlockSize * 4); user_terrain_ = NULL; } void WaveTerrainEngine::Reset() { } inline float TerrainLookup(float x, float y, const int8_t* terrain) { const int terrain_size = 64; const float value_scale = 1.0f / 128.0f; const float coord_scale = float(terrain_size - 2) * 0.5f; x = (x + 1.0f) * coord_scale; y = (y + 1.0f) * coord_scale; MAKE_INTEGRAL_FRACTIONAL(x); MAKE_INTEGRAL_FRACTIONAL(y); float xy[2]; terrain += y_integral * terrain_size; xy[0] = InterpolateWave(terrain, x_integral, x_fractional); terrain += terrain_size; xy[1] = InterpolateWave(terrain, x_integral, x_fractional); return (xy[0] + (xy[1] - xy[0]) * y_fractional) * value_scale; } template inline float InterpolateIntegratedWave( const T* table, int32_t index_integral, float index_fractional) { float a = static_cast(table[index_integral]); float b = static_cast(table[index_integral + 1]); float c = static_cast(table[index_integral + 2]); float t = index_fractional; return (b - a) + (c - b - b + a) * t; } // The wavetables are stored in integrated form. Either we directly use the // integrated data (which can have large variations in amplitude), or we // differentiate it on the fly to recover the original waveform. This second // option can be noisier, and it would ideally need a low pass-filter. #define DIFFERENTIATE_WAVE_DATA // Lookup from the wavetable data re-interpreted as a terrain. :facepalm: inline float TerrainLookupWT(float x, float y, int bank) { const int table_size = 128; const int table_size_full = table_size + 4; // Includes 4 wrapped samples const int num_waves = 64; const float sample = (y + 1.0f) * 0.5f * float(table_size); const float wt = (x + 1.0f) * 0.5f * float(num_waves - 1); const int16_t* waves = wav_integrated_waves + \ bank * num_waves * table_size_full; MAKE_INTEGRAL_FRACTIONAL(sample); MAKE_INTEGRAL_FRACTIONAL(wt); float xy[2]; #ifdef DIFFERENTIATE_WAVE_DATA const float value_scale = 1.0f / 1024.0f; waves += wt_integral * table_size_full; xy[0] = InterpolateIntegratedWave(waves, sample_integral, sample_fractional); waves += table_size_full; xy[1] = InterpolateIntegratedWave(waves, sample_integral, sample_fractional); #else const float value_scale = 1.0f / 32768.0f; waves += wt_integral * table_size_full; xy[0] = InterpolateWave(waves, sample_integral, sample_fractional); waves += table_size_full; xy[1] = InterpolateWave(waves, sample_integral, sample_fractional); #endif // DIFFERENTIATE_WAVE_DATA return (xy[0] + (xy[1] - xy[0]) * wt_fractional) * value_scale; } inline float Squash(float x, float a) { x *= a; return x / (1.0f + fabsf(x)); } inline float WaveTerrainEngine::Terrain(float x, float y, int terrain_index) { // The Sine function only works for a positive argument. // Thus, all calls to Sine include a positive offset of the argument! const float k = 4.0f; switch (terrain_index) { case 0: { return (Squash(Sine(k + x * 1.273f), 2.0f) - \ Sine(k + y * (x + 1.571f) * 0.637f)) * 0.57f; } break; case 1: { const float xy = x * y; return Sine(k + Sine(k + (x + y) * 0.637f) / (0.2f + xy * xy) * 0.159f); } break; case 2: { const float xy = x * y; return Sine(k + Sine(k + 2.387f * xy) / (0.350f + xy * xy) * 0.159f); } break; case 3: { const float xy = x * y; const float xys = (x - 0.25f) * (y + 0.25f); return Sine(k + xy / (2.0f + fabsf(5.0f * xys)) * 6.366f); } break; case 4: { return Sine( 0.159f / (0.170f + fabsf(y - 0.25f)) + \ 0.477f / (0.350f + fabsf((x + 0.5f) * (y + 1.5f))) + k); } break; case 5: case 6: case 7: { return TerrainLookupWT(x, y, 2 - (terrain_index - 5)); } break; case 8: { return TerrainLookup(x, y, user_terrain_); } } return 0.0f; } void WaveTerrainEngine::Render( const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped) { const size_t kOversampling = 2; const float kScale = 1.0f / float(kOversampling); float* path_x = &temp_buffer_[0]; float* path_y = &temp_buffer_[kOversampling * size]; const float f0 = NoteToFrequency(parameters.note); const float attenuation = max(1.0f - 8.0f * f0, 0.0f); const float radius = 0.1f + 0.9f * parameters.timbre * attenuation * \ (2.0f - attenuation); // Use the "magic sine" algorithm to generate sin and cos functions for the // trajectory coordinates. path_.RenderQuadrature( f0 * kScale, radius, path_x, path_y, size * kOversampling); ParameterInterpolator offset(&offset_, 1.9f * parameters.morph - 1.0f, size); int num_terrains = user_terrain_ ? 9 : 8; ParameterInterpolator terrain( &terrain_, min(parameters.harmonics * 1.05f, 1.0f) * float(num_terrains - 1.0001f), size); size_t ij = 0; for (size_t i = 0; i < size; ++i) { const float x_offset = offset.Next(); const float z = terrain.Next(); MAKE_INTEGRAL_FRACTIONAL(z); float out_s = 0.0f; float aux_s = 0.0f; for (size_t j = 0; j < kOversampling; ++j) { const float x = path_x[ij] * (1.0f - fabsf(x_offset)) + x_offset; const float y = path_y[ij]; ++ij; const float z0 = Terrain(x, y, z_integral); const float z1 = Terrain(x, y, z_integral + 1); const float z = (z0 + (z1 - z0) * z_fractional); out_s += z; aux_s += y + z; } out[i] = kScale * out_s; aux[i] = Sine(1.0f + 0.5f * kScale * aux_s); } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/engine2/wave_terrain_engine.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Wave terrain synthesis - a 2D function evaluated along an elliptical path of // adjustable center and excentricity. // // This implementation initially used pre-computed terrains stored in flash // memory, but even at a poor resolution of 64x64 with 8-bit samples, this // takes 4kb per terrain! It turned out that directly evaluating the terrain // function on the fly uses less flash, but is also faster than bicubic // interpolation of the terrain data. #ifndef PLAITS_DSP_ENGINE_WAVE_TERRAIN_ENGINE_H_ #define PLAITS_DSP_ENGINE_WAVE_TERRAIN_ENGINE_H_ #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/oscillator/sine_oscillator.h" namespace plaits { class WaveTerrainEngine : public Engine { public: WaveTerrainEngine() { } ~WaveTerrainEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void LoadUserData(const uint8_t* user_data) { user_terrain_ = (const int8_t*)(user_data); } virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: float Terrain(float x, float y, int terrain_index); FastSineOscillator path_; float offset_; float terrain_; float* temp_buffer_; const int8_t* user_terrain_; DISALLOW_COPY_AND_ASSIGN(WaveTerrainEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_WAVE_TERRAIN_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/envelope.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Envelope for the internal LPG. #ifndef PLAITS_DSP_ENVELOPE_H_ #define PLAITS_DSP_ENVELOPE_H_ #include "stmlib/stmlib.h" namespace plaits { class LPGEnvelope { public: LPGEnvelope() { } ~LPGEnvelope() { } inline void Init() { vactrol_state_ = 0.0f; gain_ = 1.0f; frequency_ = 0.5f; hf_bleed_ = 0.0f; ramp_up_ = false; } inline void Trigger() { ramp_up_ = true; } inline void ProcessPing( float attack, float short_decay, float decay_tail, float hf) { if (ramp_up_) { vactrol_state_ += attack; if (vactrol_state_ >= 1.0f) { vactrol_state_ = 1.0f; ramp_up_ = false; } } ProcessLP(ramp_up_ ? vactrol_state_ : 0.0f, short_decay, decay_tail, hf); } inline void ProcessLP( float level, float short_decay, float decay_tail, float hf) { float vactrol_input = level; float vactrol_error = (vactrol_input - vactrol_state_); float vactrol_state_2 = vactrol_state_ * vactrol_state_; float vactrol_state_4 = vactrol_state_2 * vactrol_state_2; float tail = 1.0f - vactrol_state_; float tail_2 = tail * tail; float vactrol_coefficient = (vactrol_error > 0.0f) ? 0.6f : short_decay + (1.0f - vactrol_state_4) * decay_tail; vactrol_state_ += vactrol_coefficient * vactrol_error; gain_ = vactrol_state_; frequency_ = 0.003f + 0.3f * vactrol_state_4 + hf * 0.04f; hf_bleed_ = (tail_2 + (1.0f - tail_2) * hf) * hf * hf; } inline float gain() const { return gain_; } inline float frequency() const { return frequency_; } inline float hf_bleed() const { return hf_bleed_; } private: float vactrol_state_; float gain_; float frequency_; float hf_bleed_; bool ramp_up_; DISALLOW_COPY_AND_ASSIGN(LPGEnvelope); }; class DecayEnvelope { public: DecayEnvelope() { } ~DecayEnvelope() { } inline void Init() { value_ = 0.0f; } inline void Trigger() { value_ = 1.0f; } inline void Process(float decay) { value_ *= (1.0f - decay); } inline float value() const { return value_; } private: float value_; DISALLOW_COPY_AND_ASSIGN(DecayEnvelope); }; } // namespace plaits #endif // PLAITS_DSP_ENVELOPE_H_ ================================================ FILE: lib/plaits/dsp/fm/algorithms.cc ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // FM Algorithms and how to render them. #include "plaits/dsp/fm/algorithms.h" namespace plaits { namespace fm { #define MOD(n) (n << 4) #define ADD(n) (n | Algorithms<4>::ADDITIVE_FLAG) #define OUT(n) n #define FB_SRC Algorithms<4>::FEEDBACK_SOURCE_FLAG #define FB_DST MOD(3) #define FB FB_SRC | FB_DST // Syntactic sugar #define NO_MOD MOD(0) // This can be replaced by OUT(0) for code that does not mix into the output buffer. #define OUTPUT ADD(0) /* static */ template<> const uint8_t Algorithms<4>::opcodes_[8][4] = { { // Algorithm 1: 4 -> 3 -> 2 -> 1 FB | OUT(1), MOD(1) | OUT(1), MOD(1) | OUT(1), MOD(1) | OUTPUT }, { // Algorithm 2: 4 + 3 -> 2 -> 1 FB | OUT(1), ADD(1), MOD(1) | OUT(1), MOD(1) | OUTPUT }, { // Algorithm 3: 4 + (3 -> 2) -> 1 FB | OUT(1), OUT(2), MOD(2) | ADD(1), MOD(1) | OUTPUT }, { // Algorithm 4: (4 -> 3) + 2 -> 1 FB | OUT(1), MOD(1) | OUT(1), ADD(1), MOD(1) | OUTPUT }, { // Algorithm 5: (4 -> 3) + (2 -> 1) FB | OUT(1), MOD(1) | OUTPUT, OUT(1), MOD(1) | ADD(0) }, { // Algorithm 6: (4 -> 3) + (4 -> 2) + (4 -> 1) FB | OUT(1), MOD(1) | OUTPUT, MOD(1) | ADD(0), MOD(1) | ADD(0) }, { // Algorithm 7: (4 -> 3) + 2 + 1 FB | OUT(1), MOD(1) | OUTPUT, ADD(0), ADD(0) }, { // Algorithm 8: 4 + 3 + 2 + 1 FB | OUTPUT, ADD(0), ADD(0), ADD(0) } }; /* static */ template<> const uint8_t Algorithms<6>::opcodes_[32][6] = { { // Algorithm 1 FB | OUT(1), // Op 6 MOD(1) | OUT(1), // Op 5 MOD(1) | OUT(1), // Op 4 MOD(1) | OUTPUT, // Op 3 NO_MOD | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 2 NO_MOD | OUT(1), // Op 6 MOD(1) | OUT(1), // Op 5 MOD(1) | OUT(1), // Op 4 MOD(1) | OUTPUT, // Op 3 FB | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 3 FB | OUT(1), // Op 6 MOD(1) | OUT(1), // Op 5 MOD(1) | OUTPUT, // Op 4 NO_MOD | OUT(1), // Op 3 MOD(1) | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 4 FB_DST | NO_MOD | OUT(1), // Op 6 MOD(1) | OUT(1), // Op 5 FB_SRC | MOD(1) | OUTPUT, // Op 4 NO_MOD | OUT(1), // Op 3 MOD(1) | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 5 FB | OUT(1), // Op 6 MOD(1) | OUTPUT, // Op 5 NO_MOD | OUT(1), // Op 4 MOD(1) | ADD(0), // Op 3 NO_MOD | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 6 FB_DST | NO_MOD | OUT(1), // Op 6 FB_SRC | MOD(1) | OUTPUT, // Op 5 NO_MOD | OUT(1), // Op 4 MOD(1) | ADD(0), // Op 3 NO_MOD | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 7 FB | OUT(1), // Op 6 MOD(1) | OUT(1), // Op 5 NO_MOD | ADD(1), // Op 4 MOD(1) | OUTPUT, // Op 3 NO_MOD | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 8 NO_MOD | OUT(1), // Op 6 MOD(1) | OUT(1), // Op 5 FB | ADD(1), // Op 4 MOD(1) | OUTPUT, // Op 3 NO_MOD | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 9 NO_MOD | OUT(1), // Op 6 MOD(1) | OUT(1), // Op 5 NO_MOD | ADD(1), // Op 4 MOD(1) | OUTPUT, // Op 3 FB | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 10 NO_MOD | OUT(1), // Op 6 NO_MOD | ADD(1), // Op 5 MOD(1) | OUTPUT, // Op 4 FB | OUT(1), // Op 3 MOD(1) | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 11 FB | OUT(1), // Op 6 NO_MOD | ADD(1), // Op 5 MOD(1) | OUTPUT, // Op 4 NO_MOD | OUT(1), // Op 3 MOD(1) | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 12 NO_MOD | OUT(1), // Op 6 NO_MOD | ADD(1), // Op 5 NO_MOD | ADD(1), // Op 4 MOD(1) | OUTPUT, // Op 3 FB | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 13 FB | OUT(1), // Op 6 NO_MOD | ADD(1), // Op 5 NO_MOD | ADD(1), // Op 4 MOD(1) | OUTPUT, // Op 3 NO_MOD | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 14 FB | OUT(1), // Op 6 NO_MOD | ADD(1), // Op 5 MOD(1) | OUT(1), // Op 4 MOD(1) | OUTPUT, // Op 3 NO_MOD | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 15 NO_MOD | OUT(1), // Op 6 NO_MOD | ADD(1), // Op 5 MOD(1) | OUT(1), // Op 4 MOD(1) | OUTPUT, // Op 3 FB | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 16 FB | OUT(1), // Op 6 MOD(1) | OUT(1), // Op 5 NO_MOD | OUT(2), // Op 4 MOD(2) | ADD(1), // Op 3 NO_MOD | ADD(1), // Op 2 MOD(1) | OUTPUT // Op 1 }, { // Algorithm 17 NO_MOD | OUT(1), // Op 6 MOD(1) | OUT(1), // Op 5 NO_MOD | OUT(2), // Op 4 MOD(2) | ADD(1), // Op 3 FB | ADD(1), // Op 2 MOD(1) | OUTPUT // Op 1 }, { // Algorithm 18 NO_MOD | OUT(1), // Op 6 MOD(1) | OUT(1), // Op 5 MOD(1) | OUT(1), // Op 4 FB | ADD(1), // Op 3 NO_MOD | ADD(1), // Op 2 MOD(1) | OUTPUT // Op 1 }, { // Algorithm 19 FB | OUT(1), // Op 6 MOD(1) | OUTPUT, // Op 5 MOD(1) | ADD(0), // Op 4 NO_MOD | OUT(1), // Op 3 MOD(1) | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 20 NO_MOD | OUT(1), // Op 6 NO_MOD | ADD(1), // Op 5 MOD(1) | OUTPUT, // Op 4 FB | OUT(1), // Op 3 MOD(1) | ADD(0), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 21 NO_MOD | OUT(1), // Op 6 MOD(1) | OUTPUT, // Op 5 MOD(1) | ADD(0), // Op 4 FB | OUT(1), // Op 3 MOD(1) | ADD(0), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 22 FB | OUT(1), // Op 6 MOD(1) | OUTPUT, // Op 5 MOD(1) | ADD(0), // Op 4 MOD(1) | ADD(0), // Op 3 NO_MOD | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 23 FB | OUT(1), // Op 6 MOD(1) | OUTPUT, // Op 5 MOD(1) | ADD(0), // Op 4 NO_MOD | OUT(1), // Op 3 MOD(1) | ADD(0), // Op 2 NO_MOD | ADD(0) // Op 1 }, { // Algorithm 24 FB | OUT(1), // Op 6 MOD(1) | OUTPUT, // Op 5 MOD(1) | ADD(0), // Op 4 MOD(1) | ADD(0), // Op 3 NO_MOD | ADD(0), // Op 2 NO_MOD | ADD(0) // Op 1 }, { // Algorithm 25 FB | OUT(1), // Op 6 MOD(1) | OUTPUT, // Op 5 MOD(1) | ADD(0), // Op 4 NO_MOD | ADD(0), // Op 3 NO_MOD | ADD(0), // Op 2 NO_MOD | ADD(0) // Op 1 }, { // Algorithm 26 FB | OUT(1), // Op 6 NO_MOD | ADD(1), // Op 5 MOD(1) | OUTPUT, // Op 4 NO_MOD | OUT(1), // Op 3 MOD(1) | ADD(0), // Op 2 NO_MOD | ADD(0) // Op 1 }, { // Algorithm 27 NO_MOD | OUT(1), // Op 6 NO_MOD | ADD(1), // Op 5 MOD(1) | OUTPUT, // Op 4 FB | OUT(1), // Op 3 MOD(1) | ADD(0), // Op 2 NO_MOD | ADD(0) // Op 1 }, { // Algorithm 28 NO_MOD | OUTPUT, // Op 6 FB | OUT(1), // Op 5 MOD(1) | OUT(1), // Op 4 MOD(1) | ADD(0), // Op 3 NO_MOD | OUT(1), // Op 2 MOD(1) | ADD(0) // Op 1 }, { // Algorithm 29 FB | OUT(1), // Op 6 MOD(1) | OUTPUT, // Op 5 NO_MOD | OUT(1), // Op 4 MOD(1) | ADD(0), // Op 3 NO_MOD | ADD(0), // Op 2 NO_MOD | ADD(0) // Op 1 }, { // Algorithm 30 NO_MOD | OUTPUT, // Op 6 FB | OUT(1), // Op 5 MOD(1) | OUT(1), // Op 4 MOD(1) | ADD(0), // Op 3 NO_MOD | ADD(0), // Op 2 NO_MOD | ADD(0) // Op 1 }, { // Algorithm 31 FB | OUT(1), // Op 6 MOD(1) | OUTPUT, // Op 5 NO_MOD | ADD(0), // Op 4 NO_MOD | ADD(0), // Op 3 NO_MOD | ADD(0), // Op 2 NO_MOD | ADD(0) // Op 1 }, { // Algorithm 32 FB | OUTPUT, // Op 6 NO_MOD | ADD(0), // Op 5 NO_MOD | ADD(0), // Op 4 NO_MOD | ADD(0), // Op 3 NO_MOD | ADD(0), // Op 2 NO_MOD | ADD(0) // Op 1 } }; #define INSTANTIATE_RENDERER(n, m, a) { n, m, a, &RenderOperators } /* static */ template<> const Algorithms<4>::RendererSpecs Algorithms<4>::renderers_[] = { // Core INSTANTIATE_RENDERER(1, -2, false), INSTANTIATE_RENDERER(1, -2, true), INSTANTIATE_RENDERER(1, -1, false), INSTANTIATE_RENDERER(1, -1, true), INSTANTIATE_RENDERER(1, 0, false), INSTANTIATE_RENDERER(1, 0, true), // Optimized /*INSTANTIATE_RENDERER(4, -1, true), INSTANTIATE_RENDERER(4, 0, true), INSTANTIATE_RENDERER(2, -1, true), INSTANTIATE_RENDERER(2, 0, false), INSTANTIATE_RENDERER(2, 0, true),*/ { 0, 0, 0, NULL} }; /* static */ template<> const Algorithms<6>::RendererSpecs Algorithms<6>::renderers_[] = { // Core INSTANTIATE_RENDERER(1, -2, false), INSTANTIATE_RENDERER(1, -2, true), INSTANTIATE_RENDERER(1, -1, false), INSTANTIATE_RENDERER(1, -1, true), INSTANTIATE_RENDERER(1, 0, false), INSTANTIATE_RENDERER(1, 0, true), // Pesky feedback loops spanning several operators INSTANTIATE_RENDERER(3, 2, true), INSTANTIATE_RENDERER(2, 1, true), // Optimized /*INSTANTIATE_RENDERER(4, -1, true), INSTANTIATE_RENDERER(4, 0, true), INSTANTIATE_RENDERER(3, -1, false), INSTANTIATE_RENDERER(3, -1, true), INSTANTIATE_RENDERER(3, 0, true), INSTANTIATE_RENDERER(2, -2, true), INSTANTIATE_RENDERER(2, -1, false), INSTANTIATE_RENDERER(2, -1, true), INSTANTIATE_RENDERER(2, 0, false), INSTANTIATE_RENDERER(2, 0, true),*/ { 0, 0, 0, NULL} }; } // namespace fm } // namespace plaits ================================================ FILE: lib/plaits/dsp/fm/algorithms.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // FM Algorithms and how to render them. #ifndef PLAITS_DSP_FM_ALGORITHMS_H_ #define PLAITS_DSP_FM_ALGORITHMS_H_ #include "stmlib/dsp/dsp.h" #include "plaits/dsp/fm/operator.h" #include namespace plaits { namespace fm { // Number of algorithms as a function of the number of operators. template struct NumAlgorithms { enum { N = 1 }; }; template<> struct NumAlgorithms<4> { enum { N = 8 }; }; template<> struct NumAlgorithms<6> { enum { N = 32 }; }; // Store information about all FM algorithms, and which functions to call // to render them. // // The raw structure of each algorithm is stored as a sequence of "opcodes", // where each opcode indicates, for each operator, from where does it get // its phase modulation signal and to which buffer it writes the result. // This data is compact - 1 byte / algorithm / operator. // // At run time, this data is "compiled" into a sequence of function calls // to pre-compiled renderers. A renderer is specialized to efficiently render // (without any branching, and as much loop unrolling as possible) one // operator or a group of operators. // // Different code space and speed trade-off can be obtained by increasing the // palette of available renderers (for example by specializing the code for // a renderer rendering in a single pass a "tower" of 4 operators). template class Algorithms { public: Algorithms() { } ~Algorithms() { } enum { NUM_ALGORITHMS = NumAlgorithms::N }; enum OpcodeFlags { DESTINATION_MASK = 0x03, SOURCE_MASK = 0x30, SOURCE_FEEDBACK = 0x30, ADDITIVE_FLAG = 0x04, FEEDBACK_SOURCE_FLAG = 0x40, }; struct RenderCall { RenderFn render_fn; int n; int input_index; int output_index; }; inline void Init() { for (int i = 0; i < NUM_ALGORITHMS; ++i) { Compile(i); } } inline const RenderCall& render_call(int algorithm, int op) const { return render_call_[algorithm][op]; } inline bool is_modulator(int algorithm, int op) const { return opcodes_[algorithm][op] & DESTINATION_MASK; } private: struct RendererSpecs { int n; int modulation_source; bool additive; RenderFn render_fn; }; inline RenderFn GetRenderer(int n, int modulation_source, bool additive) { for (const RendererSpecs* r = renderers_; r->n; ++r) { if (r->n == n && \ r->modulation_source == modulation_source && \ r->additive == additive) { return r->render_fn; } } return NULL; } inline void Compile(int algorithm) { const uint8_t* opcodes = opcodes_[algorithm]; for (int i = 0; i < num_operators; ) { uint8_t opcode = opcodes[i]; int n = 1; while (i + n < num_operators) { uint8_t from = opcodes[i + n - 1]; uint8_t to = (opcodes[i + n] & SOURCE_MASK) >> 4; bool has_additive = from & ADDITIVE_FLAG; bool broken = (from & DESTINATION_MASK) != to; if (has_additive || broken) { if (to == (opcode & DESTINATION_MASK)) { // If the same modulation happens to be reused by subsequent // operators (algorithms 19 to 25), discard the chain. n = 1; } break; } ++n; } // Try to find if a pre-compiled renderer is available for this chain. for (int attempt = 0; attempt < 2; ++attempt) { uint8_t out_opcode = opcodes[i + n - 1]; bool additive = out_opcode & ADDITIVE_FLAG; int modulation_source = -3; if (!(opcode & SOURCE_MASK)) { modulation_source = -1; } else if ((opcode & SOURCE_MASK) != SOURCE_FEEDBACK) { modulation_source = -2; } else { for (int j = 0; j < n; ++j) { if (opcodes[i + j] & FEEDBACK_SOURCE_FLAG) { modulation_source = j; } } } RenderFn fn = GetRenderer(n, modulation_source, additive); if (fn) { RenderCall* call = &render_call_[algorithm][i]; call->render_fn = fn; call->n = n; call->input_index = (opcode & SOURCE_MASK) >> 4; call->output_index = out_opcode & DESTINATION_MASK; // printf(" Algo %02d. Op %d uses renderer (%d, %d, %d)\n", // algorithm + 1, // num_operators - i, // n, modulation_source, additive); break; } else { // printf("! Algo %02d. Op %d: no renderer for (%d, %d, %d)\n", // algorithm + 1, // num_operators - i, // n, modulation_source, additive); if (n == 1) { // assert(false); } else { n = 1; } } } i += n; } } RenderCall render_call_[NUM_ALGORITHMS][num_operators]; static const uint8_t opcodes_[NUM_ALGORITHMS][num_operators]; static const RendererSpecs renderers_[]; DISALLOW_COPY_AND_ASSIGN(Algorithms); }; /* static */ template<> const uint8_t Algorithms<4>::opcodes_[][4]; // From DX100 /* static */ template<> const Algorithms<4>::RendererSpecs Algorithms<4>::renderers_[]; /* static */ template<> const uint8_t Algorithms<6>::opcodes_[][6]; // From DX7 /* static */ template<> const Algorithms<6>::RendererSpecs Algorithms<6>::renderers_[]; } // namespace fm } // namespace plaits #endif // PLAITS_DSP_FM_ALGORITHMS_H_ ================================================ FILE: lib/plaits/dsp/fm/dx_units.cc ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Various conversion routines for DX7 patch data. #include "plaits/dsp/fm/dx_units.h" namespace plaits { namespace fm { /* extern */ const float lut_coarse[32] = { -12.000000f, 0.000000f, 12.000000f, 19.019550f, 24.000000f, 27.863137f, 31.019550f, 33.688259f, 36.000000f, 38.039100f, 39.863137f, 41.513180f, 43.019550f, 44.405276f, 45.688259f, 46.882687f, 48.000000f, 49.049554f, 50.039100f, 50.975130f, 51.863137f, 52.707809f, 53.513180f, 54.282743f, 55.019550f, 55.726274f, 56.405276f, 57.058650f, 57.688259f, 58.295772f, 58.882687f, 59.450356f }; /* extern */ const float lut_amp_mod_sensitivity[4] = { 0.0f, 0.2588f, 0.4274f, 1.0f }; /* extern */ const float lut_pitch_mod_sensitivity[8] = { 0.0f, 0.0781250f, 0.1562500f, 0.2578125f, 0.4296875f, 0.7187500f, 1.1953125f, 2.0f }; /* extern */ const float lut_cube_root[17] = { 0.0f, 0.39685062976f, 0.50000000000f, 0.57235744065f, 0.62996081605f, 0.67860466725f, 0.72112502092f, 0.75914745216f, 0.79370070937f, 0.82548197054f, 0.85498810729f, 0.88258719406f, 0.90856038354f, 0.93312785379f, 0.95646563396f, 0.97871693135f, 1.0f }; } // namespace fm } // namespace plaits ================================================ FILE: lib/plaits/dsp/fm/dx_units.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Various "magic" conversion functions for DX7 patch data. #ifndef PLAITS_DSP_DX_UNITS_H_ #define PLAITS_DSP_DX_UNITS_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/units.h" #include #include #include "plaits/dsp/fm/patch.h" namespace plaits { namespace fm { extern const float lut_cube_root[17]; extern const float lut_amp_mod_sensitivity[4]; extern const float lut_pitch_mod_sensitivity[8]; extern const float lut_coarse[32]; // Computes 2^x by using a polynomial approximation of 2^frac(x) and directly // incrementing the exponent of the IEEE 754 representation of the result // by int(x). Depending on the use case, the order of the polynomial // approximation can be chosen. template inline float Pow2Fast(float x) { union { float f; int32_t w; } r; if (order == 1) { r.w = float(1 << 23) * (127.0f + x); return r.f; } int32_t x_integral = static_cast(x); if (x < 0.0f) { --x_integral; } x -= static_cast(x_integral); if (order == 1) { r.f = 1.0f + x; } else if (order == 2) { r.f = 1.0f + x * (0.6565f + x * 0.3435f); } else if (order == 3) { r.f = 1.0f + x * (0.6958f + x * (0.2251f + x * 0.0791f)); } r.w += x_integral << 23; return r.f; } // Convert an operator (envelope) level from 0-99 to the complement of the // "TL" value. // 0 = 0 (TL = 127) // 20 = 48 (TL = 79) // 50 = 78 (TL = 49) // 99 = 127 (TL = 0) inline int OperatorLevel(int level) { int tlc = int(level); if (level < 20) { tlc = tlc < 15 ? (tlc * (36 - tlc)) >> 3 : 27 + tlc; } else { tlc += 28; } return tlc; } // Convert an envelope level from 0-99 to an octave shift. // 0 = -4 octave // 18 = -1 octave // 50 = 0 // 82 = +1 octave // 99 = +4 octave inline float PitchEnvelopeLevel(int level) { float l = (float(level) - 50.0f) / 32.0f; float tail = std::max(fabsf(l + 0.02f) - 1.0f, 0.0f); return l * (1.0f + tail * tail * 5.3056f); } // Convert an operator envelope rate from 0-99 to a frequency. inline float OperatorEnvelopeIncrement(int rate) { int rate_scaled = (rate * 41) >> 6; int mantissa = 4 + (rate_scaled & 3); int exponent = 2 + (rate_scaled >> 2); return float(mantissa << exponent) / float(1 << 24); } // Convert a pitch envelope rate from 0-99 to a frequency. inline float PitchEnvelopeIncrement(int rate) { float r = float(rate) * 0.01f; return (1.0f + 192.0f * r * (r * r * r * r + 0.3333f)) / (21.3f * 44100.0f); } const float kMinLFOFrequency = 0.005865f; // Convert an LFO rate from 0-99 to a frequency. inline float LFOFrequency(int rate) { int rate_scaled = rate == 0 ? 1 : (rate * 165) >> 6; rate_scaled *= rate_scaled < 160 ? 11 : (11 + ((rate_scaled - 160) >> 4)); return float(rate_scaled) * kMinLFOFrequency; } // Convert an LFO delay from 0-99 to the two increments. inline void LFODelay(int delay, float increments[2]) { if (delay == 0) { increments[0] = increments[1] = 100000.0f; } else { int d = 99 - delay; d = (16 + (d & 15)) << (1 + (d >> 4)); increments[0] = float(d) * kMinLFOFrequency; increments[1] = float(std::max(0x80, d & 0xff80)) * kMinLFOFrequency; } } // Pre-process the velocity to easily compute the velocity scaling. inline float NormalizeVelocity(float velocity) { // float cube_root = stmlib::Sqrt( // 0.7f * stmlib::Sqrt(velocity) + 0.3f * velocity); const float cube_root = stmlib::Interpolate(lut_cube_root, velocity, 16); return 16.0f * (cube_root - 0.918f); } // MIDI note to envelope increment ratio. inline float RateScaling(float note, int rate_scaling) { return Pow2Fast<1>( float(rate_scaling) * (note * 0.33333f - 7.0f) * 0.03125f); } // Operator amplitude modulation sensitivity (0-3). inline float AmpModSensitivity(int amp_mod_sensitivity) { return lut_amp_mod_sensitivity[amp_mod_sensitivity]; } // Pitch modulation sensitivity (0-7). inline float PitchModSensitivity(int pitch_mod_sensitivity) { return lut_pitch_mod_sensitivity[pitch_mod_sensitivity]; } // Keyboard tracking to TL adjustment. inline float KeyboardScaling(float note, const Patch::KeyboardScaling& ks) { const float x = note - float(ks.break_point) - 15.0f; const int curve = x > 0.0f ? ks.right_curve : ks.left_curve; float t = fabsf(x); if (curve == 1 || curve == 2) { t = std::min(t * 0.010467f, 1.0f); t = t * t * t; t *= 96.0f; } if (curve < 2) { t = -t; } float depth = float(x > 0.0f ? ks.right_depth : ks.left_depth); return t * depth * 0.02677f; } inline float FrequencyRatio(const Patch::Operator& op) { const float detune = op.mode == 0 && op.fine ? 1.0f + 0.01f * float(op.fine) : 1.0f; float base = op.mode == 0 ? lut_coarse[op.coarse] : float(int(op.coarse & 3) * 100 + op.fine) * 0.39864f; base += (float(op.detune) - 7.0f) * 0.015f; return stmlib::SemitonesToRatioSafe(base) * detune; } } // namespace fm } // namespace plaits #endif // PLAITS_DSP_DX_UNITS_H_ ================================================ FILE: lib/plaits/dsp/fm/envelope.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Multi-segment envelope generator. // // The classic constant-time design (as found in many other MI products) might // cause differences in behavior from the original DX-series envelopes, in // particular when jumping to the last segment before having reached the sustain // phase. // // The unusual RenderAtSample() method allows the evaluation of the envelope at // an arbitrary point in time, used in Plaits' "envelope scrubbing" feature. // // A couple of quirks from the DX-series' operator envelopes are implemented, // namely: // - vaguely logarithmic shape for ascending segments. // - direct jump above a threshold for ascending segments. // - specific logic and rates for plateaus. #ifndef PLAITS_DSP_FM_ENVELOPE_H_ #define PLAITS_DSP_FM_ENVELOPE_H_ #include "stmlib/stmlib.h" #include #include "plaits/dsp/fm/dx_units.h" namespace plaits { namespace fm { template class Envelope { public: Envelope() { } ~Envelope() { } enum { NUM_STAGES = num_stages, PREVIOUS_LEVEL = -100 }; inline void Init() { Init(1.0f); } inline void Init(float scale) { scale_ = scale; stage_ = num_stages - 1; phase_ = 1.0f; start_ = 0.0f; for (int i = 0; i < num_stages; ++i) { increment_[i] = 0.001f; level_[i] = 1.0f / float(1 << i); } level_[num_stages - 1] = 0.0f; } // Directly copy the variables. void Set(const float increment[num_stages], const float level[num_stages]) { std::copy(&increment[0], &increment[num_stages], &increment_[0]); std::copy(&level[0], &level[num_stages], &level_[0]); } inline float RenderAtSample(float t, const float gate_duration) { if (t > gate_duration) { // Check how far we are into the release phase. const float phase = (t - gate_duration) * increment_[num_stages - 1]; return phase >= 1.0f ? level_[num_stages - 1] : value(num_stages - 1, phase, RenderAtSample(gate_duration, gate_duration)); } int stage = 0; for (; stage < num_stages - 1; ++stage) { const float stage_duration = 1.0f / increment_[stage]; if (t < stage_duration) { break; } t -= stage_duration; } if (stage == num_stages - 1) { t -= gate_duration; if (t <= 0.0f) { // TODO(pichenettes): this should always be true. return level_[num_stages - 2]; } else if (t * increment_[num_stages - 1] > 1.0f) { return level_[num_stages - 1]; } } return value(stage, t * increment_[stage], PREVIOUS_LEVEL); } inline float Render(bool gate) { return Render(gate, 1.0f, 1.0f, 1.0f); } inline float Render( bool gate, float rate, float ad_scale, float release_scale) { if (gate) { if (stage_ == num_stages - 1) { start_ = value(); stage_ = 0; phase_ = 0.0f; } } else { if (stage_ != num_stages - 1) { start_ = value(); stage_ = num_stages - 1; phase_ = 0.0f; } } phase_ += increment_[stage_] * rate * \ (stage_ == num_stages - 1 ? release_scale : ad_scale); if (phase_ >= 1.0f) { if (stage_ >= num_stages - 2) { phase_ = 1.0f; } else { phase_ = 0.0f; ++stage_; } start_ = PREVIOUS_LEVEL; } return value(); } private: inline float value() { return value(stage_, phase_, start_); } inline float value(int stage, float phase, float start_level) { float from = start_level == PREVIOUS_LEVEL ? level_[(stage - 1 + num_stages) % num_stages] : start_level; float to = level_[stage]; if (reshape_ascending_segments && from < to) { from = std::max(6.7f, from); to = std::max(6.7f, to); phase *= (2.5f - phase) * 0.666667f; } return phase * (to - from) + from; } int stage_; float phase_; float start_; protected: float increment_[num_stages]; float level_[num_stages]; float scale_; DISALLOW_COPY_AND_ASSIGN(Envelope); }; class OperatorEnvelope : public Envelope<4, true> { public: void Set(const uint8_t rate[NUM_STAGES], const uint8_t level[NUM_STAGES], uint8_t global_level) { // Configure levels. for (int i = 0; i < NUM_STAGES; ++i) { int level_scaled = OperatorLevel(level[i]); level_scaled = (level_scaled & ~1) + global_level - 133; // 125 ? level_[i] = 0.125f * \ (level_scaled < 1 ? 0.5f : static_cast(level_scaled)); } // Configure increments. for (int i = 0; i < NUM_STAGES; ++i) { float increment = OperatorEnvelopeIncrement(rate[i]); float from = level_[(i - 1 + NUM_STAGES) % NUM_STAGES]; float to = level_[i]; if (from == to) { // Quirk: for plateaux, the increment is scaled. increment *= 0.6f; if (i == 0 && !level[i]) { // Quirk: the attack plateau is faster. increment *= 20.0f; } } else if (from < to) { from = std::max(6.7f, from); to = std::max(6.7f, to); if (from == to) { // Quirk: because of the jump, the attack might disappear. increment = 1.0f; } else { // Quirk: because of the weird shape, the rate is adjusted. increment *= 7.2f / (to - from); } } else { increment *= 1.0f / (from - to); } increment_[i] = increment * scale_; } } }; class PitchEnvelope : public Envelope<4, false> { public: void Set(const uint8_t rate[NUM_STAGES], const uint8_t level[NUM_STAGES]) { // Configure levels. for (int i = 0; i < NUM_STAGES; ++i) { level_[i] = PitchEnvelopeLevel(level[i]); } // Configure increments. for (int i = 0; i < NUM_STAGES; ++i) { float from = level_[(i - 1 + NUM_STAGES) % NUM_STAGES]; float to = level_[i]; float increment = PitchEnvelopeIncrement(rate[i]); if (from != to) { increment *= 1.0f / fabsf(from - to); } else if (i != NUM_STAGES - 1) { increment = 0.2f; } increment_[i] = increment * scale_; } } }; } // namespace fm } // namespace plaits #endif // PLAITS_DSP_FM_ENVELOPE_H_ ================================================ FILE: lib/plaits/dsp/fm/lfo.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // DX7-compatible LFO. #ifndef PLAITS_DSP_FM_LFO_H_ #define PLAITS_DSP_FM_LFO_H_ #include "stmlib/stmlib.h" #include "stmlib/utils/random.h" #include "plaits/dsp/fm/dx_units.h" #include "plaits/dsp/fm/patch.h" #include "plaits/dsp/oscillator/sine_oscillator.h" namespace plaits { namespace fm { class Lfo { public: Lfo() { }; ~Lfo() { }; enum Waveform { WAVEFORM_TRIANGLE, WAVEFORM_RAMP_DOWN, WAVEFORM_RAMP_UP, WAVEFORM_SQUARE, WAVEFORM_SINE, WAVEFORM_S_AND_H }; inline void Init(float sample_rate) { phase_ = 0.0f; frequency_ = 0.1f; delay_phase_ = 0.0f; delay_increment_[0] = delay_increment_[1] = 0.1f; random_value_ = value_ = 0.0f; one_hz_ = 1.0f / sample_rate; amp_mod_depth_ = 0.0f; pitch_mod_depth_ = 0.0f; waveform_ = WAVEFORM_TRIANGLE; reset_phase_ = false; phase_integral_ = 0; } inline void Set(const Patch::ModulationParameters& modulations) { frequency_ = LFOFrequency(modulations.rate) * one_hz_; LFODelay(modulations.delay, delay_increment_); delay_increment_[0] *= one_hz_; delay_increment_[1] *= one_hz_; waveform_ = Waveform(modulations.waveform); reset_phase_ = modulations.reset_phase != 0; amp_mod_depth_ = float(modulations.amp_mod_depth) * 0.01f; pitch_mod_depth_ = float(modulations.pitch_mod_depth) * 0.01f * \ PitchModSensitivity(modulations.pitch_mod_sensitivity); } inline void Reset() { if (reset_phase_) { phase_ = 0.0f; } delay_phase_ = 0.0f; } inline void Step(float scale) { phase_ += scale * frequency_; if (phase_ >= 1.0f) { phase_ -= 1.0f; random_value_ = stmlib::Random::GetFloat(); } value_ = value(); delay_phase_ += scale * delay_increment_[(delay_phase_ < 0.5f) ? 0 : 1]; if (delay_phase_ >= 1.0f) { delay_phase_ = 1.0f; } } inline void Scrub(float sample) { float phase = sample * frequency_; MAKE_INTEGRAL_FRACTIONAL(phase) phase_ = phase_fractional; if (phase_integral != phase_integral_) { phase_integral_ = phase_integral; random_value_ = stmlib::Random::GetFloat(); } value_ = value(); delay_phase_ = sample * delay_increment_[0]; if (delay_phase_ > 0.5f) { sample -= 0.5f / delay_increment_[0]; delay_phase_ = 0.5f + sample * delay_increment_[1]; if (delay_phase_ >= 1.0f) { delay_phase_ = 1.0f; } } } inline float value() const { switch (waveform_) { case WAVEFORM_TRIANGLE: return 2.0f * (phase_ < 0.5f ? 0.5f - phase_ : phase_ - 0.5f); case WAVEFORM_RAMP_DOWN: return 1.0f - phase_; case WAVEFORM_RAMP_UP: return phase_; case WAVEFORM_SQUARE: return phase_ < 0.5f ? 0.0f : 1.0f; case WAVEFORM_SINE: return 0.5f + 0.5f * Sine(phase_ + 0.5f); case WAVEFORM_S_AND_H: return random_value_; } return 0.0f; } inline float delay_ramp() const { return delay_phase_ < 0.5f ? 0.0f : (delay_phase_ - 0.5f) * 2.0f; } inline float pitch_mod() const { return (value_ - 0.5f) * delay_ramp() * pitch_mod_depth_; } inline float amp_mod() const { return (1.0f - value_) * delay_ramp() * amp_mod_depth_; } private: float phase_; float frequency_; float delay_phase_; float delay_increment_[2]; float value_; float random_value_; float one_hz_; float amp_mod_depth_; float pitch_mod_depth_; Waveform waveform_; bool reset_phase_; int phase_integral_; DISALLOW_COPY_AND_ASSIGN(Lfo); }; } // namespace fm } // namespace plaits #endif // PLAITS_DSP_FM_LFO_H_ ================================================ FILE: lib/plaits/dsp/fm/operator.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // FM Operator. #ifndef PLAITS_DSP_FM_OPERATOR_H_ #define PLAITS_DSP_FM_OPERATOR_H_ #include #include "plaits/dsp/oscillator/sine_oscillator.h" #include "stmlib/dsp/dsp.h" namespace plaits { namespace fm { struct Operator { enum ModulationSource { MODULATION_SOURCE_EXTERNAL = -2, MODULATION_SOURCE_NONE = -1, MODULATION_SOURCE_FEEDBACK = 0 }; inline void Reset() { phase = 0; amplitude = 0.0f; } uint32_t phase; float amplitude; }; typedef void (*RenderFn)( Operator* ops, const float* f, const float* a, float* fb_state, int fb_amount, const float* modulation, float* out, size_t size); template void RenderOperators( Operator* ops, const float* f, const float* a, float* fb_state, int fb_amount, const float* modulation, float* out, size_t size) { float previous_0, previous_1; if (modulation_source >= Operator::MODULATION_SOURCE_FEEDBACK) { previous_0 = fb_state[0]; previous_1 = fb_state[1]; } uint32_t frequency[n]; uint32_t phase[n]; float amplitude[n]; float amplitude_increment[n]; const float scale = 1.0f / float(size); for (int i = 0; i < n; ++i) { frequency[i] = static_cast(std::min(f[i], 0.5f) * 4294967296.0f); phase[i] = ops[i].phase; amplitude[i] = ops[i].amplitude; amplitude_increment[i] = (std::min(a[i], 4.0f) - amplitude[i]) * scale; } const float fb_scale = fb_amount ? float(1 << fb_amount) / 512.0f : 0.0f; while (size--) { float pm = 0.0f; if (modulation_source >= Operator::MODULATION_SOURCE_FEEDBACK) { pm = (previous_0 + previous_1) * fb_scale; } else if (modulation_source == Operator::MODULATION_SOURCE_EXTERNAL) { pm = *modulation++; } for (int i = 0; i < n; ++i) { phase[i] += frequency[i]; pm = SinePM(phase[i], pm) * amplitude[i]; amplitude[i] += amplitude_increment[i]; if (i == modulation_source) { previous_1 = previous_0; previous_0 = pm; } } if (additive) { *out++ += pm; } else { *out++ = pm; } } for (int i = 0; i < n; ++i) { ops[i].phase = phase[i]; ops[i].amplitude = amplitude[i]; } if (modulation_source >= Operator::MODULATION_SOURCE_FEEDBACK) { fb_state[0] = previous_0; fb_state[1] = previous_1; } }; } // namespace fm } // namespace plaits #endif // PLAITS_DSP_FM_OPERATOR_H_ ================================================ FILE: lib/plaits/dsp/fm/patch.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // DX7 patch. #ifndef PLAITS_DSP_FM_PATCH_H_ #define PLAITS_DSP_FM_PATCH_H_ #include "stmlib/stmlib.h" namespace plaits { namespace fm { struct Patch { enum { SYX_SIZE = 128 }; // The layout conveniently matches the 156 bytes SysEx format. struct Envelope { uint8_t rate[4]; uint8_t level[4]; }; struct KeyboardScaling { uint8_t break_point; uint8_t left_depth; uint8_t right_depth; uint8_t left_curve; uint8_t right_curve; }; struct Operator { Envelope envelope; KeyboardScaling keyboard_scaling; uint8_t rate_scaling; uint8_t amp_mod_sensitivity; uint8_t velocity_sensitivity; uint8_t level; uint8_t mode; uint8_t coarse; uint8_t fine; // x frequency by 1 + 0.01 x fine uint8_t detune; } op[6]; Envelope pitch_envelope; uint8_t algorithm; uint8_t feedback; uint8_t reset_phase; struct ModulationParameters { uint8_t rate; uint8_t delay; uint8_t pitch_mod_depth; uint8_t amp_mod_depth; uint8_t reset_phase; uint8_t waveform; uint8_t pitch_mod_sensitivity; } modulations; uint8_t transpose; uint8_t name[10]; uint8_t active_operators; inline uint8_t* bytes() { return static_cast(static_cast(this)); } inline void Unpack(const uint8_t* data) { for (int i = 0; i < 6; ++i) { Operator* o = &op[i]; const uint8_t* op_data = &data[i * 17]; for (int j = 0; j < 4; ++j) { o->envelope.rate[j] = std::min(op_data[j] & 0x7f, 99); o->envelope.level[j] = std::min(op_data[4 + j] & 0x7f, 99); } o->keyboard_scaling.break_point = std::min(op_data[8] & 0x7f, 99); o->keyboard_scaling.left_depth = std::min(op_data[9] & 0x7f, 99); o->keyboard_scaling.right_depth = std::min(op_data[10] & 0x7f, 99); o->keyboard_scaling.left_curve = op_data[11] & 0x3; o->keyboard_scaling.right_curve = (op_data[11] >> 2) & 0x3; o->rate_scaling = op_data[12] & 0x7; o->amp_mod_sensitivity = op_data[13] & 0x3; o->velocity_sensitivity = (op_data[13] >> 2) & 0x7; o->level = std::min(op_data[14] & 0x7f, 99); o->mode = op_data[15] & 0x1; o->coarse = (op_data[15] >> 1) & 0x1f; o->fine = std::min(op_data[16] & 0x7f, 99); o->detune = std::min((op_data[12] >> 3) & 0xf, 14); } for (int j = 0; j < 4; ++j) { pitch_envelope.rate[j] = std::min(data[102 + j] & 0x7f, 99); pitch_envelope.level[j] = std::min(data[106 + j] & 0x7f, 99); } algorithm = data[110] & 0x1f; feedback = data[111] & 0x7; reset_phase = (data[111] >> 3) & 0x1; modulations.rate = std::min(data[112] & 0x7f, 99); modulations.delay = std::min(data[113] & 0x7f, 99); modulations.pitch_mod_depth = std::min(data[114] & 0x7f, 99); modulations.amp_mod_depth = std::min(data[115] & 0x7f, 99); modulations.reset_phase = data[116] & 0x1; modulations.waveform = std::min((data[116] >> 1) & 0x7, 5); modulations.pitch_mod_sensitivity = data[116] >> 4; transpose = std::min(data[117] & 0x7f, 48); for (size_t i = 0; i < sizeof(name); ++i) { name[i] = data[118 + i] & 0x7f; } active_operators = 0x3f; } }; } // namespace fm } // namespace plaits #endif // PLAITS_DSP_FM_PATCH_H_ ================================================ FILE: lib/plaits/dsp/fm/voice.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // DX7 voice. #ifndef PLAITS_DSP_FM_VOICE_H_ #define PLAITS_DSP_FM_VOICE_H_ #include "stmlib/stmlib.h" #include "plaits/dsp/fm/algorithms.h" #include "plaits/dsp/fm/dx_units.h" #include "plaits/dsp/fm/envelope.h" #include "plaits/dsp/fm/patch.h" // When enabled, the amplitude modulation LFO linearly modulates the amplitude // of an operator. Otherwise, a more complex formula involving an exponential // is used, to match Dexed's output. // #define FAST_OP_LEVEL_MODULATION namespace plaits { namespace fm { template class Voice { public: Voice() { } ~Voice() { } struct Parameters { bool sustain; bool gate; float note; float velocity; float brightness; float envelope_control; float pitch_mod; float amp_mod; }; inline void Init( const Algorithms* algorithms, float sample_rate) { algorithms_ = algorithms; sample_rate_ = sample_rate; one_hz_ = 1.0f / sample_rate; a0_ = 55.0f / sample_rate; const float native_sr = 44100.0f; // Legacy sample rate. const float envelope_scale = native_sr * one_hz_; for (int i = 0; i < num_operators; ++i) { operator_[i].Reset(); operator_envelope_[i].Init(envelope_scale); } pitch_envelope_.Init(envelope_scale); feedback_state_[0] = feedback_state_[1] = 0.0f; patch_ = NULL; gate_ = false; note_ = 48.0f; normalized_velocity_ = 10.0f; dirty_ = true; } inline void SetPatch(const Patch* patch) { patch_ = patch; dirty_ = true; } // Pre-compute everything that can be pre-computed once a patch is loaded: // - envelope constants // - frequency ratios inline bool Setup() { if (!dirty_) { return false; } pitch_envelope_.Set( patch_->pitch_envelope.rate, patch_->pitch_envelope.level); for (int i = 0; i < num_operators; ++i) { const Patch::Operator& op = patch_->op[i]; int level = OperatorLevel(op.level); operator_envelope_[i].Set(op.envelope.rate, op.envelope.level, level); // The level increase caused by keyboard scaling plus velocity // scaling should not exceed this number - otherwise it would be // equivalent to have an operator with a level above 99. level_headroom_[i] = float(127 - level); // Pre-compute frequency ratios. Encode the base frequency // (1Hz or the root note) as the sign of the ratio. float sign = op.mode == 0 ? 1.0f : -1.0f; ratios_[i] = sign * FrequencyRatio(op); } dirty_ = false; return true; } inline float op_level(int i) const { return level_[i]; } inline void Render( const Parameters& parameters, float* temp, float* out, float* aux, size_t size) { float* buffers[4] = { out, aux, temp, temp }; Render(parameters, buffers, size); } inline void Render( const Parameters& parameters, float* temp, size_t size) { float* buffers[4] = { temp, temp + size, temp + 2 * size, temp + 2 * size }; Render(parameters, buffers, size); } inline void Render( const Parameters& parameters, float* buffers[4], size_t size) { if (Setup()) { // This prevents a CPU overrun, since there is not enough CPU to perform // both a patch setup and a full render in the time alloted for // a render. As a drawback, this causes a 0.5ms blank before a new // patch starts playing. But this is a clean blank, as opposed to a // glitchy overrun. return; } const float envelope_rate = float(size); const float ad_scale = Pow2Fast<1>( (0.5f - parameters.envelope_control) * 8.0f); const float r_scale = Pow2Fast<1>( -fabsf(parameters.envelope_control - 0.3f) * 8.0f); const float gate_duration = 1.5f * sample_rate_; const float envelope_sample = gate_duration * parameters.envelope_control; // Apply LFO and pitch envelope modulations. const float pitch_envelope = parameters.sustain ? pitch_envelope_.RenderAtSample(envelope_sample, gate_duration) : pitch_envelope_.Render( parameters.gate, envelope_rate, ad_scale, r_scale); const float pitch_mod = pitch_envelope + parameters.pitch_mod; const float f0 = a0_ * 0.25f * stmlib::SemitonesToRatioSafe( parameters.note - 9.0f + pitch_mod * 12.0f); // Sample the note and velocity (used for scaling) only when a trigger // is received, or constantly when we are in free-running mode. const bool note_on = parameters.gate && !gate_; gate_ = parameters.gate; if (note_on || parameters.sustain) { normalized_velocity_ = NormalizeVelocity(parameters.velocity); note_ = parameters.note; } // Reset operator phase if a note on is detected & if the patch requires it. if (note_on && patch_->reset_phase) { for (int i = 0; i < num_operators; ++i) { operator_[i].phase = 0; } } // Compute frequencies and amplitudes. float f[num_operators]; float a[num_operators]; for (int i = 0; i < num_operators; ++i) { const Patch::Operator& op = patch_->op[i]; f[i] = ratios_[i] * (ratios_[i] < 0.0f ? -one_hz_ : f0); const float rate_scaling = RateScaling(note_, op.rate_scaling); float level = parameters.sustain ? operator_envelope_[i].RenderAtSample(envelope_sample, gate_duration) : operator_envelope_[i].Render( parameters.gate, envelope_rate * rate_scaling, ad_scale, r_scale); const float kb_scaling = KeyboardScaling(note_, op.keyboard_scaling); const float velocity_scaling = normalized_velocity_ * \ float(op.velocity_sensitivity); const float brightness = algorithms_->is_modulator(patch_->algorithm, i) ? (parameters.brightness - 0.5f) * 32.0f : 0.0f; level += 0.125f * std::min( kb_scaling + velocity_scaling + brightness, level_headroom_[i]); level_[i] = level; const float sensitivity = AmpModSensitivity(op.amp_mod_sensitivity); #ifdef FAST_OP_LEVEL_MODULATION const float level_mod = 1.0f - sensitivity * parameters.amp_mod; a[i] = Pow2Fast<2>(-14.0f + level) * level_mod; #else const float log_level_mod = sensitivity * parameters.amp_mod - 1.0f; const float level_mod = 1.0f - Pow2Fast<2>(6.4f * log_level_mod); a[i] = Pow2Fast<2>(-14.0f + level * level_mod); #endif // FAST_LINEAR_AMPLITUDE_MODULATION } for (int i = 0; i < num_operators; ) { const typename Algorithms::RenderCall& call = \ algorithms_->render_call(patch_->algorithm, i); (*call.render_fn)( &operator_[i], &f[i], &a[i], feedback_state_, patch_->feedback, buffers[call.input_index], buffers[call.output_index], size); i += call.n; } } private: const Algorithms* algorithms_; float sample_rate_; float one_hz_; float a0_; bool gate_; Operator operator_[num_operators]; OperatorEnvelope operator_envelope_[num_operators]; PitchEnvelope pitch_envelope_; float normalized_velocity_; float note_; float ratios_[num_operators]; float level_headroom_[num_operators]; float level_[num_operators]; float feedback_state_[2]; const Patch* patch_; bool dirty_; DISALLOW_COPY_AND_ASSIGN(Voice); }; } // namespace fm } // namespace plaits #endif // PLAITS_DSP_FM_VOICE_H_ ================================================ FILE: lib/plaits/dsp/fx/diffuser.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Granular diffuser. #ifndef PLAITS_DSP_FX_DIFFUSER_H_ #define PLAITS_DSP_FX_DIFFUSER_H_ #include "stmlib/stmlib.h" #include "plaits/dsp/fx/fx_engine.h" namespace plaits { class Diffuser { public: Diffuser() { } ~Diffuser() { } void Init(uint16_t* buffer) { engine_.Init(buffer); engine_.SetLFOFrequency(LFO_1, 0.3f / 48000.0f); lp_decay_ = 0.0f; } void Reset() { engine_.Clear(); } void Process(float amount, float rt, float* in_out, size_t size) { typedef E::Reserve<126, E::Reserve<180, E::Reserve<269, E::Reserve<444, E::Reserve<1653, E::Reserve<2010, E::Reserve<3411> > > > > > > Memory; E::DelayLine ap1; E::DelayLine ap2; E::DelayLine ap3; E::DelayLine ap4; E::DelayLine dapa; E::DelayLine dapb; E::DelayLine del; E::Context c; const float kap = 0.625f; const float klp = 0.75f; float lp = lp_decay_; while (size--) { float wet; engine_.Start(&c); c.Read(*in_out); c.Read(ap1 TAIL, kap); c.WriteAllPass(ap1, -kap); c.Read(ap2 TAIL, kap); c.WriteAllPass(ap2, -kap); c.Read(ap3 TAIL, kap); c.WriteAllPass(ap3, -kap); c.Interpolate(ap4, 400.0f, LFO_1, 43.0f, kap); c.WriteAllPass(ap4, -kap); c.Interpolate(del, 3070.0f, LFO_1, 340.0f, rt); c.Lp(lp, klp); c.Read(dapa TAIL, -kap); c.WriteAllPass(dapa, kap); c.Read(dapb TAIL, kap); c.WriteAllPass(dapb, -kap); c.Write(del, 2.0f); c.Write(wet, 0.0f); *in_out += amount * (wet - *in_out); ++in_out; } lp_decay_ = lp; } private: typedef FxEngine<8192, FORMAT_12_BIT> E; E engine_; float lp_decay_; DISALLOW_COPY_AND_ASSIGN(Diffuser); }; } // namespace plaits #endif // PLAITS_DSP_FX_DIFFUSER_H_ ================================================ FILE: lib/plaits/dsp/fx/ensemble.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Ensemble FX. #ifndef PLAITS_DSP_FX_ENSEMBLE_H_ #define PLAITS_DSP_FX_ENSEMBLE_H_ #include "stmlib/stmlib.h" #include "stmlib/dsp/dsp.h" #include "plaits/dsp/oscillator/sine_oscillator.h" #include "plaits/dsp/fx/fx_engine.h" #include "plaits/resources.h" namespace plaits { class Ensemble { public: typedef FxEngine<1024, FORMAT_32_BIT> E; Ensemble() { } ~Ensemble() { } void Init(E::T* buffer) { engine_.Init(buffer); phase_1_ = 0; phase_2_ = 0; } void Reset() { engine_.Clear(); } void Process(float* left, float* right, size_t size) { typedef E::Reserve<511, E::Reserve<511> > Memory; E::DelayLine line_l; E::DelayLine line_r; E::Context c; while (size--) { engine_.Start(&c); float dry_amount = 1.0f - amount_ * 0.5f; // Update LFO. const uint32_t one_third = 1417339207UL; const uint32_t two_third = 2834678415UL; phase_1_ += 67289; // 0.75 Hz phase_2_ += 589980; // 6.57 Hz float slow_0 = SineRaw(phase_1_); float slow_120 = SineRaw(phase_1_ + one_third); float slow_240 = SineRaw(phase_1_ + two_third); float fast_0 = SineRaw(phase_2_); float fast_120 = SineRaw(phase_2_ + one_third); float fast_240 = SineRaw(phase_2_ + two_third); // Max deviation: 176 float a = depth_ * 160.0f; float b = depth_ * 16.0f; float mod_1 = slow_0 * a + fast_0 * b; float mod_2 = slow_120 * a + fast_120 * b; float mod_3 = slow_240 * a + fast_240 * b; float wet = 0.0f; // Sum L & R channel to send to chorus line. c.Read(*left, 1.0f); c.Write(line_l, 0.0f); c.Read(*right, 1.0f); c.Write(line_r, 0.0f); c.Interpolate(line_l, mod_1 + 192, 0.33f); c.Interpolate(line_l, mod_2 + 192, 0.33f); c.Interpolate(line_r, mod_3 + 192, 0.33f); c.Write(wet, 0.0f); *left = wet * amount_ + *left * dry_amount; c.Interpolate(line_r, mod_1 + 192, 0.33f); c.Interpolate(line_r, mod_2 + 192, 0.33f); c.Interpolate(line_l, mod_3 + 192, 0.33f); c.Write(wet, 0.0f); *right = wet * amount_ + *right * dry_amount; left++; right++; } } inline void set_amount(float amount) { amount_ = amount; } inline void set_depth(float depth) { depth_ = depth; } private: E engine_; float amount_; float depth_; uint32_t phase_1_; uint32_t phase_2_; DISALLOW_COPY_AND_ASSIGN(Ensemble); }; } // namespace plaits #endif // PLAITS_DSP_FX_ENSEMBLE_H_ ================================================ FILE: lib/plaits/dsp/fx/fx_engine.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Base class for building reverbs. #ifndef PLAITS_DSP_FX_FX_ENGINE_H_ #define PLAITS_DSP_FX_FX_ENGINE_H_ #include #include "stmlib/stmlib.h" #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/cosine_oscillator.h" namespace plaits { #define TAIL , -1 enum Format { FORMAT_12_BIT, FORMAT_16_BIT, FORMAT_32_BIT }; enum LFOIndex { LFO_1, LFO_2 }; template struct DataType { }; template<> struct DataType { typedef uint16_t T; static inline float Decompress(T value) { return static_cast(static_cast(value)) / 4096.0f; } static inline T Compress(float value) { return static_cast( stmlib::Clip16(static_cast(value * 4096.0f))); } }; template<> struct DataType { typedef uint16_t T; static inline float Decompress(T value) { return static_cast(static_cast(value)) / 32768.0f; } static inline T Compress(float value) { return static_cast( stmlib::Clip16(static_cast(value * 32768.0f))); } }; template<> struct DataType { typedef float T; static inline float Decompress(T value) { return value;; } static inline T Compress(float value) { return value; } }; template< size_t size, Format format = FORMAT_12_BIT> class FxEngine { public: typedef typename DataType::T T; FxEngine() { } ~FxEngine() { } void Init(T* buffer) { buffer_ = buffer; } void Clear() { std::fill(&buffer_[0], &buffer_[size], 0); write_ptr_ = 0; } struct Empty { }; template struct Reserve { typedef T Tail; enum { length = l }; }; template struct DelayLine { enum { length = DelayLine::length, base = DelayLine::base + DelayLine::length + 1 }; }; template struct DelayLine { enum { length = Memory::length, base = 0 }; }; class Context { friend class FxEngine; public: Context() { } ~Context() { } inline void Load(float value) { accumulator_ = value; } inline void Read(float value, float scale) { accumulator_ += value * scale; } inline void Read(float value) { accumulator_ += value; } inline void Write(float& value) { value = accumulator_; } inline void Write(float& value, float scale) { value = accumulator_; accumulator_ *= scale; } template inline void Write(D& d, int32_t offset, float scale) { STATIC_ASSERT(D::base + D::length <= size, delay_memory_full); T w = DataType::Compress(accumulator_); if (offset == -1) { buffer_[(write_ptr_ + D::base + D::length - 1) & MASK] = w; } else { buffer_[(write_ptr_ + D::base + offset) & MASK] = w; } accumulator_ *= scale; } template inline void Write(D& d, float scale) { Write(d, 0, scale); } template inline void WriteAllPass(D& d, int32_t offset, float scale) { Write(d, offset, scale); accumulator_ += previous_read_; } template inline void WriteAllPass(D& d, float scale) { WriteAllPass(d, 0, scale); } template inline void Read(D& d, int32_t offset, float scale) { STATIC_ASSERT(D::base + D::length <= size, delay_memory_full); T r; if (offset == -1) { r = buffer_[(write_ptr_ + D::base + D::length - 1) & MASK]; } else { r = buffer_[(write_ptr_ + D::base + offset) & MASK]; } float r_f = DataType::Decompress(r); previous_read_ = r_f; accumulator_ += r_f * scale; } template inline void Read(D& d, float scale) { Read(d, 0, scale); } inline void Lp(float& state, float coefficient) { state += coefficient * (accumulator_ - state); accumulator_ = state; } inline void Hp(float& state, float coefficient) { state += coefficient * (accumulator_ - state); accumulator_ -= state; } template inline void Interpolate(D& d, float offset, float scale) { STATIC_ASSERT(D::base + D::length <= size, delay_memory_full); MAKE_INTEGRAL_FRACTIONAL(offset); float a = DataType::Decompress( buffer_[(write_ptr_ + offset_integral + D::base) & MASK]); float b = DataType::Decompress( buffer_[(write_ptr_ + offset_integral + D::base + 1) & MASK]); float x = a + (b - a) * offset_fractional; previous_read_ = x; accumulator_ += x * scale; } template inline void Interpolate( D& d, float offset, LFOIndex index, float amplitude, float scale) { STATIC_ASSERT(D::base + D::length <= size, delay_memory_full); offset += amplitude * lfo_value_[index]; MAKE_INTEGRAL_FRACTIONAL(offset); float a = DataType::Decompress( buffer_[(write_ptr_ + offset_integral + D::base) & MASK]); float b = DataType::Decompress( buffer_[(write_ptr_ + offset_integral + D::base + 1) & MASK]); float x = a + (b - a) * offset_fractional; previous_read_ = x; accumulator_ += x * scale; } private: float accumulator_; float previous_read_; float lfo_value_[2]; T* buffer_; int32_t write_ptr_; DISALLOW_COPY_AND_ASSIGN(Context); }; inline void SetLFOFrequency(LFOIndex index, float frequency) { lfo_[index].template Init(frequency * 32.0f); } inline void Start(Context* c) { --write_ptr_; if (write_ptr_ < 0) { write_ptr_ += size; } c->accumulator_ = 0.0f; c->previous_read_ = 0.0f; c->buffer_ = buffer_; c->write_ptr_ = write_ptr_; if ((write_ptr_ & 31) == 0) { c->lfo_value_[0] = lfo_[0].Next(); c->lfo_value_[1] = lfo_[1].Next(); } else { c->lfo_value_[0] = lfo_[0].value(); c->lfo_value_[1] = lfo_[1].value(); } } private: enum { MASK = size - 1 }; int32_t write_ptr_; T* buffer_; stmlib::CosineOscillator lfo_[2]; DISALLOW_COPY_AND_ASSIGN(FxEngine); }; } // namespace plaits #endif // PLAITS_DSP_FX_FX_ENGINE_H_ ================================================ FILE: lib/plaits/dsp/fx/low_pass_gate.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Approximative low pass gate. #ifndef PLAITS_DSP_FX_LOW_PASS_GATE_H_ #define PLAITS_DSP_FX_LOW_PASS_GATE_H_ #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/filter.h" #include "stmlib/dsp/parameter_interpolator.h" namespace plaits { class LowPassGate { public: LowPassGate() { } ~LowPassGate() { } void Init() { previous_gain_ = 0.0f; filter_.Init(); } void Process( float gain, float frequency, float hf_bleed, float* in_out, size_t size) { stmlib::ParameterInterpolator gain_modulation(&previous_gain_, gain, size); filter_.set_f_q(frequency, 0.4f); while (size--) { const float s = *in_out * gain_modulation.Next(); const float lp = filter_.Process(s); *in_out++ = lp + (s - lp) * hf_bleed; } } void Process( float gain, float frequency, float hf_bleed, float* in, short* out, size_t size, size_t stride) { stmlib::ParameterInterpolator gain_modulation(&previous_gain_, gain, size); filter_.set_f_q(frequency, 0.4f); while (size--) { const float s = *in++ * gain_modulation.Next(); const float lp = filter_.Process(s); *out = stmlib::Clip16(1 + static_cast(lp + (s - lp) * hf_bleed)); out += stride; } } void Process( float gain, float frequency, float hf_bleed, float* in, float* out, size_t size, size_t stride) { stmlib::ParameterInterpolator gain_modulation(&previous_gain_, gain, size); filter_.set_f_q(frequency, 0.4f); while (size--) { const float s = *in++ * gain_modulation.Next(); const float lp = filter_.Process(s); *out = (lp + (s - lp) * hf_bleed); out += stride; } } private: float previous_gain_; stmlib::Svf filter_; DISALLOW_COPY_AND_ASSIGN(LowPassGate); }; } // namespace plaits #endif // PLAITS_DSP_FX_LOW_PASS_GATE_H_ ================================================ FILE: lib/plaits/dsp/fx/overdrive.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Distortion/overdrive. #ifndef PLAITS_DSP_FX_OVERDRIVE_H_ #define PLAITS_DSP_FX_OVERDRIVE_H_ #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" namespace plaits { class Overdrive { public: Overdrive() { } ~Overdrive() { } void Init() { pre_gain_ = 0.0f; post_gain_ = 0.0f; } void Process(float drive, float* in_out, size_t size) { const float drive_2 = drive * drive; const float pre_gain_a = drive * 0.5f; const float pre_gain_b = drive_2 * drive_2 * drive * 24.0f; const float pre_gain = pre_gain_a + (pre_gain_b - pre_gain_a) * drive_2; const float drive_squashed = drive * (2.0f - drive); const float post_gain = 1.0f / stmlib::SoftClip( 0.33f + drive_squashed * (pre_gain - 0.33f)); stmlib::ParameterInterpolator pre_gain_modulation( &pre_gain_, pre_gain, size); stmlib::ParameterInterpolator post_gain_modulation( &post_gain_, post_gain, size); while (size--) { float pre = pre_gain_modulation.Next() * *in_out; *in_out++ = stmlib::SoftClip(pre) * post_gain_modulation.Next(); } } private: float pre_gain_; float post_gain_; DISALLOW_COPY_AND_ASSIGN(Overdrive); }; } // namespace plaits #endif // PLAITS_DSP_FX_OVERDRIVE_H_ ================================================ FILE: lib/plaits/dsp/fx/sample_rate_reducer.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Sample rate reducer. #ifndef PLAITS_DSP_FX_SAMPLE_RATE_REDUCER_H_ #define PLAITS_DSP_FX_SAMPLE_RATE_REDUCER_H_ #include #include "stmlib/dsp/polyblep.h" namespace plaits { class SampleRateReducer { public: SampleRateReducer() { } ~SampleRateReducer() { } void Init() { phase_ = 0.0f; sample_ = 0.0f; next_sample_ = 0.0f; previous_sample_ = 0.0f; } template void Process(float frequency, float* in_out, size_t size) { if (optimized_handling_of_special_cases) { // Use fast specialized implementations for target rates close to the // original rates. Caveats: // - The size argument must be a multiple of 4. // - There will be a transition glitch between the "optimized" and the // "common case" code, so don't use this when frequency is modulated! // - The optimized code is not a truly variable reclocking, instead, // this is a crossfade between reclocking at SR / 2N and SR / N. if (frequency >= 1.0f) { return; } else if (frequency >= 0.5f) { ProcessHalf(2.0f - 2.0f * frequency, in_out, size); return; } else if (frequency >= 0.25f) { ProcessQuarter(2.0f - 4.0f * frequency, in_out, size); return; } } else { CONSTRAIN(frequency, 0.0f, 1.0f); } float previous_sample = previous_sample_; float next_sample = next_sample_; float sample = sample_; float phase = phase_; while (size--) { float this_sample = next_sample; next_sample = 0.0f; phase += frequency; if (phase >= 1.0f) { phase -= 1.0f; float t = phase / frequency; // t = 0: the transition occurred right at this sample. // t = 1: the transition occurred at the previous sample. // Use linear interpolation to recover the fractional sample. float new_sample = \ previous_sample + (*in_out - previous_sample) * (1.0f - t); float discontinuity = new_sample - sample; this_sample += discontinuity * stmlib::ThisBlepSample(t); next_sample += discontinuity * stmlib::NextBlepSample(t); sample = new_sample; } next_sample += sample; previous_sample = *in_out; *in_out++ = this_sample; } phase_ = phase; next_sample_ = next_sample; sample_ = sample; previous_sample_ = previous_sample; } private: void ProcessHalf(float amount, float* in_out, size_t size) { // assert(size % 2 == 0); while (size) { in_out[1] += (in_out[0] - in_out[1]) * amount; in_out += 2; size -= 2; } sample_ = next_sample_ = previous_sample_ = in_out[-1]; } void ProcessQuarter(float amount, float* in_out, size_t size) { // assert(size % 4 == 0); while (size) { in_out[1] = in_out[0]; in_out[2] += (in_out[0] - in_out[2]) * amount; in_out[3] = in_out[2]; in_out += 4; size -= 4; } sample_ = next_sample_ = previous_sample_ = in_out[-1]; } float phase_; float sample_; float previous_sample_; float next_sample_; DISALLOW_COPY_AND_ASSIGN(SampleRateReducer); }; } // namespace plaits #endif // PLAITS_DSP_FX_SAMPLE_RATE_REDUCER_H_ ================================================ FILE: lib/plaits/dsp/noise/clocked_noise.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Noise processed by a sample and hold running at a target frequency. #ifndef PLAITS_DSP_NOISE_CLOCKED_NOISE_H_ #define PLAITS_DSP_NOISE_CLOCKED_NOISE_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/polyblep.h" #include "stmlib/utils/random.h" namespace plaits { class ClockedNoise { public: ClockedNoise() { } ~ClockedNoise() { } void Init() { phase_ = 0.0f; sample_ = 0.0f; next_sample_ = 0.0f; frequency_ = 0.001f; } void Render(bool sync, float frequency, float* out, size_t size) { CONSTRAIN(frequency, 0.0f, 1.0f); stmlib::ParameterInterpolator fm(&frequency_, frequency, size); float next_sample = next_sample_; float sample = sample_; if (sync) { phase_ = 1.0f; } while (size--) { float this_sample = next_sample; next_sample = 0.0f; const float frequency = fm.Next(); const float raw_sample = stmlib::Random::GetFloat() * 2.0f - 1.0f; float raw_amount = 4.0f * (frequency - 0.25f); CONSTRAIN(raw_amount, 0.0f, 1.0f); phase_ += frequency; if (phase_ >= 1.0f) { phase_ -= 1.0f; float t = phase_ / frequency; float new_sample = raw_sample; float discontinuity = new_sample - sample; this_sample += discontinuity * stmlib::ThisBlepSample(t); next_sample += discontinuity * stmlib::NextBlepSample(t); sample = new_sample; } next_sample += sample; *out++ = this_sample + raw_amount * (raw_sample - this_sample); } next_sample_ = next_sample; sample_ = sample; } private: // Oscillator state. float phase_; float sample_; float next_sample_; // For interpolation of parameters. float frequency_; DISALLOW_COPY_AND_ASSIGN(ClockedNoise); }; } // namespace plaits #endif // PLAITS_DSP_NOISE_CLOCKED_NOISE_H_ ================================================ FILE: lib/plaits/dsp/noise/dust.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Randomly clocked samples. #ifndef PLAITS_DSP_NOISE_DUST_H_ #define PLAITS_DSP_NOISE_DUST_H_ #include "stmlib/utils/random.h" namespace plaits { inline float Dust(float frequency) { float inv_frequency = 1.0f / frequency; float u = stmlib::Random::GetFloat(); if (u < frequency) { return u * inv_frequency; } else { return 0.0f; } } } // namespace plaits #endif // PLAITS_DSP_NOISE_DUST_H_ ================================================ FILE: lib/plaits/dsp/noise/fractal_random_generator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Stack octaves of a noise source to generate a fractal noise. #ifndef PLAITS_DSP_NOISE_FRACTAL_RANDOM_GENERATOR_H_ #define PLAITS_DSP_NOISE_FRACTAL_RANDOM_GENERATOR_H_ #include "stmlib/stmlib.h" namespace plaits { template class FractalRandomGenerator { public: FractalRandomGenerator() { } ~FractalRandomGenerator() { } void Init() { for (int i = 0; i < order; ++i) { generator_[i].Init(); } } float Render(float frequency) { return Render(frequency, 0.5f); } float Render(float frequency, float decay) { float gain = 0.5f; float sum = 0.0f; for (int i = 0; i < order; ++i) { sum += generator_[i].Render(frequency) * gain; gain *= decay; frequency *= 2.0f; } return sum; } private: T generator_[order]; DISALLOW_COPY_AND_ASSIGN(FractalRandomGenerator); }; } // namespace plaits #endif // PLAITS_DSP_NOISE_FRACTAL_RANDOM_GENERATOR_H_ ================================================ FILE: lib/plaits/dsp/noise/particle.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Random impulse train processed by a resonant filter. #ifndef PLAITS_DSP_NOISE_PARTICLE_H_ #define PLAITS_DSP_NOISE_PARTICLE_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/filter.h" #include "stmlib/utils/random.h" namespace plaits { class Particle { public: Particle() { } ~Particle() { } inline void Init() { pre_gain_ = 0.0f; filter_.Init(); } inline void Render( bool sync, float density, float gain, float frequency, float spread, float q, float* out, float* aux, size_t size) { float u = stmlib::Random::GetFloat(); if (sync) { u = density; } bool can_radomize_frequency = true; while (size--) { float s = 0.0f; if (u <= density) { s = u * gain; if (can_radomize_frequency) { const float u = 2.0f * stmlib::Random::GetFloat() - 1.0f; const float f = std::min( stmlib::SemitonesToRatio(spread * u) * frequency, 0.25f); pre_gain_ = 0.5f / stmlib::Sqrt(q * f * stmlib::Sqrt(density)); filter_.set_f_q(f, q); // Keep the cutoff constant for this whole block. can_radomize_frequency = false; } } *aux++ += s; *out++ += filter_.Process(pre_gain_ * s); u = stmlib::Random::GetFloat(); } } private: float pre_gain_; stmlib::Svf filter_; DISALLOW_COPY_AND_ASSIGN(Particle); }; } // namespace plaits #endif // PLAITS_DSP_NOISE_PARTICLE_H_ ================================================ FILE: lib/plaits/dsp/noise/smooth_random_generator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Smooth random generator for the internal modulations. #ifndef PLAITS_DSP_NOISE_SMOOTH_RANDOM_GENERATOR_H_ #define PLAITS_DSP_NOISE_SMOOTH_RANDOM_GENERATOR_H_ #include "stmlib/stmlib.h" #include "stmlib/utils/random.h" namespace plaits { class SmoothRandomGenerator { public: SmoothRandomGenerator() { } ~SmoothRandomGenerator() { } void Init() { phase_ = 0.0f; from_ = 0.0f; interval_ = 0.0f; } float Render(float frequency) { phase_ += frequency; if (phase_ >= 1.0f) { phase_ -= 1.0f; from_ += interval_; interval_ = stmlib::Random::GetFloat() * 2.0f - 1.0f - from_; } float t = phase_ * phase_ * (3.0f - 2.0f * phase_); return from_ + interval_ * t; } private: float phase_; float from_; float interval_; DISALLOW_COPY_AND_ASSIGN(SmoothRandomGenerator); }; } // namespace plaits #endif // PLAITS_DSP_NOISE_SMOOTH_RANDOM_GENERATOR_H_ ================================================ FILE: lib/plaits/dsp/oscillator/formant_oscillator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Sinewave with aliasing-free phase reset. #ifndef PLAITS_DSP_OSCILLATOR_FORMANT_OSCILLATOR_H_ #define PLAITS_DSP_OSCILLATOR_FORMANT_OSCILLATOR_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/polyblep.h" #include "plaits/dsp/oscillator/sine_oscillator.h" namespace plaits { class FormantOscillator { public: FormantOscillator() { } ~FormantOscillator() { } void Init() { carrier_phase_ = 0.0f; formant_phase_ = 0.0f; next_sample_ = 0.0f; carrier_frequency_ = 0.0f; formant_frequency_ = 0.01f; phase_shift_ = 0.0f; } void Render( float carrier_frequency, float formant_frequency, float phase_shift, float* out, size_t size) { if (carrier_frequency >= kMaxFrequency) { carrier_frequency = kMaxFrequency; } if (formant_frequency >= kMaxFrequency) { formant_frequency = kMaxFrequency; } stmlib::ParameterInterpolator carrier_fm( &carrier_frequency_, carrier_frequency, size); stmlib::ParameterInterpolator formant_fm( &formant_frequency_, formant_frequency, size); stmlib::ParameterInterpolator pm(&phase_shift_, phase_shift, size); float next_sample = next_sample_; while (size--) { float this_sample = next_sample; next_sample = 0.0f; const float carrier_frequency = carrier_fm.Next(); const float formant_frequency = formant_fm.Next(); carrier_phase_ += carrier_frequency; if (carrier_phase_ >= 1.0f) { carrier_phase_ -= 1.0f; float reset_time = carrier_phase_ / carrier_frequency; float formant_phase_at_reset = formant_phase_ + \ (1.0f - reset_time) * formant_frequency; float before = Sine( formant_phase_at_reset + pm.subsample(1.0f - reset_time)); float after = Sine(0.0f + pm.subsample(1.0f)); float discontinuity = after - before; this_sample += discontinuity * stmlib::ThisBlepSample(reset_time); next_sample += discontinuity * stmlib::NextBlepSample(reset_time); formant_phase_ = reset_time * formant_frequency; } else { formant_phase_ += formant_frequency; if (formant_phase_ >= 1.0f) { formant_phase_ -= 1.0f; } } const float phase_shift = pm.Next(); next_sample += Sine(formant_phase_ + phase_shift); *out++ = this_sample; } next_sample_ = next_sample; } private: // Oscillator state. float carrier_phase_; float formant_phase_; float next_sample_; // For interpolation of parameters. float carrier_frequency_; float formant_frequency_; float phase_shift_; DISALLOW_COPY_AND_ASSIGN(FormantOscillator); }; } // namespace plaits #endif // PLAITS_DSP_OSCILLATOR_FORMANT_OSCILLATOR_H_ ================================================ FILE: lib/plaits/dsp/oscillator/grainlet_oscillator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // A phase-distortd single cycle sine * another continuously running sine, // the whole thing synced to a main oscillator. #ifndef PLAITS_DSP_OSCILLATOR_GRAINLET_OSCILLATOR_H_ #define PLAITS_DSP_OSCILLATOR_GRAINLET_OSCILLATOR_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/polyblep.h" #include "plaits/dsp/oscillator/oscillator.h" #include "plaits/dsp/oscillator/sine_oscillator.h" namespace plaits { class GrainletOscillator { public: GrainletOscillator() { } ~GrainletOscillator() { } void Init() { carrier_phase_ = 0.0f; formant_phase_ = 0.0f; next_sample_ = 0.0f; carrier_frequency_ = 0.0f; formant_frequency_ = 0.0f; carrier_shape_ = 0.0f; carrier_bleed_ = 0.0f; } void Render( float carrier_frequency, float formant_frequency, float carrier_shape, float carrier_bleed, float* out, size_t size) { if (carrier_frequency >= kMaxFrequency * 0.5f) { carrier_frequency = kMaxFrequency * 0.5f; } if (formant_frequency >= kMaxFrequency) { formant_frequency = kMaxFrequency; } stmlib::ParameterInterpolator carrier_frequency_modulation( &carrier_frequency_, carrier_frequency, size); stmlib::ParameterInterpolator formant_frequency_modulation( &formant_frequency_, formant_frequency, size); stmlib::ParameterInterpolator carrier_shape_modulation( &carrier_shape_, carrier_shape, size); stmlib::ParameterInterpolator carrier_bleed_modulation( &carrier_bleed_, carrier_bleed, size); float next_sample = next_sample_; while (size--) { bool reset = false; float reset_time = 0.0f; float this_sample = next_sample; next_sample = 0.0f; const float f0 = carrier_frequency_modulation.Next(); const float f1 = formant_frequency_modulation.Next(); carrier_phase_ += f0; reset = carrier_phase_ >= 1.0f; if (reset) { carrier_phase_ -= 1.0f; reset_time = carrier_phase_ / f0; float before = Grainlet( 1.0f, formant_phase_ + (1.0f - reset_time) * f1, carrier_shape_modulation.subsample(1.0f - reset_time), carrier_bleed_modulation.subsample(1.0f - reset_time)); float after = Grainlet( 0.0f, 0.0f, carrier_shape_modulation.subsample(1.0f), carrier_bleed_modulation.subsample(1.0f)); float discontinuity = after - before; this_sample += discontinuity * stmlib::ThisBlepSample(reset_time); next_sample += discontinuity * stmlib::NextBlepSample(reset_time); formant_phase_ = reset_time * f1; } else { formant_phase_ += f1; if (formant_phase_ >= 1.0f) { formant_phase_ -= 1.0f; } } next_sample += Grainlet( carrier_phase_, formant_phase_, carrier_shape_modulation.Next(), carrier_bleed_modulation.Next()); *out++ = this_sample; } next_sample_ = next_sample; } private: inline float Carrier(float phase, float shape) { shape *= 3.0f; MAKE_INTEGRAL_FRACTIONAL(shape); float t = 1.0f - shape_fractional; if (shape_integral == 0) { phase = phase * (1.0f + t * t * t * 15.0f); if (phase >= 1.0f) { phase = 1.0f; } phase += 0.75f; } else if (shape_integral == 1) { float breakpoint = 0.001f + 0.499f * t * t * t; if (phase < breakpoint) { phase *= (0.5f / breakpoint); } else { phase = 0.5f + (phase - breakpoint) * 0.5f / (1.0f - breakpoint); } phase += 0.75f; } else { t = 1.0f - t; phase = 0.25f + phase * (0.5f + t * t * t * 14.5f); if (phase >= 0.75f) phase = 0.75f; } return (Sine(phase) + 1.0f) * 0.25f; } inline float Grainlet( float carrier_phase, float formant_phase, float shape, float bleed) { float carrier = Carrier(carrier_phase, shape); float formant = Sine(formant_phase); return carrier * (formant + bleed) / (1.0f + bleed); } // Oscillator state. float carrier_phase_; float formant_phase_; float next_sample_; // For interpolation of parameters. float carrier_frequency_; float formant_frequency_; float carrier_shape_; float carrier_bleed_; DISALLOW_COPY_AND_ASSIGN(GrainletOscillator); }; } // namespace plaits #endif // PLAITS_DSP_OSCILLATOR_GRAINLET_OSCILLATOR_H_ ================================================ FILE: lib/plaits/dsp/oscillator/harmonic_oscillator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Harmonic oscillator based on Chebyshev polynomials. // Works well for a small number of harmonics. For the higher order harmonics, // we need to reinitialize the recurrence by computing two high harmonics. #ifndef PLAITS_DSP_OSCILLATOR_HARMONIC_OSCILLATOR_H_ #define PLAITS_DSP_OSCILLATOR_HARMONIC_OSCILLATOR_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "plaits/dsp/oscillator/sine_oscillator.h" namespace plaits { template class HarmonicOscillator { public: HarmonicOscillator() { } ~HarmonicOscillator() { } void Init() { phase_ = 0.0f; frequency_ = 0.0f; for (int i = 0; i < num_harmonics; ++i) { amplitude_[i] = 0.0f; } } template void Render( float frequency, const float* amplitudes, float* out, size_t size) { if (frequency >= 0.5f) { frequency = 0.5f; } stmlib::ParameterInterpolator am[num_harmonics]; stmlib::ParameterInterpolator fm(&frequency_, frequency, size); for (int i = 0; i < num_harmonics; ++i) { float f = frequency * static_cast(first_harmonic_index + i); if (f >= 0.5f) { f = 0.5f; } am[i].Init(&litude_[i], amplitudes[i] * (1.0f - f * 2.0f), size); } while (size--) { phase_ += fm.Next(); if (phase_ >= 1.0f) { phase_ -= 1.0f; } const float two_x = 2.0f * SineNoWrap(phase_); float previous, current; if (first_harmonic_index == 1) { previous = 1.0f; current = two_x * 0.5f; } else { const float k = first_harmonic_index; previous = Sine(phase_ * (k - 1.0f) + 0.25f); current = Sine(phase_ * k); } float sum = 0.0f; for (int i = 0; i < num_harmonics; ++i) { sum += am[i].Next() * current; float temp = current; current = two_x * current - previous; previous = temp; } if (first_harmonic_index == 1) { *out++ = sum; } else { *out++ += sum; } } } private: // Oscillator state. float phase_; // For interpolation of parameters. float frequency_; float amplitude_[num_harmonics]; DISALLOW_COPY_AND_ASSIGN(HarmonicOscillator); }; } // namespace plaits #endif // PLAITS_DSP_OSCILLATOR_HARMONIC_OSCILLATOR_H_ ================================================ FILE: lib/plaits/dsp/oscillator/nes_triangle_oscillator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Triangle waveform approximated by 16 discrete steps. #ifndef PLAITS_DSP_OSCILLATOR_NES_TRIANGLE_OSCILLATOR_H_ #define PLAITS_DSP_OSCILLATOR_NES_TRIANGLE_OSCILLATOR_H_ #include #include "stmlib/dsp/dsp.h" #include "plaits/dsp/oscillator/wavetable_oscillator.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/polyblep.h" #include "plaits/resources.h" namespace plaits { template class NESTriangleOscillator { public: NESTriangleOscillator() { } ~NESTriangleOscillator() { } inline void Init() { phase_ = 0.0f; step_ = 0; ascending_ = true; next_sample_ = 0.0f; frequency_ = 0.001f; } inline void Render(float frequency, float* out, size_t size) { // Compute all constants needed to scale the waveform and its // discontinuities. const int num_steps = 1 << num_bits; const int half = num_steps / 2; const int top = num_steps != 2 ? num_steps - 1 : 2; const float num_steps_f = static_cast(num_steps); const float scale = num_steps != 2 ? 4.0f / static_cast(top - 1) : 2.0f; frequency = std::min(frequency, 0.25f); stmlib::ParameterInterpolator fm(&frequency_, frequency, size); float next_sample = next_sample_; while (size--) { const float frequency = fm.Next(); phase_ += frequency; // Compute the point at which we transition between the "full resolution" // NES triangle, and a naive band-limited triangle. float fade_to_tri = (frequency - 0.5f / num_steps_f) * 2.0f * num_steps_f; CONSTRAIN(fade_to_tri, 0.0f, 1.0f) const float nes_gain = 1.0f - fade_to_tri; const float tri_gain = fade_to_tri * 2.0f / scale; float this_sample = next_sample; next_sample = 0.0f; // Handle the discontinuity at the top of the naive triangle. if (ascending_ && phase_ >= 0.5f) { float discontinuity = 4.0f * frequency * tri_gain; if (discontinuity) { float t = (phase_ - 0.5f) / frequency; this_sample -= stmlib::ThisIntegratedBlepSample(t) * discontinuity; next_sample -= stmlib::NextIntegratedBlepSample(t) * discontinuity; } ascending_ = false; } int next_step = static_cast(phase_ * num_steps_f); if (next_step != step_) { bool wrap = false; if (next_step >= num_steps) { phase_ -= 1.0f; next_step -= num_steps; wrap = true; } float discontinuity = next_step < half ? 1.0f : -1.0f; if (num_steps == 2) { discontinuity = -discontinuity; } else { if (next_step == 0 || next_step == half) { discontinuity = 0.0f; } } // Handle the discontinuity at each step of the NES triangle. discontinuity *= nes_gain; if (discontinuity) { float frac = (phase_ * num_steps_f - static_cast(next_step)); float t = frac / (frequency * num_steps_f); this_sample += stmlib::ThisBlepSample(t) * discontinuity; next_sample += stmlib::NextBlepSample(t) * discontinuity; } // Handle the discontinuity at the bottom of the naive triangle. if (wrap) { float discontinuity = 4.0f * frequency * tri_gain; if (discontinuity) { float t = phase_ / frequency; this_sample += stmlib::ThisIntegratedBlepSample(t) * discontinuity; next_sample += stmlib::NextIntegratedBlepSample(t) * discontinuity; } ascending_ = true; } } step_ = next_step; // Contribution from NES triangle. next_sample += nes_gain * \ static_cast(step_ < half ? step_ : top - step_); // Contribution from naive triangle. next_sample += tri_gain * \ (phase_ < 0.5f ? 2.0f * phase_ : 2.0f - 2.0f * phase_); *out++ = this_sample * scale - 1.0f; } next_sample_ = next_sample; } private: // Oscillator state. float phase_; float next_sample_; int step_; bool ascending_; // For interpolation of parameters. float frequency_; DISALLOW_COPY_AND_ASSIGN(NESTriangleOscillator); }; } // namespace plaits #endif // PLAITS_DSP_OSCILLATOR_NES_TRIANGLE_OSCILLATOR_H_ ================================================ FILE: lib/plaits/dsp/oscillator/oscillator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Single waveform oscillator. Can optionally do audio-rate linear FM, with // through-zero capabilities (negative frequencies). #ifndef PLAITS_DSP_OSCILLATOR_OSCILLATOR_H_ #define PLAITS_DSP_OSCILLATOR_OSCILLATOR_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/polyblep.h" namespace plaits { enum OscillatorShape { OSCILLATOR_SHAPE_IMPULSE_TRAIN, OSCILLATOR_SHAPE_SAW, OSCILLATOR_SHAPE_TRIANGLE, OSCILLATOR_SHAPE_SLOPE, OSCILLATOR_SHAPE_SQUARE, OSCILLATOR_SHAPE_SQUARE_BRIGHT, OSCILLATOR_SHAPE_SQUARE_DARK, OSCILLATOR_SHAPE_SQUARE_TRIANGLE }; const float kMaxFrequency = 0.25f; const float kMinFrequency = 0.000001f; class Oscillator { public: Oscillator() { } ~Oscillator() { } void Init() { phase_ = 0.5f; next_sample_ = 0.0f; lp_state_ = 1.0f; hp_state_ = 0.0f; high_ = true; frequency_ = 0.001f; pw_ = 0.5f; } template void Render(float frequency, float pw, float* out, size_t size) { Render(frequency, pw, NULL, out, size); } template void Render( float frequency, float pw, const float* fm, float* out, size_t size) { if (!fm) { Render(frequency, pw, NULL, out, size); } else { Render(frequency, pw, fm, out, size); } } template void Render( float frequency, float pw, const float* external_fm, float* out, size_t size) { if (!has_external_fm) { if (!through_zero_fm) { CONSTRAIN(frequency, kMinFrequency, kMaxFrequency); } else { CONSTRAIN(frequency, -kMaxFrequency, kMaxFrequency); } CONSTRAIN(pw, fabsf(frequency) * 2.0f, 1.0f - 2.0f * fabsf(frequency)) } stmlib::ParameterInterpolator fm(&frequency_, frequency, size); stmlib::ParameterInterpolator pwm(&pw_, pw, size); float next_sample = next_sample_; while (size--) { float this_sample = next_sample; next_sample = 0.0f; float frequency = fm.Next(); if (has_external_fm) { frequency *= (1.0f + *external_fm++); if (!through_zero_fm) { CONSTRAIN(frequency, kMinFrequency, kMaxFrequency); } else { CONSTRAIN(frequency, -kMaxFrequency, kMaxFrequency); } } float pw = (shape == OSCILLATOR_SHAPE_SQUARE_TRIANGLE || shape == OSCILLATOR_SHAPE_TRIANGLE) ? 0.5f : pwm.Next(); if (has_external_fm) { CONSTRAIN(pw, fabsf(frequency) * 2.0f, 1.0f - 2.0f * fabsf(frequency)) } phase_ += frequency; if (shape <= OSCILLATOR_SHAPE_SAW) { if (phase_ >= 1.0f) { phase_ -= 1.0f; float t = phase_ / frequency; this_sample -= stmlib::ThisBlepSample(t); next_sample -= stmlib::NextBlepSample(t); } else if (through_zero_fm && phase_ < 0.0f) { float t = phase_ / frequency; phase_ += 1.0f; this_sample += stmlib::ThisBlepSample(t); next_sample += stmlib::NextBlepSample(t); } next_sample += phase_; if (shape == OSCILLATOR_SHAPE_SAW) { *out++ = 2.0f * this_sample - 1.0f; } else { lp_state_ += 0.25f * ((hp_state_ - this_sample) - lp_state_); *out++ = 4.0f * lp_state_; hp_state_ = this_sample; } } else if (shape <= OSCILLATOR_SHAPE_SLOPE) { float slope_up = 2.0f; float slope_down = 2.0f; if (shape == OSCILLATOR_SHAPE_SLOPE) { slope_up = 1.0f / (pw); slope_down = 1.0f / (1.0f - pw); } if (high_ ^ (phase_ < pw)) { float t = (phase_ - pw) / frequency; float discontinuity = (slope_up + slope_down) * frequency; if (through_zero_fm && frequency < 0.0f) { discontinuity = -discontinuity; } this_sample -= stmlib::ThisIntegratedBlepSample(t) * discontinuity; next_sample -= stmlib::NextIntegratedBlepSample(t) * discontinuity; high_ = phase_ < pw; } if (phase_ >= 1.0f) { phase_ -= 1.0f; float t = phase_ / frequency; float discontinuity = (slope_up + slope_down) * frequency; this_sample += stmlib::ThisIntegratedBlepSample(t) * discontinuity; next_sample += stmlib::NextIntegratedBlepSample(t) * discontinuity; high_ = true; } else if (through_zero_fm && phase_ < 0.0f) { float t = phase_ / frequency; phase_ += 1.0f; float discontinuity = (slope_up + slope_down) * frequency; this_sample -= stmlib::ThisIntegratedBlepSample(t) * discontinuity; next_sample -= stmlib::NextIntegratedBlepSample(t) * discontinuity; high_ = false; } next_sample += high_ ? phase_ * slope_up : 1.0f - (phase_ - pw) * slope_down; *out++ = 2.0f * this_sample - 1.0f; } else { if (high_ ^ (phase_ >= pw)) { float t = (phase_ - pw) / frequency; float discontinuity = 1.0f; if (through_zero_fm && frequency < 0.0f) { discontinuity = -discontinuity; } this_sample += stmlib::ThisBlepSample(t) * discontinuity; next_sample += stmlib::NextBlepSample(t) * discontinuity; high_ = phase_ >= pw; } if (phase_ >= 1.0f) { phase_ -= 1.0f; float t = phase_ / frequency; this_sample -= stmlib::ThisBlepSample(t); next_sample -= stmlib::NextBlepSample(t); high_ = false; } else if (through_zero_fm && phase_ < 0.0f) { float t = phase_ / frequency; phase_ += 1.0f; this_sample += stmlib::ThisBlepSample(t); next_sample += stmlib::NextBlepSample(t); high_ = true; } next_sample += phase_ < pw ? 0.0f : 1.0f; if (shape == OSCILLATOR_SHAPE_SQUARE_TRIANGLE) { const float integrator_coefficient = frequency * 0.0625f; this_sample = 128.0f * (this_sample - 0.5f); lp_state_ += integrator_coefficient * (this_sample - lp_state_); *out++ = lp_state_; } else if (shape == OSCILLATOR_SHAPE_SQUARE_DARK) { const float integrator_coefficient = frequency * 2.0f; this_sample = 4.0f * (this_sample - 0.5f); lp_state_ += integrator_coefficient * (this_sample - lp_state_); *out++ = lp_state_; } else if (shape == OSCILLATOR_SHAPE_SQUARE_BRIGHT) { const float integrator_coefficient = frequency * 2.0f; this_sample = 2.0f * this_sample - 1.0f; lp_state_ += integrator_coefficient * (this_sample - lp_state_); *out++ = (this_sample - lp_state_) * 0.5f; } else { this_sample = 2.0f * this_sample - 1.0f; *out++ = this_sample; } } } next_sample_ = next_sample; } private: // Oscillator state. float phase_; float next_sample_; float lp_state_; float hp_state_; bool high_; // For interpolation of parameters. float frequency_; float pw_; DISALLOW_COPY_AND_ASSIGN(Oscillator); }; } // namespace plaits #endif // PLAITS_DSP_OSCILLATOR_OSCILLATOR_H_ ================================================ FILE: lib/plaits/dsp/oscillator/sine_oscillator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Simple sine oscillator (wavetable) + fast sine oscillator (magic circle). // // The fast implementation might glitch a bit under heavy modulations of the // frequency. #ifndef PLAITS_DSP_OSCILLATOR_SINE_OSCILLATOR_H_ #define PLAITS_DSP_OSCILLATOR_SINE_OSCILLATOR_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/rsqrt.h" #include "plaits/resources.h" namespace plaits { const float kSineLUTSize = 512.0f; const size_t kSineLUTQuadrature = 128; const size_t kSineLUTBits = 9; // Safe for phase >= 0.0f, will wrap. inline float Sine(float phase) { return stmlib::InterpolateWrap(lut_sine, phase, kSineLUTSize); } // Potentially unsafe, if phase >= 1.25. inline float SineNoWrap(float phase) { return stmlib::Interpolate(lut_sine, phase, kSineLUTSize); } // With positive of negative phase modulation up to an index of 32. inline float SinePM(uint32_t phase, float pm) { const float max_uint32 = 4294967296.0f; const int max_index = 32; const float offset = float(max_index); const float scale = max_uint32 / float(max_index * 2); phase += static_cast((pm + offset) * scale) * max_index * 2; uint32_t integral = phase >> (32 - kSineLUTBits); float fractional = static_cast(phase << kSineLUTBits) / float(max_uint32); float a = lut_sine[integral]; float b = lut_sine[integral + 1]; return a + (b - a) * fractional; } // Direct lookup without interpolation. inline float SineRaw(uint32_t phase) { return lut_sine[phase >> (32 - kSineLUTBits)]; } class SineOscillator { public: SineOscillator() { } ~SineOscillator() { } void Init() { phase_ = 0.0f; frequency_ = 0.0f; amplitude_ = 0.0f; } inline float Next(float frequency) { if (frequency >= 0.5f) { frequency = 0.5f; } phase_ += frequency; if (phase_ >= 1.0f) { phase_ -= 1.0f; } return SineNoWrap(phase_); } inline void Next(float frequency, float amplitude, float* sin, float* cos) { if (frequency >= 0.5f) { frequency = 0.5f; } phase_ += frequency; if (phase_ >= 1.0f) { phase_ -= 1.0f; } *sin = amplitude * SineNoWrap(phase_); *cos = amplitude * SineNoWrap(phase_ + 0.25f); } void Render(float frequency, float amplitude, float* out, size_t size) { RenderInternal(frequency, amplitude, out, size); } void Render(float frequency, float* out, size_t size) { RenderInternal(frequency, 1.0f, out, size); } private: template void RenderInternal( float frequency, float amplitude, float* out, size_t size) { if (frequency >= 0.5f) { frequency = 0.5f; } stmlib::ParameterInterpolator fm(&frequency_, frequency, size); stmlib::ParameterInterpolator am(&litude_, amplitude, size); while (size--) { phase_ += fm.Next(); if (phase_ >= 1.0f) { phase_ -= 1.0f; } float s = SineNoWrap(phase_); if (additive) { *out++ += am.Next() * s; } else { *out++ = s; } } } // Oscillator state. float phase_; // For interpolation of parameters. float frequency_; float amplitude_; DISALLOW_COPY_AND_ASSIGN(SineOscillator); }; class FastSineOscillator { public: FastSineOscillator() { } ~FastSineOscillator() { } void Init() { x_ = 1.0f; y_ = 0.0f; epsilon_ = 0.0f; amplitude_ = 0.0f; } enum Mode { NORMAL, ADDITIVE, QUADRATURE }; static inline float Fast2Sin(float f) { // In theory, epsilon = 2 sin(pi f) // Here, to avoid the call to sinf, we use a 3rd order polynomial // approximation, which looks like a Taylor expansion, but with a // correction term to give a good trade-off between average error // (1.13 cents) and maximum error (7.33 cents) when generating sinewaves // in the 16 Hz to 16kHz range (with sr = 48kHz). const float f_pi = f * float(M_PI); return f_pi * (2.0f - (2.0f * 0.96f / 6.0f) * f_pi * f_pi); } void Render(float frequency, float* out, size_t size) { RenderInternal(frequency, 1.0f, out, NULL, size); } void Render(float frequency, float amplitude, float* out, size_t size) { RenderInternal(frequency, amplitude, out, NULL, size); } void RenderQuadrature( float frequency, float amplitude, float* x, float* y, size_t size) { RenderInternal(frequency, amplitude, x, y, size); } private: template void RenderInternal( float frequency, float amplitude, float* out, float* out_2, size_t size) { if (frequency >= 0.25f) { frequency = 0.25f; amplitude = 0.0f; } else { amplitude *= 1.0f - frequency * 4.0f; } stmlib::ParameterInterpolator epsilon(&epsilon_, Fast2Sin(frequency), size); stmlib::ParameterInterpolator am(&litude_, amplitude, size); float x = x_; float y = y_; const float norm = x * x + y * y; if (norm <= 0.5f || norm >= 2.0f) { const float scale = stmlib::fast_rsqrt_carmack(norm); x *= scale; y *= scale; } while (size--) { const float e = epsilon.Next(); x += e * y; y -= e * x; if (mode == ADDITIVE) { *out++ += am.Next() * x; } else if (mode == NORMAL) { *out++ = x; } else if (mode == QUADRATURE) { const float amplitude = am.Next(); *out++ = x * amplitude; *out_2++ = y * amplitude; } } x_ = x; y_ = y; } // Oscillator state. float x_; float y_; // For interpolation of parameters. float epsilon_; float amplitude_; DISALLOW_COPY_AND_ASSIGN(FastSineOscillator); }; } // namespace plaits #endif // PLAITS_DSP_OSCILLATOR_SINE_OSCILLATOR_H_ ================================================ FILE: lib/plaits/dsp/oscillator/string_synth_oscillator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // A mixture of 7 sawtooth and square waveforms in the style of divide-down // organs: // // [0] [1] [2] [3] [4] [5] [6] // Saw 8', Square 8', Saw 4', Square 4', Saw 2', Square 2', Saw 1' // // Internally, this renders 4 band-limited sawtooths, from 8' to 1' from a // single phase counter. The square waveforms are obtained by algebraic // manipulations on the sawtooths, using the identity: // Square 16' = 2 Sawtooth 16' - Sawtooth 8' #ifndef PLAITS_DSP_OSCILLATOR_STRING_SYNTH_OSCILLATOR_H_ #define PLAITS_DSP_OSCILLATOR_STRING_SYNTH_OSCILLATOR_H_ #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/polyblep.h" namespace plaits { class StringSynthOscillator { public: StringSynthOscillator() { } ~StringSynthOscillator() { } inline void Init() { phase_ = 0.0f; next_sample_ = 0.0f; segment_ = 0.0f; frequency_ = 0.001f; saw_8_gain_ = 0.0f; saw_4_gain_ = 0.0f; saw_2_gain_ = 0.0f; saw_1_gain_ = 0.0f; } inline void Render( float frequency, const float* unshifted_registration, float gain, float* out, size_t size) { frequency *= 8.0f; // Deal with very high frequencies by shifting everything 1 or 2 octave // down: Instead of playing the 1st harmonic of a 8kHz wave, we play the // second harmonic of a 4kHz wave. size_t shift = 0; while (frequency > 0.5f) { shift += 2; frequency *= 0.5f; } // Frequency is just too high. if (shift >= 8) { return; } float registration[7]; std::fill(®istration[0], ®istration[shift], 0.0f); std::copy( &unshifted_registration[0], &unshifted_registration[7 - shift], ®istration[shift]); stmlib::ParameterInterpolator fm(&frequency_, frequency, size); stmlib::ParameterInterpolator saw_8_gain_modulation( &saw_8_gain_, (registration[0] + 2.0f * registration[1]) * gain, size); stmlib::ParameterInterpolator saw_4_gain_modulation( &saw_4_gain_, (registration[2] - registration[1] + 2.0f * registration[3]) * gain, size); stmlib::ParameterInterpolator saw_2_gain_modulation( &saw_2_gain_, (registration[4] - registration[3] + 2.0f * registration[5]) * gain, size); stmlib::ParameterInterpolator saw_1_gain_modulation( &saw_1_gain_, (registration[6] - registration[5]) * gain, size); float phase = phase_; float next_sample = next_sample_; int segment = segment_; while (size--) { float this_sample = next_sample; next_sample = 0.0f; const float frequency = fm.Next(); const float saw_8_gain = saw_8_gain_modulation.Next(); const float saw_4_gain = saw_4_gain_modulation.Next(); const float saw_2_gain = saw_2_gain_modulation.Next(); const float saw_1_gain = saw_1_gain_modulation.Next(); phase += frequency; int next_segment = static_cast(phase); if (next_segment != segment) { float discontinuity = 0.0f; if (next_segment == 8) { phase -= 8.0f; next_segment -= 8; discontinuity -= saw_8_gain; } if ((next_segment & 3) == 0) { discontinuity -= saw_4_gain; } if ((next_segment & 1) == 0) { discontinuity -= saw_2_gain; } discontinuity -= saw_1_gain; if (discontinuity != 0.0f) { float fraction = phase - static_cast(next_segment); float t = fraction / frequency; this_sample += stmlib::ThisBlepSample(t) * discontinuity; next_sample += stmlib::NextBlepSample(t) * discontinuity; } } segment = next_segment; next_sample += (phase - 4.0f) * saw_8_gain * 0.125f; next_sample += (phase - float(segment & 4) - 2.0f) * saw_4_gain * 0.25f; next_sample += (phase - float(segment & 6) - 1.0f) * saw_2_gain * 0.5f; next_sample += (phase - float(segment & 7) - 0.5f) * saw_1_gain; *out++ += 2.0f * this_sample; } next_sample_ = next_sample; phase_ = phase; segment_ = segment; } private: // Oscillator state. float phase_; float next_sample_; int segment_; // For interpolation of parameters. float frequency_; float saw_8_gain_; float saw_4_gain_; float saw_2_gain_; float saw_1_gain_; DISALLOW_COPY_AND_ASSIGN(StringSynthOscillator); }; } // namespace plaits #endif // PLAITS_DSP_OSCILLATOR_STRING_SYNTH_OSCILLATOR_H_ ================================================ FILE: lib/plaits/dsp/oscillator/super_square_oscillator.h ================================================ // Copyright 2021 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Two hard-sync'ed square waves with a meta-parameter, also faking PWM. // Based on VariableShapeOscillator, with hard-coded pulse width (0.5), // waveshape (only square), and sync enabled by default. #ifndef PLAITS_DSP_OSCILLATOR_SUPERSQUARE_OSCILLATOR_H_ #define PLAITS_DSP_OSCILLATOR_SUPERSQUARE_OSCILLATOR_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/polyblep.h" #include namespace plaits { class SuperSquareOscillator { public: SuperSquareOscillator() { } ~SuperSquareOscillator() { } void Init() { master_phase_ = 0.0f; slave_phase_ = 0.0f; next_sample_ = 0.0f; high_ = false; master_frequency_ = 0.0f; slave_frequency_ = 0.01f; } void Render( float frequency, float shape, float* out, size_t size) { float master_frequency = frequency; frequency *= shape < 0.5f ? (0.51f + 0.98f * shape) : 1.0f + 16.0f * (shape - 0.5f) * (shape - 0.5f); if (master_frequency >= kMaxFrequency) { master_frequency = kMaxFrequency; } if (frequency >= kMaxFrequency) { frequency = kMaxFrequency; } stmlib::ParameterInterpolator master_fm( &master_frequency_, master_frequency, size); stmlib::ParameterInterpolator fm(&slave_frequency_, frequency, size); float next_sample = next_sample_; while (size--) { bool reset = false; bool transition_during_reset = false; float reset_time = 0.0f; float this_sample = next_sample; next_sample = 0.0f; const float master_frequency = master_fm.Next(); const float slave_frequency = fm.Next(); master_phase_ += master_frequency; if (master_phase_ >= 1.0f) { master_phase_ -= 1.0f; reset_time = master_phase_ / master_frequency; float slave_phase_at_reset = slave_phase_ + \ (1.0f - reset_time) * slave_frequency; reset = true; if (slave_phase_at_reset >= 1.0f) { slave_phase_at_reset -= 1.0f; transition_during_reset = true; } if (!high_ && slave_phase_at_reset >= 0.5f) { transition_during_reset = true; } float value = slave_phase_at_reset < 0.5f ? 0.0f : 1.0f; this_sample -= value * stmlib::ThisBlepSample(reset_time); next_sample -= value * stmlib::NextBlepSample(reset_time); } slave_phase_ += slave_frequency; while (transition_during_reset || !reset) { if (!high_) { if (slave_phase_ < 0.5f) { break; } float t = (slave_phase_ - 0.5f) / slave_frequency; this_sample += stmlib::ThisBlepSample(t); next_sample += stmlib::NextBlepSample(t); high_ = true; } if (high_) { if (slave_phase_ < 1.0f) { break; } slave_phase_ -= 1.0f; float t = slave_phase_ / slave_frequency; this_sample -= stmlib::ThisBlepSample(t); next_sample -= stmlib::NextBlepSample(t); high_ = false; } } if (reset) { slave_phase_ = reset_time * slave_frequency; high_ = false; } next_sample += slave_phase_ < 0.5f ? 0.0f : 1.0f; *out++ = 2.0f * this_sample - 1.0f; } next_sample_ = next_sample; } private: // Oscillator state. float master_phase_; float slave_phase_; float next_sample_; bool high_; // For interpolation of parameters. float master_frequency_; float slave_frequency_; DISALLOW_COPY_AND_ASSIGN(SuperSquareOscillator); }; } // namespace plaits #endif // PLAITS_DSP_OSCILLATOR_SUPERSQUARE_OSCILLATOR_H_ ================================================ FILE: lib/plaits/dsp/oscillator/variable_saw_oscillator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Saw with variable slope or notch #ifndef PLAITS_DSP_OSCILLATOR_VARIABLE_SAW_OSCILLATOR_H_ #define PLAITS_DSP_OSCILLATOR_VARIABLE_SAW_OSCILLATOR_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/polyblep.h" #include #include "plaits/dsp/oscillator/oscillator.h" namespace plaits { const float kVariableSawNotchDepth = 0.2f; class VariableSawOscillator { public: VariableSawOscillator() { } ~VariableSawOscillator() { } void Init() { phase_ = 0.0f; next_sample_ = 0.0f; previous_pw_ = 0.5f; high_ = false; frequency_ = 0.01f; pw_ = 0.5f; waveshape_ = 0.0f; } void Render( float frequency, float pw, float waveshape, float* out, size_t size) { if (frequency >= kMaxFrequency) { frequency = kMaxFrequency; } if (frequency >= 0.25f) { pw = 0.5f; } else { CONSTRAIN(pw, frequency * 2.0f, 1.0f - 2.0f * frequency); } stmlib::ParameterInterpolator fm(&frequency_, frequency, size); stmlib::ParameterInterpolator pwm(&pw_, pw, size); stmlib::ParameterInterpolator waveshape_modulation( &waveshape_, waveshape, size); float next_sample = next_sample_; while (size--) { float this_sample = next_sample; next_sample = 0.0f; const float frequency = fm.Next(); const float pw = pwm.Next(); const float waveshape = waveshape_modulation.Next(); const float triangle_amount = waveshape; const float notch_amount = 1.0f - waveshape; const float slope_up = 1.0f / (pw); const float slope_down = 1.0f / (1.0f - pw); phase_ += frequency; if (!high_ && phase_ >= pw) { const float triangle_step = (slope_up + slope_down) * frequency * triangle_amount; const float notch = (kVariableSawNotchDepth + 1.0f - pw) * notch_amount; const float t = (phase_ - pw) / (previous_pw_ - pw + frequency); this_sample += notch * stmlib::ThisBlepSample(t); next_sample += notch * stmlib::NextBlepSample(t); this_sample -= triangle_step * stmlib::ThisIntegratedBlepSample(t); next_sample -= triangle_step * stmlib::NextIntegratedBlepSample(t); high_ = true; } else if (phase_ >= 1.0f) { phase_ -= 1.0f; const float triangle_step = (slope_up + slope_down) * frequency * triangle_amount; const float notch = (kVariableSawNotchDepth + 1.0f) * notch_amount; const float t = phase_ / frequency; this_sample -= notch * stmlib::ThisBlepSample(t); next_sample -= notch * stmlib::NextBlepSample(t); this_sample += triangle_step * stmlib::ThisIntegratedBlepSample(t); next_sample += triangle_step * stmlib::NextIntegratedBlepSample(t); high_ = false; } next_sample += ComputeNaiveSample( phase_, pw, slope_up, slope_down, triangle_amount, notch_amount); previous_pw_ = pw; *out++ = (2.0f * this_sample - 1.0f) / (1.0f + kVariableSawNotchDepth); } next_sample_ = next_sample; } private: inline float ComputeNaiveSample( float phase, float pw, float slope_up, float slope_down, float triangle_amount, float notch_amount) const { float notch_saw = phase < pw ? phase : 1.0f + kVariableSawNotchDepth; float triangle = phase < pw ? phase * slope_up : 1.0f - (phase - pw) * slope_down; return notch_saw * notch_amount + triangle * triangle_amount; } // Oscillator state. float phase_; float next_sample_; float previous_pw_; bool high_; // For interpolation of parameters. float frequency_; float pw_; float waveshape_; DISALLOW_COPY_AND_ASSIGN(VariableSawOscillator); }; } // namespace plaits #endif // PLAITS_DSP_OSCILLATOR_VARIABLE_SAW_OSCILLATOR_H_ ================================================ FILE: lib/plaits/dsp/oscillator/variable_shape_oscillator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Continuously variable waveform: triangle > saw > square. Both square and // triangle have variable slope / pulse-width. Additionally, the phase resets // can be locked to a master frequency. // // A template parameter allows the generation of a master + slave signal, // which can be used as the phase for phase distortion or modulation synthesis. #ifndef PLAITS_DSP_OSCILLATOR_VARIABLE_SHAPE_OSCILLATOR_H_ #define PLAITS_DSP_OSCILLATOR_VARIABLE_SHAPE_OSCILLATOR_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/polyblep.h" #include "plaits/dsp/oscillator/oscillator.h" #include namespace plaits { class VariableShapeOscillator { public: VariableShapeOscillator() { } ~VariableShapeOscillator() { } void Init() { master_phase_ = 0.0f; slave_phase_ = 0.0f; next_sample_ = 0.0f; previous_pw_ = 0.5f; high_ = false; master_frequency_ = 0.0f; slave_frequency_ = 0.01f; pw_ = 0.5f; waveshape_ = 0.0f; phase_modulation_ = 0.0f; } void Render( float frequency, float pw, float waveshape, float* out, size_t size) { Render(0.0f, frequency, pw, waveshape, 0.0f, out, size); } void Render( float master_frequency, float frequency, float pw, float waveshape, float* out, size_t size) { Render( master_frequency, frequency, pw, waveshape, 0.0f, out, size); } template void Render( float master_frequency, float frequency, float pw, float waveshape, float phase_modulation_amount, float* out, size_t size) { if (master_frequency >= kMaxFrequency) { master_frequency = kMaxFrequency; } if (frequency >= kMaxFrequency) { frequency = kMaxFrequency; } if (frequency >= 0.25f) { pw = 0.5f; } else { CONSTRAIN(pw, frequency * 2.0f, 1.0f - 2.0f * frequency); } stmlib::ParameterInterpolator master_fm( &master_frequency_, master_frequency, size); stmlib::ParameterInterpolator fm(&slave_frequency_, frequency, size); stmlib::ParameterInterpolator pwm(&pw_, pw, size); stmlib::ParameterInterpolator waveshape_modulation( &waveshape_, waveshape, size); stmlib::ParameterInterpolator phase_modulation( &phase_modulation_, phase_modulation_amount, size); float next_sample = next_sample_; while (size--) { bool reset = false; bool transition_during_reset = false; float reset_time = 0.0f; float this_sample = next_sample; next_sample = 0.0f; const float master_frequency = master_fm.Next(); const float slave_frequency = fm.Next(); const float pw = pwm.Next(); const float waveshape = waveshape_modulation.Next(); const float square_amount = std::max(waveshape - 0.5f, 0.0f) * 2.0f; const float triangle_amount = std::max(1.0f - waveshape * 2.0f, 0.0f); const float slope_up = 1.0f / (pw); const float slope_down = 1.0f / (1.0f - pw); if (enable_sync) { master_phase_ += master_frequency; if (master_phase_ >= 1.0f) { master_phase_ -= 1.0f; reset_time = master_phase_ / master_frequency; float slave_phase_at_reset = slave_phase_ + \ (1.0f - reset_time) * slave_frequency; reset = true; if (slave_phase_at_reset >= 1.0f) { slave_phase_at_reset -= 1.0f; transition_during_reset = true; } if (!high_ && slave_phase_at_reset >= pw) { transition_during_reset = true; } float value = ComputeNaiveSample( slave_phase_at_reset, pw, slope_up, slope_down, triangle_amount, square_amount); this_sample -= value * stmlib::ThisBlepSample(reset_time); next_sample -= value * stmlib::NextBlepSample(reset_time); } } else if (output_phase) { master_phase_ += master_frequency; if (master_phase_ >= 1.0f) { master_phase_ -= 1.0f; } } slave_phase_ += slave_frequency; while (transition_during_reset || !reset) { if (!high_) { if (slave_phase_ < pw) { break; } float t = (slave_phase_ - pw) / (previous_pw_ - pw + slave_frequency); float triangle_step = (slope_up + slope_down) * slave_frequency; triangle_step *= triangle_amount; this_sample += square_amount * stmlib::ThisBlepSample(t); next_sample += square_amount * stmlib::NextBlepSample(t); this_sample -= triangle_step * stmlib::ThisIntegratedBlepSample(t); next_sample -= triangle_step * stmlib::NextIntegratedBlepSample(t); high_ = true; } if (high_) { if (slave_phase_ < 1.0f) { break; } slave_phase_ -= 1.0f; float t = slave_phase_ / slave_frequency; float triangle_step = (slope_up + slope_down) * slave_frequency; triangle_step *= triangle_amount; this_sample -= (1.0f - triangle_amount) * stmlib::ThisBlepSample(t); next_sample -= (1.0f - triangle_amount) * stmlib::NextBlepSample(t); this_sample += triangle_step * stmlib::ThisIntegratedBlepSample(t); next_sample += triangle_step * stmlib::NextIntegratedBlepSample(t); high_ = false; } } if (enable_sync && reset) { slave_phase_ = reset_time * slave_frequency; high_ = false; } next_sample += ComputeNaiveSample( slave_phase_, pw, slope_up, slope_down, triangle_amount, square_amount); previous_pw_ = pw; if (output_phase) { float phasor = master_phase_; if (enable_sync) { // A trick to prevent discontinuities when the phase wraps around. const float w = 4.0f * (1.0f - master_phase_) * master_phase_; this_sample *= w * (2.0f - w); // Apply some asymmetry on the main phasor too. const float p2 = phasor * phasor; phasor += (p2 * p2 - phasor) * fabsf(pw - 0.5f) * 2.0f; } *out++ = phasor + phase_modulation.Next() * this_sample; } else { *out++ = (2.0f * this_sample - 1.0f); } } next_sample_ = next_sample; } inline void set_master_phase(float master_phase) { master_phase_ = master_phase; } private: inline float ComputeNaiveSample( float phase, float pw, float slope_up, float slope_down, float triangle_amount, float square_amount) const { float saw = phase; float square = phase < pw ? 0.0f : 1.0f; float triangle = phase < pw ? phase * slope_up : 1.0f - (phase - pw) * slope_down; saw += (square - saw) * square_amount; saw += (triangle - saw) * triangle_amount; return saw; } // Oscillator state. float master_phase_; float slave_phase_; float next_sample_; float previous_pw_; bool high_; // For interpolation of parameters. float master_frequency_; float slave_frequency_; float pw_; float waveshape_; float phase_modulation_; DISALLOW_COPY_AND_ASSIGN(VariableShapeOscillator); }; } // namespace plaits #endif // PLAITS_DSP_OSCILLATOR_VARIABLE_SHAPE_OSCILLATOR_H_ ================================================ FILE: lib/plaits/dsp/oscillator/vosim_oscillator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Two sinewaves multiplied by and sync'ed to a carrier. #ifndef PLAITS_DSP_OSCILLATOR_VOSIM_OSCILLATOR_H_ #define PLAITS_DSP_OSCILLATOR_VOSIM_OSCILLATOR_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "plaits/dsp/oscillator/oscillator.h" #include "plaits/dsp/oscillator/sine_oscillator.h" #include "plaits/resources.h" namespace plaits { class VOSIMOscillator { public: VOSIMOscillator() { } ~VOSIMOscillator() { } void Init() { carrier_phase_ = 0.0f; formant_1_phase_ = 0.0f; formant_2_phase_ = 0.0f; carrier_frequency_ = 0.0f; formant_1_frequency_ = 0.0f; formant_2_frequency_ = 0.0f; carrier_shape_ = 0.0f; } void Render( float carrier_frequency, float formant_frequency_1, float formant_frequency_2, float carrier_shape, float* out, size_t size) { if (carrier_frequency >= kMaxFrequency) { carrier_frequency = kMaxFrequency; } if (formant_frequency_1 >= kMaxFrequency) { formant_frequency_1 = kMaxFrequency; } if (formant_frequency_2 >= kMaxFrequency) { formant_frequency_2 = kMaxFrequency; } stmlib::ParameterInterpolator f0_modulation( &carrier_frequency_, carrier_frequency, size); stmlib::ParameterInterpolator f1_modulation( &formant_1_frequency_, formant_frequency_1, size); stmlib::ParameterInterpolator f2_modulation( &formant_2_frequency_, formant_frequency_2, size); stmlib::ParameterInterpolator carrier_shape_modulation( &carrier_shape_, carrier_shape, size); while (size--) { const float f0 = f0_modulation.Next(); const float f1 = f1_modulation.Next(); const float f2 = f2_modulation.Next(); carrier_phase_ += carrier_frequency; if (carrier_phase_ >= 1.0f) { carrier_phase_ -= 1.0f; float reset_time = carrier_phase_ / f0; formant_1_phase_ = reset_time * f1; formant_2_phase_ = reset_time * f2; } else { formant_1_phase_ += f1; if (formant_1_phase_ >= 1.0f) { formant_1_phase_ -= 1.0f; } formant_2_phase_ += f2; if (formant_2_phase_ >= 1.0f) { formant_2_phase_ -= 1.0f; } } float carrier = Sine(carrier_phase_ * 0.5f + 0.25f) + 1.0f; float reset_phase = 0.75f - 0.25f * carrier_shape_modulation.Next(); float reset_amplitude = Sine(reset_phase); float formant_0 = Sine(formant_1_phase_ + reset_phase) - reset_amplitude; float formant_1 = Sine(formant_2_phase_ + reset_phase) - reset_amplitude; *out++ = carrier * (formant_0 + formant_1) * 0.25f + reset_amplitude; } } private: // Oscillator state. float carrier_phase_; float formant_1_phase_; float formant_2_phase_; // For interpolation of parameters. float carrier_frequency_; float formant_1_frequency_; float formant_2_frequency_; float carrier_shape_; DISALLOW_COPY_AND_ASSIGN(VOSIMOscillator); }; } // namespace plaits #endif // PLAITS_DSP_OSCILLATOR_VOSIM_OSCILLATOR_H_ ================================================ FILE: lib/plaits/dsp/oscillator/wavetable_oscillator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Integrated wavetable synthesis. #ifndef PLAITS_DSP_OSCILLATOR_WAVETABLE_OSCILLATOR_H_ #define PLAITS_DSP_OSCILLATOR_WAVETABLE_OSCILLATOR_H_ #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "plaits/dsp/oscillator/oscillator.h" namespace plaits { class Differentiator { public: Differentiator() { } ~Differentiator() { } void Init() { previous_ = 0.0f; lp_ = 0.0f; } float Process(float coefficient, float s) { ONE_POLE(lp_, s - previous_, coefficient); previous_ = s; return lp_; } private: float lp_; float previous_; DISALLOW_COPY_AND_ASSIGN(Differentiator); }; template inline float InterpolateWave( const T* table, int32_t index_integral, float index_fractional) { float a = static_cast(table[index_integral]); float b = static_cast(table[index_integral + 1]); float t = index_fractional; return a + (b - a) * t; } template inline float InterpolateWaveHermite( const T* table, int32_t index_integral, float index_fractional) { const float xm1 = static_cast(table[index_integral]); const float x0 = static_cast(table[index_integral + 1]); const float x1 = static_cast(table[index_integral + 2]); const float x2 = static_cast(table[index_integral + 3]); const float c = (x1 - xm1) * 0.5f; const float v = x0 - x1; const float w = c + v; const float a = w + v + (x2 - x0) * 0.5f; const float b_neg = w + a; const float f = index_fractional; return (((a * f) - b_neg) * f + c) * f + x0; } template< size_t wavetable_size, size_t num_waves, bool approximate_scale=true, bool attenuate_high_frequencies=true> class WavetableOscillator { public: WavetableOscillator() { } ~WavetableOscillator() { } void Init() { phase_ = 0.0f; frequency_ = 0.0f; amplitude_ = 0.0f; waveform_ = 0.0f; lp_ = 0.0f; differentiator_.Init(); } void Render( float frequency, float amplitude, float waveform, const int16_t* const* wavetable, float* out, size_t size) { CONSTRAIN(frequency, 0.0000001f, kMaxFrequency) if (attenuate_high_frequencies) { amplitude *= 1.0f - 2.0f * frequency; } if (approximate_scale) { amplitude *= 1.0f / (frequency * 131072.0f); } stmlib::ParameterInterpolator frequency_modulation( &frequency_, frequency, size); stmlib::ParameterInterpolator amplitude_modulation( &litude_, amplitude, size); stmlib::ParameterInterpolator waveform_modulation( &waveform_, waveform * float(num_waves - 1.0001f), size); float lp = lp_; float phase = phase_; while (size--) { const float f0 = frequency_modulation.Next(); const float cutoff = std::min(float(wavetable_size) * f0, 1.0f); const float scale = approximate_scale ? 1.0f : 1.0f / (f0 * 131072.0f); phase += f0; if (phase >= 1.0f) { phase -= 1.0f; } const float waveform = waveform_modulation.Next(); MAKE_INTEGRAL_FRACTIONAL(waveform); const float p = phase * float(wavetable_size); MAKE_INTEGRAL_FRACTIONAL(p); const float x0 = InterpolateWave( wavetable[waveform_integral], p_integral, p_fractional); const float x1 = InterpolateWave( wavetable[waveform_integral + 1], p_integral, p_fractional); const float s = differentiator_.Process( cutoff, (x0 + (x1 - x0) * waveform_fractional) * scale); ONE_POLE(lp, s, cutoff); *out++ += amplitude_modulation.Next() * lp; } lp_ = lp; phase_ = phase; } private: // Oscillator state. float phase_; // For interpolation of parameters. float frequency_; float amplitude_; float waveform_; float lp_; Differentiator differentiator_; DISALLOW_COPY_AND_ASSIGN(WavetableOscillator); }; } // namespace plaits #endif // PLAITS_DSP_OSCILLATOR_WAVETABLE_OSCILLATOR_H_ ================================================ FILE: lib/plaits/dsp/oscillator/z_oscillator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Sinewave multiplied by and sync'ed to a carrier. #ifndef PLAITS_DSP_OSCILLATOR_Z_OSCILLATOR_H_ #define PLAITS_DSP_OSCILLATOR_Z_OSCILLATOR_H_ #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/polyblep.h" #include "plaits/dsp/oscillator/sine_oscillator.h" namespace plaits { class ZOscillator { public: ZOscillator() { } ~ZOscillator() { } void Init() { carrier_phase_ = 0.0f; discontinuity_phase_ = 0.0f; formant_phase_ = 0.0f; next_sample_ = 0.0f; carrier_frequency_ = 0.0f; formant_frequency_ = 0.0f; carrier_shape_ = 0.0f; mode_ = 0.0f; } void Render( float carrier_frequency, float formant_frequency, float carrier_shape, float mode, float* out, size_t size) { if (carrier_frequency >= kMaxFrequency * 0.5f) { carrier_frequency = kMaxFrequency * 0.5f; } if (formant_frequency >= kMaxFrequency) { formant_frequency = kMaxFrequency; } stmlib::ParameterInterpolator carrier_frequency_modulation( &carrier_frequency_, carrier_frequency, size); stmlib::ParameterInterpolator formant_frequency_modulation( &formant_frequency_, formant_frequency, size); stmlib::ParameterInterpolator carrier_shape_modulation( &carrier_shape_, carrier_shape, size); stmlib::ParameterInterpolator mode_modulation( &mode_, mode, size); float next_sample = next_sample_; while (size--) { bool reset = false; float reset_time = 0.0f; float this_sample = next_sample; next_sample = 0.0f; const float f0 = carrier_frequency_modulation.Next(); const float f1 = formant_frequency_modulation.Next(); discontinuity_phase_ += 2.0f * f0; carrier_phase_ += f0; reset = discontinuity_phase_ >= 1.0f; if (reset) { discontinuity_phase_ -= 1.0f; reset_time = discontinuity_phase_ / (2.0f * f0); float carrier_phase_before = carrier_phase_ >= 1.0f ? 1.0f : 0.5f; float carrier_phase_after = carrier_phase_ >= 1.0f ? 0.0f : 0.5f; float before = Z( carrier_phase_before, 1.0f, formant_phase_ + (1.0f - reset_time) * f1, carrier_shape_modulation.subsample(1.0f - reset_time), mode_modulation.subsample(1.0f - reset_time)); float after = Z( carrier_phase_after, 0.0f, 0.0f, carrier_shape_modulation.subsample(1.0f), mode_modulation.subsample(1.0f)); float discontinuity = after - before; this_sample += discontinuity * stmlib::ThisBlepSample(reset_time); next_sample += discontinuity * stmlib::NextBlepSample(reset_time); formant_phase_ = reset_time * f1; if (carrier_phase_ > 1.0f) { carrier_phase_ = discontinuity_phase_ * 0.5f; } } else { formant_phase_ += f1; if (formant_phase_ >= 1.0f) { formant_phase_ -= 1.0f; } } if (carrier_phase_ >= 1.0f) { carrier_phase_ -= 1.0f; } next_sample += Z( carrier_phase_, discontinuity_phase_, formant_phase_, carrier_shape_modulation.Next(), mode_modulation.Next()); *out++ = this_sample; } next_sample_ = next_sample; } private: inline float Z(float c, float d, float f, float shape, float mode) { float ramp_down = 0.5f * (1.0f + Sine(0.5f * d + 0.25f)); float offset; float phase_shift; if (mode < 0.333f) { offset = 1.0f; phase_shift = 0.25f + mode * 1.50f; } else if (mode < 0.666f) { phase_shift = 0.7495f - (mode - 0.33f) * 0.75f; offset = -Sine(phase_shift); } else { phase_shift = 0.7495f - (mode - 0.33f) * 0.75f; offset = 0.001f; } float discontinuity = Sine(f + phase_shift); float contour; if (shape < 0.5f) { shape *= 2.0f; if (c >= 0.5f) { ramp_down *= shape; } contour = 1.0f + (Sine(c + 0.25f) - 1.0f) * shape; } else { contour = Sine(c + shape * 0.5f); } return (ramp_down * (offset + discontinuity) - offset) * contour; } // Oscillator state. float carrier_phase_; float discontinuity_phase_; float formant_phase_; float next_sample_; // For interpolation of parameters. float carrier_frequency_; float formant_frequency_; float carrier_shape_; float mode_; DISALLOW_COPY_AND_ASSIGN(ZOscillator); }; } // namespace plaits #endif // PLAITS_DSP_OSCILLATOR_Z_OSCILLATOR_H_ ================================================ FILE: lib/plaits/dsp/physical_modelling/delay_line.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Delay line (same implementation as from stmlib, but does not own its buffer). #ifndef PLAITS_DSP_PHYSICAL_MODELLING_DELAY_LINE_H_ #define PLAITS_DSP_PHYSICAL_MODELLING_DELAY_LINE_H_ #include #include "stmlib/dsp/dsp.h" namespace plaits { template class DelayLine { public: DelayLine() { } ~DelayLine() { } void Init(float* buffer) { line_ = buffer; Reset(); } void Reset() { std::fill(&line_[0], &line_[max_delay], T(0)); write_ptr_ = 0; } inline void Write(const T sample) { line_[write_ptr_] = sample; write_ptr_ = (write_ptr_ - 1 + max_delay) % max_delay; } inline const T Allpass(const T sample, size_t delay, const T coefficient) { T read = line_[(write_ptr_ + delay) % max_delay]; T write = sample + coefficient * read; Write(write); return -write * coefficient + read; } inline const T WriteRead(const T sample, float delay) { Write(sample); return Read(delay); } inline const T Read(float delay) const { MAKE_INTEGRAL_FRACTIONAL(delay) const T a = line_[(write_ptr_ + delay_integral) % max_delay]; const T b = line_[(write_ptr_ + delay_integral + 1) % max_delay]; return a + (b - a) * T(delay_fractional); } inline const T ReadHermite(float delay) const { MAKE_INTEGRAL_FRACTIONAL(delay) int32_t t = (write_ptr_ + delay_integral + max_delay); const T xm1 = line_[(t - 1) % max_delay]; const T x0 = line_[(t) % max_delay]; const T x1 = line_[(t + 1) % max_delay]; const T x2 = line_[(t + 2) % max_delay]; const T c = (x1 - xm1) * 0.5f; const T v = x0 - x1; const T w = c + v; const T a = w + v + (x2 - x0) * 0.5f; const T b_neg = w + a; const T f = delay_fractional; return (((a * f) - b_neg) * f + c) * f + x0; } private: size_t write_ptr_; T* line_; DISALLOW_COPY_AND_ASSIGN(DelayLine); }; } // namespace plaits #endif // PLAITS_DSP_PHYSICAL_MODELLING_DELAY_LINE_H_ ================================================ FILE: lib/plaits/dsp/physical_modelling/modal_voice.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Simple modal synthesis voice with a mallet exciter: // click -> LPF -> resonator. // // The click is replaced by continuous white noise when the trigger input // of the module is not patched. #include "plaits/dsp/physical_modelling/modal_voice.h" #include #include "stmlib/dsp/units.h" #include "stmlib/utils/random.h" #include "plaits/dsp/noise/dust.h" namespace plaits { using namespace std; using namespace stmlib; void ModalVoice::Init() { excitation_filter_.Init(); resonator_.Init(0.015f, kMaxNumModes); } void ModalVoice::Render( bool sustain, bool trigger, float accent, float f0, float structure, float brightness, float damping, float* temp, float* out, float* aux, size_t size) { const float density = brightness * brightness; brightness += 0.25f * accent * (1.0f - brightness); damping += 0.25f * accent * (1.0f - damping); const float range = sustain ? 36.0f : 60.0f; const float f = sustain ? 4.0f * f0 : 2.0f * f0; const float cutoff = min( f * SemitonesToRatio((brightness * (2.0f - brightness) - 0.5f) * range), 0.499f); const float q = sustain ? 0.7f : 1.5f; // Synthesize excitation signal. if (sustain) { const float dust_f = 0.00005f + 0.99995f * density * density; for (size_t i = 0; i < size; ++i) { temp[i] = Dust(dust_f) * (4.0f - dust_f * 3.0f) * accent; } } else { fill(&temp[0], &temp[size], 0.0f); if (trigger) { const float attenuation = 1.0f - damping * 0.5f; const float amplitude = (0.12f + 0.08f * accent) * attenuation; temp[0] = amplitude * SemitonesToRatio(cutoff * cutoff * 24.0f) / cutoff; } } const float one = 1.0f; excitation_filter_.Process( &cutoff, &q, &one, temp, temp, size); for (size_t i = 0; i < size; ++i) { aux[i] += temp[i]; } resonator_.Process(f0, structure, brightness, damping, temp, out, size); } } // namespace plaits ================================================ FILE: lib/plaits/dsp/physical_modelling/modal_voice.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Simple modal synthesis voice with a mallet exciter: // click -> LPF -> resonator. // // The click is replaced by continuous white noise when the trigger input // of the module is not patched. #ifndef PLAITS_DSP_PHYSICAL_MODELLING_MODAL_VOICE_H_ #define PLAITS_DSP_PHYSICAL_MODELLING_MODAL_VOICE_H_ #include "plaits/dsp/physical_modelling/resonator.h" namespace plaits { class ModalVoice { public: ModalVoice() { } ~ModalVoice() { } void Init(); void Render( bool sustain, bool trigger, float accent, float f0, float structure, float brightness, float damping, float* temp, float* out, float* aux, size_t size); private: ResonatorSvf<1> excitation_filter_; Resonator resonator_; DISALLOW_COPY_AND_ASSIGN(ModalVoice); }; } // namespace plaits #endif // PLAITS_DSP_PHYSICAL_MODELLING_MODAL_VOICE_H_ ================================================ FILE: lib/plaits/dsp/physical_modelling/resonator.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resonator, taken from Rings' code but with fixed position. #include "plaits/dsp/physical_modelling/resonator.h" #include #include "stmlib/dsp/cosine_oscillator.h" #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/units.h" #include "plaits/resources.h" namespace plaits { using namespace std; using namespace stmlib; void Resonator::Init(float position, int resolution) { resolution_ = min(resolution, kMaxNumModes); CosineOscillator amplitudes; amplitudes.Init(position); for (int i = 0; i < resolution; ++i) { mode_amplitude_[i] = amplitudes.Next() * 0.25f; } for (int i = 0; i < kMaxNumModes / kModeBatchSize; ++i) { mode_filters_[i].Init(); } } inline float NthHarmonicCompensation(int n, float stiffness) { float stretch_factor = 1.0f; for (int i = 0; i < n - 1; ++i) { stretch_factor += stiffness; if (stiffness < 0.0f) { stiffness *= 0.93f; } else { stiffness *= 0.98f; } } return 1.0f / stretch_factor; } void Resonator::Process( float f0, float structure, float brightness, float damping, const float* in, float* out, size_t size) { float stiffness = Interpolate(lut_stiffness, structure, 64.0f); f0 *= NthHarmonicCompensation(3, stiffness); float harmonic = f0; float stretch_factor = 1.0f; float q_sqrt = SemitonesToRatio(damping * 79.7f); float q = 500.0f * q_sqrt * q_sqrt; brightness *= 1.0f - structure * 0.3f; brightness *= 1.0f - damping * 0.3f; float q_loss = brightness * (2.0f - brightness) * 0.85f + 0.15f; float mode_q[kModeBatchSize]; float mode_f[kModeBatchSize]; float mode_a[kModeBatchSize]; int batch_counter = 0; ResonatorSvf* batch_processor = &mode_filters_[0]; for (int i = 0; i < resolution_; ++i) { float mode_frequency = harmonic * stretch_factor; if (mode_frequency >= 0.499f) { mode_frequency = 0.499f; } const float mode_attenuation = 1.0f - mode_frequency * 2.0f; mode_f[batch_counter] = mode_frequency; mode_q[batch_counter] = 1.0f + mode_frequency * q; mode_a[batch_counter] = mode_amplitude_[i] * mode_attenuation; ++batch_counter; if (batch_counter == kModeBatchSize) { batch_counter = 0; batch_processor->Process( mode_f, mode_q, mode_a, in, out, size); ++batch_processor; } stretch_factor += stiffness; if (stiffness < 0.0f) { // Make sure that the partials do not fold back into negative frequencies. stiffness *= 0.93f; } else { // This helps adding a few extra partials in the highest frequencies. stiffness *= 0.98f; } harmonic += f0; q *= q_loss; } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/physical_modelling/resonator.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resonator, taken from Rings' code but with fixed position. #ifndef PLAITS_DSP_PHYSICAL_MODELLING_RESONATOR_H_ #define PLAITS_DSP_PHYSICAL_MODELLING_RESONATOR_H_ #include "stmlib/dsp/filter.h" namespace plaits { const int kMaxNumModes = 24; const int kModeBatchSize = 4; // We render 4 modes simultaneously since there are enough registers to hold // all state variables. template class ResonatorSvf { public: ResonatorSvf() { } ~ResonatorSvf() { } void Init() { for (int i = 0; i < batch_size; ++i) { state_1_[i] = state_2_[i] = 0.0f; } } template void Process( const float* f, const float* q, const float* gain, const float* in, float* out, size_t size) { float g[batch_size]; float r[batch_size]; float r_plus_g[batch_size]; float h[batch_size]; float state_1[batch_size]; float state_2[batch_size]; float gains[batch_size]; for (int i = 0; i < batch_size; ++i) { g[i] = stmlib::OnePole::tan(f[i]); r[i] = 1.0f / q[i]; h[i] = 1.0f / (1.0f + r[i] * g[i] + g[i] * g[i]); r_plus_g[i] = r[i] + g[i]; state_1[i] = state_1_[i]; state_2[i] = state_2_[i]; gains[i] = gain[i]; } while (size--) { float s_in = *in++; float s_out = 0.0f; for (int i = 0; i < batch_size; ++i) { const float hp = (s_in - r_plus_g[i] * state_1[i] - state_2[i]) * h[i]; const float bp = g[i] * hp + state_1[i]; state_1[i] = g[i] * hp + bp; const float lp = g[i] * bp + state_2[i]; state_2[i] = g[i] * bp + lp; s_out += gains[i] * ((mode == stmlib::FILTER_MODE_LOW_PASS) ? lp : bp); } if (add) { *out++ += s_out; } else { *out++ = s_out; } } for (int i = 0; i < batch_size; ++i) { state_1_[i] = state_1[i]; state_2_[i] = state_2[i]; } } private: float state_1_[batch_size]; float state_2_[batch_size]; DISALLOW_COPY_AND_ASSIGN(ResonatorSvf); }; class Resonator { public: Resonator() { } ~Resonator() { } void Init(float position, int resolution); void Process( float f0, float structure, float brightness, float damping, const float* in, float* out, size_t size); private: int resolution_; float mode_amplitude_[kMaxNumModes]; ResonatorSvf mode_filters_[kMaxNumModes / kModeBatchSize]; DISALLOW_COPY_AND_ASSIGN(Resonator); }; } // namespace plaits #endif // PLAITS_DSP_PHYSICAL_MODELLING_RESONATOR_H_ ================================================ FILE: lib/plaits/dsp/physical_modelling/string.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Comb filter / KS string. "Lite" version of the implementation used in Rings. #include "plaits/dsp/physical_modelling/string.h" #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/units.h" #include "stmlib/utils/random.h" #include "plaits/dsp/dsp.h" #include "plaits/resources.h" namespace plaits { using namespace std; using namespace stmlib; void String::Init(BufferAllocator* allocator) { string_.Init(allocator->Allocate(kDelayLineSize)); stretch_.Init(allocator->Allocate(kDelayLineSize / 4)); delay_ = 100.0f; Reset(); } void String::Reset() { string_.Reset(); stretch_.Reset(); iir_damping_filter_.Init(); dc_blocker_.Init(1.0f - 20.0f / kSampleRate); dispersion_noise_ = 0.0f; curved_bridge_ = 0.0f; out_sample_[0] = out_sample_[1] = 0.0f; src_phase_ = 0.0f; } void String::Process( float f0, float non_linearity_amount, float brightness, float damping, const float* in, float* out, size_t size) { if (non_linearity_amount <= 0.0f) { ProcessInternal( f0, -non_linearity_amount, brightness, damping, in, out, size); } else { ProcessInternal( f0, non_linearity_amount, brightness, damping, in, out, size); } } template void String::ProcessInternal( float f0, float non_linearity_amount, float brightness, float damping, const float* in, float* out, size_t size) { float delay = 1.0f / f0; CONSTRAIN(delay, 4.0f, kDelayLineSize - 4.0f); // If there is not enough delay time in the delay line, we play at the // lowest possible note and we upsample on the fly with a shitty linear // interpolator. We don't care because it's a corner case (f0 < 11.7Hz) float src_ratio = delay * f0; if (src_ratio >= 0.9999f) { // When we are above 11.7 Hz, we make sure that the linear interpolator // does not get in the way. src_phase_ = 1.0f; src_ratio = 1.0f; } float damping_cutoff = min( 12.0f + damping * damping * 60.0f + brightness * 24.0f, 84.0f); float damping_f = min(f0 * SemitonesToRatio(damping_cutoff), 0.499f); // Crossfade to infinite decay. if (damping >= 0.95f) { float to_infinite = 20.0f * (damping - 0.95f); brightness += to_infinite * (1.0f - brightness); damping_f += to_infinite * (0.4999f - damping_f); damping_cutoff += to_infinite * (128.0f - damping_cutoff); } iir_damping_filter_.set_f_q(damping_f, 0.5f); float damping_compensation = Interpolate(lut_svf_shift, damping_cutoff, 1.0f); // Linearly interpolate delay time. ParameterInterpolator delay_modulation( &delay_, delay * damping_compensation, size); float stretch_point = non_linearity_amount * (2.0f - non_linearity_amount) * 0.225f; float stretch_correction = (160.0f / kSampleRate) * delay; CONSTRAIN(stretch_correction, 1.0f, 2.1f); float noise_amount_sqrt = non_linearity_amount > 0.75f ? 4.0f * (non_linearity_amount - 0.75f) : 0.0f; float noise_amount = noise_amount_sqrt * noise_amount_sqrt * 0.1f; float noise_filter = 0.06f + 0.94f * brightness * brightness; float bridge_curving_sqrt = non_linearity_amount; float bridge_curving = bridge_curving_sqrt * bridge_curving_sqrt * 0.01f; float ap_gain = -0.618f * non_linearity_amount / (0.15f + fabsf(non_linearity_amount)); while (size--) { src_phase_ += src_ratio; if (src_phase_ > 1.0f) { src_phase_ -= 1.0f; float delay = delay_modulation.Next(); float s = 0.0f; if (non_linearity == STRING_NON_LINEARITY_DISPERSION) { float noise = Random::GetFloat() - 0.5f; ONE_POLE(dispersion_noise_, noise, noise_filter) delay *= 1.0f + dispersion_noise_ * noise_amount; } else { delay *= 1.0f - curved_bridge_ * bridge_curving; } if (non_linearity == STRING_NON_LINEARITY_DISPERSION) { float ap_delay = delay * stretch_point; float main_delay = delay - ap_delay * (0.408f - stretch_point * 0.308f) * stretch_correction; if (ap_delay >= 4.0f && main_delay >= 4.0f) { s = string_.Read(main_delay); s = stretch_.Allpass(s, ap_delay, ap_gain); } else { s = string_.ReadHermite(delay); } } else { s = string_.ReadHermite(delay); } if (non_linearity == STRING_NON_LINEARITY_CURVED_BRIDGE) { float value = fabsf(s) - 0.025f; float sign = s > 0.0f ? 1.0f : -1.5f; curved_bridge_ = (fabsf(value) + value) * sign; } s += *in; CONSTRAIN(s, -20.0f, +20.0f); dc_blocker_.Process(&s, 1); s = iir_damping_filter_.Process(s); string_.Write(s); out_sample_[1] = out_sample_[0]; out_sample_[0] = s; } *out++ += Crossfade(out_sample_[1], out_sample_[0], src_phase_); in++; } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/physical_modelling/string.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Comb filter / KS string. "Lite" version of the implementation used in Rings. #ifndef PLAITS_DSP_PHYSICAL_MODELLING_STRING_H_ #define PLAITS_DSP_PHYSICAL_MODELLING_STRING_H_ #include #include "stmlib/stmlib.h" #include "stmlib/dsp/filter.h" #include "stmlib/utils/buffer_allocator.h" #include "plaits/dsp/physical_modelling/delay_line.h" namespace plaits { const size_t kDelayLineSize = 1024; enum StringNonLinearity { STRING_NON_LINEARITY_CURVED_BRIDGE, STRING_NON_LINEARITY_DISPERSION }; class String { public: String() { } ~String() { } void Init(stmlib::BufferAllocator* allocator); void Reset(); void Process( float f0, float non_linearity_amount, float brightness, float damping, const float* in, float* out, size_t size); private: template void ProcessInternal( float f0, float non_linearity_amount, float brightness, float damping, const float* in, float* out, size_t size); DelayLine string_; DelayLine stretch_; stmlib::Svf iir_damping_filter_; stmlib::DCBlocker dc_blocker_; float delay_; float dispersion_noise_; float curved_bridge_; // Very crappy linear interpolation upsampler used for low pitches that // do not fit the delay line. Rarely used. float src_phase_; float out_sample_[2]; DISALLOW_COPY_AND_ASSIGN(String); }; } // namespace plaits #endif // PLAITS_DSP_PHYSICAL_MODELLING_STRING_H_ ================================================ FILE: lib/plaits/dsp/physical_modelling/string_voice.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Extended Karplus-Strong, with all the niceties from Rings. #include "plaits/dsp/physical_modelling/string_voice.h" #include #include "stmlib/dsp/units.h" #include "stmlib/utils/random.h" #include "plaits/dsp/noise/dust.h" namespace plaits { using namespace std; using namespace stmlib; void StringVoice::Init(BufferAllocator* allocator) { excitation_filter_.Init(); string_.Init(allocator); remaining_noise_samples_ = 0; } void StringVoice::Reset() { string_.Reset(); } void StringVoice::Render( bool sustain, bool trigger, float accent, float f0, float structure, float brightness, float damping, float* temp, float* out, float* aux, size_t size) { const float density = brightness * brightness; brightness += 0.25f * accent * (1.0f - brightness); damping += 0.25f * accent * (1.0f - damping); // Synthesize excitation signal. if (trigger || sustain) { const float range = 72.0f; const float f = 4.0f * f0; const float cutoff = min( f * SemitonesToRatio((brightness * (2.0f - brightness) - 0.5f) * range), 0.499f); const float q = sustain ? 1.0f : 0.5f; remaining_noise_samples_ = static_cast(1.0f / f0); excitation_filter_.set_f_q(cutoff, q); } if (sustain) { const float dust_f = 0.00005f + 0.99995f * density * density; for (size_t i = 0; i < size; ++i) { temp[i] = Dust(dust_f) * (8.0f - dust_f * 6.0f) * accent; } } else if (remaining_noise_samples_) { size_t noise_samples = min(remaining_noise_samples_, size); remaining_noise_samples_ -= noise_samples; size_t tail = size - noise_samples; float* start = temp; while (noise_samples--) { *start++ = 2.0f * Random::GetFloat() - 1.0f; } while (tail--) { *start++ = 0.0f; } } else { fill(&temp[0], &temp[size], 0.0f); } excitation_filter_.Process(temp, temp, size); for (size_t i = 0; i < size; ++i) { aux[i] += temp[i]; } float non_linearity = structure < 0.24f ? (structure - 0.24f) * 4.166f : (structure > 0.26f ? (structure - 0.26f) * 1.35135f : 0.0f); string_.Process(f0, non_linearity, brightness, damping, temp, out, size); } } // namespace plaits ================================================ FILE: lib/plaits/dsp/physical_modelling/string_voice.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Extended Karplus-Strong, with all the niceties from Rings. #ifndef PLAITS_DSP_PHYSICAL_STRING_VOICE_H_ #define PLAITS_DSP_PHYSICAL_STRING_VOICE_H_ #include "stmlib/dsp/filter.h" #include "stmlib/utils/buffer_allocator.h" #include "plaits/dsp/physical_modelling/string.h" namespace plaits { class StringVoice { public: StringVoice() { } ~StringVoice() { } void Init(stmlib::BufferAllocator* allocator); void Reset(); void Render( bool sustain, bool trigger, float accent, float f0, float structure, float brightness, float damping, float* temp, float* out, float* aux, size_t size); private: stmlib::Svf excitation_filter_; String string_; size_t remaining_noise_samples_; DISALLOW_COPY_AND_ASSIGN(StringVoice); }; } // namespace plaits #endif // PLAITS_DSP_PHYSICAL_STRING_VOICE_H_ ================================================ FILE: lib/plaits/dsp/speech/lpc_speech_synth.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // LPC10 speech synth. #include "plaits/dsp/speech/lpc_speech_synth.h" #include #include "stmlib/utils/random.h" #include "plaits/dsp/oscillator/oscillator.h" #include "plaits/resources.h" namespace plaits { using namespace std; using namespace stmlib; void LPCSpeechSynth::Init() { phase_ = 0.0f; frequency_ = 0.0125f; noise_energy_ = 0.0f; pulse_energy_ = 0.0f; next_sample_ = 0.0f; excitation_pulse_sample_index_ = 0; fill(&k_[0], &k_[kLPCOrder], 0); fill(&s_[0], &s_[kLPCOrder + 1], 0); } void LPCSpeechSynth::Render( float prosody_amount, float pitch_shift, float* excitation, float* output, size_t size) { const float base_f0 = kLPCSpeechSynthDefaultF0 / 8000.0f; float d = frequency_ - base_f0; float f = (base_f0 + d * prosody_amount) * pitch_shift; CONSTRAIN(f, 0.0f, 0.5f); float next_sample = next_sample_; while (size--) { phase_ += f; float this_sample = next_sample; next_sample = 0.0f; if (phase_ >= 1.0f) { phase_ -= 1.0f; float reset_time = phase_ / f; int reset_sample = static_cast(32.0f * reset_time); float discontinuity = 0.0f; if (excitation_pulse_sample_index_ < LUT_LPC_EXCITATION_PULSE_SIZE) { excitation_pulse_sample_index_ -= reset_sample; int8_t s = lut_lpc_excitation_pulse[excitation_pulse_sample_index_]; discontinuity = static_cast(s) / 128.0f * pulse_energy_; } this_sample += -discontinuity * ThisBlepSample(reset_time); next_sample += -discontinuity * NextBlepSample(reset_time); excitation_pulse_sample_index_ = reset_sample; } float e[11]; e[10] = Random::GetSample() > 0 ? noise_energy_ : -noise_energy_; if (excitation_pulse_sample_index_ < LUT_LPC_EXCITATION_PULSE_SIZE) { int8_t s = lut_lpc_excitation_pulse[excitation_pulse_sample_index_]; next_sample += static_cast(s) / 128.0f * pulse_energy_; excitation_pulse_sample_index_ += 32; } e[10] += this_sample; e[10] *= 1.5f; e[9] = e[10] - k_[9] * s_[9]; e[8] = e[9] - k_[8] * s_[8]; e[7] = e[8] - k_[7] * s_[7]; e[6] = e[7] - k_[6] * s_[6]; e[5] = e[6] - k_[5] * s_[5]; e[4] = e[5] - k_[4] * s_[4]; e[3] = e[4] - k_[3] * s_[3]; e[2] = e[3] - k_[2] * s_[2]; e[1] = e[2] - k_[1] * s_[1]; e[0] = e[1] - k_[0] * s_[0]; CONSTRAIN(e[0], -2.0f, 2.0f); s_[9] = s_[8] + k_[8] * e[8]; s_[8] = s_[7] + k_[7] * e[7]; s_[7] = s_[6] + k_[6] * e[6]; s_[6] = s_[5] + k_[5] * e[5]; s_[5] = s_[4] + k_[4] * e[4]; s_[4] = s_[3] + k_[3] * e[3]; s_[3] = s_[2] + k_[2] * e[2]; s_[2] = s_[1] + k_[1] * e[1]; s_[1] = s_[0] + k_[0] * e[0]; s_[0] = e[0]; *excitation++ = e[10]; *output++ = e[0]; } next_sample_ = next_sample; } void LPCSpeechSynth::PlayFrame(const Frame& f1, const Frame& f2, float blend) { float frequency_1 = f1.period == 0 ? frequency_ : 1.0f / static_cast(f1.period); float frequency_2 = f2.period == 0 ? frequency_ : 1.0f / static_cast(f2.period); frequency_ = frequency_1 + (frequency_2 - frequency_1) * blend; float energy_1 = static_cast(f1.energy) / 256.0f; float energy_2 = static_cast(f2.energy) / 256.0f; float noise_energy_1 = f1.period == 0 ? energy_1 : 0.0f; float noise_energy_2 = f2.period == 0 ? energy_2 : 0.0f; noise_energy_ = noise_energy_1 + (noise_energy_2 - noise_energy_1) * blend; float pulse_energy_1 = f1.period != 0 ? energy_1 : 0; float pulse_energy_2 = f2.period != 0 ? energy_2 : 0; pulse_energy_ = pulse_energy_1 + (pulse_energy_2 - pulse_energy_1) * blend; k_[0] = BlendCoefficient<32768>(f1.k0, f2.k0, blend); k_[1] = BlendCoefficient<32768>(f1.k1, f2.k1, blend); k_[2] = BlendCoefficient<128>(f1.k2, f2.k2, blend); k_[3] = BlendCoefficient<128>(f1.k3, f2.k3, blend); k_[4] = BlendCoefficient<128>(f1.k4, f2.k4, blend); k_[5] = BlendCoefficient<128>(f1.k5, f2.k5, blend); k_[6] = BlendCoefficient<128>(f1.k6, f2.k6, blend); k_[7] = BlendCoefficient<128>(f1.k7, f2.k7, blend); k_[8] = BlendCoefficient<128>(f1.k8, f2.k8, blend); k_[9] = BlendCoefficient<128>(f1.k9, f2.k9, blend); } } // namespace plaits ================================================ FILE: lib/plaits/dsp/speech/lpc_speech_synth.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // LPC10 speech synth. #ifndef PLAITS_DSP_SPEECH_LPC_SPEECH_SYNTH_H_ #define PLAITS_DSP_SPEECH_LPC_SPEECH_SYNTH_H_ #include "stmlib/dsp/dsp.h" #include "plaits/dsp/dsp.h" namespace plaits { const int kLPCOrder = 10; const float kLPCSpeechSynthDefaultF0 = 100.0f; class LPCSpeechSynth { public: LPCSpeechSynth() { } ~LPCSpeechSynth() { } struct Frame { // 14 bytes. uint8_t energy; uint8_t period; int16_t k0; int16_t k1; int8_t k2; int8_t k3; int8_t k4; int8_t k5; int8_t k6; int8_t k7; int8_t k8; int8_t k9; }; void Init(); void Render( float prosody_amount, float pitch_shift, float* excitation, float* output, size_t size); void PlayFrame(const Frame* frames, float frame, bool interpolate) { MAKE_INTEGRAL_FRACTIONAL(frame); if (!interpolate) { frame_fractional = 0.0f; } PlayFrame( frames[frame_integral], frames[frame_integral + 1], frame_fractional); } private: void PlayFrame(const Frame& f1, const Frame& f2, float blend); template float BlendCoefficient(X a, X b, float blend) { float a_f = static_cast(a) / float(scale); float b_f = static_cast(b) / float(scale); return a_f + (b_f - a_f) * blend; } float phase_; float frequency_; float noise_energy_; float pulse_energy_; float next_sample_; int excitation_pulse_sample_index_; float k_[kLPCOrder]; float s_[kLPCOrder + 1]; DISALLOW_COPY_AND_ASSIGN(LPCSpeechSynth); }; }; // namespace plaits #endif // PLAITS_DSP_SPEECH_LPC_SPEECH_SYNTH_H_ ================================================ FILE: lib/plaits/dsp/speech/lpc_speech_synth_controller.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Feeds frames to the LPC10 speech synth. #include "plaits/dsp/speech/lpc_speech_synth_controller.h" #include #include "stmlib/dsp/units.h" #include "stmlib/utils/random.h" #include "plaits/dsp/oscillator/oscillator.h" namespace plaits { using namespace std; using namespace stmlib; /* static */ const uint8_t LPCSpeechSynthWordBank::energy_lut_[16] = { 0x00, 0x02, 0x03, 0x04, 0x05, 0x07, 0x0a, 0x0f, 0x14, 0x20, 0x29, 0x39, 0x51, 0x72, 0xa1, 0xff }; /* static */ const uint8_t LPCSpeechSynthWordBank::period_lut_[64] = { 0, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 47, 49, 51, 53, 54, 57, 59, 61, 63, 66, 69, 71, 73, 77, 79, 81, 85, 87, 92, 95, 99, 102, 106, 110, 115, 119, 123, 128, 133, 138, 143, 149, 154, 160 }; /* static */ const int16_t LPCSpeechSynthWordBank::k0_lut_[32] = { -32064, -31872, -31808, -31680, -31552, -31424, -31232, -30848, -30592, -30336, -30016, -29696, -29376, -28928, -28480, -27968, -26368, -24256, -21632, -18368, -14528, -10048, -5184, 0, 5184, 10048, 14528, 18368, 21632, 24256, 26368, 27968 }; /* static */ const int16_t LPCSpeechSynthWordBank::k1_lut_[32] = { -20992, -19328, -17536, -15552, -13440, -11200, -8768, -6272, -3712, -1088, 1536, 4160, 6720, 9216, 11584, 13824, 15936, 17856, 19648, 21248, 22656, 24000, 25152, 26176, 27072, 27840, 28544, 29120, 29632, 30080, 30464, 32384 }; /* static */ const int8_t LPCSpeechSynthWordBank::k2_lut_[16] = { -110, -97, -83, -70, -56, -43, -29, -16, -2, 11, 25, 38, 52, 65, 79, 92 }; /* static */ const int8_t LPCSpeechSynthWordBank::k3_lut_[16] = { -82, -68, -54, -40, -26, -12, 1, 15, 29, 43, 57, 71, 85, 99, 113, 126 }; /* static */ const int8_t LPCSpeechSynthWordBank::k4_lut_[16] = { -82, -70, -59, -47, -35, -24, -12, -1, 11, 23, 34, 46, 57, 69, 81, 92 }; /* static */ const int8_t LPCSpeechSynthWordBank::k5_lut_[16] = { -64, -53, -42, -31, -20, -9, 3, 14, 25, 36, 47, 58, 69, 80, 91, 102 }; /* static */ const int8_t LPCSpeechSynthWordBank::k6_lut_[16] = { -77, -65, -53, -41, -29, -17, -5, 7, 19, 31, 43, 55, 67, 79, 90, 102 }; /* static */ const int8_t LPCSpeechSynthWordBank::k7_lut_[8] = { -64, -40, -16, 7, 31, 55, 79, 102 }; /* static */ const int8_t LPCSpeechSynthWordBank::k8_lut_[8] = { -64, -44, -24, -4, 16, 37, 57, 77 }; /* static */ const int8_t LPCSpeechSynthWordBank::k9_lut_[8] = { -51, -33, -15, 4, 22, 32, 59, 77 }; void LPCSpeechSynthWordBank::Init( const LPCSpeechSynthWordBankData* word_banks, int num_banks, BufferAllocator* allocator) { word_banks_ = word_banks; num_banks_ = num_banks; frames_ = allocator->Allocate( kLPCSpeechSynthMaxFrames); word_boundaries_ = allocator->Allocate(kLPCSpeechSynthMaxWords); Reset(); } void LPCSpeechSynthWordBank::Reset() { loaded_bank_ = -1; num_frames_ = 0; num_words_ = 0; fill( &word_boundaries_[0], &word_boundaries_[kLPCSpeechSynthMaxWords], 0); } size_t LPCSpeechSynthWordBank::LoadNextWord(const uint8_t* data) { BitStream bitstream; bitstream.Init(data); LPCSpeechSynth::Frame frame; frame.energy = 0; frame.period = 0; frame.k0 = 0; frame.k1 = 0; frame.k2 = 0; frame.k3 = 0; frame.k4 = 0; frame.k5 = 0; frame.k6 = 0; frame.k7 = 0; frame.k8 = 0; frame.k9 = 0; while (true) { int energy = bitstream.GetBits(4); if (energy == 0) { frame.energy = 0; } else if (energy == 0xf) { bitstream.Flush(); break; } else { frame.energy = energy_lut_[energy]; bool repeat = bitstream.GetBits(1); frame.period = period_lut_[bitstream.GetBits(6)]; if (!repeat) { frame.k0 = k0_lut_[bitstream.GetBits(5)]; frame.k1 = k1_lut_[bitstream.GetBits(5)]; frame.k2 = k2_lut_[bitstream.GetBits(4)]; frame.k3 = k3_lut_[bitstream.GetBits(4)]; if (frame.period) { frame.k4 = k4_lut_[bitstream.GetBits(4)]; frame.k5 = k5_lut_[bitstream.GetBits(4)]; frame.k6 = k6_lut_[bitstream.GetBits(4)]; frame.k7 = k7_lut_[bitstream.GetBits(3)]; frame.k8 = k8_lut_[bitstream.GetBits(3)]; frame.k9 = k9_lut_[bitstream.GetBits(3)]; } } } frames_[num_frames_++] = frame; } return bitstream.ptr() - data; } bool LPCSpeechSynthWordBank::Load(int bank) { if (bank == loaded_bank_ || bank >= num_banks_) { return false; } num_frames_ = 0; num_words_ = 0; const uint8_t* data = word_banks_[bank].data; size_t size = word_banks_[bank].size; while (size) { word_boundaries_[num_words_] = num_frames_; size_t consumed = LoadNextWord(data); data += consumed; size -= consumed; ++num_words_; } word_boundaries_[num_words_] = num_frames_; loaded_bank_ = bank; return true; } void LPCSpeechSynthController::Init(LPCSpeechSynthWordBank* word_bank) { word_bank_ = word_bank; clock_phase_ = 0.0f; playback_frame_ = -1; last_playback_frame_ = -1; remaining_frame_samples_ = 0; fill(&sample_[0], &sample_[2], 0.0f); fill(&next_sample_[0], &next_sample_[2], 0.0f); gain_ = 0.0f; synth_.Init(); } void LPCSpeechSynthController::Render( bool free_running, bool trigger, int bank, float frequency, float prosody_amount, float speed, float address, float formant_shift, float gain, float* excitation, float* output, size_t size) { const float rate_ratio = SemitonesToRatio((formant_shift - 0.5f) * 36.0f); const float rate = rate_ratio / 6.0f; // All utterances have been normalized for an average f0 of 100 Hz. const float pitch_shift = frequency / \ (rate_ratio * kLPCSpeechSynthDefaultF0 / kCorrectedSampleRate); const float time_stretch = SemitonesToRatio(-speed * 24.0f + (formant_shift < 0.4f ? (formant_shift - 0.4f) * -45.0f : (formant_shift > 0.6f ? (formant_shift - 0.6f) * -45.0f : 0.0f))); if (bank != -1) { bool reset_everything = word_bank_->Load(bank); if (reset_everything) { playback_frame_ = -1; last_playback_frame_ = -1; } } const int num_frames = bank == -1 ? kLPCSpeechSynthNumVowels : word_bank_->num_frames(); const LPCSpeechSynth::Frame* frames = bank == -1 ? phonemes_ : word_bank_->frames(); if (trigger) { if (bank == -1) { // Pick a pseudo-random consonant, and play it for the duration of a // frame. int r = (address + 3.0f * formant_shift + 7.0f * frequency) * 8.0f; playback_frame_ = (r % kLPCSpeechSynthNumConsonants); playback_frame_ += kLPCSpeechSynthNumVowels; last_playback_frame_ = playback_frame_ + 1; } else { word_bank_->GetWordBoundaries( address, &playback_frame_, &last_playback_frame_); } remaining_frame_samples_ = 0; } if (playback_frame_ == -1 && remaining_frame_samples_ == 0) { synth_.PlayFrame( frames, address * (static_cast(num_frames) - 1.0001f), true); } else { if (remaining_frame_samples_ == 0) { synth_.PlayFrame(frames, float(playback_frame_), false); remaining_frame_samples_ = kSampleRate / kLPCSpeechSynthFPS * \ time_stretch; ++playback_frame_; if (playback_frame_ >= last_playback_frame_) { bool back_to_scan_mode = bank == -1 || free_running; playback_frame_ = back_to_scan_mode ? -1 : last_playback_frame_; } } remaining_frame_samples_ -= min(size, remaining_frame_samples_); } ParameterInterpolator gain_modulation(&gain_, gain, size); while (size--) { float this_sample[2]; copy(&next_sample_[0], &next_sample_[2], &this_sample[0]); fill(&next_sample_[0], &next_sample_[2], 0.0f); clock_phase_ += rate; if (clock_phase_ >= 1.0f) { clock_phase_ -= 1.0f; float reset_time = clock_phase_ / rate; float new_sample[2]; synth_.Render( prosody_amount, pitch_shift, &new_sample[0], &new_sample[1], 1); float discontinuity[2] = { new_sample[0] - sample_[0], new_sample[1] - sample_[1] }; this_sample[0] += discontinuity[0] * ThisBlepSample(reset_time); next_sample_[0] += discontinuity[0] * NextBlepSample(reset_time); this_sample[1] += discontinuity[1] * ThisBlepSample(reset_time); next_sample_[1] += discontinuity[1] * NextBlepSample(reset_time); copy(&new_sample[0], &new_sample[2], &sample_[0]); } next_sample_[0] += sample_[0]; next_sample_[1] += sample_[1]; const float gain = gain_modulation.Next(); *excitation++ = this_sample[0] * gain; *output++ = this_sample[1] * gain; } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/speech/lpc_speech_synth_controller.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Feeds frames to the LPC10 speech synth. #ifndef PLAITS_DSP_SPEECH_LPC_SPEECH_SYNTH_CONTROLLER_H_ #define PLAITS_DSP_SPEECH_LPC_SPEECH_SYNTH_CONTROLLER_H_ #include "plaits/dsp/speech/lpc_speech_synth.h" #include "stmlib/utils/buffer_allocator.h" namespace plaits { class BitStream { public: BitStream() { } ~BitStream() { } inline void Init(const uint8_t* p) { p_ = p; available_ = 0; bits_ = 0; } inline void Flush() { while (available_) { GetBits(1); } } inline uint8_t GetBits(int num_bits) { int shift = num_bits; if (num_bits > available_) { bits_ <<= available_; shift -= available_; bits_ |= Reverse(*p_++); available_ += 8; } bits_ <<= shift; uint8_t result = bits_ >> 8; bits_ &= 0xff; available_ -= num_bits; return result; } inline const uint8_t* ptr() const { return p_; } private: inline uint8_t Reverse(uint8_t b) const { b = (b >> 4) | (b << 4); b = ((b & 0xcc) >> 2) | ((b & 0x33) << 2); b = ((b & 0xaa) >> 1) | ((b & 0x55) << 1); return b; } const uint8_t* p_; int available_; uint16_t bits_; DISALLOW_COPY_AND_ASSIGN(BitStream); }; const int kLPCSpeechSynthMaxWords = 32; const int kLPCSpeechSynthMaxFrames = 1024; const int kLPCSpeechSynthNumVowels = 5; const int kLPCSpeechSynthNumConsonants = 10; const int kLPCSpeechSynthNumPhonemes = \ kLPCSpeechSynthNumVowels + kLPCSpeechSynthNumConsonants; const float kLPCSpeechSynthFPS = 40.0f; struct LPCSpeechSynthWordBankData { const uint8_t* data; size_t size; }; class LPCSpeechSynthWordBank { public: LPCSpeechSynthWordBank() { } ~LPCSpeechSynthWordBank() { } void Init( const LPCSpeechSynthWordBankData* word_banks, int num_banks, stmlib::BufferAllocator* allocator); bool Load(int index); void Reset(); inline int num_frames() const { return num_frames_; } inline const LPCSpeechSynth::Frame* frames() const { return frames_; } inline void GetWordBoundaries(float address, int* start, int* end) { if (num_words_ == 0) { *start = *end = -1; } else { int word = static_cast(address * static_cast(num_words_)); if (word >= num_words_) { word = num_words_ - 1; } *start = word_boundaries_[word]; *end = word_boundaries_[word + 1] - 1; } } private: size_t LoadNextWord(const uint8_t* data); const LPCSpeechSynthWordBankData* word_banks_; int num_banks_; int loaded_bank_; int num_frames_; int num_words_; int* word_boundaries_; LPCSpeechSynth::Frame* frames_; static const uint8_t energy_lut_[16]; static const uint8_t period_lut_[64]; static const int16_t k0_lut_[32]; static const int16_t k1_lut_[32]; static const int8_t k2_lut_[16]; static const int8_t k3_lut_[16]; static const int8_t k4_lut_[16]; static const int8_t k5_lut_[16]; static const int8_t k6_lut_[16]; static const int8_t k7_lut_[8]; static const int8_t k8_lut_[8]; static const int8_t k9_lut_[8]; }; class LPCSpeechSynthController { public: LPCSpeechSynthController() { } ~LPCSpeechSynthController() { } void Init(LPCSpeechSynthWordBank* word_bank); void Render( bool free_running, bool trigger, int bank, float frequency, float prosody_amount, float speed, float address, float formant_shift, float gain, float* excitation, float* output, size_t size); private: float clock_phase_; float sample_[2]; float next_sample_[2]; float gain_; LPCSpeechSynth synth_; int playback_frame_; int last_playback_frame_; size_t remaining_frame_samples_; LPCSpeechSynthWordBank* word_bank_; static const LPCSpeechSynth::Frame phonemes_[kLPCSpeechSynthNumPhonemes]; DISALLOW_COPY_AND_ASSIGN(LPCSpeechSynthController); }; }; // namespace plaits #endif // PLAITS_DSP_SPEECH_LPC_SPEECH_SYNTH_CONTROLLER_H_ ================================================ FILE: lib/plaits/dsp/speech/lpc_speech_synth_phonemes.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // This is a table with vowels (a, e, i, o, u) and a random selection of // consonnants for the LPC10 speech synth. #include "plaits/dsp/speech/lpc_speech_synth_controller.h" namespace plaits { /* static */ const LPCSpeechSynth::Frame LPCSpeechSynthController::phonemes_[kLPCSpeechSynthNumPhonemes] = { { 192, 80, -18368, 11584, 52, 29, 23, 14, -17, 79, 37, 4 }, { 192, 80, -14528, 1536, 38, 29, 11, 14, -41, 79, 57, 4 }, { 192, 80, 14528, 9216, 25, -54, -70, 36, 19, 79, 57, 22 }, { 192, 80, -14528, -13440, 38, 57, 57, 14, -53, 7, 37, 77 }, { 192, 80, -26368, 4160, 11, 15, -1, 36, -41, 31, 77, 22 }, { 15, 0, 5184, 9216, -29, -12, 0, 0, 0, 0, 0, 0 }, { 10, 0, 27968, 17856, 25, 43, -24, -20, -53, 55, -4, -51 }, { 128, 160, 14528, -3712, -43, -26, -24, -20, -53, 55, -4, -51 }, { 128, 160, 10048, 11584, -16, 15, 0, 0, 0, 0, 0, 0 }, { 224, 100, 18368, -13440, -97, -26, -12, -53, -41, 7, 57, 32 }, { 192, 80, -10048, 9216, -70, 15, 34, -20, -17, 31, -24, 22 }, { 96, 160, -18368, 17856, -29, -12, -35, 3, -5, 7, 37, 22 }, { 64, 80, -21632, -6272, -83, 29, 57, 3, -5, 7, 16, 32 }, { 192, 80, 0, -1088, 11, -26, -24, -9, -5, 55, 37, 22 }, { 64, 80, 21632, -17536, -97, 85, 57, -20, -17, 31, -4, 59 } }; } // namespace plaits ================================================ FILE: lib/plaits/dsp/speech/lpc_speech_synth_words.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // LPC10 encoded words extracted from various TI ROMs. #ifndef FLASHMEM #include "pgmspace.h" #endif #include "plaits/dsp/speech/lpc_speech_synth_words.h" namespace plaits { /* extern */ const uint8_t FLASHMEM bank_0[] = { // red 0x30, 0x4a, 0x57, 0xd8, 0x23, 0x2c, 0xc9, 0xa9, 0x62, 0xa1, 0x88, 0xb2, 0x36, 0xa7, 0xca, 0x95, 0xc3, 0xc3, 0x66, 0x9f, 0xb2, 0x64, 0x09, 0x4f, 0x9b, 0x7d, 0x8a, 0x52, 0x24, 0x35, 0xb3, 0xec, 0xc9, 0x6b, 0x92, 0xb2, 0xe8, 0xb0, 0x27, 0xcf, 0x41, 0x2a, 0x63, 0xcc, 0x9e, 0x22, 0x3b, 0x8d, 0xf2, 0x0e, 0x7b, 0xca, 0x1c, 0x34, 0xca, 0xda, 0xec, 0x29, 0xb3, 0xb7, 0x28, 0x6b, 0xb3, 0xa7, 0xce, 0xc1, 0xbc, 0xb2, 0xad, 0x9e, 0x2e, 0x05, 0xcd, 0x8c, 0x96, 0x7a, 0xfa, 0xe4, 0xcd, 0x3b, 0xd3, 0xcc, 0xe9, 0x8b, 0x76, 0xab, 0xa8, 0xd2, 0x67, 0xac, 0x5e, 0xdc, 0x63, 0xe2, 0x9c, 0xa9, 0x45, 0x71, 0xd3, 0x8e, 0x72, 0xa6, 0xee, 0x44, 0x43, 0x6a, 0x2a, 0xc0, 0x98, 0x07, 0x0b, 0xb5, 0xb0, 0x38, 0x6d, 0xae, 0x5a, 0x38, 0x7d, 0x8a, 0x00, 0x00, 0xfc, // orange 0xa3, 0x0d, 0xa3, 0x9a, 0x39, 0x23, 0x9f, 0xcc, 0xd7, 0x0d, 0x57, 0x8b, 0x73, 0x92, 0x50, 0x2e, 0x8d, 0xad, 0xc9, 0x89, 0x43, 0x99, 0x74, 0x8c, 0xba, 0x23, 0xf6, 0xc3, 0xd3, 0xc8, 0x1b, 0x8d, 0xc4, 0x4f, 0xb7, 0x64, 0x9d, 0x3c, 0x92, 0x30, 0x92, 0x4b, 0x69, 0xf2, 0xc8, 0xc2, 0x54, 0x69, 0x91, 0x39, 0xab, 0x08, 0xc3, 0xa9, 0x8c, 0xeb, 0x8e, 0x3a, 0x4e, 0xaa, 0xc2, 0x2c, 0xd3, 0xda, 0x38, 0xb0, 0x92, 0xb3, 0xe8, 0xe8, 0x63, 0xa3, 0x0a, 0x8d, 0x30, 0xa3, 0x4f, 0x85, 0xda, 0x3d, 0x83, 0xac, 0x21, 0x67, 0x6a, 0xb3, 0x0a, 0xb3, 0x86, 0x92, 0xb0, 0xdc, 0x33, 0xcc, 0x18, 0xb3, 0xa3, 0x8c, 0xd6, 0xc0, 0x6b, 0x2c, 0x01, 0xd3, 0x3a, 0x2d, 0x8d, 0x29, 0x4b, 0x4a, 0x5d, 0xb5, 0x5c, 0x66, 0xcb, 0x6d, 0xd9, 0x2c, 0x49, 0x99, 0x8d, 0xb4, 0xd1, 0x34, 0x36, 0x69, 0xe1, 0xc6, 0x2a, 0xd2, 0x91, 0xa4, 0x95, 0x1b, 0xcf, 0xce, 0x82, 0xdb, 0xd6, 0x28, 0x39, 0xbc, 0xc5, 0xb1, 0x03, 0x02, 0xe5, 0x48, 0xc0, 0x0c, 0x42, 0x0e, 0x18, 0xa7, 0x4b, 0x01, 0x73, 0xa7, 0x01, 0x00, 0xfc, // yellow 0xa9, 0xda, 0x94, 0xdc, 0x32, 0xe4, 0xb6, 0xaa, 0x03, 0xf2, 0xe8, 0xb2, 0x3b, 0x8a, 0x01, 0xb8, 0xb2, 0xc7, 0xea, 0xca, 0x33, 0x36, 0xef, 0x0e, 0x31, 0x27, 0x2f, 0x92, 0x3d, 0x3b, 0xa5, 0x9c, 0xac, 0x78, 0xca, 0xae, 0xb0, 0x7c, 0xb2, 0x1a, 0x39, 0x23, 0xd3, 0xca, 0xc9, 0x4a, 0x96, 0x28, 0x6b, 0x2b, 0x27, 0xcb, 0x59, 0x33, 0xac, 0xc2, 0x9c, 0x3c, 0x57, 0x2b, 0xb3, 0xb6, 0x72, 0xf2, 0xd4, 0x2c, 0xdd, 0x2a, 0xcc, 0xca, 0x63, 0x4e, 0x37, 0x8d, 0x28, 0xad, 0x08, 0x3e, 0x9a, 0xa4, 0x23, 0x8f, 0x3a, 0xd4, 0x0a, 0xe6, 0xae, 0xdc, 0x6a, 0x5f, 0xcb, 0x59, 0x3a, 0xca, 0x68, 0x43, 0x19, 0x55, 0xa9, 0xb2, 0xa3, 0x0b, 0x3d, 0xd5, 0x3c, 0xa3, 0xae, 0x2e, 0x94, 0x51, 0xf3, 0x8a, 0xb2, 0xfa, 0x58, 0xd3, 0xdc, 0x2a, 0xec, 0xe9, 0x53, 0x8a, 0x92, 0x68, 0x2b, 0x67, 0x48, 0x29, 0x53, 0xbd, 0xc2, 0x9c, 0x21, 0x87, 0x4a, 0xd3, 0x18, 0x73, 0xc6, 0x1c, 0xb2, 0x5c, 0x7d, 0xcc, 0x19, 0xb3, 0xaf, 0x72, 0x93, 0x31, 0x6b, 0xcc, 0x3e, 0xda, 0x55, 0xa6, 0xac, 0x29, 0xbb, 0x2a, 0x33, 0xae, 0x3c, 0xa6, 0xe4, 0x2b, 0x4d, 0xa5, 0x72, 0x9b, 0x63, 0xee, 0x14, 0xb1, 0xca, 0x61, 0x8d, 0xb5, 0x9d, 0x58, 0x2a, 0x9b, 0x29, 0x84, 0x0a, 0x64, 0xae, 0xa2, 0xa6, 0xe8, 0xda, 0xd0, 0xc9, 0x0a, 0x00, 0xc0, 0xff, // green 0x80, 0x1a, 0xf0, 0xd7, 0x88, 0x25, 0x8d, 0x68, 0x40, 0x37, 0x9f, 0x4a, 0x4b, 0xa5, 0xce, 0x37, 0xdd, 0xd5, 0x62, 0xaf, 0xb2, 0x94, 0x74, 0x17, 0xb6, 0x3d, 0x6a, 0x1f, 0xdc, 0xc2, 0x23, 0x4e, 0x2b, 0x4d, 0xe5, 0xcc, 0x08, 0x27, 0xa5, 0xb0, 0x05, 0xab, 0xcd, 0x63, 0xb7, 0xc2, 0x47, 0x8a, 0x71, 0x2f, 0xb2, 0x0a, 0xef, 0xd4, 0xb6, 0x38, 0xf4, 0x2a, 0x92, 0x21, 0xdf, 0xb4, 0xc0, 0xa7, 0xc8, 0x9a, 0x6c, 0x5b, 0x43, 0x9f, 0x22, 0x6b, 0xb2, 0x19, 0x0b, 0x7d, 0xea, 0xaa, 0x48, 0x7b, 0xdc, 0xf4, 0xe9, 0xaa, 0x22, 0xeb, 0x36, 0x2b, 0x67, 0x68, 0x86, 0x34, 0xdb, 0xac, 0x9c, 0xa1, 0x1b, 0x92, 0x6c, 0x8b, 0x73, 0x86, 0x61, 0x98, 0xb3, 0x3d, 0xce, 0x19, 0xba, 0x25, 0x8d, 0x8c, 0x28, 0x67, 0xea, 0x9e, 0x2c, 0x3c, 0xe3, 0x8c, 0xa9, 0x7a, 0x92, 0xd4, 0x2c, 0x33, 0xa6, 0xe2, 0xd0, 0x5c, 0x3b, 0xea, 0x98, 0x6b, 0x40, 0x57, 0x1b, 0x3b, 0x6b, 0xae, 0x91, 0x4c, 0xb4, 0x93, 0xb6, 0x29, 0x19, 0x0a, 0x8f, 0x56, 0x92, 0xca, 0xa0, 0xc5, 0xad, 0x3c, 0x76, 0xf0, 0x9b, 0x56, 0x47, 0xb7, 0x35, 0x00, 0x00, 0xff, // blue 0xa2, 0x81, 0x39, 0xd2, 0x2c, 0xa3, 0xa8, 0x12, 0x14, 0x2f, 0xf5, 0xb4, 0xa2, 0x4a, 0xd2, 0x39, 0x3d, 0xcd, 0x71, 0xcb, 0xbb, 0x4e, 0x17, 0xb5, 0x26, 0x2b, 0x8b, 0x2a, 0xd3, 0xc2, 0xcb, 0xac, 0x3a, 0xe8, 0x4d, 0x53, 0xab, 0xda, 0x2a, 0xaf, 0xde, 0xd1, 0xa3, 0x72, 0x29, 0x9d, 0xfc, 0x20, 0xf7, 0x3a, 0xa5, 0x70, 0x62, 0x4b, 0x5d, 0xe3, 0x94, 0x5c, 0x9b, 0x09, 0x53, 0xaf, 0x33, 0x72, 0xa7, 0x3a, 0xc4, 0xa3, 0xce, 0x28, 0x8c, 0xdb, 0x70, 0xc9, 0xd2, 0xa3, 0x50, 0x61, 0x3a, 0x39, 0x2a, 0xaf, 0x5a, 0xfb, 0xae, 0xd2, 0x2a, 0x7c, 0x5a, 0xe7, 0xc2, 0x23, 0xbb, 0xd2, 0xe9, 0x92, 0x72, 0x77, 0xcf, 0x45, 0xa7, 0xcf, 0xca, 0x4d, 0xc3, 0x57, 0x9e, 0x3e, 0x49, 0x0b, 0x0f, 0x5b, 0x78, 0x86, 0xa4, 0x2d, 0xdc, 0xec, 0xf6, 0x1a, 0xa2, 0xf6, 0x70, 0xb5, 0xdb, 0x6d, 0x08, 0x3e, 0x5d, 0xd9, 0x6e, 0xb7, 0x31, 0xa4, 0x54, 0x56, 0xaf, 0x13, 0x46, 0xef, 0xd2, 0x4c, 0xb5, 0xb6, 0x99, 0xa2, 0x0b, 0x55, 0xe5, 0x70, 0x66, 0x8e, 0xc9, 0x82, 0x49, 0xa3, 0xb2, 0x49, 0x07, 0x4d, 0x61, 0xb7, 0x0b, 0x00, 0xf0, // indigo 0xae, 0xa8, 0x86, 0xbc, 0x33, 0x94, 0x9e, 0x62, 0x04, 0x43, 0x8b, 0xae, 0x7b, 0x8a, 0xa6, 0x48, 0x63, 0xda, 0xca, 0xc9, 0x47, 0x74, 0x62, 0xef, 0x26, 0x27, 0xef, 0x8a, 0xd5, 0xbb, 0x2d, 0x8f, 0x2c, 0x49, 0x72, 0xef, 0xb2, 0x3d, 0x92, 0x20, 0x39, 0xb3, 0xd2, 0x76, 0x4b, 0x9c, 0x92, 0xf2, 0x4d, 0x86, 0x25, 0x51, 0x56, 0xc6, 0x57, 0x6c, 0xa5, 0x8c, 0x26, 0x1f, 0x2b, 0x72, 0x14, 0x32, 0x12, 0xa2, 0xd3, 0x9d, 0xce, 0xca, 0x87, 0x4d, 0x15, 0x6d, 0xab, 0xa7, 0xa8, 0x86, 0xcd, 0x6a, 0x6c, 0x9f, 0x2a, 0x1b, 0xb6, 0xae, 0xb6, 0x72, 0xaa, 0x62, 0xd8, 0xb2, 0xdb, 0xce, 0x69, 0xab, 0x65, 0xa9, 0x9c, 0x28, 0xad, 0xcf, 0x9a, 0x22, 0xbd, 0x95, 0xa8, 0x91, 0x29, 0xeb, 0xc9, 0x90, 0x4c, 0x00, 0x6c, 0xa9, 0x03, 0x90, 0x03, 0xf9, 0xca, 0x8b, 0x13, 0xce, 0xec, 0x2a, 0x67, 0x28, 0x4a, 0xad, 0x3d, 0x8b, 0x9c, 0x21, 0x5b, 0xb7, 0xf0, 0xae, 0x72, 0x86, 0xe8, 0x2c, 0x23, 0x26, 0xca, 0x19, 0x83, 0x2f, 0x0f, 0xef, 0xd2, 0x67, 0x8c, 0x21, 0x3d, 0xbc, 0xaa, 0x9c, 0x31, 0xa4, 0x54, 0x8f, 0xaa, 0x72, 0xc6, 0x10, 0x46, 0xdd, 0x73, 0xd2, 0x19, 0x83, 0x5f, 0x35, 0xcf, 0xca, 0x67, 0x4c, 0x31, 0x8a, 0xa5, 0x5a, 0x9d, 0x29, 0xc6, 0x2c, 0xd6, 0x6c, 0x39, 0xa6, 0x98, 0x33, 0x49, 0x6b, 0xe5, 0x98, 0x42, 0xaa, 0x44, 0x8d, 0x56, 0x63, 0x0a, 0xb9, 0x02, 0x35, 0x5b, 0x8e, 0xc5, 0xd5, 0x74, 0xd6, 0x6e, 0xa4, 0x96, 0xe4, 0xc3, 0xcd, 0x3c, 0x09, 0x00, 0xfc, // violet 0xa9, 0x11, 0x36, 0xb3, 0x5c, 0x23, 0xa6, 0x2e, 0x48, 0x73, 0x55, 0x4b, 0x5a, 0x9a, 0xa4, 0x5d, 0x4d, 0xd9, 0xc9, 0x68, 0xaa, 0x32, 0x77, 0x27, 0x2b, 0xab, 0xae, 0x32, 0x22, 0x1c, 0x1d, 0x9f, 0x32, 0xd9, 0x88, 0x14, 0xa9, 0x73, 0xca, 0x18, 0xcb, 0x43, 0x6d, 0xea, 0xa9, 0xe2, 0x28, 0x0d, 0xcd, 0x2a, 0xa7, 0x8a, 0x3b, 0xb8, 0x22, 0x43, 0x9f, 0x3c, 0xf6, 0xd2, 0xd2, 0x1c, 0x7d, 0xf2, 0xd8, 0xd2, 0x4b, 0xaa, 0xf4, 0xc9, 0x53, 0x1e, 0xa9, 0xb4, 0x4a, 0x27, 0x4f, 0x2d, 0x74, 0xd2, 0x23, 0x9f, 0x3c, 0xd5, 0xd0, 0xf1, 0x0c, 0x73, 0xca, 0x9c, 0x2c, 0xca, 0x26, 0xcc, 0xa9, 0x4a, 0x74, 0x2b, 0x9b, 0x2a, 0xa7, 0xc9, 0xd1, 0x3c, 0x7d, 0xad, 0x9c, 0x2e, 0x9b, 0xd2, 0xb4, 0x2a, 0x7d, 0xfa, 0x24, 0x47, 0xc3, 0xa3, 0xca, 0xe9, 0x33, 0x1f, 0x57, 0xb5, 0x39, 0x6b, 0x88, 0xba, 0xdc, 0xb8, 0xea, 0x9c, 0x21, 0xe9, 0x54, 0xd7, 0xae, 0x72, 0x86, 0xa4, 0x53, 0x43, 0xbb, 0xca, 0x19, 0x8a, 0xd2, 0x28, 0xe9, 0x2a, 0x67, 0x2c, 0xd6, 0xcc, 0x6d, 0xaa, 0x9e, 0x39, 0x6b, 0xd7, 0xb0, 0x1a, 0x72, 0xd6, 0x64, 0xdc, 0xc2, 0x6b, 0x6c, 0x1a, 0xa2, 0x57, 0xb5, 0x98, 0xa2, 0xa6, 0x51, 0xcd, 0xc3, 0x35, 0xac, 0x08, 0x20, 0x11, 0x4d, 0x06, 0x34, 0x2e, 0xc6, 0x80, 0x2c, 0xdc, 0x08, 0x90, 0x94, 0x39, 0x00, 0xc0, 0xff }; /* extern */ const uint8_t FLASHMEM bank_1[] = { // zero 0x69, 0xfc, 0x59, 0xdd, 0x51, 0xd5, 0xd7, 0xa1, 0x8f, 0x0a, 0x78, 0xc0, 0x52, 0x01, 0x0f, 0x50, 0xac, 0xfc, 0xa8, 0x16, 0x15, 0xf2, 0x7b, 0xb2, 0x19, 0x47, 0xd0, 0x64, 0xeb, 0x4d, 0x77, 0xba, 0xb3, 0x91, 0x97, 0x24, 0x6e, 0x62, 0x6d, 0x5b, 0x15, 0x0a, 0xa7, 0xb9, 0xc5, 0xab, 0xd5, 0xaa, 0x63, 0xf0, 0xf0, 0xe2, 0x6c, 0xb3, 0x19, 0x5d, 0x52, 0x1d, 0x19, 0x94, 0x6f, 0x76, 0x7d, 0xe8, 0x43, 0x19, 0x83, 0xdc, 0x48, 0xc7, 0x2e, 0x71, 0x8c, 0x93, 0x9f, 0xe0, 0xff, // one 0xa6, 0x4e, 0xa8, 0x7a, 0x8d, 0xed, 0xc4, 0xb6, 0xd5, 0x89, 0xd4, 0xbc, 0xa2, 0xdb, 0x91, 0x25, 0xbe, 0x33, 0x4c, 0xd9, 0x4f, 0x92, 0x4d, 0x57, 0x8a, 0x76, 0xbe, 0xf1, 0x89, 0xaa, 0x2e, 0x4f, 0xd5, 0xcd, 0x37, 0xd9, 0x45, 0x6b, 0x87, 0x13, 0x4c, 0x0d, 0xa7, 0xb5, 0xab, 0x7d, 0x1e, 0xe3, 0x18, 0x67, 0x3f, 0xa7, 0xa5, 0xf9, 0xd0, 0x30, 0x5b, 0x1d, 0x96, 0x9a, 0x34, 0x44, 0xbc, 0xb6, 0x5d, 0xe0, 0xff, // two 0x06, 0xb8, 0x59, 0x34, 0x00, 0x27, 0xd6, 0x38, 0x60, 0x58, 0xd3, 0x11, 0x55, 0x2d, 0xaa, 0x65, 0x9d, 0x4f, 0xd2, 0xb8, 0x39, 0x17, 0x67, 0xbf, 0xc9, 0xce, 0x5a, 0x1e, 0xb5, 0x7a, 0x06, 0xf6, 0xa9, 0x75, 0xed, 0x52, 0x6f, 0x55, 0xa5, 0x26, 0x75, 0xc9, 0x93, 0x9f, 0xfc, 0x6c, 0x16, 0x63, 0x3a, 0x34, 0x70, 0xaf, 0x5e, 0xe1, 0xff, // three 0x0c, 0xe8, 0x2e, 0x94, 0x01, 0x4d, 0xba, 0x4a, 0x40, 0x03, 0x16, 0x68, 0x41, 0x36, 0x1c, 0xe9, 0xba, 0xb8, 0x45, 0x39, 0x70, 0x72, 0x84, 0xdb, 0x11, 0xa7, 0xa8, 0x4e, 0xa3, 0xc9, 0x77, 0xbc, 0x92, 0xd6, 0x52, 0xa8, 0x71, 0xed, 0x4a, 0x7a, 0x4b, 0xa6, 0xe0, 0x37, 0x37, 0x5d, 0xe5, 0x48, 0x8e, 0x94, 0xf1, 0x64, 0x76, 0xad, 0x1f, 0x55, 0x91, 0xbc, 0x6e, 0xd7, 0xb1, 0xce, 0x75, 0xad, 0x5b, 0xda, 0xc7, 0x70, 0x22, 0xcd, 0xc7, 0x79, 0x8f, 0x3b, 0xfc, // four 0x08, 0x68, 0x21, 0x0d, 0x03, 0x1c, 0x90, 0xc0, 0x70, 0x93, 0xb2, 0x29, 0x87, 0x76, 0x2b, 0x28, 0x5c, 0x7b, 0x06, 0xd9, 0xed, 0x60, 0x04, 0x51, 0x54, 0x4d, 0xa2, 0xba, 0x19, 0xb5, 0x2c, 0xf8, 0xea, 0x74, 0xca, 0xd3, 0xeb, 0xde, 0x97, 0x29, 0xa4, 0xd4, 0x4e, 0xc9, 0x5f, 0xa7, 0xb2, 0xa5, 0x9c, 0x1c, 0x63, 0xde, 0xf2, 0x91, 0xce, 0x34, 0x84, 0x27, 0x2d, 0x4b, 0xb8, 0x52, 0x09, 0x9c, 0x0e, 0xb7, 0xee, 0xcc, 0x5b, 0x70, 0xdd, 0xb2, 0xc0, 0xff, // five 0x08, 0x68, 0x4e, 0x9d, 0x02, 0x1c, 0x60, 0xc0, 0x8c, 0x69, 0x12, 0xb0, 0xc0, 0x88, 0xaa, 0x8c, 0x9c, 0xc0, 0x2d, 0x3b, 0x3a, 0x41, 0x31, 0x15, 0xa3, 0xb6, 0xe4, 0x46, 0x37, 0xda, 0xc9, 0xce, 0x56, 0xde, 0x54, 0x5b, 0x85, 0xbe, 0xd9, 0xd5, 0x6c, 0x47, 0xdf, 0x6d, 0xb1, 0xa5, 0xbf, 0x99, 0x7d, 0x1b, 0x5b, 0x30, 0x09, 0xaf, 0x2f, 0x6d, 0xea, 0x31, 0xc4, 0x5c, 0xbe, 0xd6, 0x29, 0x2d, 0xad, 0x88, 0x87, 0xe2, 0xd2, 0xb2, 0xf6, 0xe0, 0x16, 0x2a, 0xb2, 0xe3, 0x6a, 0x57, 0xb9, 0xf2, 0x15, 0xfe, // six 0x04, 0xf8, 0xb9, 0x55, 0x01, 0xbf, 0xa5, 0x1b, 0xe0, 0x37, 0x0f, 0x03, 0xfc, 0x96, 0x61, 0x80, 0xdf, 0x3c, 0x0c, 0xf0, 0x93, 0xda, 0xea, 0x86, 0x49, 0x53, 0x91, 0x37, 0xab, 0x6b, 0xd2, 0x55, 0x23, 0xde, 0xac, 0xb9, 0xb9, 0x16, 0x09, 0xff, 0xb2, 0xf6, 0x66, 0x93, 0x3c, 0x63, 0xf3, 0xbc, 0x11, 0x3e, 0x45, 0xa9, 0x0a, 0xd5, 0x00, 0x00, 0x02, 0x14, 0x97, 0xaa, 0x80, 0xab, 0x6b, 0x0d, 0xf0, 0x63, 0xa5, 0x01, 0x7e, 0xcb, 0x30, 0xc0, 0x6f, 0xe9, 0x0a, 0xf8, 0x25, 0x93, 0x01, 0x3f, 0x57, 0xc0, 0xff, // seven 0x0c, 0x78, 0xc6, 0x95, 0x01, 0x3f, 0xa5, 0x28, 0xe0, 0xb7, 0x52, 0x0b, 0x04, 0xe0, 0xb7, 0x54, 0x07, 0xfc, 0x52, 0x66, 0x80, 0x9f, 0xcb, 0x56, 0x5d, 0x6c, 0x98, 0x47, 0x3e, 0x59, 0x5d, 0x89, 0x69, 0x66, 0xb9, 0x7a, 0x74, 0x39, 0x86, 0x9b, 0xd9, 0xa6, 0x34, 0xe4, 0x10, 0xae, 0xca, 0xad, 0xc7, 0x90, 0x5d, 0x9a, 0xa9, 0xae, 0x1a, 0x6d, 0xb1, 0xa5, 0x66, 0xf9, 0xb2, 0xb4, 0x4d, 0x63, 0xb6, 0x84, 0x9a, 0x52, 0x77, 0x45, 0x11, 0x1a, 0xaa, 0x4b, 0x35, 0x0c, 0x79, 0x4a, 0xb0, 0x49, 0xd5, 0x50, 0xa2, 0x41, 0xa1, 0xc9, 0xe5, 0xd9, 0xab, 0x89, 0x56, 0x04, 0xf8, // eight 0x6d, 0x18, 0xde, 0x58, 0x23, 0x17, 0xaf, 0x61, 0xe8, 0x20, 0xeb, 0x5c, 0xbc, 0xba, 0x61, 0x03, 0xad, 0x73, 0xf6, 0x6a, 0x66, 0x4a, 0xd0, 0xcc, 0xd9, 0xab, 0x1b, 0x45, 0xc1, 0xa3, 0x66, 0xaf, 0x69, 0x36, 0x03, 0x8b, 0x5a, 0x9c, 0xd6, 0x51, 0x04, 0xa2, 0x66, 0x96, 0x7b, 0xba, 0x47, 0xec, 0xed, 0x8a, 0x08, 0x9a, 0xa2, 0x54, 0x85, 0x6a, 0x00, 0x80, 0x02, 0x86, 0x74, 0x63, 0xc0, 0xe6, 0x6a, 0xf0, // nine 0xa2, 0x73, 0xdc, 0x33, 0xb5, 0x62, 0xb9, 0x36, 0x0b, 0x8e, 0x34, 0x8f, 0xd3, 0xea, 0xae, 0x59, 0xd2, 0x34, 0xe9, 0xa8, 0x86, 0x27, 0xc9, 0xd0, 0x78, 0x2b, 0x6f, 0xce, 0xc2, 0x45, 0x1b, 0xaf, 0xb4, 0xf8, 0x51, 0x73, 0x9d, 0xb3, 0xd2, 0x12, 0xc7, 0x2c, 0x6d, 0xc9, 0x4a, 0x72, 0x4b, 0xf3, 0x88, 0x26, 0x2b, 0xc9, 0x2d, 0xcc, 0x23, 0xea, 0xac, 0x34, 0xb7, 0xd0, 0x88, 0x98, 0xb3, 0xf2, 0x5c, 0x43, 0x32, 0x7d, 0xce, 0x2a, 0x4b, 0x0a, 0xcd, 0xf4, 0x39, 0xab, 0xae, 0x3e, 0x24, 0xcb, 0x67, 0xaf, 0xae, 0xd9, 0xe4, 0x18, 0x5f, 0xb4, 0x86, 0x6e, 0x92, 0x62, 0x7d, 0xd1, 0x18, 0xbb, 0x09, 0xf2, 0x8d, 0x59, 0x6d, 0xec, 0x3a, 0xd8, 0x27, 0x16, 0xa6, 0xa5, 0x7b, 0xf2, 0x74, 0x4f, 0x92, 0xd6, 0x1e, 0xc8, 0x4a, 0xc3, 0x49, 0x5a, 0x9b, 0x25, 0x2b, 0xf5, 0x24, 0x69, 0xe9, 0xd1, 0x24, 0x25, 0x27, 0xba, 0xa5, 0x25, 0x51, 0xd3, 0xaa, 0x24, 0xe6, 0x5e, 0x54, 0x55, 0x3a, 0x14, 0xfc, // ten 0x0a, 0xd8, 0x5c, 0x4d, 0x03, 0x2b, 0xa8, 0x5e, 0xc4, 0x33, 0x2b, 0xaf, 0x78, 0x84, 0x12, 0x0d, 0x7b, 0xb3, 0xe2, 0x66, 0x43, 0xa2, 0xe3, 0xf6, 0x4a, 0xaa, 0x4e, 0xc9, 0x89, 0xdb, 0x2b, 0x6b, 0xba, 0xc5, 0xdb, 0x66, 0xaf, 0xb6, 0xe8, 0xe6, 0x4c, 0xbf, 0x3d, 0xda, 0x6a, 0xc4, 0x4b, 0xca, 0x49, 0x19, 0xba, 0x61, 0x2b, 0x09, 0x25, 0x6d, 0xea, 0x5a, 0xb4, 0xc4, 0xed, 0xa6, 0x65, 0x18, 0xe1, 0x56, 0xb7, 0x9a, 0x96, 0xa6, 0x44, 0x47, 0xdc, 0x6e, 0x5e, 0xc2, 0xda, 0xa5, 0xf0, 0xb8, 0xd9, 0x85, 0xff }; /* extern */ const uint8_t FLASHMEM bank_2[] = { // a 0xa5, 0x2f, 0x96, 0xad, 0x7b, 0x6a, 0x9f, 0x6a, 0xe4, 0x20, 0x8d, 0x9c, 0x73, 0xf3, 0x9b, 0xdd, 0xec, 0xe6, 0x37, 0xbf, 0xe5, 0xaa, 0x66, 0x28, 0xa0, 0xce, 0xd5, 0xbb, 0xd9, 0xed, 0xee, 0x66, 0x3f, 0x87, 0x36, 0xce, 0x9c, 0x80, 0x51, 0x8b, 0xeb, 0x54, 0xe7, 0xbc, 0xc2, 0xff, // b 0xa6, 0x2a, 0xaa, 0x05, 0x5c, 0xd6, 0x8c, 0xb8, 0xc7, 0x16, 0x70, 0x59, 0x33, 0xa2, 0x95, 0x0b, 0xc1, 0xfd, 0xcd, 0x8c, 0x66, 0x38, 0xe3, 0x91, 0xad, 0x98, 0x00, 0x55, 0x8b, 0x67, 0xd1, 0xdb, 0xde, 0xd5, 0xa9, 0xce, 0x75, 0x2e, 0xeb, 0x2c, 0x4d, 0x60, 0xbe, 0x26, 0xef, 0xf1, 0x88, 0x27, 0xfc, // c 0x04, 0xf8, 0xa5, 0x83, 0x03, 0x12, 0xb0, 0x80, 0x07, 0x22, 0xb0, 0x9c, 0xee, 0x8d, 0x45, 0x7d, 0xc9, 0x8a, 0x66, 0x29, 0x42, 0xf5, 0x35, 0x3b, 0xda, 0xd1, 0x88, 0x67, 0x0d, 0x40, 0xcf, 0xd7, 0x33, 0x19, 0xf9, 0xac, 0x06, 0x14, 0xb5, 0x68, 0xd6, 0xbd, 0xeb, 0x7d, 0x1f, 0xd3, 0x32, 0x5b, 0x02, 0x44, 0xbd, 0xce, 0x6b, 0x5e, 0xf3, 0x96, 0xb6, 0x55, 0x0a, 0xc1, 0x73, 0x4d, 0xde, 0xf3, 0x0e, 0xff, // d 0x08, 0x20, 0xba, 0x0d, 0x03, 0x6d, 0x38, 0x2c, 0x55, 0x45, 0xb3, 0x8c, 0xba, 0x05, 0x65, 0xd5, 0x78, 0x32, 0xaa, 0xee, 0x85, 0x34, 0xf2, 0xf6, 0xa8, 0x87, 0x33, 0xe0, 0xca, 0xc7, 0xad, 0x9e, 0xce, 0x81, 0xbb, 0x66, 0xb7, 0x76, 0x06, 0x07, 0xee, 0x9c, 0xd5, 0xba, 0xa9, 0x1d, 0x65, 0x72, 0x11, 0xfc, // e 0xa2, 0x5a, 0x95, 0x51, 0xba, 0x17, 0xf7, 0x62, 0xe5, 0xab, 0x38, 0x42, 0xe4, 0x92, 0x9d, 0xef, 0x6c, 0x65, 0x33, 0x3b, 0x50, 0xd6, 0x92, 0x9d, 0xaf, 0x62, 0xc5, 0x04, 0xa8, 0x5a, 0xbc, 0xcb, 0x5d, 0xed, 0x7a, 0x37, 0xbb, 0xdd, 0xc3, 0x1e, 0xf6, 0x34, 0xa7, 0xbe, 0xf4, 0xa5, 0xad, 0xb3, 0x34, 0x81, 0xf9, 0x1a, 0xf8, // f 0xab, 0x1a, 0x61, 0x94, 0xdd, 0xd6, 0xdc, 0xf6, 0x54, 0xdd, 0x37, 0xb9, 0xe7, 0xea, 0x53, 0x35, 0xb3, 0x1c, 0xe1, 0xaf, 0x6f, 0x75, 0xdb, 0x35, 0xd4, 0xe0, 0x56, 0x9c, 0x77, 0xdb, 0x58, 0x9d, 0xeb, 0x98, 0x8c, 0x61, 0xc0, 0x30, 0xe9, 0x1a, 0xb0, 0x80, 0x05, 0x14, 0x30, 0x6d, 0xbb, 0x06, 0x24, 0x20, 0x01, 0x0e, 0x10, 0xa0, 0x06, 0x35, 0xf8, // g 0x6e, 0x3e, 0x29, 0x8d, 0x98, 0x95, 0xcd, 0x39, 0x00, 0xab, 0x38, 0x95, 0xf4, 0xd4, 0xeb, 0x34, 0x81, 0x7a, 0xe2, 0x51, 0x53, 0x50, 0x75, 0xeb, 0x8e, 0x76, 0xb4, 0xc3, 0x15, 0x8d, 0x92, 0x48, 0x99, 0xab, 0x77, 0xbc, 0xd3, 0x5d, 0x8e, 0x76, 0x96, 0x04, 0x8c, 0x5a, 0x3c, 0xfb, 0xd9, 0xf7, 0xa9, 0x4e, 0x75, 0x2b, 0xdb, 0x2a, 0x85, 0xe0, 0xb9, 0x26, 0x1e, 0xf1, 0x80, 0xff, // h 0xa5, 0x1d, 0x6d, 0x90, 0x2d, 0xd6, 0xec, 0xf2, 0xe6, 0x37, 0xbb, 0xe9, 0x2e, 0x46, 0x3b, 0xa3, 0x01, 0x6d, 0x2d, 0xce, 0xa3, 0x5d, 0xdd, 0xdc, 0x3c, 0x61, 0x76, 0xc5, 0x25, 0xb3, 0x08, 0xe5, 0x2e, 0x22, 0x1b, 0x00, 0x80, 0x01, 0x2b, 0x87, 0x38, 0x60, 0xe5, 0xed, 0x08, 0x58, 0xc0, 0x02, 0x16, 0xb0, 0x80, 0x06, 0x34, 0x40, 0x80, 0x76, 0xd3, 0xe0, 0xff, // i 0x2a, 0x8b, 0x63, 0xa8, 0xaa, 0x66, 0xad, 0xb6, 0xa8, 0xcb, 0x08, 0xdd, 0x7c, 0x8b, 0x9b, 0xde, 0xf4, 0x66, 0x37, 0x3b, 0x59, 0xb5, 0xa3, 0x15, 0xba, 0xf8, 0xe6, 0xbb, 0xd8, 0xcd, 0x6e, 0x57, 0xdf, 0x5c, 0x49, 0xa5, 0x2d, 0xde, 0x63, 0x1b, 0x6b, 0x76, 0x29, 0xaf, 0xc7, 0x6d, 0xec, 0x31, 0xd8, 0x5c, 0x1e, 0xf7, 0xb1, 0x4e, 0x75, 0x4a, 0xf3, 0x28, 0x89, 0xe2, 0xf2, 0x38, 0x2f, 0x79, 0x85, 0xff, // j 0xae, 0x5e, 0xc1, 0x99, 0x54, 0xb2, 0x09, 0x60, 0x49, 0x22, 0x07, 0xec, 0xa8, 0x16, 0x80, 0x5d, 0x26, 0x47, 0xd5, 0xa3, 0x92, 0x78, 0x74, 0x3e, 0x71, 0x2f, 0x21, 0x6a, 0xb1, 0xfa, 0xc6, 0x37, 0xbe, 0xf1, 0x4d, 0x6f, 0x7a, 0xf3, 0x5d, 0x8d, 0x7e, 0xb4, 0x22, 0x36, 0x7f, 0x53, 0xe7, 0xbe, 0xb4, 0x6d, 0x96, 0x61, 0x34, 0xdb, 0x52, 0xb7, 0xb4, 0x8f, 0xdc, 0x88, 0xe1, 0x5f, 0xf2, 0x9a, 0x57, 0xf8, // k 0x01, 0x18, 0x91, 0xb9, 0x00, 0x4d, 0x91, 0x46, 0x60, 0x05, 0x2d, 0xb3, 0xb8, 0x67, 0xed, 0x13, 0xf7, 0x14, 0x64, 0x11, 0x4b, 0x6e, 0x7c, 0xe3, 0x1b, 0xdf, 0xf8, 0x14, 0xc3, 0x05, 0x6a, 0xe7, 0xea, 0x5d, 0xef, 0x7a, 0xf7, 0x6d, 0x1a, 0xb1, 0x00, 0x2b, 0xdf, 0xf4, 0xa9, 0x4d, 0xb3, 0x24, 0x60, 0xd4, 0xe2, 0xba, 0xe6, 0x35, 0x6f, 0x69, 0x1b, 0x43, 0x48, 0xa3, 0xeb, 0xe4, 0x0d, 0xfe, // l 0xab, 0x6c, 0x2e, 0xd8, 0x2a, 0x37, 0xdf, 0xe2, 0x16, 0xa7, 0xa8, 0x21, 0xbc, 0xc4, 0x17, 0xdf, 0xe2, 0x16, 0xa7, 0xcc, 0x6a, 0xc3, 0x4d, 0x3a, 0xdf, 0x72, 0xd5, 0x95, 0x6c, 0xa6, 0x71, 0x9e, 0xd1, 0x35, 0x98, 0x53, 0x49, 0x5e, 0x7b, 0x57, 0xc6, 0x0a, 0x7a, 0x43, 0xd9, 0x4f, 0x1c, 0xc3, 0x54, 0xe0, 0xf4, 0x08, 0xf9, 0x09, 0x53, 0x03, 0x31, 0x19, 0xa2, 0x25, 0x4e, 0xf0, // m 0x29, 0xea, 0xc5, 0xd8, 0x73, 0x16, 0xcf, 0xe8, 0x56, 0x37, 0xbf, 0xd9, 0x49, 0xbb, 0x6f, 0xf1, 0xf0, 0xd5, 0x37, 0xbd, 0xd9, 0xce, 0x47, 0x55, 0x63, 0x72, 0x98, 0x58, 0xee, 0x6d, 0xef, 0xdb, 0xd0, 0x62, 0x72, 0x98, 0x58, 0xae, 0x63, 0x1d, 0xd3, 0x58, 0x45, 0x72, 0x93, 0xd8, 0x8d, 0x93, 0x9d, 0xec, 0x64, 0xe7, 0x30, 0x97, 0x58, 0xe1, 0xa2, 0x4d, 0xe2, 0x12, 0x57, 0xf8, // n 0x81, 0xed, 0xd1, 0xc8, 0xb3, 0x16, 0xef, 0xe2, 0x64, 0xc3, 0x35, 0x59, 0xc4, 0xe3, 0x9b, 0xde, 0xf4, 0xa6, 0x3b, 0x5f, 0xf9, 0x92, 0xcd, 0x91, 0xb4, 0x78, 0xb7, 0xa3, 0x1f, 0x9e, 0x38, 0x2c, 0x9c, 0xce, 0xbe, 0x0f, 0x75, 0x0e, 0xf3, 0xb0, 0xc2, 0x61, 0x1e, 0x35, 0xce, 0x71, 0x89, 0x6b, 0xdc, 0xd2, 0xd6, 0x4d, 0x49, 0xb8, 0xce, 0x0e, 0xdb, 0x34, 0xad, 0x16, 0xbc, 0x19, 0xfe, // o 0xa3, 0x68, 0xb4, 0xba, 0x8d, 0xbc, 0xad, 0xbc, 0x92, 0xec, 0x0e, 0xf2, 0xb6, 0xd3, 0x1d, 0x8f, 0xb8, 0xe0, 0xee, 0x16, 0xf6, 0x3f, 0x93, 0x59, 0xcf, 0xa6, 0x0c, 0x91, 0xe5, 0x0c, 0x8b, 0xbf, 0x30, 0x39, 0xd3, 0x1d, 0x28, 0x59, 0xe2, 0xe2, 0x17, 0xbb, 0xfa, 0x1d, 0xfe, // p 0x02, 0x88, 0x26, 0xd4, 0x00, 0x6d, 0x96, 0xb5, 0xb8, 0x25, 0x05, 0x89, 0x6c, 0x3d, 0x92, 0xe6, 0x51, 0xb3, 0xa6, 0xf4, 0x48, 0x66, 0x09, 0xa0, 0x8c, 0xc7, 0x33, 0x9d, 0x79, 0xcb, 0x67, 0x0e, 0x80, 0xca, 0xd7, 0xbd, 0x6c, 0xe5, 0x72, 0x06, 0xb4, 0xb5, 0xba, 0x37, 0xbd, 0xab, 0x53, 0x5d, 0xf2, 0x9e, 0xf7, 0x78, 0xc0, 0xff, // q 0x0e, 0x98, 0xd5, 0x28, 0x02, 0x11, 0x18, 0xc9, 0xcc, 0x46, 0x98, 0xf1, 0x66, 0x27, 0x27, 0x19, 0x21, 0x99, 0x92, 0xb6, 0xdc, 0x6c, 0xe7, 0xab, 0x28, 0xd2, 0x2d, 0x13, 0x3b, 0xef, 0xb2, 0xb5, 0xce, 0x94, 0x47, 0xd0, 0xee, 0xda, 0xc7, 0x31, 0xcf, 0x61, 0x31, 0x31, 0xa2, 0x50, 0xb6, 0xf8, 0xd5, 0xef, 0xf0, // r 0x2b, 0xce, 0x72, 0x33, 0x93, 0xbb, 0xdc, 0xf2, 0x16, 0x37, 0xbf, 0xd9, 0x28, 0x52, 0x5c, 0xa9, 0xa6, 0x4d, 0xb3, 0x6c, 0x5d, 0x0a, 0xcb, 0x71, 0xd8, 0xbb, 0x0f, 0x7d, 0x2a, 0x73, 0xb6, 0xc7, 0xf4, 0x94, 0x37, 0x2d, 0xa9, 0x34, 0xf8, 0x53, 0x97, 0xb8, 0xc2, 0xff, // s 0xab, 0x6f, 0xd9, 0x34, 0x6c, 0xe6, 0xdc, 0xe2, 0x16, 0x37, 0xbf, 0xf9, 0x69, 0xaa, 0x0f, 0x2d, 0xda, 0x25, 0x7b, 0x18, 0x53, 0x4d, 0x9a, 0xa2, 0xe7, 0xb8, 0x2d, 0x23, 0xa5, 0x26, 0x71, 0x2a, 0x03, 0xfc, 0x94, 0xe6, 0x01, 0x0f, 0x68, 0x40, 0x03, 0x12, 0xe0, 0x00, 0x07, 0x30, 0x00, 0xff, // t 0x01, 0xd8, 0xb6, 0xdd, 0x01, 0x2f, 0xf4, 0x38, 0x60, 0xd5, 0xd1, 0x91, 0x4c, 0x97, 0x84, 0xe6, 0x4b, 0x4e, 0x32, 0xb2, 0x10, 0x67, 0xcd, 0x19, 0xc9, 0x2c, 0x01, 0x94, 0xf1, 0x78, 0x26, 0x33, 0xe9, 0x69, 0x2f, 0x7b, 0x53, 0xbb, 0x36, 0xae, 0x52, 0x08, 0x9e, 0x6b, 0xea, 0x5c, 0x97, 0xba, 0x95, 0x7d, 0x45, 0x47, 0xac, 0x5a, 0x9c, 0x0f, 0xf8, // u 0xa1, 0x99, 0x9c, 0x94, 0x72, 0x26, 0x8d, 0x6a, 0x07, 0x55, 0x90, 0x78, 0x3c, 0x8b, 0x99, 0x9f, 0xac, 0x87, 0x60, 0x76, 0xda, 0x72, 0xb3, 0x93, 0x35, 0xa5, 0x64, 0x2d, 0x7b, 0x6e, 0xbe, 0x9a, 0x24, 0xdc, 0x32, 0xb1, 0x73, 0xef, 0xfa, 0x10, 0x46, 0xab, 0xc6, 0xca, 0xe0, 0xb5, 0x5f, 0xcc, 0xaa, 0xd4, 0x78, 0x1b, 0xb6, 0x53, 0xbb, 0x74, 0xa7, 0x21, 0xbc, 0x04, 0xfe, // v 0x66, 0xf0, 0xd2, 0x38, 0x43, 0xb3, 0xd8, 0x21, 0xf4, 0x4d, 0xbb, 0x70, 0xb0, 0xdb, 0xd0, 0x0f, 0x17, 0x2c, 0x26, 0xae, 0x53, 0x37, 0x6c, 0xbb, 0x32, 0xab, 0x19, 0x75, 0xf7, 0x21, 0x6c, 0x9c, 0xe5, 0x64, 0x33, 0xb6, 0x80, 0xcb, 0x9a, 0x1b, 0xae, 0x60, 0xe5, 0x42, 0x70, 0x7f, 0xb3, 0x83, 0xed, 0xef, 0x70, 0x25, 0x2b, 0x26, 0x40, 0xd5, 0xe2, 0x99, 0xf7, 0xba, 0xb7, 0x75, 0xa8, 0x63, 0x9d, 0xca, 0x32, 0x4b, 0x13, 0x98, 0xaf, 0xa9, 0x4b, 0xde, 0xf3, 0x91, 0x8e, 0x19, 0x0b, 0x31, 0xf3, 0x0d, 0xfc, // w 0x21, 0xdb, 0xc2, 0x44, 0xc2, 0xfc, 0x9c, 0x64, 0x88, 0x70, 0x09, 0x59, 0x7b, 0xe2, 0xca, 0x3b, 0x3d, 0xa4, 0xcf, 0x0d, 0x56, 0x90, 0xc4, 0xa6, 0xbb, 0xf4, 0x6e, 0x41, 0xe2, 0x9d, 0xea, 0xe2, 0x4a, 0x65, 0x12, 0x65, 0xbb, 0xb3, 0xeb, 0x91, 0x55, 0x12, 0x99, 0xc1, 0xd9, 0x6e, 0xb1, 0x9b, 0xd1, 0x36, 0x92, 0x6a, 0xc9, 0x9b, 0x47, 0x3b, 0x4c, 0x12, 0x46, 0x6c, 0x99, 0x5d, 0xef, 0x5b, 0xdf, 0x92, 0x92, 0x64, 0x6c, 0xee, 0x43, 0x19, 0x6b, 0x22, 0x71, 0x8f, 0xcf, 0x65, 0x29, 0x41, 0xd4, 0xdd, 0x36, 0xa5, 0x2d, 0x19, 0xf5, 0x0c, 0xee, 0x13, 0xb7, 0x7c, 0x98, 0xc3, 0x85, 0xc8, 0x62, 0xee, 0x6d, 0x4f, 0xf8, // x 0xad, 0x69, 0xc9, 0xc5, 0x32, 0x56, 0xdf, 0xfe, 0x74, 0x2d, 0x35, 0x7b, 0xf8, 0xea, 0xdb, 0xdd, 0xe1, 0x6c, 0x6d, 0x04, 0xa6, 0xc5, 0xea, 0xb9, 0x87, 0xa3, 0x75, 0x23, 0x37, 0x4f, 0x83, 0x60, 0x11, 0xca, 0x5d, 0x44, 0x36, 0x00, 0x28, 0xa0, 0xe6, 0x31, 0x0f, 0x68, 0xc0, 0x00, 0xbf, 0x8d, 0x79, 0xc0, 0x03, 0x16, 0xd0, 0x00, 0x07, 0xe0, 0xff, // y 0xaa, 0xb3, 0xa2, 0xa7, 0x95, 0xd2, 0xd8, 0x2e, 0x57, 0x23, 0x2f, 0xb2, 0x7a, 0x1c, 0xb3, 0xde, 0xec, 0xa4, 0x45, 0x6d, 0x56, 0xca, 0x9a, 0x9b, 0xde, 0xf4, 0xe6, 0xbb, 0xd8, 0xc5, 0xaa, 0x8a, 0x6f, 0x2b, 0xf3, 0x37, 0xbb, 0x1b, 0x5d, 0xd3, 0x25, 0x39, 0xfa, 0xb9, 0x0f, 0x6d, 0xe8, 0x31, 0xc4, 0x5c, 0x1e, 0xf7, 0xa1, 0x4f, 0x65, 0x1e, 0xa5, 0x48, 0x5c, 0x1e, 0xd7, 0x25, 0x2f, 0x79, 0x81, 0xff, // z 0xad, 0xfb, 0xc6, 0x5c, 0x95, 0xd5, 0xf5, 0xce, 0x02, 0xbb, 0x5b, 0xf9, 0x51, 0x2d, 0x2a, 0xe4, 0x77, 0xe5, 0xa3, 0x3a, 0xb1, 0xfa, 0x9b, 0x9d, 0xec, 0x78, 0xc5, 0x33, 0x27, 0x60, 0xd4, 0xe2, 0x99, 0xce, 0x74, 0xd6, 0xb3, 0x9b, 0x43, 0x9f, 0xfa, 0x54, 0xe6, 0x55, 0x0a, 0xc1, 0x73, 0x4d, 0x9d, 0xeb, 0x92, 0xd6, 0x15, 0x12, 0xa0, 0x6b, 0x75, 0x5e, 0xe1, 0xff }; /* extern */ const uint8_t FLASHMEM bank_3[] = { // alpha 0x63, 0xac, 0x21, 0xb4, 0x3c, 0x16, 0xaf, 0xb2, 0x84, 0xd2, 0x0a, 0x5f, 0xb3, 0xf2, 0xe2, 0xda, 0x32, 0xf4, 0xcd, 0xca, 0x92, 0xdf, 0x28, 0xd7, 0x27, 0x2b, 0xcd, 0xe2, 0x5b, 0x93, 0x57, 0xaf, 0xac, 0xd0, 0x1b, 0x0b, 0xee, 0xb2, 0xb2, 0x24, 0xae, 0xc3, 0x28, 0x4b, 0x29, 0x0a, 0xaf, 0x0e, 0x13, 0x47, 0x02, 0xa8, 0xa6, 0x4c, 0x00, 0x4d, 0x57, 0x08, 0xa0, 0x99, 0x0c, 0x01, 0x74, 0xed, 0xb1, 0x8a, 0x22, 0xba, 0xd4, 0xa9, 0xcd, 0x2a, 0x2a, 0xef, 0xd6, 0xe0, 0xbd, 0x6b, 0x6c, 0xac, 0x5a, 0x83, 0xf7, 0xae, 0xad, 0xb1, 0x6a, 0x0b, 0xde, 0x32, 0x96, 0xa2, 0x3a, 0xc2, 0x79, 0x73, 0xdd, 0xf3, 0x01, 0xff, // bravo 0x02, 0x10, 0x2c, 0x34, 0x94, 0x46, 0xaf, 0xc8, 0x8a, 0xbd, 0x54, 0x84, 0xa9, 0xe6, 0x2d, 0xfc, 0x46, 0x1e, 0x7b, 0x48, 0x87, 0x2a, 0x5f, 0x59, 0x76, 0x13, 0xe9, 0xba, 0x7a, 0xa7, 0x3b, 0x9d, 0x59, 0x29, 0xa3, 0xab, 0x48, 0xd7, 0xd5, 0xb1, 0x0e, 0x6d, 0xf7, 0xa1, 0xe6, 0x2a, 0x3b, 0xb6, 0xa5, 0x0d, 0xa9, 0x52, 0x55, 0x56, 0x8d, 0xb2, 0x92, 0x6a, 0x77, 0xf1, 0xbb, 0xda, 0x86, 0xb2, 0x3a, 0x44, 0xfd, 0xec, 0xdb, 0x50, 0x48, 0xd7, 0x38, 0xb9, 0xef, 0x73, 0x9d, 0xc3, 0xec, 0x7d, 0x67, 0xb0, 0xf4, 0x89, 0x6b, 0xdc, 0xe0, 0xff, // charlie 0x06, 0xd8, 0x2d, 0x2c, 0x01, 0x33, 0xb7, 0x67, 0xa0, 0xb9, 0xc5, 0x8d, 0xc8, 0xb2, 0xb7, 0x16, 0x16, 0xbf, 0x26, 0x87, 0xf9, 0x5a, 0x94, 0xf3, 0xb0, 0x1f, 0x75, 0x19, 0x51, 0xce, 0xcd, 0x71, 0xd4, 0x65, 0xc4, 0x39, 0x8e, 0xda, 0x71, 0xb6, 0x91, 0xc7, 0x30, 0xe9, 0x6e, 0x69, 0x4b, 0x5b, 0x51, 0x8f, 0x15, 0x66, 0x49, 0xe3, 0x80, 0x31, 0xa2, 0xe6, 0x7d, 0xcd, 0x55, 0xb6, 0x59, 0xd8, 0xea, 0xb1, 0x0e, 0xde, 0xca, 0xe5, 0x9b, 0xc7, 0xd6, 0x65, 0x92, 0x55, 0x6c, 0x2e, 0xfb, 0x30, 0x49, 0x92, 0xb1, 0x3a, 0xed, 0xc3, 0x04, 0x72, 0xe7, 0xe6, 0x70, 0x74, 0xeb, 0xa8, 0x93, 0xab, 0xe1, 0xff, // delta 0x0a, 0x28, 0x30, 0x6c, 0x8d, 0xc3, 0xa7, 0xaa, 0x70, 0xd7, 0x55, 0x76, 0x5d, 0x22, 0xee, 0x5b, 0x57, 0xd6, 0xf9, 0xb8, 0xa6, 0x6d, 0x59, 0x59, 0x16, 0x9b, 0xa1, 0xde, 0x7b, 0x15, 0x99, 0x6d, 0xa5, 0x58, 0xde, 0x55, 0x64, 0x11, 0x5d, 0xc2, 0x69, 0x4a, 0x3b, 0x25, 0x5b, 0x85, 0x32, 0x21, 0x40, 0x96, 0x26, 0x0e, 0x58, 0x4a, 0x33, 0x00, 0x4b, 0xb5, 0xad, 0xaa, 0x9a, 0xf0, 0x30, 0xdf, 0xb2, 0xbb, 0xd1, 0x37, 0x55, 0xe9, 0x21, 0x5d, 0x7b, 0x3f, 0x96, 0xaa, 0xc6, 0x3c, 0xa5, 0x73, 0x5f, 0xe1, 0xff, // echo 0x2b, 0x6e, 0xb1, 0xd9, 0xd3, 0x36, 0xdf, 0xf2, 0x16, 0x37, 0x27, 0xa9, 0x08, 0xe5, 0x2e, 0x22, 0x1b, 0x20, 0x00, 0x25, 0xac, 0x2a, 0x20, 0xcf, 0xd3, 0x92, 0x45, 0x53, 0x6a, 0xa9, 0x9e, 0x4f, 0x99, 0x54, 0x47, 0xb9, 0xe4, 0xdf, 0xed, 0x6c, 0x47, 0x9b, 0x45, 0x65, 0xbb, 0x78, 0x9f, 0xc3, 0x1c, 0xd2, 0xe8, 0x43, 0x67, 0xb0, 0xe5, 0xcd, 0x73, 0x58, 0x9d, 0xad, 0x2c, 0x15, 0x37, 0x71, 0x85, 0xff, // foxtrot 0x04, 0x18, 0xb6, 0x82, 0x00, 0xd3, 0x57, 0x08, 0x60, 0xba, 0xf4, 0x91, 0xc7, 0x58, 0x15, 0xca, 0x8b, 0x47, 0x9e, 0xfc, 0x64, 0x1a, 0xaf, 0x19, 0x45, 0x4a, 0x9d, 0xa1, 0xfa, 0x64, 0x14, 0xa9, 0x65, 0x86, 0xe4, 0xe2, 0x51, 0xa5, 0xee, 0x99, 0x92, 0xab, 0x04, 0xe0, 0xa2, 0x93, 0x04, 0x08, 0x90, 0x9d, 0x33, 0x03, 0x9e, 0x71, 0x65, 0xc0, 0x4f, 0x29, 0x0a, 0xf8, 0xad, 0xd4, 0x02, 0x08, 0x9e, 0xa2, 0x54, 0x85, 0x6a, 0x80, 0x00, 0x86, 0x21, 0x57, 0xc0, 0x48, 0x53, 0x01, 0x18, 0x36, 0xbc, 0x15, 0xa9, 0x4b, 0xaa, 0x4b, 0x9b, 0xd6, 0xc7, 0xee, 0x11, 0x41, 0x6b, 0xdb, 0x9a, 0xec, 0x94, 0x36, 0xed, 0x6d, 0x5b, 0x76, 0x93, 0x9e, 0xfc, 0xa5, 0x5d, 0xd9, 0x4d, 0x58, 0xea, 0x9a, 0x7e, 0xb5, 0x37, 0xc5, 0x76, 0x4f, 0x7f, 0x14, 0xfe, 0xd8, 0xcd, 0x2b, 0x7a, 0xb2, 0xfa, 0x9b, 0xf2, 0x88, 0xf0, 0xae, 0x08, 0x16, 0xa1, 0xdc, 0x45, 0x64, 0x03, 0x80, 0x00, 0x8e, 0xe0, 0x30, 0xc0, 0xb2, 0x53, 0xf0, // golf 0x0a, 0x88, 0xa1, 0x71, 0x65, 0x85, 0x76, 0x45, 0x8a, 0xff, 0x9b, 0xde, 0x78, 0xc5, 0x99, 0x5c, 0xb7, 0x72, 0xde, 0x1d, 0xef, 0x7c, 0xd7, 0xb3, 0x6f, 0x63, 0x54, 0x35, 0x63, 0xe4, 0xa6, 0xae, 0x79, 0x33, 0x47, 0x94, 0x39, 0x63, 0xe4, 0x86, 0x1f, 0x04, 0x98, 0x34, 0xdd, 0x02, 0x0e, 0x98, 0x32, 0x5d, 0x03, 0x12, 0xe0, 0x00, 0xfc, // hotel 0x08, 0xc8, 0x4a, 0x0c, 0x01, 0xc5, 0x74, 0x11, 0xa0, 0xca, 0xea, 0xd1, 0x35, 0x5a, 0xdd, 0x46, 0xde, 0x56, 0x5d, 0x49, 0x76, 0x07, 0x79, 0xdb, 0xd5, 0xa8, 0x0a, 0xee, 0x6e, 0x61, 0xff, 0xbd, 0xaa, 0x2d, 0x82, 0x44, 0x70, 0x17, 0x11, 0xd9, 0x00, 0x02, 0xe8, 0x54, 0x2d, 0x00, 0xd5, 0x84, 0x05, 0x60, 0x2a, 0xb3, 0x93, 0x37, 0x67, 0x66, 0x9c, 0x6b, 0x4e, 0x5e, 0xbd, 0x9b, 0x6a, 0xdd, 0x39, 0x79, 0xf1, 0xae, 0x6e, 0xbd, 0xf8, 0x54, 0xc5, 0xa7, 0x85, 0xe5, 0xe2, 0x53, 0x17, 0xd5, 0x9e, 0x2e, 0x9f, 0xcf, 0x58, 0xe4, 0xa6, 0x07, 0xbf, 0x59, 0x5b, 0xc5, 0x33, 0x19, 0xd8, 0xa5, 0x9c, 0x89, 0xce, 0x94, 0x61, 0x9b, 0x74, 0x79, 0xdd, 0x13, 0xc4, 0x4b, 0xfc, 0xe5, 0x2e, 0xa7, 0xae, 0x0a, 0xa5, 0x0d, 0xfc, // india 0xa3, 0x98, 0xd6, 0x99, 0x32, 0x17, 0x8f, 0x7c, 0x86, 0x16, 0x74, 0x5f, 0xb3, 0xf2, 0xe1, 0x4a, 0xc4, 0xf4, 0xce, 0x4e, 0x47, 0xdc, 0x1d, 0x5a, 0x46, 0x3a, 0x99, 0x71, 0x8b, 0xab, 0x82, 0xac, 0x08, 0x27, 0x3e, 0x5d, 0xe5, 0x0c, 0x25, 0x42, 0xbc, 0x7b, 0x55, 0xd3, 0x17, 0x61, 0xf8, 0x96, 0x5d, 0xed, 0x7a, 0xf4, 0xcd, 0x8a, 0x44, 0xc6, 0xe3, 0x31, 0x55, 0x1b, 0x62, 0x69, 0xaf, 0xc7, 0x92, 0x9c, 0x7b, 0x66, 0x2c, 0x6e, 0x5b, 0xf6, 0x69, 0x11, 0xf6, 0xaa, 0x1c, 0x29, 0xa4, 0x87, 0xdb, 0xe7, 0x74, 0xe6, 0x14, 0x1e, 0x1a, 0xab, 0xdd, 0x95, 0x62, 0x7a, 0x68, 0xac, 0x82, 0xff, // juliet 0x61, 0x5d, 0x96, 0x49, 0x34, 0xd2, 0x06, 0x60, 0xc7, 0x90, 0x0c, 0x8c, 0x66, 0xf6, 0x15, 0x22, 0x4d, 0x37, 0xaa, 0x6a, 0xc8, 0x2c, 0x6d, 0xcd, 0x28, 0xb2, 0x15, 0x8b, 0xe4, 0x35, 0xb3, 0x68, 0x79, 0x51, 0xe6, 0xda, 0x9c, 0xbe, 0x15, 0x43, 0x89, 0xf0, 0xa2, 0xdb, 0x95, 0x77, 0xa7, 0xa6, 0x66, 0x49, 0x77, 0xb1, 0x9a, 0x9e, 0x0a, 0xd5, 0x75, 0xeb, 0xee, 0xf6, 0xb0, 0xc6, 0xe6, 0x83, 0xd2, 0xe3, 0xeb, 0x5e, 0xd7, 0xda, 0x5c, 0x48, 0x87, 0x6d, 0x9e, 0x7b, 0xdf, 0xf3, 0x89, 0x40, 0x11, 0xca, 0x5d, 0x44, 0x36, 0x00, 0x38, 0x60, 0xea, 0x8c, 0x00, 0x2c, 0xb3, 0x6d, 0x01, 0x01, 0x14, 0x5f, 0x8e, 0x01, 0xf8, // kilo 0x06, 0xe8, 0x12, 0xd9, 0x02, 0x12, 0x68, 0xee, 0x8c, 0x86, 0xd4, 0xf5, 0x76, 0x7a, 0xd3, 0x1d, 0xee, 0x74, 0x4a, 0x54, 0x1e, 0x6f, 0xfa, 0x2b, 0x5c, 0xdc, 0x42, 0x93, 0xb2, 0xed, 0x66, 0xb5, 0x95, 0x7b, 0x8e, 0x53, 0xdf, 0x3d, 0xac, 0xa1, 0xb0, 0xcc, 0x2a, 0xee, 0xbb, 0xa7, 0xb6, 0x24, 0x53, 0xd9, 0x4a, 0x7d, 0xfb, 0x52, 0x36, 0x1f, 0x2b, 0x1b, 0x75, 0x4d, 0xdc, 0xe2, 0x1e, 0x8e, 0xa0, 0xa6, 0x32, 0xc8, 0xaf, 0xbb, 0x92, 0x18, 0xaf, 0x20, 0x7d, 0xf0, // lima 0xa1, 0x5f, 0x90, 0xba, 0xc0, 0xd7, 0xa6, 0x7e, 0x00, 0x19, 0x85, 0x6a, 0xda, 0xca, 0xcd, 0x24, 0xd9, 0xcc, 0xcb, 0x4a, 0x47, 0x76, 0x66, 0xf5, 0x37, 0x3b, 0x9e, 0xe1, 0x88, 0x7a, 0x50, 0xd4, 0x8e, 0xd9, 0x3d, 0xad, 0x45, 0x2b, 0xb3, 0x62, 0xee, 0xf4, 0xb8, 0xb5, 0xac, 0xf5, 0xa8, 0x1b, 0xaf, 0xcc, 0xa2, 0xce, 0xbb, 0xdd, 0xcb, 0xd8, 0xb2, 0xda, 0xc8, 0xd0, 0x55, 0xfd, 0xac, 0x57, 0xbd, 0xe0, 0xff, // mike 0x66, 0x31, 0x3c, 0x7c, 0x52, 0xe3, 0xc4, 0x69, 0xf5, 0x85, 0x57, 0x86, 0x51, 0xaa, 0xd3, 0x56, 0x75, 0xa1, 0x69, 0x9d, 0x6f, 0x7d, 0xca, 0x6a, 0x57, 0x23, 0x6d, 0xf5, 0xcd, 0x57, 0xd1, 0x4b, 0x50, 0x78, 0x2c, 0xda, 0x75, 0x69, 0x46, 0x77, 0xb4, 0xce, 0xdb, 0xb1, 0x45, 0xad, 0x08, 0xe5, 0x2e, 0x22, 0x1b, 0x00, 0x18, 0xd0, 0x3c, 0x91, 0x03, 0x5a, 0x09, 0xb1, 0x80, 0x00, 0xb2, 0x13, 0x86, 0xff, // november 0x66, 0x2c, 0x02, 0x62, 0x4b, 0xe3, 0x8e, 0xa1, 0xeb, 0x10, 0x77, 0x6e, 0xb3, 0xb2, 0x2a, 0x2a, 0x39, 0x74, 0xcb, 0x4a, 0x0b, 0xcb, 0xb2, 0xe4, 0xae, 0x2b, 0x4d, 0xbc, 0xdb, 0x9c, 0xfa, 0xb6, 0x2c, 0x8a, 0x29, 0x33, 0xee, 0x93, 0xf2, 0xa0, 0xa6, 0xc4, 0xb9, 0x55, 0xa8, 0x92, 0xa8, 0x54, 0xa7, 0xc4, 0xae, 0x1d, 0x32, 0xcc, 0x54, 0x2d, 0xb7, 0xb1, 0xa9, 0x72, 0x53, 0x51, 0xbc, 0xb2, 0xe2, 0x53, 0x2c, 0xb4, 0xf5, 0x4a, 0x8b, 0x2b, 0xb5, 0xd2, 0xd5, 0x2b, 0x2d, 0xa6, 0xd4, 0xda, 0x5a, 0xaf, 0x34, 0xfb, 0x32, 0x2b, 0x4b, 0xd3, 0xd2, 0x14, 0xdc, 0xda, 0xc8, 0x4e, 0xc9, 0x52, 0x24, 0x6b, 0x53, 0xb9, 0xaa, 0xf5, 0x51, 0xb5, 0x42, 0xe9, 0x31, 0xc0, 0x9b, 0xb0, 0xd4, 0xa7, 0xa6, 0xd4, 0x85, 0x6f, 0xca, 0x58, 0xc2, 0x0a, 0x2e, 0xe6, 0x6b, 0x6b, 0x89, 0xc3, 0xb4, 0xd8, 0x2f, 0x6d, 0x25, 0x0d, 0xd3, 0x52, 0xdf, 0x74, 0x14, 0xdf, 0x44, 0x47, 0xfb, 0xd2, 0x51, 0x72, 0xa2, 0x1e, 0x75, 0x09, 0x47, 0x89, 0x8d, 0x7c, 0xb4, 0x07, 0xfe, // oscar 0xab, 0xcd, 0xe2, 0xb2, 0x42, 0x3a, 0xdf, 0xe2, 0xa6, 0x27, 0x49, 0xae, 0x7d, 0xc4, 0x17, 0xb7, 0x38, 0x45, 0xaf, 0xa4, 0xb6, 0x6d, 0x80, 0x03, 0xd8, 0x0c, 0xf0, 0xa7, 0x9b, 0x07, 0x3c, 0xe0, 0x80, 0xeb, 0xb5, 0x11, 0x38, 0x45, 0xa9, 0x0a, 0xd5, 0x00, 0x02, 0x34, 0x75, 0x65, 0xe6, 0xa6, 0xae, 0xa2, 0x34, 0x6e, 0xaa, 0x8b, 0x9b, 0x24, 0x13, 0xa5, 0xad, 0xca, 0xa9, 0xc8, 0x86, 0xf3, 0xce, 0x7a, 0x76, 0x6d, 0xcc, 0xcd, 0xb0, 0x5a, 0x7a, 0xcf, 0xb9, 0x2e, 0x75, 0x4b, 0x47, 0x89, 0x83, 0x3a, 0xa9, 0x37, 0xdf, 0xe1, 0x29, 0xad, 0x48, 0x87, 0xb3, 0xc0, 0xff, // papa 0x0a, 0x28, 0x56, 0xb9, 0xe5, 0x45, 0x55, 0x84, 0x49, 0xcc, 0x93, 0x67, 0xd7, 0x19, 0x26, 0x4b, 0x4e, 0x91, 0xdd, 0x44, 0xba, 0xae, 0xbe, 0xc5, 0x2c, 0x10, 0x24, 0x42, 0xb9, 0x8b, 0xc8, 0x06, 0x60, 0x80, 0xf1, 0xe9, 0xab, 0xc9, 0xa6, 0x23, 0xd4, 0x36, 0xdf, 0xe9, 0xcc, 0x55, 0x74, 0x86, 0x6b, 0x9f, 0x71, 0x66, 0xbd, 0xe1, 0xe6, 0xbb, 0xdb, 0x9f, 0x53, 0x45, 0x88, 0xcf, 0xae, 0x3f, 0xfc, // quebec 0x0c, 0x88, 0x7e, 0x8c, 0x02, 0xa5, 0x0c, 0x31, 0xdd, 0x5c, 0xb2, 0xac, 0x3a, 0x5b, 0xcf, 0x4c, 0xee, 0xbb, 0xbb, 0xde, 0xa5, 0xcd, 0xa8, 0xb4, 0x75, 0x4d, 0x1c, 0xb7, 0xd1, 0xd5, 0x28, 0xee, 0xe6, 0x5b, 0x76, 0x73, 0xea, 0x1a, 0xc4, 0x33, 0xf3, 0xf1, 0xad, 0x77, 0x37, 0xa7, 0xb6, 0xb6, 0xec, 0x12, 0x91, 0x9b, 0xf2, 0x8e, 0x40, 0x11, 0xca, 0x5d, 0x44, 0x36, 0x80, 0x00, 0x7a, 0x2f, 0x53, 0x40, 0x2d, 0x24, 0x14, 0x80, 0xff, // romeo 0x22, 0xd7, 0x39, 0x38, 0xca, 0xec, 0xdb, 0xbe, 0xb4, 0xa1, 0x98, 0x5a, 0xb9, 0xf2, 0x53, 0x46, 0x6f, 0xe9, 0x69, 0xca, 0x4e, 0xd6, 0x89, 0x57, 0x0e, 0x69, 0x3f, 0x71, 0x61, 0xd9, 0x95, 0x98, 0x65, 0x87, 0x25, 0x6c, 0x86, 0x64, 0x4c, 0xac, 0xf5, 0xf8, 0xa4, 0xcd, 0x86, 0x7a, 0xd0, 0xe6, 0x55, 0x4f, 0xd7, 0x02, 0xa5, 0x7b, 0x76, 0xbd, 0xdb, 0xdd, 0xaf, 0xa1, 0xaa, 0x54, 0x1d, 0xdb, 0xb2, 0xa6, 0xec, 0xc3, 0xd3, 0x64, 0x73, 0x99, 0x62, 0xc8, 0x2c, 0xd5, 0xdf, 0x69, 0x09, 0xa1, 0x33, 0xd8, 0xf2, 0xe6, 0x25, 0xae, 0x6e, 0x0f, 0xb6, 0xb2, 0x54, 0xdc, 0xf8, 0x1d, 0xfe, // sierra 0x0c, 0xf8, 0xad, 0x54, 0x03, 0x06, 0xf8, 0x2d, 0xd5, 0x01, 0xbf, 0x94, 0x39, 0xe0, 0xe7, 0x32, 0x0b, 0xb4, 0xb0, 0x3b, 0x25, 0x75, 0x5f, 0xbd, 0xe2, 0x11, 0x0d, 0x39, 0x63, 0xf5, 0x48, 0x46, 0x34, 0xe0, 0xea, 0x4d, 0x23, 0x1d, 0x49, 0x91, 0xbb, 0x56, 0x8d, 0x6c, 0x78, 0x45, 0xd9, 0x7c, 0xb2, 0xf2, 0xe1, 0x9c, 0x78, 0xe2, 0xf1, 0xc9, 0x87, 0x09, 0x92, 0xb1, 0xd7, 0x27, 0x6b, 0x2e, 0xd9, 0xc7, 0x5e, 0x9f, 0xac, 0x84, 0xe4, 0x1c, 0x79, 0xbd, 0xd2, 0xd4, 0xc4, 0xb2, 0x79, 0xcd, 0xc8, 0x52, 0x97, 0xf0, 0xa6, 0x3c, 0xa3, 0x4c, 0x53, 0xc3, 0x9a, 0xf2, 0x8c, 0x26, 0x55, 0x0b, 0x1d, 0xea, 0xb3, 0xa6, 0x14, 0x3d, 0x2d, 0x35, 0xcf, 0x99, 0xb2, 0x1b, 0xf3, 0xd0, 0x3e, 0x6b, 0x29, 0x7a, 0xdc, 0x53, 0x36, 0x8f, 0x35, 0xc5, 0xd6, 0x70, 0x7f, 0xd5, 0xf6, 0x14, 0xdb, 0xc2, 0x7c, 0x55, 0x39, 0x73, 0x4c, 0x2f, 0xf1, 0x97, 0xe9, 0xca, 0x6a, 0xb5, 0xc2, 0x76, 0x96, 0x2b, 0x87, 0xd2, 0xd2, 0x58, 0x09, 0xff, // tango 0x0e, 0xd8, 0x5c, 0xcd, 0x03, 0xcb, 0x2b, 0xd9, 0xd4, 0x23, 0x2b, 0xad, 0xa8, 0x26, 0x57, 0x8f, 0x58, 0xb2, 0xe2, 0x56, 0x5c, 0x2d, 0x63, 0xf6, 0x8a, 0x5b, 0x36, 0xf5, 0xcc, 0x59, 0x2b, 0x6e, 0x91, 0xb5, 0xdb, 0x42, 0xb7, 0xa4, 0x5a, 0xea, 0x34, 0x57, 0x5d, 0xb2, 0x62, 0x68, 0x5c, 0x55, 0xb5, 0x2b, 0xa2, 0xa2, 0x09, 0x13, 0xa7, 0xa5, 0xad, 0x2a, 0x98, 0x53, 0x56, 0x8f, 0xbe, 0xb2, 0x30, 0x19, 0xdd, 0xb3, 0xfa, 0x22, 0xcb, 0xa4, 0xb4, 0xeb, 0xe8, 0xb2, 0xea, 0x90, 0x92, 0x2e, 0x6d, 0x0a, 0xbe, 0xc3, 0x52, 0x3a, 0xa7, 0x35, 0xc4, 0x0a, 0x4b, 0xd9, 0x5b, 0xf6, 0x50, 0x32, 0x3c, 0xa4, 0x73, 0xb8, 0x43, 0x0b, 0x37, 0x93, 0xd5, 0xe6, 0xf6, 0x35, 0xdd, 0x95, 0x7f, 0xab, 0xdb, 0x87, 0xf2, 0x34, 0xde, 0x07, 0xff, // uniform 0xa1, 0x3f, 0x56, 0x98, 0xd4, 0xb6, 0xe6, 0xae, 0xd5, 0xc7, 0xa8, 0x01, 0xc5, 0xda, 0x53, 0x2d, 0x97, 0x06, 0x12, 0xd9, 0x4f, 0xdc, 0x6d, 0x30, 0xa6, 0x65, 0xdf, 0x61, 0xf3, 0x8b, 0x11, 0xcf, 0xe0, 0xae, 0xc9, 0xcf, 0x4e, 0x5d, 0x38, 0xea, 0x75, 0xff, 0x04, 0x45, 0x47, 0x84, 0xca, 0xe6, 0x1d, 0xf7, 0x8c, 0x01, 0xcd, 0x97, 0x6a, 0x40, 0x03, 0x1a, 0x28, 0x45, 0xd0, 0xdb, 0x61, 0xec, 0x7d, 0x17, 0xbb, 0x3e, 0x4d, 0x16, 0xdb, 0x9a, 0xea, 0xf5, 0x76, 0xab, 0x2f, 0x6a, 0x43, 0x46, 0xbc, 0xcd, 0xb9, 0x6d, 0xd9, 0xb5, 0xda, 0x70, 0xdf, 0xb2, 0xe6, 0x94, 0xea, 0xcd, 0x9d, 0xdd, 0x9a, 0xbc, 0x73, 0xa9, 0x28, 0x35, 0x5b, 0x12, 0x41, 0xe1, 0x96, 0xd4, 0x6d, 0x4d, 0x24, 0xa7, 0x8a, 0x94, 0xb8, 0xfb, 0x3d, 0x1c, 0xcd, 0x76, 0x78, 0x50, 0xea, 0x78, 0xc0, 0xff, // victor 0xae, 0x6f, 0x52, 0x55, 0xcd, 0xdd, 0xa8, 0xb9, 0x72, 0x55, 0x95, 0x70, 0xe3, 0xe6, 0xe9, 0xdd, 0xd4, 0x84, 0x4e, 0x99, 0xa7, 0x4b, 0x0b, 0x65, 0xa5, 0x2b, 0x6c, 0x2e, 0x4d, 0x42, 0xb6, 0xac, 0xa8, 0xdb, 0x12, 0x49, 0x5d, 0xbd, 0xe2, 0x1e, 0x02, 0x2d, 0x6c, 0x35, 0x30, 0xa0, 0x72, 0x46, 0x04, 0x4e, 0x51, 0xaa, 0x42, 0x35, 0x00, 0x40, 0x01, 0x33, 0x49, 0x3a, 0x60, 0x5a, 0xf1, 0xd2, 0x95, 0x6c, 0x2c, 0x2d, 0x5d, 0x5a, 0x9f, 0x63, 0x21, 0x9f, 0xe6, 0x2f, 0x73, 0x29, 0x4d, 0xbc, 0x94, 0xaf, 0x2d, 0xa5, 0x34, 0xf1, 0x72, 0xb6, 0xb4, 0x94, 0xba, 0x82, 0xc3, 0xfe, 0xcb, 0x5a, 0x46, 0x93, 0x34, 0xe5, 0x2b, 0x5b, 0xe9, 0x85, 0x5a, 0xe2, 0xc7, 0xed, 0xe5, 0x0a, 0xa7, 0x4b, 0x27, 0xf8, // whiskey 0x04, 0x88, 0xae, 0x8c, 0x03, 0x12, 0x08, 0x5e, 0x74, 0x65, 0xe9, 0xec, 0x68, 0x04, 0x59, 0x46, 0x78, 0x41, 0xd7, 0xe3, 0x37, 0x6d, 0x62, 0xc3, 0x5b, 0xaf, 0xdf, 0xc2, 0xea, 0x54, 0xd2, 0xe3, 0x89, 0x01, 0x7e, 0x2b, 0xf7, 0x80, 0x07, 0x14, 0xd0, 0xe5, 0x15, 0x38, 0x60, 0x8c, 0x70, 0x03, 0x04, 0x29, 0x36, 0xaa, 0x5e, 0x14, 0x34, 0x72, 0xf6, 0xa8, 0xa6, 0x6f, 0x82, 0xf4, 0x2d, 0xb3, 0xeb, 0x4b, 0x5a, 0x67, 0x6a, 0xc0, 0xf0, 0x2f, 0x71, 0x4f, 0xc7, 0xa8, 0x8a, 0x1c, 0xb9, 0xd8, 0xdf, 0xee, 0x1e, 0xbb, 0x59, 0xd0, 0xd6, 0xc2, 0xff, // xray 0x2b, 0xae, 0xde, 0xb4, 0x62, 0x66, 0x9f, 0xb0, 0x75, 0x73, 0xd3, 0x6e, 0x72, 0xfc, 0x56, 0x54, 0xcb, 0xba, 0xb6, 0x01, 0x92, 0xc7, 0x26, 0x40, 0x4b, 0x43, 0x0c, 0xc8, 0x29, 0xc5, 0x01, 0xcf, 0xb8, 0x1a, 0xe0, 0xa7, 0x14, 0x07, 0xfc, 0x56, 0xea, 0x01, 0x05, 0x98, 0x60, 0x5a, 0x92, 0xd4, 0x29, 0xb5, 0xb8, 0xeb, 0xc8, 0x52, 0x17, 0xb3, 0x96, 0x6e, 0x23, 0x2f, 0x29, 0x54, 0x5b, 0xf6, 0x8d, 0xae, 0xa9, 0x32, 0x5e, 0xdb, 0x37, 0xfa, 0xa1, 0xdb, 0xb1, 0x74, 0xcb, 0x68, 0xbb, 0x49, 0x91, 0xf6, 0xcd, 0x63, 0x1e, 0x3a, 0x85, 0x3a, 0x56, 0xb7, 0x79, 0x98, 0x62, 0xea, 0xf8, 0xdc, 0xf6, 0x9e, 0x83, 0xd4, 0xe3, 0x49, 0x38, 0x7a, 0x71, 0x54, 0xaf, 0xd9, 0xe1, 0xe8, 0x53, 0x55, 0xb8, 0xe7, 0xc2, 0xff, // yankee 0x6e, 0xe8, 0x42, 0x58, 0xb6, 0x6b, 0xa7, 0x61, 0x68, 0x25, 0xcc, 0x59, 0xb4, 0x86, 0x11, 0x82, 0xc8, 0x6a, 0xf1, 0x2a, 0x47, 0x2e, 0x12, 0x8d, 0x37, 0x27, 0xef, 0xc9, 0xc9, 0xa3, 0x6e, 0x9f, 0x6c, 0xd4, 0x22, 0x73, 0x7f, 0xb4, 0x92, 0x51, 0x0b, 0x2d, 0x62, 0xe2, 0x48, 0x46, 0x43, 0xd7, 0x2e, 0x29, 0x2e, 0x4b, 0x92, 0xaa, 0x28, 0x5c, 0x8b, 0xa6, 0x6a, 0xeb, 0x24, 0x95, 0xe3, 0x80, 0x1d, 0x93, 0x35, 0x90, 0xf2, 0x59, 0x03, 0x45, 0xb3, 0x75, 0x29, 0x47, 0x27, 0x96, 0x98, 0xc5, 0x65, 0x18, 0xcd, 0x88, 0xbc, 0x16, 0xd7, 0x21, 0xad, 0x63, 0x10, 0x49, 0x6e, 0xed, 0xb8, 0xf9, 0x1d, 0xfe, // zulu 0x6d, 0xf8, 0xde, 0xc4, 0xc4, 0xe8, 0x29, 0x60, 0x00, 0x2e, 0x0f, 0x9c, 0x78, 0x29, 0x71, 0x2a, 0x4e, 0x77, 0xc3, 0x15, 0x74, 0x2a, 0xae, 0xc3, 0xce, 0x76, 0x30, 0xc2, 0xa5, 0x44, 0x78, 0xd1, 0x6d, 0x4f, 0x46, 0x39, 0xb8, 0xbb, 0x07, 0xf6, 0x5b, 0x6d, 0x91, 0x6e, 0xa9, 0xf2, 0x65, 0xf4, 0xc9, 0x98, 0x97, 0x69, 0x9f, 0x3a, 0xe7, 0x2d, 0x6c, 0xc1, 0x9a, 0x8f, 0xca, 0xde, 0x70, 0x04, 0x9d, 0xee, 0xc9, 0x79, 0xe2, 0xe1, 0x1f, 0xf8 }; /* extern */ const uint8_t FLASHMEM bank_4[] = { // analog 0xa7, 0xa8, 0x51, 0xc3, 0x3b, 0xa4, 0x9c, 0xbc, 0x66, 0x73, 0x8f, 0xb2, 0x73, 0xf2, 0x1a, 0x35, 0xbc, 0x52, 0xf6, 0x49, 0x6b, 0x32, 0xf3, 0x48, 0xc9, 0x27, 0xa9, 0x5e, 0xd3, 0x3a, 0x64, 0x9f, 0xa4, 0x78, 0x75, 0x8f, 0xb2, 0x72, 0xd2, 0x6c, 0xa4, 0x35, 0x43, 0xce, 0xc8, 0x82, 0xd6, 0xd6, 0x30, 0x27, 0x2d, 0xf3, 0x5a, 0x5b, 0x22, 0x92, 0x8e, 0xdc, 0x1b, 0x6d, 0x33, 0x73, 0xb2, 0x0a, 0x6f, 0x23, 0x4d, 0xcd, 0xf1, 0xa8, 0x7c, 0x8d, 0x20, 0xcb, 0xd4, 0xa3, 0xf6, 0x35, 0x9d, 0x25, 0x13, 0xb7, 0xda, 0xc6, 0x35, 0x96, 0x98, 0xda, 0x3a, 0x67, 0xce, 0x59, 0x7c, 0xce, 0xe8, 0x6c, 0x58, 0x67, 0xae, 0x2a, 0xa7, 0x8b, 0x6e, 0x53, 0x39, 0xa3, 0x9d, 0x3e, 0xba, 0x4d, 0xa5, 0x1a, 0x7d, 0xfa, 0x18, 0x36, 0x94, 0xab, 0xca, 0xe9, 0x93, 0xbb, 0x50, 0xce, 0x51, 0x67, 0x48, 0xe1, 0xc2, 0x38, 0xc7, 0x9c, 0x21, 0xf9, 0x0b, 0x15, 0x9f, 0x7c, 0xc6, 0x58, 0x56, 0xcd, 0x7c, 0xf2, 0x19, 0x93, 0xbb, 0x30, 0xd3, 0xd9, 0x67, 0x2c, 0x66, 0x32, 0x54, 0xe6, 0x9c, 0xb9, 0xa8, 0x8a, 0x52, 0x99, 0x7d, 0xd6, 0x22, 0x53, 0x8b, 0x65, 0x4e, 0xd9, 0xa2, 0x35, 0x4b, 0xa8, 0xb9, 0x6a, 0x83, 0xc9, 0x4f, 0xd4, 0xed, 0x98, 0x0d, 0xa6, 0x9a, 0x64, 0x89, 0xac, 0x00, 0x27, 0x78, 0x08, 0x20, 0x04, 0x1d, 0x00, 0xc0, 0xff, // circuit 0x0c, 0x98, 0xb2, 0x4d, 0x00, 0x47, 0x85, 0x0b, 0xe0, 0xe8, 0x0c, 0x03, 0xbc, 0x90, 0xe1, 0x80, 0x6f, 0xdd, 0x03, 0x70, 0xb5, 0x79, 0x01, 0x2a, 0x51, 0x3f, 0x65, 0x72, 0xea, 0xe9, 0x19, 0xfb, 0x94, 0x29, 0x8a, 0x57, 0x58, 0xa3, 0x53, 0xa5, 0x42, 0x5e, 0x6e, 0x8d, 0x4f, 0x95, 0x0a, 0xeb, 0x38, 0x2f, 0x59, 0x75, 0xac, 0xa4, 0x6b, 0x32, 0x65, 0xd4, 0x79, 0x62, 0x0c, 0xc6, 0xe8, 0xd6, 0xe6, 0x8d, 0x3e, 0x14, 0xb3, 0x08, 0xc0, 0x13, 0x36, 0x01, 0x54, 0xc1, 0x02, 0x05, 0x54, 0xa3, 0x62, 0x80, 0x20, 0x25, 0x4f, 0xdf, 0x2d, 0x8b, 0x67, 0x46, 0x3e, 0x43, 0x73, 0x22, 0x9a, 0x59, 0xe7, 0xcc, 0xcd, 0x8a, 0x5a, 0x66, 0xe5, 0xb3, 0x34, 0x2f, 0x66, 0x59, 0x55, 0xcf, 0x5a, 0x3d, 0xbb, 0x57, 0x85, 0x3d, 0x6b, 0x35, 0x62, 0x11, 0x55, 0xf9, 0x6c, 0xd5, 0xa8, 0x46, 0x56, 0xe9, 0xb6, 0x44, 0x61, 0xd5, 0x69, 0xa6, 0x08, 0xe0, 0x70, 0x0c, 0x01, 0x06, 0xa6, 0x6a, 0xf1, 0xf6, 0xa6, 0x91, 0x11, 0x6b, 0xc5, 0x4b, 0xa9, 0x79, 0x66, 0x64, 0xa3, 0x36, 0x11, 0xdc, 0x5d, 0xb5, 0x00, 0x00, 0xfe, // clock 0xa0, 0x80, 0x72, 0x35, 0x14, 0x90, 0x36, 0xa5, 0x01, 0xf2, 0x75, 0x35, 0x40, 0x32, 0x4b, 0x06, 0x88, 0xba, 0x59, 0x01, 0xca, 0xb6, 0xb6, 0xda, 0x84, 0x35, 0xd5, 0xb4, 0x57, 0x6a, 0x53, 0xc7, 0x58, 0xc7, 0x4e, 0xab, 0x5c, 0x2b, 0x32, 0x6d, 0x6b, 0xa3, 0xf2, 0x23, 0x54, 0xb5, 0x9d, 0xac, 0x2a, 0xce, 0x0c, 0xf1, 0x55, 0xba, 0x9a, 0xb8, 0x22, 0x39, 0x47, 0xf1, 0xe9, 0xe2, 0x8c, 0xe4, 0x6c, 0xc5, 0x67, 0x88, 0xdb, 0x4b, 0x3a, 0x9c, 0xac, 0x39, 0x1e, 0x0f, 0xf7, 0x92, 0xd3, 0xb6, 0x58, 0x23, 0x95, 0xc3, 0x4a, 0x3b, 0x73, 0x8a, 0x72, 0x0a, 0xcb, 0xe3, 0xaf, 0xc9, 0x26, 0x38, 0x22, 0x1b, 0x20, 0x78, 0x11, 0x01, 0x04, 0xaf, 0x44, 0x80, 0x10, 0x04, 0x08, 0x10, 0xb3, 0x12, 0x01, 0x1c, 0x77, 0x41, 0x7e, 0x13, 0x6e, 0x51, 0x9e, 0xb8, 0xf8, 0xb5, 0xb5, 0x86, 0x7b, 0x9c, 0xe6, 0xb7, 0xde, 0xe4, 0xee, 0x75, 0x14, 0x50, 0x92, 0xa9, 0x02, 0x6a, 0x61, 0x61, 0x40, 0x89, 0xcc, 0x04, 0x48, 0x5a, 0x89, 0x00, 0xd1, 0x08, 0x03, 0x00, 0xfc, // control 0x50, 0x82, 0xda, 0x56, 0x32, 0x3d, 0xce, 0x09, 0x5a, 0x38, 0xb1, 0x72, 0xcb, 0x27, 0x69, 0x75, 0x4d, 0x4d, 0x93, 0x9e, 0xb2, 0x06, 0x55, 0x57, 0xaf, 0x75, 0x9a, 0x1a, 0x45, 0x2d, 0x22, 0xd6, 0x69, 0x6a, 0x10, 0x55, 0x8f, 0xc6, 0xa7, 0xa9, 0x96, 0x9c, 0x23, 0x13, 0xae, 0x36, 0x4a, 0xca, 0xf0, 0xb2, 0x3d, 0x9a, 0xa8, 0xa8, 0x2c, 0xda, 0xd1, 0x68, 0x82, 0xe4, 0xd4, 0x1c, 0x45, 0xa3, 0x89, 0x9a, 0x9d, 0xa7, 0x1d, 0xb5, 0xc6, 0x2b, 0x09, 0xed, 0x95, 0x33, 0x9a, 0xa2, 0xd0, 0x2c, 0x33, 0x69, 0x00, 0x66, 0x11, 0x0a, 0xc0, 0x9c, 0x1d, 0x09, 0x98, 0x7d, 0x3c, 0x01, 0xbd, 0xa7, 0x25, 0xa0, 0xd7, 0xb4, 0x00, 0xb4, 0x14, 0x71, 0xd2, 0x16, 0xc2, 0x55, 0x55, 0xee, 0x49, 0x63, 0xe1, 0xb0, 0x30, 0xb7, 0x27, 0x8b, 0x5d, 0xd2, 0x4c, 0xd2, 0x9e, 0x22, 0x36, 0x69, 0x31, 0x69, 0xbd, 0xca, 0x30, 0x2c, 0xc5, 0xb4, 0xd5, 0xa9, 0x43, 0xcb, 0x10, 0xd3, 0x4e, 0xa7, 0x0d, 0xa5, 0x43, 0x55, 0x56, 0x9d, 0x2e, 0xe4, 0x09, 0x76, 0x5d, 0xb8, 0xfa, 0x90, 0x36, 0xc9, 0x75, 0xd5, 0xea, 0x43, 0xda, 0x24, 0xd7, 0x55, 0x63, 0xf0, 0x75, 0x9c, 0xdc, 0x66, 0xb6, 0xd1, 0x5f, 0x17, 0xa9, 0x2a, 0xdc, 0x46, 0x77, 0x43, 0xa4, 0xb2, 0x50, 0x99, 0xdc, 0x09, 0x92, 0xf1, 0xd0, 0x65, 0xf2, 0x7d, 0x0c, 0xcb, 0x4b, 0x95, 0xd9, 0xcd, 0x36, 0xf2, 0xa8, 0x99, 0x16, 0xdb, 0x46, 0xa1, 0xa2, 0x66, 0x5a, 0x6c, 0xda, 0x00, 0xf3, 0x59, 0x69, 0x35, 0x71, 0x0b, 0xcc, 0x6b, 0x13, 0x00, 0x6f, 0x67, 0x00, 0xf8, // digital 0x20, 0x80, 0xc4, 0x6c, 0x4e, 0xb6, 0x9c, 0xb2, 0x69, 0xc6, 0x39, 0x79, 0x77, 0xc2, 0x1a, 0x13, 0xe7, 0xe4, 0xdd, 0x2a, 0x9b, 0x77, 0x95, 0x93, 0x37, 0xab, 0xe4, 0x59, 0x95, 0x4f, 0xde, 0xad, 0x91, 0x46, 0x4d, 0x3e, 0x79, 0xb7, 0xca, 0xea, 0x5d, 0xa5, 0xe5, 0x99, 0xb3, 0x67, 0x56, 0xa0, 0x50, 0x1a, 0xe6, 0x95, 0x13, 0x42, 0x52, 0x59, 0x31, 0x46, 0x75, 0xd7, 0x6e, 0xe9, 0x72, 0xca, 0xa4, 0x9e, 0x24, 0x00, 0x8d, 0xa2, 0x25, 0xa0, 0x10, 0x8c, 0xd3, 0x8c, 0xa0, 0x2a, 0x66, 0xad, 0x4e, 0x57, 0xa4, 0x9a, 0x65, 0xa5, 0x3a, 0x5d, 0x51, 0xe2, 0xd2, 0xde, 0x38, 0x00, 0x2a, 0x50, 0x05, 0x40, 0x46, 0xee, 0xd5, 0x87, 0x2c, 0xa1, 0x13, 0x8e, 0xcf, 0xe0, 0x93, 0xa6, 0x79, 0xd4, 0x5e, 0x83, 0xef, 0x6a, 0xd6, 0x19, 0x65, 0x0d, 0x3e, 0xa7, 0x71, 0x65, 0xa5, 0x31, 0xf8, 0xe1, 0xa2, 0x5d, 0x61, 0xd7, 0x10, 0x52, 0x05, 0x79, 0x8d, 0x5e, 0x63, 0xb4, 0x5d, 0x24, 0x7e, 0x7b, 0x8d, 0xd1, 0x75, 0x13, 0xfb, 0xec, 0x35, 0x46, 0x37, 0xc5, 0xec, 0x93, 0xc6, 0x14, 0xec, 0x34, 0x71, 0x4c, 0x19, 0x53, 0x70, 0xd3, 0xc8, 0x39, 0xa6, 0x4c, 0xc1, 0xcd, 0x20, 0xe7, 0x59, 0x00, 0x80, 0xff, // electronic 0xa7, 0xef, 0xd2, 0xc5, 0xdd, 0x2b, 0x9f, 0xbe, 0x78, 0x17, 0xaf, 0x8a, 0x72, 0xba, 0x62, 0x5d, 0xcd, 0xb3, 0xcc, 0xe9, 0xb2, 0xf6, 0x50, 0xab, 0x29, 0xab, 0x8f, 0xdc, 0xd3, 0x35, 0xa6, 0x8e, 0x3e, 0xd0, 0x0e, 0x33, 0x1f, 0xd3, 0x3a, 0x4f, 0x36, 0xb9, 0xa2, 0x76, 0xeb, 0x3c, 0x5d, 0x97, 0x88, 0x29, 0xab, 0x0d, 0x36, 0xcd, 0x6c, 0xc2, 0x9e, 0x36, 0x79, 0x37, 0x8d, 0x91, 0x72, 0xda, 0x1c, 0xdd, 0xb5, 0x46, 0xca, 0x69, 0x4b, 0x32, 0xf7, 0x6a, 0xd9, 0xa7, 0x2d, 0x51, 0xc3, 0xb2, 0x2c, 0x9f, 0xa6, 0x26, 0x0e, 0x89, 0x92, 0x1d, 0xea, 0xec, 0xd5, 0x53, 0xdd, 0x32, 0xa9, 0x9b, 0x32, 0xcd, 0x8a, 0x34, 0x0a, 0x68, 0x8e, 0x95, 0x01, 0x99, 0x53, 0x10, 0x20, 0x11, 0x0a, 0x07, 0x34, 0xa3, 0x9d, 0x80, 0x55, 0xd3, 0x13, 0x30, 0xfa, 0x54, 0x02, 0x5a, 0xeb, 0x4c, 0x40, 0x8e, 0x6c, 0x27, 0xcf, 0x8d, 0xdd, 0xd3, 0xec, 0x9c, 0x22, 0x35, 0xae, 0x70, 0x4d, 0x73, 0x8a, 0xd4, 0xb4, 0xcd, 0xad, 0xc9, 0x29, 0x52, 0xf5, 0x76, 0x8d, 0x29, 0xa7, 0x48, 0x35, 0x33, 0x38, 0xab, 0x9c, 0x32, 0xe5, 0xca, 0xe4, 0xa8, 0x7a, 0x9a, 0x94, 0x2a, 0x5d, 0x32, 0xca, 0xe9, 0x52, 0x8b, 0x34, 0x2f, 0x39, 0xa7, 0x4f, 0x39, 0xc3, 0x35, 0xac, 0x9c, 0xb1, 0x84, 0x28, 0x0d, 0xb7, 0xbc, 0xe6, 0x6a, 0xa5, 0x78, 0x24, 0x74, 0xdb, 0x82, 0x92, 0x94, 0x76, 0x2b, 0x6b, 0x2f, 0xca, 0x4a, 0x2b, 0x44, 0x9f, 0x2d, 0x1b, 0xb7, 0x8a, 0x10, 0x73, 0xf6, 0x1a, 0x54, 0x2b, 0x3d, 0xf0, 0xd9, 0x5b, 0x11, 0x8d, 0xf0, 0xd0, 0x67, 0x6b, 0x4d, 0xc4, 0xdd, 0x4b, 0x0b, 0xc0, 0x6a, 0x32, 0x02, 0xc8, 0xe0, 0x4e, 0x00, 0x6a, 0xd3, 0x13, 0xd9, 0xc7, 0x79, 0x98, 0x2a, 0x29, 0x64, 0x6f, 0xcd, 0x6a, 0xde, 0x44, 0x01, 0x3d, 0x3a, 0x29, 0xa0, 0x79, 0x25, 0x01, 0x14, 0xc3, 0xcc, 0x80, 0xac, 0x54, 0x08, 0x90, 0x0d, 0x09, 0x00, 0xc0, 0xff, // filter 0x8c, 0x9f, 0x69, 0x2a, 0x3d, 0xe2, 0x38, 0x7e, 0xfa, 0x9d, 0x72, 0x8f, 0xab, 0x80, 0x11, 0xca, 0x05, 0xd0, 0x4d, 0x9a, 0x02, 0x86, 0x73, 0x73, 0x40, 0x57, 0x69, 0x09, 0x90, 0x2a, 0xe2, 0x14, 0x45, 0xbb, 0x86, 0x66, 0xe5, 0x53, 0x45, 0x33, 0x1a, 0x9e, 0x45, 0x56, 0x15, 0xe4, 0xa7, 0xa9, 0x95, 0x5a, 0x55, 0x12, 0xb1, 0x45, 0x52, 0x7b, 0x55, 0x81, 0x6d, 0x07, 0x4b, 0x95, 0x51, 0x05, 0xbe, 0x9d, 0xa0, 0x93, 0x4b, 0xe5, 0xc5, 0x85, 0x92, 0xcf, 0x31, 0x5d, 0x04, 0x91, 0xe9, 0xe1, 0x14, 0x1c, 0xd0, 0x58, 0x59, 0x00, 0x36, 0x31, 0x4f, 0x40, 0xc6, 0x66, 0xa7, 0xcf, 0xc1, 0xcc, 0xdd, 0x2b, 0x9f, 0xbe, 0x24, 0x89, 0x08, 0x8d, 0xb3, 0xa6, 0x54, 0xa8, 0xc2, 0xac, 0xca, 0x9a, 0x53, 0xa3, 0x2a, 0xf5, 0xca, 0x63, 0x8e, 0x85, 0xb3, 0x5d, 0x26, 0x8d, 0x39, 0x57, 0xec, 0x52, 0x1b, 0xd2, 0xe6, 0x5c, 0xb1, 0xda, 0x74, 0x50, 0x5b, 0x52, 0xa1, 0x2c, 0xd3, 0x08, 0x65, 0xc9, 0x05, 0x23, 0x4d, 0x23, 0xa6, 0x35, 0x67, 0xf4, 0x70, 0xac, 0xe4, 0xd6, 0x14, 0x31, 0xdc, 0xa8, 0x8a, 0x28, 0x63, 0x80, 0x52, 0xd7, 0xb0, 0x62, 0xce, 0x11, 0x4c, 0x5d, 0x2a, 0x03, 0x00, 0xfc, // frequency 0x04, 0xe8, 0x21, 0x9c, 0x00, 0xa3, 0x94, 0x33, 0x60, 0x78, 0x33, 0x03, 0x54, 0x13, 0xe6, 0x80, 0x61, 0x22, 0x1c, 0xd0, 0x6d, 0x78, 0x00, 0x9a, 0x0a, 0x73, 0x40, 0xd3, 0x61, 0x27, 0x2e, 0x2a, 0xdc, 0xdd, 0x9c, 0x8c, 0x30, 0x4c, 0xb4, 0x34, 0x5d, 0xbd, 0x82, 0xd8, 0xc8, 0xc3, 0x74, 0xca, 0x09, 0x72, 0x25, 0x0d, 0xd7, 0xc5, 0x27, 0xa8, 0x95, 0xc4, 0xdd, 0x6e, 0x9f, 0xb0, 0x26, 0xe2, 0xcc, 0x98, 0x72, 0xa2, 0xea, 0x89, 0x27, 0x73, 0x54, 0x4a, 0x8a, 0x27, 0x2e, 0xa9, 0xb1, 0xac, 0x60, 0xb6, 0xad, 0xc2, 0x6a, 0x97, 0x28, 0xe7, 0xb2, 0x0e, 0x4f, 0x32, 0xdc, 0x94, 0xca, 0x4b, 0x34, 0x76, 0xcb, 0xb3, 0x2b, 0x77, 0x05, 0xc7, 0xab, 0x8f, 0xc9, 0xc2, 0x30, 0xe6, 0x9c, 0x3e, 0x59, 0x8e, 0x56, 0x9b, 0x7d, 0xfa, 0xe2, 0x28, 0x43, 0xab, 0xca, 0x19, 0x8a, 0x23, 0x77, 0x9f, 0x28, 0x6b, 0xcc, 0x86, 0x22, 0x6c, 0xa3, 0x8c, 0x31, 0x6a, 0xca, 0xf4, 0xb5, 0x3c, 0xa6, 0x24, 0x29, 0x56, 0xc7, 0x6c, 0x99, 0x82, 0xe4, 0x7a, 0x49, 0xb1, 0x63, 0xec, 0xc4, 0x45, 0xc3, 0x13, 0x2b, 0xa0, 0x00, 0x77, 0x05, 0x2c, 0x16, 0xae, 0x80, 0x23, 0xcd, 0x15, 0xb0, 0x78, 0xa8, 0x01, 0x96, 0x4c, 0x75, 0x40, 0xc1, 0xae, 0x09, 0x10, 0xd6, 0xf3, 0x8c, 0xdd, 0x2a, 0x79, 0xd4, 0x94, 0x33, 0x76, 0x23, 0x14, 0x59, 0x93, 0xcf, 0xd4, 0x8d, 0x50, 0x54, 0x4d, 0x3e, 0x53, 0x37, 0x42, 0xd1, 0x35, 0xe5, 0xcc, 0x4d, 0x33, 0x67, 0x4f, 0xd9, 0x33, 0x37, 0xc3, 0x1c, 0xbd, 0xa5, 0xc7, 0x52, 0x24, 0x66, 0x4d, 0x84, 0x19, 0x4b, 0xb7, 0x28, 0xb1, 0x19, 0x65, 0x2c, 0xc3, 0x22, 0xfb, 0x76, 0x98, 0xb6, 0x0c, 0x03, 0x62, 0x5b, 0x61, 0xcb, 0xd2, 0x0d, 0xa8, 0x5f, 0x85, 0x29, 0x6b, 0x65, 0xa4, 0x7d, 0x1e, 0x06, 0x00, 0xe0, 0xff, // generator 0xc8, 0x29, 0x98, 0xcb, 0x23, 0x24, 0x1b, 0x60, 0x7a, 0xce, 0x04, 0xac, 0x28, 0x9a, 0x80, 0xd5, 0xdb, 0x0b, 0x90, 0x05, 0xc5, 0x49, 0x8b, 0x67, 0x8d, 0xce, 0xca, 0x27, 0x2d, 0x5e, 0x34, 0x23, 0x2b, 0x9d, 0x34, 0x07, 0xb5, 0xf2, 0x8a, 0x74, 0xd2, 0x12, 0xcd, 0xda, 0x32, 0xf2, 0x49, 0x73, 0xd4, 0x28, 0xab, 0xc8, 0x27, 0xcb, 0xc9, 0xa2, 0xb4, 0x2c, 0x9f, 0x2c, 0x45, 0x4d, 0xf3, 0xb0, 0xb5, 0x8a, 0xec, 0xa5, 0xb1, 0x35, 0xd2, 0x29, 0x72, 0x90, 0xa2, 0xd6, 0xca, 0xa7, 0xcc, 0x49, 0x52, 0x86, 0x8b, 0xae, 0x2a, 0x17, 0x2a, 0x2d, 0x1a, 0xbb, 0x9a, 0xd4, 0x29, 0xbd, 0xb0, 0xe1, 0x68, 0x53, 0xc7, 0x31, 0xb5, 0x1a, 0xad, 0x8d, 0x1d, 0xc7, 0xd4, 0x6a, 0xb6, 0x2e, 0x36, 0x1c, 0x31, 0xab, 0x3c, 0xba, 0xdc, 0x31, 0xc3, 0x6d, 0xc8, 0xe9, 0x52, 0x14, 0xeb, 0xe6, 0x4a, 0xa7, 0xcb, 0x81, 0xbd, 0xc3, 0x4b, 0x9f, 0xbe, 0x18, 0x89, 0x0e, 0x0b, 0x73, 0xfa, 0x62, 0x54, 0x27, 0x2d, 0xf2, 0xe9, 0xb3, 0x32, 0xef, 0xb2, 0x30, 0xa7, 0xcf, 0xc6, 0xb4, 0xd3, 0xcd, 0x9c, 0x3e, 0x19, 0xb1, 0xca, 0x8c, 0x74, 0xfa, 0xe2, 0xd9, 0xad, 0xb2, 0xd2, 0xe9, 0x93, 0x93, 0xf4, 0x76, 0x5b, 0x67, 0xc8, 0x99, 0xd2, 0xdb, 0x63, 0xad, 0x21, 0x65, 0x8a, 0x18, 0x89, 0x3c, 0x86, 0x5c, 0x30, 0xb3, 0x65, 0x52, 0x1b, 0x52, 0xa6, 0xc8, 0xe6, 0x21, 0x6d, 0xc8, 0x95, 0x2c, 0x97, 0x86, 0xb4, 0xb1, 0x2c, 0x4c, 0x0f, 0x3d, 0xda, 0xc6, 0xb2, 0x30, 0x3c, 0xf4, 0x70, 0x19, 0x4b, 0x27, 0xf3, 0xe4, 0x23, 0x69, 0xac, 0x0b, 0x53, 0xcc, 0x86, 0x86, 0xb1, 0x66, 0x0c, 0x75, 0x29, 0xea, 0x96, 0x92, 0x39, 0xd4, 0xb9, 0x28, 0x01, 0xb8, 0xc7, 0x02, 0x00, 0xf8, // instrument 0x27, 0x2f, 0x82, 0xbd, 0xa6, 0xac, 0x9c, 0x7c, 0x48, 0x61, 0xe9, 0x9a, 0x73, 0xf2, 0xee, 0x58, 0xb4, 0xb2, 0xca, 0xc8, 0xbd, 0xe5, 0x6c, 0x6d, 0xa6, 0x2d, 0x97, 0xd6, 0xda, 0xdd, 0xd5, 0xac, 0x34, 0x13, 0xb3, 0x48, 0x0f, 0x9d, 0x80, 0x06, 0x30, 0x02, 0xb0, 0x9d, 0x40, 0x00, 0x5e, 0x2d, 0x0f, 0xc0, 0xee, 0xe3, 0x06, 0x58, 0xad, 0x52, 0x01, 0x63, 0x76, 0x18, 0xa0, 0xcf, 0xee, 0x00, 0xf4, 0x39, 0x55, 0x80, 0x5e, 0x55, 0x4e, 0x51, 0xa3, 0xaa, 0x84, 0xa7, 0x3a, 0x55, 0xca, 0x98, 0x51, 0x9e, 0xf8, 0xd4, 0x29, 0x63, 0x44, 0x79, 0xe2, 0xd5, 0xa4, 0x44, 0x69, 0xa1, 0x8d, 0x5b, 0x1b, 0x1d, 0xb4, 0x47, 0xd4, 0x6e, 0x6d, 0x72, 0xd0, 0x1e, 0x59, 0x7b, 0xf4, 0xc9, 0x41, 0x69, 0x54, 0xec, 0xd5, 0x17, 0x8f, 0x29, 0x19, 0x55, 0x4e, 0x5f, 0x3c, 0xb9, 0xb9, 0xd7, 0x3e, 0x7d, 0x8d, 0x66, 0xea, 0x56, 0xeb, 0xf4, 0x35, 0x9b, 0x59, 0x78, 0x99, 0x33, 0xd4, 0xa2, 0x6e, 0x1e, 0x61, 0xcf, 0x58, 0x93, 0x99, 0x46, 0x9a, 0x3e, 0x63, 0x4d, 0x66, 0x96, 0x61, 0xe5, 0x8c, 0x2d, 0x9a, 0xa9, 0x97, 0x95, 0x33, 0xb6, 0x60, 0xaa, 0x56, 0x56, 0xda, 0x54, 0x2c, 0x05, 0x75, 0xca, 0x6a, 0x63, 0x31, 0x98, 0xd2, 0x41, 0x2b, 0xf5, 0x51, 0x61, 0xea, 0xb4, 0xec, 0x54, 0x55, 0x6e, 0x1e, 0x61, 0xb6, 0x4f, 0xb2, 0x9c, 0x97, 0x55, 0x99, 0x56, 0x40, 0xe1, 0x11, 0x00, 0x00, 0xff, // knob 0xad, 0x31, 0xd2, 0xb3, 0x35, 0xa2, 0x96, 0x5a, 0x4a, 0xef, 0x33, 0x37, 0x5b, 0x2a, 0xad, 0x64, 0x32, 0x8b, 0xe1, 0xa8, 0x02, 0x57, 0xef, 0xcc, 0x52, 0xa7, 0x48, 0x81, 0x25, 0x2a, 0xac, 0x9c, 0x3c, 0x7b, 0x0d, 0xcb, 0x94, 0x7c, 0xb2, 0x50, 0xdd, 0xc5, 0x42, 0xf2, 0xc9, 0x62, 0x0f, 0x09, 0x0b, 0xb3, 0x27, 0x8b, 0x23, 0x29, 0xd2, 0xcc, 0xac, 0x2c, 0x2e, 0x93, 0x8c, 0x10, 0xbb, 0xb2, 0xb8, 0x4d, 0x32, 0x5c, 0xec, 0x2a, 0xe2, 0x32, 0x93, 0x72, 0x29, 0xab, 0x8e, 0xd3, 0x4d, 0x32, 0xc4, 0x9e, 0x26, 0xcd, 0xd0, 0x88, 0x30, 0x73, 0xfa, 0x54, 0x2b, 0x4c, 0x2b, 0xec, 0x19, 0x52, 0xae, 0x08, 0xcd, 0x30, 0x67, 0x48, 0x39, 0x23, 0x34, 0xc2, 0x9c, 0x29, 0x95, 0x0a, 0xd7, 0x0c, 0x73, 0xe6, 0x94, 0x2a, 0x42, 0xbd, 0xcc, 0x99, 0x53, 0xcc, 0x70, 0xf5, 0x32, 0x63, 0x49, 0x2e, 0x33, 0x54, 0xc7, 0x98, 0x85, 0x04, 0x2f, 0xd1, 0xae, 0x62, 0x26, 0x9e, 0x43, 0xc3, 0xdd, 0x0e, 0x01, 0xc0, 0x4b, 0x23, 0x80, 0x8c, 0x16, 0x04, 0x10, 0xd1, 0x02, 0x00, 0xfe, // machine 0xad, 0x4a, 0x1a, 0xdb, 0x2c, 0xe4, 0x94, 0xd6, 0x49, 0xda, 0xf4, 0x92, 0x53, 0x5a, 0x23, 0x79, 0xca, 0xc6, 0x74, 0x6b, 0x83, 0xc6, 0xae, 0x68, 0x4b, 0xab, 0x8a, 0x96, 0x2a, 0xd3, 0x4b, 0xae, 0x3a, 0x19, 0x8a, 0x1a, 0x29, 0x72, 0xea, 0x1e, 0x44, 0x78, 0x74, 0x4c, 0x00, 0xbc, 0xc0, 0x28, 0xc0, 0x08, 0x42, 0x05, 0x98, 0xb3, 0x2c, 0x01, 0xf3, 0x74, 0x24, 0x60, 0xae, 0xcd, 0x04, 0xac, 0xbd, 0x99, 0x80, 0x39, 0x4b, 0x4e, 0xdc, 0x3d, 0x71, 0x64, 0xd4, 0x59, 0x71, 0x92, 0xec, 0xb3, 0x16, 0x7a, 0xc5, 0x49, 0x72, 0xec, 0x9a, 0xa8, 0x95, 0x64, 0x49, 0xbe, 0x13, 0x46, 0x57, 0x96, 0x39, 0xfb, 0xae, 0x88, 0x59, 0x79, 0x11, 0xe4, 0xd7, 0x26, 0xfe, 0xe4, 0x4d, 0xa1, 0x4e, 0x59, 0x94, 0x53, 0x0d, 0x4f, 0x9c, 0x15, 0x56, 0x4f, 0xdb, 0x3d, 0x6a, 0x46, 0xd8, 0x3d, 0x7d, 0xd3, 0x68, 0x1d, 0x2e, 0xf7, 0x0c, 0x85, 0x4b, 0x94, 0x9b, 0x9d, 0x33, 0x76, 0x43, 0x1e, 0x1e, 0x76, 0xd6, 0x58, 0x3d, 0xa9, 0x6a, 0xdb, 0x19, 0x63, 0x71, 0xe8, 0x52, 0x65, 0xbb, 0x8d, 0xd9, 0x60, 0x6a, 0x95, 0xe3, 0x36, 0x65, 0x8b, 0xa1, 0x5d, 0xb6, 0xc7, 0x54, 0x1c, 0x9a, 0x44, 0x39, 0x4a, 0x53, 0x50, 0x94, 0xd6, 0x19, 0xab, 0x3c, 0x49, 0x60, 0xf9, 0x14, 0x6d, 0x02, 0x78, 0x2e, 0x0d, 0x00, 0xf0, // modular 0xad, 0x8e, 0x86, 0xd2, 0xd3, 0x9d, 0x8c, 0x3a, 0x69, 0xb2, 0xf0, 0x4a, 0xb2, 0xaa, 0xa4, 0xd8, 0x42, 0xd3, 0xe9, 0x2a, 0x83, 0xe4, 0x48, 0x2f, 0xa7, 0x23, 0xb7, 0x56, 0x3d, 0x34, 0x93, 0x9d, 0x3c, 0x84, 0x08, 0x13, 0x89, 0x73, 0xe2, 0x54, 0xaa, 0x55, 0x3d, 0xca, 0x89, 0x52, 0xcd, 0x16, 0x8f, 0x28, 0x27, 0x4c, 0x2d, 0x5b, 0x2d, 0xe2, 0x9c, 0x30, 0x8d, 0x28, 0xf1, 0xb2, 0x7b, 0xa2, 0xb4, 0x22, 0xd5, 0xdb, 0xca, 0x89, 0xe3, 0x8c, 0x74, 0x69, 0xab, 0x27, 0x4d, 0x35, 0xca, 0xb9, 0xa3, 0x9c, 0x32, 0x47, 0xed, 0x90, 0x8e, 0xd2, 0xda, 0x96, 0xa8, 0x45, 0x2d, 0xf1, 0x1a, 0xd7, 0x70, 0x22, 0x8f, 0xc4, 0x67, 0x18, 0x86, 0x39, 0x3a, 0x62, 0x9f, 0xbe, 0x2a, 0x72, 0xef, 0x6c, 0xb0, 0xfa, 0x24, 0x24, 0xb3, 0x2b, 0xc2, 0xea, 0xa3, 0xb4, 0x8c, 0xc9, 0x52, 0x6b, 0x88, 0xca, 0x3c, 0xab, 0x0a, 0xaf, 0x21, 0xe8, 0xf0, 0xa8, 0x8c, 0xbc, 0xc6, 0xe0, 0x33, 0xd8, 0xb2, 0xca, 0x1a, 0x42, 0xa8, 0x10, 0xaf, 0xd8, 0x6b, 0x88, 0x2e, 0x5b, 0xcc, 0x6b, 0x8e, 0x21, 0x86, 0x28, 0x75, 0x8d, 0xb9, 0x86, 0xe4, 0x3c, 0x2d, 0x25, 0xc5, 0x18, 0x72, 0xa1, 0xd2, 0xf4, 0x50, 0x63, 0x28, 0x99, 0xdd, 0x53, 0x46, 0x8d, 0x21, 0x47, 0xce, 0x08, 0x2a, 0x3d, 0xc6, 0x32, 0xd9, 0x2c, 0x79, 0xd4, 0x1a, 0x6b, 0xe3, 0xb0, 0xe0, 0x8a, 0x6d, 0xac, 0x1d, 0x53, 0x4d, 0x43, 0x97, 0xa9, 0x54, 0x0c, 0x37, 0x1a, 0x52, 0xa6, 0x52, 0xd1, 0xcd, 0x78, 0x48, 0x99, 0x6a, 0x27, 0x57, 0xe5, 0xb1, 0x61, 0xa8, 0x9d, 0x5c, 0x95, 0xc7, 0x00, 0x00, 0xfc, // modulator 0xad, 0x0e, 0x9a, 0xd2, 0xd3, 0x9d, 0x8c, 0x2a, 0x69, 0xb2, 0xb0, 0x4a, 0x72, 0xaa, 0xa4, 0xd8, 0x42, 0xd3, 0xe9, 0x28, 0xbd, 0x94, 0x28, 0xab, 0x64, 0x2b, 0x0f, 0x8a, 0xb3, 0xbc, 0x92, 0xad, 0xcc, 0x68, 0x8b, 0xf2, 0xac, 0x7b, 0xe2, 0xd0, 0xbd, 0xd8, 0xc3, 0xc9, 0x89, 0xe3, 0x8c, 0x10, 0x73, 0x3b, 0x27, 0x4a, 0x23, 0x4d, 0x35, 0xec, 0x9c, 0x30, 0xd5, 0x16, 0x33, 0x8f, 0x72, 0xc2, 0x34, 0xdd, 0xdc, 0xcd, 0xca, 0x89, 0x52, 0xf5, 0x34, 0x8b, 0x28, 0x27, 0xc9, 0x59, 0x5b, 0xbc, 0xac, 0x9c, 0xac, 0x44, 0x09, 0xc9, 0xa8, 0xd2, 0x9a, 0xe4, 0xb4, 0x54, 0xd9, 0x4e, 0xa9, 0xab, 0x50, 0xd7, 0x30, 0xcb, 0xa7, 0xd9, 0x6b, 0x4b, 0x59, 0x28, 0x9f, 0x6e, 0x59, 0x51, 0x89, 0x48, 0x7d, 0xba, 0x6a, 0xc5, 0x3c, 0x33, 0xd6, 0xe9, 0x5b, 0x54, 0x17, 0xf3, 0x59, 0xa7, 0xaf, 0x4e, 0xc2, 0x3c, 0xa2, 0x8c, 0x21, 0xca, 0x2a, 0x65, 0x5b, 0xd2, 0x06, 0x1f, 0xcb, 0xc9, 0xb3, 0xea, 0xe8, 0x43, 0x28, 0xe5, 0x88, 0xaa, 0xab, 0x8f, 0x21, 0xd4, 0xdc, 0xab, 0x9e, 0x3e, 0x05, 0x37, 0x8b, 0x8c, 0x7b, 0xfa, 0x6a, 0xd5, 0xcd, 0xb3, 0xce, 0xe9, 0xab, 0x13, 0xf3, 0xa8, 0xaa, 0xa7, 0x2f, 0x9e, 0x2d, 0xb2, 0xa2, 0x9e, 0xa1, 0x58, 0xd6, 0xca, 0x2a, 0xbd, 0x86, 0xa4, 0xc4, 0xb7, 0x22, 0xe4, 0x18, 0x92, 0xe6, 0x8c, 0xaa, 0x4a, 0x63, 0xc8, 0x86, 0xc2, 0x2b, 0x63, 0xad, 0xa1, 0x44, 0x0a, 0x6b, 0xaf, 0xb5, 0x86, 0x92, 0x30, 0xbd, 0xbc, 0xd6, 0x1a, 0x4a, 0x23, 0xf7, 0xd2, 0x49, 0x63, 0x2c, 0x03, 0xd3, 0xdc, 0x27, 0x8d, 0xb1, 0x4c, 0xb2, 0x48, 0xbe, 0xd4, 0xc6, 0xb2, 0xb0, 0xd5, 0x7d, 0x58, 0x1a, 0x53, 0x26, 0xcd, 0xc1, 0x4a, 0x65, 0xca, 0x89, 0xd5, 0x0b, 0x4b, 0x85, 0xb1, 0x64, 0x54, 0x0f, 0xa9, 0xe5, 0xe6, 0x52, 0x29, 0x54, 0xcc, 0x92, 0x9a, 0x4a, 0xc5, 0x30, 0x93, 0x22, 0x04, 0xa0, 0x0e, 0x9b, 0x00, 0xc0, 0x4a, 0x01, 0x00, 0xfc, // operator 0x09, 0x70, 0x9d, 0x2d, 0x00, 0x61, 0x91, 0x9e, 0x2c, 0xe5, 0xca, 0x14, 0xab, 0x72, 0x92, 0xd4, 0xa3, 0x8c, 0x2b, 0xec, 0x89, 0xd3, 0xf2, 0x52, 0x2b, 0x73, 0x2b, 0x8a, 0xcf, 0x2c, 0x3c, 0xc2, 0xac, 0x38, 0x3e, 0xe7, 0x2c, 0x8b, 0xd2, 0xe2, 0xb0, 0x2c, 0xcd, 0x2a, 0xac, 0xc9, 0x42, 0xa3, 0x94, 0x08, 0x29, 0x24, 0x53, 0x6e, 0x42, 0x59, 0x9d, 0x32, 0xa0, 0x28, 0x55, 0x06, 0x64, 0xad, 0xca, 0x00, 0x6f, 0xc4, 0x5a, 0x15, 0x9b, 0x99, 0xb8, 0xdb, 0x2e, 0xa5, 0x1d, 0xec, 0x51, 0xee, 0xa4, 0xb5, 0x61, 0x93, 0x95, 0xbb, 0xdd, 0xd2, 0xba, 0x89, 0xde, 0xe9, 0x71, 0x52, 0xab, 0x3a, 0x65, 0xa5, 0xa5, 0x5e, 0x6d, 0xac, 0x6c, 0x59, 0x9a, 0xa6, 0x74, 0x2e, 0xf3, 0x86, 0x5b, 0x91, 0xd1, 0xfb, 0xe0, 0xd1, 0x45, 0x95, 0x47, 0x1f, 0x83, 0xe8, 0x0c, 0x97, 0x39, 0x7d, 0x8d, 0x18, 0x5a, 0x55, 0x7b, 0xf5, 0x35, 0x60, 0x58, 0x75, 0xe5, 0xd1, 0x47, 0xc7, 0x55, 0x1d, 0xb6, 0xc6, 0x90, 0x2c, 0x55, 0x5c, 0x58, 0x6c, 0x7d, 0xab, 0xec, 0x64, 0xde, 0x78, 0xf5, 0xc5, 0xb1, 0xd9, 0x44, 0xad, 0x31, 0x44, 0xc3, 0x59, 0x27, 0xa1, 0xc6, 0x90, 0x02, 0x79, 0x8e, 0xcf, 0x1c, 0x63, 0x8a, 0x98, 0x39, 0x36, 0xab, 0x8d, 0x31, 0x62, 0x57, 0xf9, 0xa4, 0x36, 0xc6, 0x88, 0xd9, 0x6d, 0x33, 0xdb, 0x54, 0x26, 0x36, 0x65, 0x05, 0x6b, 0x53, 0x59, 0x58, 0x62, 0x31, 0xb4, 0x4d, 0x65, 0x60, 0xa9, 0x45, 0xe9, 0x34, 0x95, 0x81, 0x29, 0x16, 0xc5, 0xcc, 0x9c, 0x33, 0xba, 0x99, 0x0d, 0x25, 0x00, 0xf0, 0x34, 0x00, 0x00, 0xff, // oscillator 0x27, 0x4d, 0xa5, 0x23, 0x3d, 0x6b, 0x9f, 0x34, 0xad, 0xb4, 0x8c, 0x8a, 0x72, 0xd2, 0x34, 0x2a, 0xc2, 0x2a, 0xca, 0x49, 0xd3, 0x8c, 0x34, 0xef, 0x28, 0x27, 0x8e, 0x3b, 0x34, 0xa2, 0xcd, 0x9c, 0x38, 0x4e, 0x0f, 0x8b, 0x96, 0x7a, 0xa2, 0x94, 0x7d, 0x28, 0x5b, 0x8a, 0x00, 0x98, 0x6c, 0x13, 0x40, 0x27, 0x69, 0x02, 0xd8, 0x22, 0x5c, 0x01, 0x5b, 0x84, 0x2b, 0xe0, 0x48, 0x0f, 0x03, 0x0c, 0xda, 0xe6, 0x80, 0x28, 0x3c, 0x4f, 0x1b, 0x5c, 0xbb, 0x6a, 0x54, 0x1e, 0xad, 0xf3, 0x23, 0x6e, 0x51, 0x77, 0xb5, 0x51, 0x76, 0x18, 0xc6, 0x9c, 0xd5, 0x26, 0x59, 0x65, 0x18, 0x73, 0x4e, 0x5b, 0x44, 0x85, 0xb3, 0xd7, 0x3d, 0x6d, 0x51, 0xe5, 0x2e, 0x51, 0xf7, 0xb4, 0xd5, 0xb9, 0x19, 0x77, 0x9d, 0xd3, 0x36, 0x6f, 0xe6, 0xdc, 0x55, 0x4f, 0xdf, 0xa3, 0x72, 0x68, 0x4d, 0x39, 0x7d, 0x0f, 0x46, 0xe1, 0x39, 0xe5, 0xf4, 0x2d, 0x89, 0xa4, 0xd5, 0x98, 0xd3, 0xf7, 0xa8, 0x9c, 0x96, 0x67, 0x56, 0x5f, 0x03, 0x9b, 0x59, 0x54, 0x3e, 0x7d, 0x4b, 0x6c, 0x5a, 0x36, 0xfb, 0xf4, 0xb5, 0xb0, 0x5a, 0xd9, 0xa2, 0xd3, 0xd7, 0x46, 0xee, 0xe9, 0xb3, 0x4f, 0x5f, 0x3a, 0x5a, 0x86, 0xce, 0x1e, 0x7d, 0xe9, 0x68, 0x99, 0x72, 0x79, 0xf5, 0xa5, 0xa3, 0x57, 0xc8, 0xa5, 0xd1, 0x97, 0x81, 0x11, 0x6a, 0x63, 0xda, 0x50, 0x16, 0x36, 0x45, 0x15, 0x6b, 0x43, 0x99, 0x58, 0x62, 0x31, 0xb4, 0x0c, 0x65, 0x40, 0x89, 0x47, 0xb1, 0x34, 0x94, 0x8e, 0x29, 0x16, 0xc5, 0xcc, 0x98, 0x33, 0x9a, 0x99, 0x0d, 0x05, 0x00, 0x80, 0xff, // patch 0xc8, 0x2b, 0x2a, 0x3c, 0xcd, 0x12, 0x23, 0x2f, 0xba, 0xca, 0xf4, 0xb0, 0xa3, 0xbc, 0xa1, 0xdc, 0xc3, 0xd3, 0x8a, 0x01, 0x82, 0x09, 0x0f, 0x40, 0xf4, 0xee, 0xa7, 0xae, 0x51, 0xd2, 0xcd, 0x25, 0x9d, 0xa6, 0x46, 0x2d, 0x8f, 0x90, 0x7c, 0x9a, 0x9a, 0xb4, 0x2c, 0x42, 0xca, 0x69, 0x4a, 0xd6, 0xb6, 0x0c, 0xcb, 0xa7, 0x2b, 0xd5, 0xca, 0xa3, 0xec, 0x9c, 0xbe, 0x54, 0x6b, 0xad, 0x92, 0x73, 0xfa, 0x52, 0xad, 0xb5, 0x4a, 0xf1, 0x19, 0x4b, 0xb5, 0x96, 0x4e, 0xc5, 0x67, 0x2e, 0x4d, 0x5b, 0x26, 0x55, 0x9f, 0x25, 0x37, 0x1d, 0x59, 0x57, 0x75, 0xd6, 0x52, 0xb4, 0x65, 0x42, 0xf1, 0x39, 0x6b, 0xd4, 0x72, 0x6f, 0x3b, 0xe7, 0xaa, 0x41, 0x53, 0xb3, 0x2c, 0x9f, 0xab, 0x1a, 0x49, 0x8d, 0x8a, 0x92, 0xd6, 0xac, 0xdd, 0x2c, 0xc3, 0x8a, 0xe9, 0xaa, 0xac, 0x31, 0xf3, 0x38, 0x25, 0xdd, 0x25, 0xcb, 0x32, 0xe2, 0x38, 0x60, 0x79, 0xb1, 0x00, 0xec, 0xde, 0xe6, 0x80, 0xbd, 0xc7, 0x1d, 0xb0, 0x7b, 0x87, 0x01, 0x56, 0x16, 0x04, 0x40, 0x74, 0x57, 0x61, 0x6e, 0x66, 0x1b, 0xfe, // sequencer 0x41, 0xba, 0xbe, 0xdd, 0xdd, 0x93, 0x28, 0x60, 0x09, 0x35, 0x05, 0x4c, 0x69, 0xa2, 0x80, 0xa5, 0x8c, 0x0d, 0x30, 0x85, 0x8b, 0x03, 0x96, 0x73, 0x09, 0xc0, 0xb4, 0xc2, 0x27, 0xa8, 0x92, 0x35, 0xa3, 0xad, 0xac, 0xa0, 0x28, 0x8c, 0xb8, 0x60, 0x7c, 0x82, 0xa6, 0xc8, 0x7c, 0x4b, 0xd6, 0x09, 0x9a, 0x24, 0x8b, 0x2b, 0x59, 0x2b, 0x6a, 0x8c, 0x35, 0x37, 0xad, 0xac, 0xb4, 0x7b, 0xe4, 0xe8, 0x8a, 0x32, 0xb2, 0x1e, 0x50, 0xbc, 0x2b, 0x8a, 0x00, 0xb8, 0xd2, 0x14, 0x40, 0x94, 0xcc, 0x0c, 0xc8, 0xdc, 0x90, 0x00, 0xbe, 0x2a, 0xa7, 0xde, 0x16, 0xd6, 0x4c, 0x6f, 0x5c, 0x46, 0x55, 0xa4, 0x39, 0x36, 0x6c, 0x19, 0x65, 0xb2, 0x71, 0xe9, 0xc2, 0x67, 0x4c, 0x56, 0xbd, 0x4c, 0x67, 0x9f, 0xb9, 0x05, 0x65, 0x8f, 0x28, 0x73, 0xe6, 0x62, 0x59, 0x3d, 0xaa, 0xf4, 0x9a, 0xb3, 0x42, 0xeb, 0xa8, 0xda, 0x6d, 0x76, 0x52, 0x6a, 0x3c, 0xcd, 0xb4, 0xd9, 0x09, 0xcd, 0xb1, 0x0a, 0x2d, 0x00, 0x8e, 0xa6, 0x15, 0xf0, 0x25, 0xa9, 0x03, 0x9e, 0x55, 0x3f, 0xe3, 0xd2, 0xa2, 0x5a, 0x96, 0xfa, 0x8c, 0xd9, 0xaa, 0x5b, 0x79, 0xa2, 0x31, 0x9b, 0x14, 0x51, 0x29, 0x96, 0xc6, 0xec, 0xa3, 0x56, 0x15, 0xd9, 0x6e, 0x73, 0x28, 0x34, 0x99, 0x1a, 0x6a, 0xcc, 0x29, 0x51, 0x67, 0xf2, 0x90, 0x36, 0xa7, 0x44, 0x9d, 0xc9, 0x43, 0xdb, 0x1c, 0x13, 0xad, 0xba, 0x87, 0x19, 0x6b, 0xce, 0x38, 0xee, 0x16, 0xaa, 0xad, 0xa9, 0xe2, 0x68, 0x58, 0xd0, 0xb2, 0x96, 0x86, 0x83, 0xe5, 0x54, 0xc2, 0x5c, 0x2a, 0x24, 0x59, 0xdb, 0x21, 0x00, 0x88, 0xb4, 0x00, 0x08, 0xed, 0x32, 0xcc, 0xcd, 0x6d, 0xc3, 0xff, // synthesizer 0x0c, 0xe8, 0x22, 0x54, 0x01, 0x93, 0x87, 0x2a, 0x60, 0x0b, 0x57, 0x01, 0x1c, 0x1b, 0x2e, 0x80, 0x2b, 0x3c, 0x46, 0xf8, 0x5c, 0x5a, 0xb8, 0xc6, 0x1e, 0xd6, 0x15, 0x6e, 0xa6, 0x56, 0xfb, 0x44, 0xc9, 0x49, 0x68, 0xa7, 0xa2, 0x13, 0xa5, 0xc0, 0x91, 0xd9, 0xac, 0x4f, 0x94, 0x22, 0x7b, 0x66, 0x33, 0x49, 0xb1, 0xb3, 0x5c, 0xb2, 0xe9, 0xca, 0xc5, 0x34, 0x7a, 0x9b, 0xa7, 0x6a, 0x00, 0x05, 0x04, 0x6b, 0xb1, 0xca, 0xe4, 0x24, 0x34, 0x47, 0xce, 0xa9, 0xb2, 0x91, 0x70, 0x5b, 0x3b, 0xa7, 0x4a, 0x56, 0xdc, 0xfc, 0xec, 0x8c, 0x3a, 0x59, 0x35, 0x8f, 0x29, 0xab, 0x00, 0xc9, 0xca, 0x15, 0xd0, 0x80, 0xbb, 0x00, 0x36, 0x73, 0x55, 0xc0, 0x96, 0xe5, 0x06, 0xd8, 0xb2, 0xdc, 0x01, 0x81, 0x97, 0x9d, 0xa6, 0x78, 0x4b, 0xb7, 0x8c, 0x72, 0x9a, 0xec, 0x3d, 0x5d, 0x2b, 0xca, 0xe9, 0x52, 0xcc, 0x08, 0xad, 0xca, 0xa7, 0x4b, 0xb9, 0x22, 0x34, 0x2b, 0xaf, 0x3e, 0xb6, 0x68, 0x89, 0xb6, 0x7a, 0xfa, 0x14, 0x23, 0x8b, 0x33, 0xca, 0xea, 0x63, 0x2c, 0x6b, 0x77, 0x2b, 0xa7, 0xcf, 0xc1, 0xb5, 0x2c, 0x43, 0x9f, 0xa1, 0x78, 0xf5, 0xf2, 0x32, 0x72, 0x86, 0x12, 0xc4, 0x3c, 0x2a, 0xcc, 0x1a, 0xb2, 0x31, 0x4d, 0x9d, 0x30, 0x6d, 0xc9, 0x3c, 0x28, 0x2b, 0x46, 0x19, 0x20, 0x82, 0x4e, 0x03, 0x2c, 0xc0, 0x66, 0x80, 0x2f, 0xc9, 0x03, 0x50, 0x80, 0xf5, 0x19, 0xaa, 0x72, 0xd3, 0xb0, 0xc4, 0x6b, 0xc8, 0x81, 0x22, 0x3c, 0x1b, 0x8d, 0x21, 0x79, 0x4a, 0x4f, 0x8f, 0x35, 0x86, 0x9c, 0x30, 0x23, 0xad, 0xd6, 0x18, 0x4a, 0xc1, 0xf4, 0xb0, 0xca, 0x6d, 0xc8, 0x19, 0xcb, 0xd3, 0x2a, 0x95, 0x31, 0x25, 0x2c, 0x77, 0x8f, 0x5c, 0xc6, 0x52, 0x31, 0xcd, 0xad, 0x52, 0x19, 0x6b, 0x47, 0x57, 0x97, 0x49, 0x61, 0x2c, 0x8d, 0x54, 0x5d, 0x63, 0xb8, 0xb1, 0x24, 0x52, 0x73, 0xb3, 0xe1, 0xe6, 0x5a, 0xd8, 0xc9, 0x24, 0x91, 0x1b, 0x6a, 0x70, 0x65, 0x51, 0x3b, 0x00, 0x00, 0xff, // vca 0x69, 0x10, 0x36, 0xb2, 0x5c, 0x23, 0xa6, 0xc1, 0xab, 0x70, 0x75, 0x8b, 0x93, 0xfa, 0xa0, 0xcc, 0x54, 0xd5, 0xcd, 0x6a, 0x5b, 0x0e, 0x55, 0x15, 0xdb, 0x2b, 0xef, 0xb1, 0x55, 0x99, 0xec, 0x9c, 0xac, 0x5a, 0x66, 0x2b, 0xaf, 0x72, 0xb2, 0xac, 0xd8, 0x72, 0x32, 0xcc, 0xca, 0x92, 0x10, 0xef, 0xf5, 0x30, 0x2b, 0x2f, 0x1a, 0x3d, 0xa6, 0xcc, 0x8c, 0xb2, 0x70, 0xcc, 0x9e, 0x92, 0xbc, 0xea, 0xca, 0xc9, 0xba, 0x5b, 0xca, 0x6a, 0x86, 0x21, 0xf6, 0x1a, 0xcb, 0xab, 0xde, 0x26, 0x48, 0x34, 0x62, 0x07, 0x60, 0x72, 0x23, 0x03, 0x6c, 0xe5, 0xe2, 0x80, 0xa5, 0x5d, 0x1c, 0x30, 0x5c, 0x52, 0x00, 0x88, 0x89, 0x59, 0x7d, 0x92, 0x94, 0x3d, 0x45, 0x7b, 0x74, 0x81, 0x79, 0x5e, 0x39, 0xdd, 0xd1, 0x45, 0xae, 0xb1, 0x93, 0x74, 0x56, 0x9b, 0x88, 0xe6, 0x74, 0x49, 0x3d, 0x6d, 0x61, 0xac, 0xb5, 0x2d, 0xfb, 0x34, 0x9d, 0xb3, 0xe4, 0xae, 0x95, 0xd3, 0x34, 0xc5, 0x9c, 0xd3, 0x76, 0x4e, 0xdd, 0x03, 0xb3, 0x57, 0x5b, 0x39, 0x45, 0x4f, 0xc2, 0x99, 0x61, 0xf9, 0x14, 0x3d, 0x92, 0x45, 0x85, 0x9d, 0x93, 0xf7, 0x40, 0x96, 0x99, 0x76, 0x4f, 0xde, 0x23, 0x59, 0x56, 0xda, 0x39, 0x55, 0x4f, 0xac, 0x9e, 0x65, 0xe5, 0x34, 0xdd, 0xb1, 0x44, 0x76, 0xa4, 0xd3, 0x8d, 0x20, 0x6c, 0x59, 0x95, 0xce, 0x30, 0x02, 0x93, 0x57, 0x55, 0x3a, 0x53, 0xf7, 0x24, 0x9e, 0x5d, 0xe9, 0xac, 0xcd, 0xa2, 0x65, 0x4d, 0xe4, 0xb3, 0x35, 0x8b, 0x56, 0xd5, 0x91, 0xcf, 0x31, 0x12, 0x8a, 0x77, 0xd7, 0x4a, 0x7d, 0x33, 0x98, 0x95, 0x61, 0x15, 0x00, 0xe0, 0xff, // voltage 0xae, 0x75, 0x45, 0x13, 0x86, 0xdd, 0xa4, 0xd6, 0xe7, 0x70, 0x72, 0x1b, 0x9f, 0x9a, 0xe0, 0x32, 0x98, 0xa5, 0xf2, 0xa8, 0x86, 0x09, 0x57, 0x17, 0xc5, 0xa7, 0x48, 0x3e, 0xc3, 0x4d, 0xa3, 0x9c, 0x32, 0xc6, 0x31, 0x09, 0x49, 0x72, 0xca, 0x68, 0x27, 0xd5, 0x64, 0xd6, 0x28, 0x7d, 0x9c, 0x12, 0xf1, 0x4b, 0xa3, 0x74, 0x79, 0x53, 0xc4, 0x2e, 0x95, 0xd2, 0x8c, 0x49, 0x94, 0x1c, 0x5d, 0x0a, 0xdd, 0xce, 0x48, 0x72, 0x54, 0x29, 0x55, 0x5f, 0x67, 0xca, 0xda, 0xad, 0xf4, 0x66, 0xc3, 0x28, 0xa2, 0x96, 0xaa, 0xe0, 0xcc, 0x50, 0x49, 0x02, 0xe0, 0x80, 0xca, 0x52, 0x1c, 0x70, 0x98, 0x59, 0x02, 0x02, 0x76, 0x3b, 0x7d, 0xf7, 0xaa, 0xae, 0x3e, 0xfb, 0xf4, 0xdd, 0xaa, 0x58, 0xf8, 0xec, 0xd3, 0x77, 0xa7, 0x62, 0xe1, 0x53, 0x4e, 0xd7, 0x83, 0x88, 0x79, 0xcc, 0x3e, 0x7d, 0x77, 0xaa, 0xea, 0xb1, 0x68, 0x0d, 0x23, 0x91, 0x8a, 0xfa, 0xaa, 0x31, 0x8c, 0x80, 0x46, 0x96, 0x8d, 0xc3, 0xd8, 0x34, 0xa4, 0xe6, 0x54, 0x5c, 0xcb, 0x74, 0xec, 0x1a, 0x2a, 0xc7, 0x01, 0xd3, 0x10, 0x05, 0x60, 0x4e, 0xa7, 0x00, 0xcc, 0x99, 0x1a, 0x80, 0x35, 0x3a, 0x02, 0x30, 0x47, 0x6a, 0x00, 0x66, 0x4b, 0x75, 0xc0, 0x1c, 0xc6, 0x0e, 0x18, 0x51, 0x58, 0x00, 0x23, 0x8b, 0x00, 0xc0, 0xff, // waveform 0xa9, 0x65, 0xd3, 0xc3, 0xc2, 0x22, 0xbb, 0x96, 0x3e, 0x53, 0x8d, 0xb0, 0x12, 0x6a, 0x7e, 0x59, 0x2d, 0xd2, 0x4a, 0xaa, 0xd8, 0x34, 0x33, 0x4d, 0xdb, 0xad, 0x10, 0xcd, 0x43, 0xcd, 0xed, 0x8e, 0xdc, 0x74, 0xa3, 0x9a, 0x8c, 0x3d, 0x32, 0x5b, 0xc5, 0xab, 0x22, 0xec, 0x8a, 0xbd, 0xf1, 0xce, 0xf0, 0x32, 0x27, 0x0e, 0x5a, 0xb3, 0x22, 0xca, 0x9e, 0x38, 0x29, 0xee, 0x69, 0xb7, 0x73, 0x82, 0x9e, 0x48, 0xbc, 0x3b, 0xf6, 0x09, 0x7a, 0x44, 0xc9, 0x9a, 0xd8, 0x27, 0x6a, 0x8e, 0x34, 0xa7, 0x63, 0x9f, 0xa4, 0x79, 0x94, 0xaa, 0x89, 0x73, 0xf2, 0x16, 0x50, 0xaa, 0xa6, 0x4a, 0x2b, 0xb2, 0x41, 0xcb, 0xa8, 0xaa, 0xa5, 0x0d, 0x5a, 0xb5, 0xd2, 0xaa, 0xa4, 0x21, 0x0a, 0xd1, 0x6e, 0x2d, 0xd3, 0x86, 0xa1, 0x55, 0xc4, 0x2c, 0xb6, 0x00, 0x02, 0x13, 0x15, 0x40, 0x15, 0x26, 0x02, 0xe8, 0xc6, 0xb5, 0x54, 0xc3, 0xb6, 0xb9, 0x7b, 0xdc, 0x56, 0x65, 0x6e, 0x11, 0xe9, 0x51, 0x56, 0xef, 0x43, 0x97, 0x9a, 0x26, 0x6e, 0x83, 0x8b, 0xd3, 0x2c, 0xd6, 0xba, 0x0c, 0xb6, 0x6c, 0x91, 0x78, 0x9b, 0x32, 0x9a, 0x3a, 0x45, 0xea, 0x69, 0xda, 0xe8, 0x73, 0x8e, 0xb0, 0xb6, 0x6e, 0x63, 0xc8, 0xbe, 0x24, 0xda, 0x78, 0x8c, 0x61, 0xba, 0x9b, 0x78, 0xa3, 0x31, 0xc5, 0xee, 0x9e, 0xaa, 0x0d, 0xc7, 0x14, 0xbb, 0x85, 0x9b, 0x54, 0x1a, 0x4b, 0x8a, 0x12, 0xe9, 0x94, 0x6a, 0x2c, 0xd1, 0x8a, 0x46, 0x88, 0xe7, 0xb6, 0x44, 0xc7, 0xe6, 0xc1, 0xa9, 0xca, 0xec, 0x2d, 0x65, 0xba, 0x36, 0x2e, 0x4b, 0x32, 0x18, 0x11, 0x56, 0xbb, 0x2c, 0xd9, 0xa2, 0x45, 0x59, 0xcd, 0x50, 0x07, 0x45, 0xd5, 0xa5, 0x0d, 0xcc, 0x62, 0xb4, 0x65, 0x8c, 0x1e, 0x54, 0x4b, 0x94, 0xe2, 0x3e, 0x3a, 0x1a, 0x00, 0xe0, 0xff }; /* extern */ const LPCSpeechSynthWordBankData word_banks_[] = { { bank_0, 1233 }, { bank_1, 900 }, { bank_2, 1552 }, { bank_3, 2524 }, { bank_4, 4802 }, }; } // namespace plaits ================================================ FILE: lib/plaits/dsp/speech/lpc_speech_synth_words.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // LPC10 encoded words extracted from various TI ROMs. #ifndef PLAITS_DSP_SPEECH_LPC_SPEECH_SYNTH_WORDS_H_ #define PLAITS_DSP_SPEECH_LPC_SPEECH_SYNTH_WORDS_H_ #include "plaits/dsp/speech/lpc_speech_synth_controller.h" namespace plaits { #define LPC_SPEECH_SYNTH_NUM_WORD_BANKS 5 extern const uint8_t bank_0[1233]; extern const uint8_t bank_1[900]; extern const uint8_t bank_2[1552]; extern const uint8_t bank_3[2524]; extern const uint8_t bank_4[4802]; extern const LPCSpeechSynthWordBankData word_banks_[LPC_SPEECH_SYNTH_NUM_WORD_BANKS]; } // namespace plaits #endif // PLAITS_DSP_SPEECH_LPC_SPEECH_SYNTH_WORDS_H_ ================================================ FILE: lib/plaits/dsp/speech/naive_speech_synth.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Naive speech synth - made from "synthesizer" building blocks (pulse // oscillator and zero-delay SVF). #include "plaits/dsp/speech/naive_speech_synth.h" #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/units.h" #include "stmlib/utils/random.h" #include "plaits/resources.h" namespace plaits { using namespace std; using namespace stmlib; /* static */ const NaiveSpeechSynth::Phoneme NaiveSpeechSynth::phonemes_[][kNaiveSpeechNumRegisters] = { { { { { 74, 255 }, { 83, 114 }, { 97, 90 }, { 98, 90 }, { 100, 25 } } }, { { { 75, 255 }, { 84, 128 }, { 100, 114 }, { 101, 101 }, { 103, 20 } } }, { { { 76, 255 }, { 85, 128 }, { 100, 18 }, { 102, 16 }, { 104, 3 } } }, { { { 79, 255 }, { 85, 161 }, { 101, 25 }, { 104, 4 }, { 110, 0 } } }, { { { 79, 255 }, { 85, 128 }, { 101, 6 }, { 106, 25 }, { 110, 0 } } } }, { { { { 67, 255 }, { 91, 64 }, { 98, 90 }, { 101, 64 }, { 102, 32 } } }, { { { 67, 255 }, { 92, 51 }, { 99, 64 }, { 103, 51 }, { 105, 25 } } }, { { { 69, 255 }, { 93, 51 }, { 100, 32 }, { 102, 25 }, { 103, 25 } } }, { { { 67, 255 }, { 91, 16 }, { 100, 8 }, { 103, 4 }, { 110, 0 } } }, { { { 65, 255 }, { 95, 25 }, { 101, 45 }, { 105, 2 }, { 110, 0 } } } }, { { { { 59, 255 }, { 92, 8 }, { 99, 40 }, { 102, 20 }, { 104, 10 } } }, { { { 61, 255 }, { 94, 45 }, { 101, 32 }, { 103, 25 }, { 105, 8 } } }, { { { 60, 255 }, { 93, 16 }, { 101, 16 }, { 104, 4 }, { 105, 4 } } }, { { { 65, 255 }, { 92, 25 }, { 100, 8 }, { 105, 4 }, { 110, 0 } } }, { { { 60, 255 }, { 96, 64 }, { 101, 12 }, { 106, 12 }, { 110, 1 } } } }, { { { { 67, 255 }, { 78, 72 }, { 98, 22 }, { 99, 25 }, { 101, 2 } } }, { { { 67, 255 }, { 79, 80 }, { 99, 64 }, { 101, 64 }, { 102, 12 } } }, { { { 68, 255 }, { 79, 80 }, { 100, 12 }, { 102, 20 }, { 103, 5 } } }, { { { 69, 255 }, { 79, 90 }, { 101, 40 }, { 104, 10 }, { 110, 0 } } }, { { { 69, 255 }, { 79, 72 }, { 101, 20 }, { 106, 20 }, { 110, 0 } } } }, { { { { 65, 255 }, { 74, 25 }, { 98, 6 }, { 100, 10 }, { 101, 4 } } }, { { { 65, 255 }, { 74, 25 }, { 100, 36 }, { 101, 51 }, { 103, 12 } } }, { { { 66, 255 }, { 75, 25 }, { 100, 18 }, { 102, 8 }, { 104, 5 } } }, { { { 63, 255 }, { 77, 64 }, { 99, 8 }, { 104, 2 }, { 110, 0 } } }, { { { 63, 255 }, { 77, 40 }, { 100, 4 }, { 106, 2 }, { 110, 0 } } } }, }; void NaiveSpeechSynth::Init() { pulse_.Init(); frequency_ = 0.0f; click_duration_ = 0; for (int i = 0; i < kNaiveSpeechNumFormants; ++i) { filter_[i].Init(); } pulse_coloration_.Init(); pulse_coloration_.set_f_q(800.0f / kSampleRate, 0.5f); } void NaiveSpeechSynth::Render( bool click, float frequency, float phoneme, float vocal_register, float* temp, float* excitation, float* output, size_t size) { if (click) { click_duration_ = kSampleRate * 0.05f; } click_duration_ -= min(click_duration_, size); if (click_duration_) { frequency *= 0.5f; } // Generate excitation signal (glottal pulse). pulse_.Render( frequency, 0.5f, excitation, size); pulse_coloration_.Process( excitation, excitation, size); for (size_t i = 0; i < size; ++i) { excitation[i] *= 4.0f; } float p = phoneme * (kNaiveSpeechNumPhonemes - 1.001f); float r = vocal_register * (kNaiveSpeechNumRegisters - 1.001f); MAKE_INTEGRAL_FRACTIONAL(p); MAKE_INTEGRAL_FRACTIONAL(r); fill(&output[0], &output[size], 0.0f); for (int i = 0; i < kNaiveSpeechNumFormants; ++i) { const Formant& p0r0 = phonemes_[p_integral][r_integral].formant[i]; const Formant& p0r1 = phonemes_[p_integral][r_integral + 1].formant[i]; const Formant& p1r0 = phonemes_[p_integral + 1][r_integral].formant[i]; const Formant& p1r1 = phonemes_[p_integral + 1][r_integral + 1].formant[i]; float p0r_f = p0r0.frequency + \ (p0r1.frequency - p0r0.frequency) * r_fractional; float p1r_f = p1r0.frequency + \ (p1r1.frequency - p1r0.frequency) * r_fractional; float f = p0r_f + (p1r_f - p0r_f) * p_fractional; float p0r_a = p0r0.amplitude + \ (p0r1.amplitude - p0r0.amplitude) * r_fractional; float p1r_a = p1r0.amplitude + \ (p1r1.amplitude - p1r0.amplitude) * r_fractional; float a = (p0r_a + (p1r_a - p0r_a) * p_fractional) / 256.0f; if (f >= 160.0f) { f = 160.0f; } f = a0 * stmlib::SemitonesToRatio(f - 33.0f); if (click_duration_ && i == 0) { f *= 0.5f; } filter_[i].set_f_q(f, 20.0f); filter_[i].ProcessAdd(excitation, output, size, a); } } } // namespace plaits ================================================ FILE: lib/plaits/dsp/speech/naive_speech_synth.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Naive speech synth - made from "synthesizer" building blocks (pulse // oscillator and zero-delay SVF). #ifndef PLAITS_DSP_SPEECH_NAIVE_SPEECH_SYNTH_H_ #define PLAITS_DSP_SPEECH_NAIVE_SPEECH_SYNTH_H_ #include "stmlib/dsp/filter.h" #include "plaits/dsp/dsp.h" #include "plaits/dsp/oscillator/oscillator.h" namespace plaits { const int kNaiveSpeechNumFormants = 5; const int kNaiveSpeechNumPhonemes = 5; const int kNaiveSpeechNumRegisters = 5; class NaiveSpeechSynth { public: NaiveSpeechSynth() { } ~NaiveSpeechSynth() { } void Init(); void Render( bool click, float frequency, float phoneme, float vocal_register, float* temp, float* excitation, float* output, size_t size); private: struct Formant { uint8_t frequency; uint8_t amplitude; }; struct Phoneme { Formant formant[kNaiveSpeechNumFormants]; }; Oscillator pulse_; float frequency_; size_t click_duration_; stmlib::Svf filter_[kNaiveSpeechNumFormants]; stmlib::Svf pulse_coloration_; static const Phoneme phonemes_[kNaiveSpeechNumPhonemes][kNaiveSpeechNumRegisters]; DISALLOW_COPY_AND_ASSIGN(NaiveSpeechSynth); }; } // namespace plaits #endif // PLAITS_DSP_SPEECH_NAIVE_SPEECH_SYNTH_H_ ================================================ FILE: lib/plaits/dsp/speech/sam_speech_synth.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // SAM-inspired speech synth (as used in Shruthi/Ambika/Braids). #include "plaits/dsp/speech/sam_speech_synth.h" #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "plaits/dsp/oscillator/sine_oscillator.h" #include "plaits/dsp/oscillator/oscillator.h" #include "plaits/resources.h" namespace plaits { using namespace std; using namespace stmlib; void SAMSpeechSynth::Init() { phase_ = 0.0f; frequency_ = 0.0f; pulse_next_sample_ = 0.0f; pulse_lp_ = 0.0f; fill(&formant_phase_[0], &formant_phase_[3], 0); consonant_samples_ = 0; consonant_index_ = 0.0f; } // Phoneme data /* static */ const SAMSpeechSynth::Phoneme SAMSpeechSynth::phonemes_[] = { { { { 60, 15 }, { 90, 13 }, { 200, 1 } } }, { { { 40, 13 }, { 114, 12 }, { 139, 6 } } }, { { { 33, 14 }, { 155, 12 }, { 209, 7 } } }, { { { 22, 13 }, { 189, 10 }, { 247, 8 } } }, { { { 51, 15 }, { 99, 12 }, { 195, 1 } } }, { { { 29, 13 }, { 65, 8 }, { 180, 0 } } }, { { { 13, 12 }, { 103, 3 }, { 182, 0 } } }, { { { 20, 15 }, { 114, 3 }, { 213, 0 } } }, { { { 13, 7 }, { 164, 3 }, { 222, 14 } } }, { { { 13, 9 }, { 121, 9 }, { 254, 0 } } }, { { { 40, 12 }, { 112, 10 }, { 114, 5 } } }, { { { 24, 13 }, { 54, 8 }, { 157, 0 } } }, { { { 33, 14 }, { 155, 12 }, { 166, 7 } } }, { { { 36, 14 }, { 83, 8 }, { 249, 1 } } }, { { { 40, 14 }, { 114, 12 }, { 139, 6 } } }, { { { 13, 5 }, { 58, 5 }, { 182, 5 } } }, { { { 13, 7 }, { 164, 10 }, { 222, 14 } } }, { { { 13, 7 }, { 164, 10 }, { 222, 14 } } } // GUARD }; /* static */ const float SAMSpeechSynth::formant_amplitude_lut[] = { 0.03125000f, 0.03756299f, 0.04515131f, 0.05427259f, 0.06523652f, 0.07841532f, 0.09425646f, 0.11329776f, 0.13618570f, 0.16369736f, 0.19676682f, 0.23651683f, 0.28429697f, 0.34172946f, 0.41076422f, 0.49374509f }; void SAMSpeechSynth::InterpolatePhonemeData( float phoneme, float formant_shift, uint32_t* formant_frequency, float* formant_amplitude) { MAKE_INTEGRAL_FRACTIONAL(phoneme); const Phoneme& p_1 = phonemes_[phoneme_integral]; const Phoneme& p_2 = phonemes_[phoneme_integral + 1]; formant_shift = 1.0f + formant_shift * 2.5f; for (int i = 0; i < kSAMNumFormants; ++i) { float f_1 = p_1.formant[i].frequency; float f_2 = p_2.formant[i].frequency; float f = f_1 + (f_2 - f_1) * phoneme_fractional; f *= 8.0f * formant_shift * 4294967296.0f / kSampleRate; formant_frequency[i] = static_cast(f); float a_1 = formant_amplitude_lut[p_1.formant[i].amplitude]; float a_2 = formant_amplitude_lut[p_2.formant[i].amplitude]; formant_amplitude[i] = a_1 + (a_2 - a_1) * phoneme_fractional; } } void SAMSpeechSynth::Render( bool consonant, float frequency, float vowel, float formant_shift, float* excitation, float* output, size_t size) { if (frequency >= 0.0625f) { frequency = 0.0625f; } if (consonant) { consonant_samples_ = kSampleRate * 0.05f; int r = (vowel + 3.0f * frequency + 7.0f * formant_shift) * 8.0f; consonant_index_ = (r % kSAMNumConsonants); } consonant_samples_ -= min(consonant_samples_, size); float phoneme = consonant_samples_ ? (consonant_index_ + kSAMNumVowels) : vowel * (kSAMNumVowels - 1.0001f); uint32_t formant_frequency[kSAMNumFormants]; float formant_amplitude[kSAMNumFormants]; InterpolatePhonemeData( phoneme, formant_shift, formant_frequency, formant_amplitude); ParameterInterpolator fm(&frequency_, frequency, size); float pulse_next_sample = pulse_next_sample_; while (size--) { float pulse_this_sample = pulse_next_sample; pulse_next_sample = 0.0f; const float frequency = fm.Next(); phase_ += frequency; if (phase_ >= 1.0f) { phase_ -= 1.0f; float t = phase_ / frequency; formant_phase_[0] = static_cast( t * static_cast(formant_frequency[0])); formant_phase_[1] = static_cast( t * static_cast(formant_frequency[1])); formant_phase_[2] = static_cast( t * static_cast(formant_frequency[2])); pulse_this_sample -= ThisBlepSample(t); pulse_next_sample -= NextBlepSample(t); } else { formant_phase_[0] += formant_frequency[0]; formant_phase_[1] += formant_frequency[1]; formant_phase_[2] += formant_frequency[2]; } pulse_next_sample += phase_; float d = pulse_this_sample - 0.5f - pulse_lp_; pulse_lp_ += min(16.0f * frequency, 1.0f) * d; *excitation++ = d; float s = 0; s += SineRaw(formant_phase_[0]) * formant_amplitude[0]; s += SineRaw(formant_phase_[1]) * formant_amplitude[1]; s += SineRaw(formant_phase_[2]) * formant_amplitude[2]; s *= (1.0f - phase_); *output++ = s; } pulse_next_sample_ = pulse_next_sample; } } // namespace plaits ================================================ FILE: lib/plaits/dsp/speech/sam_speech_synth.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // SAM-inspired speech synth (as used in Shruthi/Ambika/Braids). #ifndef PLAITS_DSP_SPEECH_SAM_SPEECH_SYNTH_H_ #define PLAITS_DSP_SPEECH_SAM_SPEECH_SYNTH_H_ #include "plaits/dsp/dsp.h" namespace plaits { const int kSAMNumFormants = 3; const int kSAMNumVowels = 9; const int kSAMNumConsonants = 8; const int kSAMNumPhonemes = kSAMNumVowels + kSAMNumConsonants; class SAMSpeechSynth { public: SAMSpeechSynth() { } ~SAMSpeechSynth() { } void Init(); void Render( bool consonant, float frequency, float vowel, float formant_shift, float* excitation, float* output, size_t size); private: void InterpolatePhonemeData( float phoneme, float formant_shift, uint32_t* formant_frequency, float* formant_amplitude); struct Formant { uint8_t frequency; uint8_t amplitude; }; struct Phoneme { Formant formant[kSAMNumFormants]; }; float phase_; float frequency_; float pulse_next_sample_; float pulse_lp_; uint32_t formant_phase_[3]; size_t consonant_samples_; float consonant_index_; static const Phoneme phonemes_[kSAMNumPhonemes + 1]; static const float formant_amplitude_lut[16]; DISALLOW_COPY_AND_ASSIGN(SAMSpeechSynth); }; } // namespace plaits #endif // PLAITS_DSP_SPEECH_SAM_SPEECH_SYNTH_H_ ================================================ FILE: lib/plaits/dsp/voice.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Main synthesis voice. #include "plaits/dsp/voice.h" //[eh2k] #include "plaits/user_data.h" namespace plaits { using namespace std; using namespace stmlib; void Voice::Init() { // engines_.Init(); // engines_.RegisterInstance(&virtual_analog_vcf_engine_, false, 1.0f, 1.0f); // engines_.RegisterInstance(&phase_distortion_engine_, false, 0.7f, 0.7f); // engines_.RegisterInstance(&six_op_engine_, true, 1.0f, 1.0f); // engines_.RegisterInstance(&six_op_engine_, true, 1.0f, 1.0f); // engines_.RegisterInstance(&six_op_engine_, true, 1.0f, 1.0f); // engines_.RegisterInstance(&wave_terrain_engine_, false, 0.7f, 0.7f); // engines_.RegisterInstance(&string_machine_engine_, false, 0.8f, 0.8f); // engines_.RegisterInstance(&chiptune_engine_, false, 0.5f, 0.5f); // engines_.RegisterInstance(&virtual_analog_engine_, false, 0.8f, 0.8f); // engines_.RegisterInstance(&waveshaping_engine_, false, 0.7f, 0.6f); // engines_.RegisterInstance(&fm_engine_, false, 0.6f, 0.6f); // engines_.RegisterInstance(&grain_engine_, false, 0.7f, 0.6f); // engines_.RegisterInstance(&additive_engine_, false, 0.8f, 0.8f); // engines_.RegisterInstance(&wavetable_engine_, false, 0.6f, 0.6f); // engines_.RegisterInstance(&chord_engine_, false, 0.8f, 0.8f); // engines_.RegisterInstance(&speech_engine_, false, -0.7f, 0.8f); // engines_.RegisterInstance(&swarm_engine_, false, -3.0f, 1.0f); // engines_.RegisterInstance(&noise_engine_, false, -1.0f, -1.0f); // engines_.RegisterInstance(&particle_engine_, false, -2.0f, 1.0f); // engines_.RegisterInstance(&string_engine_, true, -1.0f, 0.8f); // engines_.RegisterInstance(&modal_engine_, true, -1.0f, 0.8f); // engines_.RegisterInstance(&bass_drum_engine_, true, 0.8f, 0.8f); // engines_.RegisterInstance(&snare_drum_engine_, true, 0.8f, 0.8f); // engines_.RegisterInstance(&hi_hat_engine_, true, 0.8f, 0.8f); // for (int i = 0; i < engines_.size(); ++i) { // // All engines will share the same RAM space. // allocator->Free(); // engines_.get(i)->Init(allocator); // } // engine_quantizer_.Init(engines_.size(), 0.05f, true); // previous_engine_index_ = -1; // reload_user_data_ = false; // engine_cv_ = 0.0f; out_post_processor_.Init(); aux_post_processor_.Init(); decay_envelope_.Init(); lpg_envelope_.Init(); trigger_state_ = false; previous_note_ = 0.0f; trigger_delay_.Init(trigger_delay_line_); } void Voice::Render( Engine* e, const Patch& patch, const Modulations& modulations, float* out, float* aux, size_t size) { // Trigger, LPG, internal envelope. // Delay trigger by 1ms to deal with sequencers or MIDI interfaces whose // CV out lags behind the GATE out. trigger_delay_.Write(modulations.trigger); float trigger_value = trigger_delay_.Read(kTriggerDelay); bool previous_trigger_state = trigger_state_; if (!previous_trigger_state) { if (trigger_value > 0.3f) { trigger_state_ = true; if (!modulations.level_patched) { lpg_envelope_.Trigger(); } decay_envelope_.Trigger(); //engine_cv_ = modulations.engine; } } else { if (trigger_value < 0.1f) { trigger_state_ = false; } } if (!modulations.trigger_patched) { //engine_cv_ = modulations.engine; } int engine_index = patch.engine; // Engine selection. // int engine_index = engine_quantizer_.Process( // patch.engine, // engine_cv_); // Engine* e = engines_.get(engine_index); // if (engine_index != previous_engine_index_ || reload_user_data_) { // UserData user_data; // const uint8_t* data = user_data.ptr(engine_index); // if (!data && engine_index >= 2 && engine_index <= 4) { // data = fm_patches_table[engine_index - 2]; // } // e->LoadUserData(data); // e->Reset(); // out_post_processor_.Reset(); // previous_engine_index_ = engine_index; // reload_user_data_ = false; // } EngineParameters p; bool rising_edge = trigger_state_ && !previous_trigger_state; float note = (modulations.note + previous_note_) * 0.5f; previous_note_ = modulations.note; const PostProcessingSettings& pp_s = e->post_processing_settings; if (modulations.trigger_patched) { p.trigger = (rising_edge ? TRIGGER_RISING_EDGE : TRIGGER_LOW) | \ (trigger_state_ ? TRIGGER_HIGH : TRIGGER_LOW); } else { p.trigger = TRIGGER_UNPATCHED; } const float short_decay = (200.0f * kBlockSize) / kSampleRate * SemitonesToRatio(-96.0f * patch.decay); decay_envelope_.Process(short_decay * 2.0f); float compressed_level = 1.3f * modulations.level / (0.3f + fabsf(modulations.level)); CONSTRAIN(compressed_level, 0.0f, 1.0f); p.accent = modulations.level_patched ? compressed_level : 0.8f; bool use_internal_envelope = modulations.trigger_patched; // Actual synthesis parameters. p.harmonics = patch.harmonics + modulations.harmonics; CONSTRAIN(p.harmonics, 0.0f, 1.0f); float internal_envelope_amplitude = 1.0f; float internal_envelope_amplitude_timbre = 1.0f; if (engine_index == 15) { internal_envelope_amplitude = 2.0f - p.harmonics * 6.0f; CONSTRAIN(internal_envelope_amplitude, 0.0f, 1.0f); auto& speech_engine_ = *static_cast(e); speech_engine_.set_prosody_amount( !modulations.trigger_patched || modulations.frequency_patched ? 0.0f : patch.frequency_modulation_amount); speech_engine_.set_speed( !modulations.trigger_patched || modulations.morph_patched ? 0.0f : patch.morph_modulation_amount); } else if (engine_index == 7) { auto& chiptune_engine_ = *static_cast(e); if (modulations.trigger_patched && !modulations.timbre_patched) { // Disable internal envelope on TIMBRE, and enable the envelope generator // built into the chiptune engine. internal_envelope_amplitude_timbre = 0.0f; chiptune_engine_.set_envelope_shape(patch.timbre_modulation_amount); } else { chiptune_engine_.set_envelope_shape(ChiptuneEngine::NO_ENVELOPE); } } p.note = ApplyModulations( patch.note + note, patch.frequency_modulation_amount, modulations.frequency_patched, modulations.frequency, use_internal_envelope, internal_envelope_amplitude * \ decay_envelope_.value() * decay_envelope_.value() * 48.0f, 1.0f, -119.0f, 120.0f); p.timbre = ApplyModulations( patch.timbre, patch.timbre_modulation_amount, modulations.timbre_patched, modulations.timbre, use_internal_envelope, internal_envelope_amplitude_timbre * decay_envelope_.value(), 0.0f, 0.0f, 1.0f); p.morph = ApplyModulations( patch.morph, patch.morph_modulation_amount, modulations.morph_patched, modulations.morph, use_internal_envelope, internal_envelope_amplitude * decay_envelope_.value(), 0.0f, 0.0f, 1.0f); bool already_enveloped = pp_s.already_enveloped; e->Render(p, out ? out_buffer_ : nullptr, aux ? aux_buffer_ : nullptr, size, &already_enveloped); bool lpg_bypass = already_enveloped || \ (!modulations.level_patched && !modulations.trigger_patched); // Compute LPG parameters. if (!lpg_bypass) { const float hf = patch.lpg_colour; const float decay_tail = (20.0f * kBlockSize) / kSampleRate * SemitonesToRatio(-72.0f * patch.decay + 12.0f * hf) - short_decay; if (modulations.level_patched) { lpg_envelope_.ProcessLP(compressed_level, short_decay, decay_tail, hf); } else { const float attack = NoteToFrequency(p.note) * float(kBlockSize) * 2.0f; lpg_envelope_.ProcessPing(attack, short_decay, decay_tail, hf); } } else { lpg_envelope_.Init(); } if(out) out_post_processor_.Process( pp_s.out_gain, lpg_bypass, lpg_envelope_.gain(), lpg_envelope_.frequency(), lpg_envelope_.hf_bleed(), out_buffer_, out, size, 1); if(aux) aux_post_processor_.Process( pp_s.aux_gain, lpg_bypass, lpg_envelope_.gain(), lpg_envelope_.frequency(), lpg_envelope_.hf_bleed(), aux_buffer_, aux, size, 1); } } // namespace plaits ================================================ FILE: lib/plaits/dsp/voice.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Main synthesis voice. #ifndef PLAITS_DSP_VOICE_H_ #define PLAITS_DSP_VOICE_H_ #include "stmlib/stmlib.h" #include "stmlib/dsp/filter.h" #include "stmlib/dsp/limiter.h" #include "stmlib/utils/buffer_allocator.h" #include "plaits/dsp/engine/additive_engine.h" #include "plaits/dsp/engine/bass_drum_engine.h" #include "plaits/dsp/engine/chord_engine.h" #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/engine/fm_engine.h" #include "plaits/dsp/engine/grain_engine.h" #include "plaits/dsp/engine/hi_hat_engine.h" #include "plaits/dsp/engine/modal_engine.h" #include "plaits/dsp/engine/noise_engine.h" #include "plaits/dsp/engine/particle_engine.h" #include "plaits/dsp/engine/snare_drum_engine.h" #include "plaits/dsp/engine/speech_engine.h" #include "plaits/dsp/engine/string_engine.h" #include "plaits/dsp/engine/swarm_engine.h" #include "plaits/dsp/engine/virtual_analog_engine.h" #include "plaits/dsp/engine/waveshaping_engine.h" #include "plaits/dsp/engine/wavetable_engine.h" #include "plaits/dsp/engine2/chiptune_engine.h" #include "plaits/dsp/engine2/phase_distortion_engine.h" #include "plaits/dsp/engine2/six_op_engine.h" #include "plaits/dsp/engine2/string_machine_engine.h" #include "plaits/dsp/engine2/virtual_analog_vcf_engine.h" #include "plaits/dsp/engine2/wave_terrain_engine.h" #include "plaits/dsp/envelope.h" #include "plaits/dsp/fx/low_pass_gate.h" namespace plaits { const int kMaxEngines = 24; const int kMaxTriggerDelay = 8; const int kTriggerDelay = 0; class ChannelPostProcessor { public: ChannelPostProcessor() { } ~ChannelPostProcessor() { } void Init() { lpg_.Init(); Reset(); } void Reset() { limiter_.Init(); } void Process( float gain, bool bypass_lpg, float low_pass_gate_gain, float low_pass_gate_frequency, float low_pass_gate_hf_bleed, float* in, float* out, size_t size, size_t stride) { if (gain < 0.0f) { limiter_.Process(-gain, in, size); } const float post_gain = (gain < 0.0f ? 1.0f : gain); if (!bypass_lpg) { lpg_.Process( post_gain * low_pass_gate_gain, low_pass_gate_frequency, low_pass_gate_hf_bleed, in, out, size, stride); } else { while (size--) { *out = *in++ * post_gain; out += stride; } } } private: stmlib::Limiter limiter_; LowPassGate lpg_; DISALLOW_COPY_AND_ASSIGN(ChannelPostProcessor); }; struct Patch { float note; float harmonics; float timbre; float morph; float frequency_modulation_amount; float timbre_modulation_amount; float morph_modulation_amount; int engine; float decay; float lpg_colour; }; struct Modulations { float engine; float note; float frequency; float harmonics; float timbre; float morph; float trigger; float level; bool frequency_patched; bool timbre_patched; bool morph_patched; bool trigger_patched; bool level_patched; }; // char (*__foo)[sizeof(HiHatEngine)] = 1; class Voice { public: Voice() { } ~Voice() { } void Init(); void ReloadUserData() { reload_user_data_ = true; } void Render( Engine* engine, const Patch& patch, const Modulations& modulations, float* out, float* aux, size_t size); private: void ComputeDecayParameters(const Patch& settings); inline float ApplyModulations( float base_value, float modulation_amount, bool use_external_modulation, float external_modulation, bool use_internal_envelope, float envelope, float default_internal_modulation, float minimum_value, float maximum_value) { float value = base_value; modulation_amount *= std::max(fabsf(modulation_amount) - 0.05f, 0.05f); modulation_amount *= 1.05f; float modulation = use_external_modulation ? external_modulation : (use_internal_envelope ? envelope : default_internal_modulation); value += modulation_amount * modulation; CONSTRAIN(value, minimum_value, maximum_value); return value; } // VirtualAnalogEngine virtual_analog_engine_; // WaveshapingEngine waveshaping_engine_; // FMEngine fm_engine_; // GrainEngine grain_engine_; // AdditiveEngine additive_engine_; // WavetableEngine wavetable_engine_; // ChordEngine chord_engine_; // SpeechEngine speech_engine_; // SwarmEngine swarm_engine_; // NoiseEngine noise_engine_; // ParticleEngine particle_engine_; // StringEngine string_engine_; // ModalEngine modal_engine_; // BassDrumEngine bass_drum_engine_; // SnareDrumEngine snare_drum_engine_; // HiHatEngine hi_hat_engine_; // VirtualAnalogVCFEngine virtual_analog_vcf_engine_; // PhaseDistortionEngine phase_distortion_engine_; // SixOpEngine six_op_engine_; // WaveTerrainEngine wave_terrain_engine_; // StringMachineEngine string_machine_engine_; // ChiptuneEngine chiptune_engine_; // stmlib::HysteresisQuantizer2 engine_quantizer_; bool reload_user_data_; // int previous_engine_index_; // float engine_cv_; float previous_note_; bool trigger_state_; DecayEnvelope decay_envelope_; LPGEnvelope lpg_envelope_; float trigger_delay_line_[kMaxTriggerDelay]; DelayLine trigger_delay_; ChannelPostProcessor out_post_processor_; ChannelPostProcessor aux_post_processor_; //EngineRegistry engines_; float out_buffer_[kMaxBlockSize]; float aux_buffer_[kMaxBlockSize]; DISALLOW_COPY_AND_ASSIGN(Voice); }; } // namespace plaits #endif // PLAITS_DSP_VOICE_H_ ================================================ FILE: lib/plaits/resources.cc ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resources definitions. // // Automatically generated with: // make resources #include "plaits/resources.h" #ifndef FLASHMEM #define FLASHMEM #endif namespace plaits { const uint8_t syx_bank_0[] FLASHMEM = { 99, 58, 99, 60, 99, 0, 0, 0, 0, 0, 0, 0, 56, 0, 79, 2, 0, 99, 99, 99, 60, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 50, 2, 0, 99, 99, 99, 66, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 70, 0, 0, 99, 41, 99, 65, 99, 0, 0, 0, 0, 0, 0, 0, 56, 0, 99, 0, 0, 99, 99, 99, 99, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 0, 2, 0, 99, 99, 99, 99, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 0, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 13, 15, 35, 0, 0, 0, 49, 12, 83, 79, 76, 73, 68, 32, 66, 65, 83, 83, 85, 55, 55, 65, 99, 0, 0, 0, 0, 0, 0, 0, 56, 0, 85, 2, 50, 80, 50, 40, 65, 99, 95, 0, 0, 27, 0, 20, 3, 56, 0, 80, 2, 0, 90, 30, 14, 65, 99, 95, 85, 0, 39, 0, 15, 3, 56, 0, 99, 0, 0, 90, 30, 14, 65, 99, 95, 85, 0, 27, 0, 10, 3, 56, 0, 80, 0, 0, 90, 30, 14, 65, 99, 95, 85, 0, 39, 0, 10, 3, 56, 0, 99, 0, 0, 90, 30, 14, 65, 99, 95, 85, 0, 39, 0, 15, 3, 56, 0, 99, 0, 0, 99, 99, 99, 99, 50, 50, 50, 50, 25, 14, 35, 0, 0, 0, 49, 12, 77, 111, 111, 103, 101, 114, 32, 76, 111, 119, 99, 99, 99, 39, 99, 99, 99, 0, 81, 0, 0, 0, 65, 20, 70, 4, 0, 49, 19, 0, 49, 99, 99, 99, 0, 55, 0, 99, 0, 63, 3, 75, 4, 0, 70, 39, 29, 33, 99, 9, 0, 0, 0, 0, 0, 0, 34, 12, 95, 0, 0, 70, 29, 29, 54, 99, 9, 0, 0, 0, 0, 0, 0, 80, 0, 99, 0, 0, 99, 70, 19, 9, 99, 59, 0, 0, 0, 0, 0, 0, 56, 0, 99, 6, 0, 70, 18, 18, 32, 99, 29, 0, 0, 0, 0, 0, 0, 63, 8, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 5, 0, 35, 0, 0, 0, 49, 12, 76, 101, 97, 100, 101, 114, 84, 97, 112, 101, 90, 42, 7, 55, 90, 30, 99, 0, 0, 0, 0, 0, 56, 8, 99, 0, 0, 88, 96, 32, 30, 79, 65, 99, 0, 0, 0, 0, 0, 56, 0, 65, 2, 0, 99, 20, 0, 99, 99, 0, 99, 0, 0, 0, 0, 0, 56, 8, 89, 0, 0, 95, 62, 17, 58, 99, 99, 99, 0, 0, 0, 0, 0, 56, 12, 99, 0, 0, 99, 55, 0, 90, 99, 76, 99, 0, 48, 6, 0, 3, 56, 8, 96, 2, 0, 99, 99, 90, 99, 99, 99, 99, 0, 0, 0, 0, 0, 56, 12, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 1, 13, 35, 0, 0, 0, 49, 12, 77, 79, 82, 72, 79, 76, 32, 84, 66, 49, 25, 50, 24, 55, 96, 97, 0, 0, 0, 0, 0, 0, 65, 0, 91, 0, 0, 99, 0, 0, 0, 99, 0, 0, 0, 34, 0, 32, 0, 56, 8, 66, 2, 1, 80, 44, 28, 53, 86, 57, 0, 0, 0, 0, 0, 0, 60, 16, 99, 0, 0, 27, 25, 32, 30, 85, 78, 0, 0, 0, 0, 0, 0, 112, 14, 99, 0, 0, 28, 37, 42, 50, 99, 0, 0, 0, 41, 0, 35, 0, 56, 8, 74, 0, 3, 89, 30, 28, 63, 99, 90, 0, 0, 48, 0, 32, 0, 59, 8, 99, 0, 1, 94, 67, 95, 60, 50, 50, 50, 50, 16, 15, 31, 33, 0, 0, 24, 12, 66, 65, 83, 83, 32, 32, 32, 32, 51, 32, 94, 56, 24, 80, 93, 28, 0, 0, 0, 0, 0, 0, 57, 0, 99, 8, 0, 99, 50, 50, 80, 99, 0, 0, 0, 52, 75, 0, 0, 63, 0, 99, 0, 0, 90, 60, 16, 80, 90, 30, 0, 0, 0, 0, 0, 0, 61, 0, 92, 10, 0, 99, 50, 20, 53, 79, 65, 0, 0, 0, 0, 0, 0, 62, 0, 90, 0, 0, 99, 10, 50, 57, 99, 0, 0, 0, 41, 0, 0, 0, 63, 4, 80, 0, 0, 96, 10, 17, 63, 99, 95, 0, 0, 36, 57, 14, 3, 63, 0, 99, 0, 0, 94, 67, 96, 57, 50, 50, 50, 50, 15, 15, 50, 25, 99, 0, 0, 24, 66, 73, 76, 76, 32, 66, 65, 83, 83, 32, 94, 56, 24, 55, 93, 28, 0, 0, 0, 0, 0, 0, 57, 28, 85, 18, 0, 99, 0, 0, 0, 99, 0, 0, 0, 52, 75, 0, 0, 63, 12, 62, 0, 0, 90, 42, 7, 55, 90, 30, 0, 0, 0, 0, 0, 0, 61, 20, 93, 10, 0, 88, 96, 32, 30, 79, 65, 0, 0, 0, 0, 0, 0, 62, 12, 99, 0, 0, 99, 20, 0, 0, 99, 0, 0, 0, 41, 0, 0, 0, 63, 0, 80, 0, 0, 95, 62, 17, 58, 99, 95, 32, 0, 36, 57, 14, 3, 63, 0, 99, 0, 0, 94, 67, 95, 60, 50, 50, 50, 50, 15, 15, 35, 0, 0, 0, 48, 12, 66, 65, 83, 83, 32, 32, 32, 32, 49, 32, 99, 99, 62, 99, 99, 99, 0, 0, 0, 0, 0, 0, 60, 20, 99, 12, 0, 99, 99, 38, 99, 99, 99, 0, 0, 0, 0, 0, 0, 61, 28, 70, 18, 0, 59, 99, 41, 71, 99, 99, 0, 0, 0, 0, 0, 0, 53, 28, 63, 18, 0, 59, 99, 99, 71, 99, 99, 99, 0, 0, 0, 0, 0, 61, 0, 75, 0, 0, 59, 99, 22, 71, 99, 86, 0, 0, 0, 0, 0, 0, 101, 20, 69, 6, 0, 99, 64, 33, 71, 99, 86, 0, 0, 0, 0, 0, 0, 72, 8, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 16, 15, 35, 0, 0, 0, 49, 24, 69, 76, 69, 67, 32, 66, 65, 83, 83, 32, 64, 54, 40, 72, 81, 83, 0, 0, 43, 0, 18, 0, 69, 16, 62, 12, 25, 99, 99, 99, 64, 99, 99, 99, 0, 0, 0, 0, 0, 60, 4, 71, 2, 0, 99, 99, 99, 66, 99, 99, 99, 0, 0, 0, 0, 0, 51, 4, 90, 0, 0, 82, 52, 23, 67, 99, 99, 0, 0, 0, 0, 0, 0, 60, 0, 99, 1, 26, 93, 72, 39, 57, 93, 99, 92, 0, 0, 0, 0, 0, 56, 8, 90, 0, 0, 80, 26, 18, 59, 99, 97, 0, 0, 0, 0, 0, 0, 60, 0, 99, 1, 10, 99, 99, 99, 99, 50, 50, 50, 50, 11, 13, 35, 0, 0, 0, 49, 12, 83, 46, 66, 65, 83, 32, 50, 55, 46, 55, 95, 90, 18, 32, 99, 50, 99, 99, 0, 0, 20, 0, 104, 0, 83, 10, 0, 95, 90, 18, 26, 99, 84, 99, 99, 0, 0, 20, 0, 8, 4, 94, 2, 0, 95, 90, 18, 32, 99, 50, 99, 99, 0, 0, 20, 0, 8, 15, 83, 14, 0, 95, 90, 18, 31, 99, 84, 99, 99, 0, 0, 20, 0, 112, 0, 94, 2, 0, 63, 15, 99, 28, 99, 0, 0, 0, 0, 0, 0, 0, 3, 0, 80, 0, 0, 63, 15, 99, 28, 99, 0, 0, 0, 0, 0, 0, 0, 83, 0, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 15, 14, 50, 44, 36, 99, 22, 36, 82, 69, 83, 79, 78, 65, 78, 67, 69, 83, 99, 39, 32, 71, 99, 98, 70, 0, 39, 0, 59, 3, 56, 0, 80, 0, 0, 99, 39, 32, 71, 99, 98, 70, 0, 39, 0, 0, 15, 64, 0, 99, 0, 0, 99, 39, 32, 71, 99, 98, 70, 0, 39, 0, 0, 3, 40, 0, 99, 0, 0, 99, 39, 32, 71, 99, 98, 70, 0, 39, 0, 0, 15, 32, 0, 99, 2, 0, 99, 39, 32, 46, 99, 98, 70, 0, 39, 0, 0, 15, 112, 4, 89, 0, 0, 99, 25, 25, 61, 99, 98, 70, 0, 39, 0, 0, 15, 112, 0, 99, 4, 0, 84, 95, 95, 60, 50, 50, 50, 50, 8, 14, 37, 0, 0, 0, 56, 12, 83, 89, 78, 45, 66, 65, 83, 83, 32, 50, 85, 16, 75, 61, 88, 44, 25, 0, 15, 0, 62, 4, 34, 24, 80, 16, 0, 85, 38, 75, 61, 88, 44, 25, 0, 48, 0, 0, 0, 58, 16, 86, 2, 0, 85, 28, 75, 61, 88, 44, 25, 0, 48, 0, 0, 0, 90, 16, 98, 0, 0, 98, 72, 75, 61, 99, 89, 99, 0, 32, 0, 0, 1, 51, 12, 99, 0, 0, 74, 28, 29, 61, 99, 71, 71, 0, 48, 0, 0, 0, 90, 8, 92, 0, 0, 98, 72, 75, 61, 99, 99, 99, 0, 32, 0, 0, 1, 64, 8, 99, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 7, 13, 30, 23, 0, 0, 40, 24, 80, 82, 67, 32, 83, 89, 78, 84, 72, 49, 99, 25, 25, 54, 99, 98, 90, 0, 31, 0, 99, 12, 115, 8, 80, 0, 0, 75, 25, 25, 34, 99, 96, 90, 0, 31, 99, 0, 3, 48, 8, 99, 2, 0, 99, 25, 25, 0, 99, 96, 96, 0, 43, 0, 99, 12, 0, 8, 99, 0, 0, 75, 25, 25, 39, 99, 96, 96, 0, 31, 99, 0, 3, 64, 8, 99, 1, 0, 99, 25, 25, 36, 99, 96, 96, 0, 31, 0, 99, 12, 112, 8, 99, 0, 0, 75, 25, 25, 39, 99, 96, 96, 0, 43, 99, 0, 3, 48, 0, 99, 1, 0, 99, 99, 99, 99, 50, 50, 50, 50, 5, 11, 35, 0, 0, 0, 39, 24, 67, 82, 79, 77, 65, 32, 50, 32, 32, 32, 60, 16, 42, 59, 99, 44, 30, 0, 49, 2, 0, 3, 112, 8, 47, 4, 0, 60, 32, 12, 61, 99, 80, 60, 0, 50, 0, 36, 3, 80, 12, 91, 4, 0, 88, 31, 29, 60, 99, 92, 60, 0, 53, 17, 0, 3, 113, 4, 60, 2, 0, 81, 39, 27, 60, 99, 74, 84, 0, 42, 0, 0, 0, 16, 13, 96, 2, 0, 61, 32, 23, 62, 99, 71, 39, 0, 46, 3, 35, 3, 16, 14, 91, 4, 0, 99, 57, 24, 61, 99, 94, 90, 0, 98, 0, 0, 15, 88, 9, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 11, 5, 42, 0, 0, 0, 49, 12, 65, 78, 65, 76, 79, 71, 32, 32, 52, 32, 99, 57, 24, 81, 99, 82, 58, 79, 45, 21, 17, 3, 112, 16, 61, 10, 0, 99, 50, 15, 41, 99, 72, 61, 87, 34, 0, 78, 7, 96, 20, 92, 6, 0, 99, 46, 22, 80, 99, 60, 57, 78, 53, 7, 2, 15, 88, 8, 91, 2, 0, 99, 30, 27, 67, 99, 99, 57, 0, 0, 0, 0, 0, 16, 4, 99, 2, 0, 90, 50, 48, 90, 99, 92, 42, 0, 57, 2, 17, 15, 16, 4, 80, 4, 0, 99, 27, 26, 73, 99, 96, 60, 0, 98, 99, 99, 15, 112, 4, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 8, 7, 35, 0, 0, 0, 49, 12, 65, 78, 65, 76, 79, 71, 32, 65, 32, 32, 99, 57, 42, 81, 99, 75, 53, 79, 15, 28, 99, 3, 112, 20, 69, 10, 0, 99, 32, 62, 41, 99, 39, 69, 87, 34, 48, 7, 7, 56, 20, 57, 4, 0, 99, 46, 22, 80, 99, 31, 89, 78, 53, 7, 41, 11, 56, 8, 91, 2, 0, 99, 39, 27, 67, 94, 99, 28, 0, 0, 0, 0, 0, 56, 8, 99, 2, 0, 99, 50, 23, 90, 99, 71, 71, 0, 99, 99, 99, 15, 112, 28, 99, 2, 0, 99, 57, 46, 73, 60, 94, 99, 0, 98, 99, 99, 15, 56, 8, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 7, 5, 35, 0, 0, 0, 49, 12, 65, 78, 65, 76, 79, 71, 32, 32, 54, 32, 99, 80, 80, 80, 99, 99, 99, 99, 39, 10, 15, 3, 96, 0, 76, 2, 0, 99, 80, 80, 80, 99, 99, 99, 99, 39, 5, 0, 3, 56, 8, 80, 1, 23, 99, 80, 80, 80, 99, 99, 99, 99, 0, 0, 0, 0, 56, 0, 75, 1, 0, 50, 80, 80, 40, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 99, 1, 32, 15, 80, 20, 30, 99, 92, 95, 0, 0, 0, 0, 0, 112, 4, 97, 2, 0, 80, 10, 99, 30, 99, 0, 0, 0, 0, 0, 0, 0, 32, 0, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 1, 11, 35, 50, 30, 0, 16, 12, 67, 83, 32, 56, 48, 32, 32, 32, 32, 32, 52, 42, 39, 25, 99, 99, 99, 0, 0, 0, 0, 0, 0, 0, 77, 4, 0, 52, 42, 39, 25, 99, 99, 99, 0, 0, 0, 0, 0, 116, 8, 77, 1, 0, 52, 42, 39, 25, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 50, 4, 0, 99, 42, 39, 25, 99, 88, 99, 0, 0, 0, 0, 0, 62, 4, 99, 4, 0, 35, 42, 39, 25, 99, 88, 89, 0, 0, 0, 0, 0, 96, 0, 81, 0, 0, 61, 42, 39, 25, 99, 99, 99, 0, 0, 0, 0, 0, 101, 16, 99, 0, 0, 99, 99, 99, 99, 50, 50, 50, 50, 6, 7, 26, 0, 5, 0, 49, 12, 73, 78, 83, 69, 82, 84, 32, 49, 32, 32, 99, 0, 0, 99, 99, 99, 99, 0, 0, 0, 0, 0, 5, 0, 30, 2, 0, 99, 42, 71, 34, 99, 99, 99, 0, 0, 0, 0, 0, 113, 0, 95, 2, 0, 81, 70, 9, 15, 99, 81, 0, 0, 0, 0, 0, 0, 62, 0, 91, 2, 50, 80, 49, 19, 30, 99, 91, 0, 0, 0, 0, 0, 0, 58, 0, 98, 0, 0, 99, 0, 0, 0, 39, 99, 99, 0, 0, 0, 0, 0, 103, 0, 88, 0, 0, 99, 42, 71, 35, 99, 99, 99, 0, 0, 0, 0, 0, 59, 0, 95, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 0, 15, 25, 15, 0, 0, 55, 36, 83, 80, 73, 82, 65, 76, 32, 32, 32, 32, 99, 99, 99, 7, 99, 99, 99, 0, 0, 0, 0, 0, 104, 0, 67, 6, 0, 69, 64, 39, 41, 99, 78, 94, 0, 0, 0, 0, 0, 72, 0, 99, 2, 0, 99, 99, 99, 99, 99, 99, 99, 0, 0, 0, 0, 0, 104, 0, 66, 4, 25, 99, 99, 99, 99, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 99, 0, 0, 98, 68, 99, 99, 99, 0, 0, 0, 0, 0, 0, 0, 56, 0, 58, 14, 0, 99, 99, 99, 41, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 99, 0, 0, 99, 99, 99, 99, 51, 50, 50, 50, 5, 15, 24, 0, 2, 0, 51, 24, 68, 88, 45, 84, 82, 79, 84, 84, 32, 32, 95, 82, 31, 35, 99, 95, 0, 0, 39, 99, 99, 11, 91, 16, 85, 10, 0, 95, 77, 55, 40, 99, 95, 0, 0, 39, 0, 40, 4, 27, 11, 99, 32, 0, 95, 84, 20, 25, 99, 0, 0, 0, 38, 0, 0, 10, 59, 4, 99, 22, 0, 96, 25, 25, 30, 99, 75, 0, 0, 38, 0, 0, 10, 59, 8, 99, 2, 0, 99, 46, 35, 0, 80, 75, 55, 0, 39, 99, 99, 8, 60, 8, 82, 24, 0, 95, 47, 30, 30, 99, 92, 0, 0, 2, 0, 0, 10, 59, 4, 99, 0, 0, 94, 67, 95, 60, 50, 50, 50, 50, 27, 7, 34, 0, 0, 0, 1, 24, 71, 65, 83, 72, 65, 85, 83, 32, 32, 32, 95, 46, 28, 24, 94, 70, 0, 0, 0, 0, 0, 0, 6, 5, 90, 42, 0, 95, 35, 99, 28, 99, 70, 0, 0, 51, 0, 35, 3, 92, 8, 79, 10, 0, 95, 32, 49, 33, 99, 70, 0, 0, 0, 0, 0, 0, 27, 0, 99, 6, 0, 95, 50, 44, 10, 99, 70, 0, 0, 58, 0, 37, 0, 11, 4, 77, 6, 0, 95, 46, 99, 12, 99, 70, 0, 0, 51, 8, 0, 3, 43, 8, 75, 0, 0, 95, 32, 45, 31, 99, 70, 0, 0, 0, 0, 0, 0, 99, 4, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 10, 14, 34, 33, 0, 0, 23, 12, 82, 73, 78, 71, 32, 68, 73, 78, 71, 32, 99, 99, 60, 80, 99, 99, 80, 90, 39, 0, 10, 0, 96, 16, 85, 22, 0, 75, 99, 50, 80, 99, 99, 90, 90, 0, 0, 0, 0, 112, 4, 80, 4, 0, 99, 99, 99, 70, 99, 99, 99, 0, 0, 0, 0, 0, 112, 0, 99, 2, 0, 99, 99, 60, 80, 99, 99, 80, 90, 39, 0, 10, 0, 16, 16, 90, 22, 0, 75, 99, 50, 80, 99, 99, 90, 90, 0, 0, 0, 0, 0, 4, 80, 4, 0, 99, 99, 99, 70, 99, 99, 99, 0, 0, 0, 0, 0, 0, 0, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 2, 8, 35, 0, 0, 0, 17, 12, 80, 65, 80, 65, 71, 65, 89, 79, 32, 32, 99, 62, 99, 52, 99, 32, 0, 0, 39, 12, 12, 12, 127, 12, 99, 36, 0, 80, 85, 24, 46, 99, 90, 0, 0, 0, 0, 0, 0, 115, 8, 99, 4, 0, 80, 85, 24, 35, 99, 90, 0, 0, 0, 0, 0, 0, 107, 28, 99, 8, 0, 80, 59, 43, 35, 99, 74, 0, 0, 39, 12, 12, 12, 60, 8, 99, 30, 0, 80, 85, 24, 35, 99, 90, 0, 0, 39, 4, 12, 12, 58, 4, 99, 8, 0, 99, 28, 99, 35, 99, 25, 0, 0, 39, 12, 12, 12, 58, 4, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 22, 13, 34, 39, 38, 0, 33, 24, 87, 73, 78, 69, 71, 76, 65, 83, 83, 32, 63, 99, 99, 99, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 90, 16, 11, 38, 99, 99, 99, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 70, 2, 0, 37, 99, 99, 57, 99, 99, 99, 0, 0, 0, 0, 0, 56, 2, 82, 0, 0, 55, 99, 99, 60, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 90, 28, 0, 31, 99, 99, 21, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 99, 0, 0, 99, 99, 99, 52, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 0, 12, 35, 0, 0, 99, 49, 0, 65, 77, 89, 84, 65, 76, 32, 32, 32, 32, 99, 99, 99, 0, 99, 99, 99, 0, 0, 0, 0, 0, 56, 28, 60, 62, 0, 99, 99, 99, 0, 99, 99, 99, 0, 0, 0, 15, 0, 56, 16, 80, 22, 0, 99, 99, 99, 0, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 70, 0, 0, 99, 80, 99, 99, 99, 0, 0, 0, 0, 0, 0, 0, 56, 28, 99, 63, 85, 99, 99, 99, 99, 99, 99, 99, 0, 0, 0, 15, 0, 56, 8, 99, 0, 0, 65, 99, 99, 46, 99, 99, 99, 0, 0, 0, 0, 0, 58, 0, 99, 1, 30, 99, 99, 99, 99, 50, 50, 50, 50, 17, 7, 35, 0, 30, 0, 22, 24, 70, 65, 73, 82, 76, 73, 71, 72, 84, 32, 94, 58, 0, 8, 99, 85, 75, 0, 38, 12, 54, 0, 112, 0, 53, 50, 0, 71, 15, 0, 15, 99, 69, 33, 64, 37, 17, 0, 0, 112, 0, 95, 0, 1, 99, 33, 0, 51, 99, 96, 0, 0, 40, 0, 8, 0, 64, 8, 99, 2, 1, 94, 58, 0, 8, 99, 85, 75, 0, 38, 17, 54, 0, 24, 0, 53, 50, 0, 71, 15, 0, 15, 99, 69, 33, 64, 37, 20, 0, 0, 8, 0, 96, 0, 1, 99, 33, 0, 51, 99, 96, 0, 0, 40, 0, 8, 0, 16, 8, 99, 2, 0, 99, 99, 43, 99, 50, 48, 50, 50, 3, 8, 50, 0, 29, 0, 25, 12, 42, 80, 80, 71, 42, 86, 111, 108, 46, 49, 80, 42, 38, 46, 99, 90, 0, 0, 51, 0, 17, 0, 56, 0, 63, 22, 1, 75, 24, 29, 6, 99, 89, 0, 0, 51, 0, 0, 0, 1, 4, 87, 0, 1, 57, 50, 56, 38, 99, 86, 99, 0, 17, 0, 0, 0, 43, 8, 99, 4, 1, 80, 42, 38, 46, 99, 90, 0, 0, 51, 0, 17, 0, 64, 0, 67, 22, 0, 75, 24, 29, 6, 99, 89, 0, 0, 51, 0, 0, 0, 41, 4, 87, 0, 0, 57, 50, 56, 38, 99, 86, 99, 0, 17, 0, 0, 0, 83, 8, 99, 4, 0, 0, 0, 0, 0, 50, 50, 50, 50, 2, 3, 19, 29, 35, 0, 24, 24, 42, 80, 80, 71, 42, 86, 111, 108, 46, 50, 80, 59, 24, 25, 99, 28, 0, 0, 0, 0, 0, 0, 57, 4, 99, 0, 0, 94, 52, 37, 17, 99, 86, 0, 0, 52, 0, 0, 0, 63, 12, 77, 38, 0, 90, 42, 7, 40, 90, 30, 0, 0, 0, 0, 0, 0, 61, 20, 93, 10, 0, 88, 96, 32, 42, 79, 65, 0, 0, 0, 0, 0, 0, 62, 12, 99, 0, 0, 99, 20, 0, 0, 99, 0, 0, 0, 41, 0, 0, 0, 63, 28, 99, 0, 0, 95, 62, 17, 39, 99, 95, 32, 0, 36, 57, 14, 3, 111, 0, 99, 0, 0, 94, 67, 95, 60, 50, 50, 50, 50, 15, 15, 35, 0, 0, 0, 48, 12, 42, 70, 97, 105, 114, 108, 46, 32, 51, 32, 65, 35, 32, 28, 98, 89, 89, 0, 0, 0, 0, 0, 56, 24, 67, 26, 0, 89, 37, 32, 28, 98, 0, 0, 0, 0, 0, 0, 0, 32, 0, 89, 0, 0, 75, 0, 87, 53, 99, 82, 94, 0, 0, 0, 0, 0, 88, 0, 71, 0, 1, 44, 56, 87, 75, 98, 75, 99, 0, 0, 0, 0, 0, 24, 0, 64, 1, 27, 75, 0, 87, 53, 99, 82, 94, 0, 0, 0, 0, 0, 0, 0, 92, 0, 1, 67, 56, 87, 75, 98, 99, 99, 0, 0, 0, 0, 0, 56, 0, 94, 1, 19, 94, 67, 95, 60, 50, 50, 50, 50, 15, 7, 25, 71, 0, 99, 32, 12, 42, 86, 111, 99, 111, 100, 101, 114, 32, 50, 76, 69, 14, 35, 99, 66, 0, 0, 32, 0, 0, 4, 88, 0, 67, 18, 1, 64, 32, 21, 39, 99, 78, 0, 0, 42, 0, 19, 0, 24, 8, 99, 0, 3, 84, 42, 25, 51, 99, 97, 0, 0, 35, 0, 0, 3, 80, 8, 99, 1, 14, 76, 69, 14, 35, 99, 66, 0, 0, 32, 0, 0, 4, 48, 4, 70, 18, 0, 64, 32, 21, 39, 99, 78, 0, 0, 42, 0, 19, 0, 72, 8, 99, 0, 1, 84, 42, 25, 51, 99, 97, 0, 0, 35, 0, 0, 3, 88, 8, 99, 1, 10, 94, 3, 95, 60, 50, 50, 50, 50, 2, 2, 40, 0, 6, 0, 72, 36, 42, 83, 101, 113, 117, 101, 110, 99, 101, 32, 68, 19, 2, 34, 99, 65, 50, 0, 44, 0, 0, 0, 70, 8, 99, 8, 0, 88, 35, 5, 14, 99, 83, 86, 0, 51, 0, 20, 0, 48, 0, 73, 1, 45, 58, 35, 0, 45, 99, 80, 80, 0, 51, 0, 0, 0, 64, 0, 80, 0, 50, 99, 99, 99, 55, 99, 99, 99, 0, 0, 0, 0, 0, 56, 8, 99, 0, 0, 89, 35, 0, 34, 99, 83, 92, 0, 51, 0, 0, 1, 72, 0, 99, 0, 0, 80, 99, 99, 66, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 99, 1, 0, 99, 99, 94, 62, 48, 50, 50, 50, 7, 14, 35, 65, 1, 0, 48, 36, 66, 111, 117, 110, 99, 101, 32, 52, 32, 32, // }; // const uint8_t syx_bank_1[] FLASHMEM = { 95, 29, 20, 50, 99, 95, 0, 0, 41, 0, 19, 0, 115, 24, 79, 2, 0, 95, 20, 20, 50, 99, 95, 0, 0, 0, 0, 0, 0, 3, 0, 99, 2, 0, 95, 29, 20, 50, 99, 95, 0, 0, 0, 0, 0, 0, 59, 24, 89, 2, 0, 95, 20, 20, 50, 99, 95, 0, 0, 0, 0, 0, 0, 59, 8, 99, 2, 0, 95, 50, 35, 78, 99, 75, 0, 0, 0, 0, 0, 0, 59, 28, 58, 28, 0, 96, 25, 25, 67, 99, 75, 0, 0, 0, 0, 0, 0, 83, 8, 99, 2, 0, 94, 67, 95, 60, 50, 50, 50, 50, 4, 6, 34, 33, 0, 0, 56, 24, 69, 46, 80, 73, 65, 78, 79, 32, 49, 32, 95, 29, 20, 50, 99, 95, 0, 0, 41, 0, 19, 12, 115, 24, 81, 2, 0, 95, 20, 20, 50, 99, 95, 0, 0, 0, 0, 0, 0, 3, 0, 99, 2, 0, 95, 25, 20, 50, 99, 95, 0, 0, 0, 0, 0, 0, 59, 24, 92, 2, 0, 95, 20, 20, 50, 99, 95, 0, 0, 0, 0, 0, 0, 59, 8, 99, 4, 0, 95, 50, 35, 78, 99, 75, 0, 0, 0, 0, 0, 0, 59, 28, 75, 42, 0, 96, 25, 25, 67, 99, 75, 0, 0, 0, 0, 0, 0, 80, 8, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 4, 14, 34, 33, 0, 0, 54, 12, 70, 69, 78, 68, 69, 82, 32, 49, 32, 32, 95, 29, 59, 50, 99, 95, 0, 0, 41, 0, 19, 0, 99, 28, 39, 10, 80, 99, 99, 20, 50, 73, 96, 0, 0, 98, 99, 0, 2, 67, 0, 99, 2, 0, 95, 29, 20, 50, 99, 95, 0, 0, 99, 99, 0, 3, 63, 28, 85, 2, 0, 99, 20, 20, 50, 99, 95, 0, 0, 54, 87, 0, 2, 3, 8, 99, 2, 0, 99, 50, 35, 99, 94, 75, 0, 0, 99, 20, 0, 2, 7, 20, 99, 24, 25, 93, 25, 25, 67, 99, 75, 0, 0, 27, 99, 0, 0, 93, 28, 99, 4, 50, 94, 67, 95, 60, 50, 50, 50, 50, 5, 6, 34, 33, 0, 0, 8, 12, 87, 73, 78, 84, 82, 72, 79, 68, 69, 83, 95, 39, 20, 50, 99, 73, 0, 0, 41, 0, 19, 0, 115, 12, 60, 2, 0, 95, 22, 20, 50, 99, 99, 0, 0, 0, 0, 0, 0, 83, 12, 99, 2, 0, 95, 22, 20, 50, 99, 99, 0, 0, 0, 0, 0, 0, 59, 0, 74, 2, 0, 95, 26, 20, 50, 99, 99, 0, 0, 0, 0, 0, 0, 59, 20, 99, 2, 0, 99, 46, 35, 78, 99, 80, 0, 0, 0, 0, 0, 0, 51, 16, 67, 32, 0, 99, 41, 25, 67, 99, 99, 0, 0, 0, 0, 0, 0, 59, 12, 99, 2, 0, 98, 98, 98, 98, 50, 50, 50, 50, 4, 14, 34, 33, 0, 99, 24, 24, 82, 83, 45, 69, 80, 32, 67, 32, 32, 32, 42, 51, 79, 50, 99, 16, 0, 0, 60, 0, 92, 0, 56, 8, 53, 18, 17, 77, 84, 79, 0, 99, 0, 0, 0, 46, 27, 0, 8, 59, 12, 95, 23, 5, 78, 26, 42, 67, 99, 21, 0, 0, 32, 55, 23, 0, 58, 20, 99, 2, 0, 75, 20, 25, 67, 99, 75, 0, 0, 37, 0, 59, 0, 47, 28, 66, 10, 0, 75, 20, 21, 68, 99, 99, 0, 0, 48, 0, 70, 0, 59, 20, 87, 2, 0, 75, 20, 21, 49, 99, 99, 0, 2, 91, 0, 67, 0, 59, 12, 99, 2, 0, 24, 12, 19, 59, 50, 50, 50, 50, 9, 8, 34, 33, 24, 12, 8, 12, 42, 77, 97, 114, 107, 32, 73, 73, 73, 32, 85, 38, 75, 61, 88, 44, 25, 0, 0, 0, 0, 0, 38, 28, 98, 28, 0, 85, 38, 75, 61, 88, 44, 25, 0, 0, 0, 0, 0, 58, 28, 67, 18, 0, 73, 35, 25, 61, 99, 93, 0, 0, 0, 0, 0, 0, 91, 28, 84, 2, 0, 73, 35, 25, 61, 99, 93, 0, 0, 0, 0, 0, 0, 51, 4, 99, 2, 0, 76, 64, 37, 61, 99, 94, 0, 0, 0, 0, 0, 0, 93, 12, 70, 20, 4, 73, 35, 25, 61, 99, 93, 0, 0, 0, 0, 0, 0, 67, 8, 99, 2, 0, 98, 98, 98, 98, 50, 50, 50, 50, 8, 15, 35, 23, 0, 0, 40, 24, 67, 76, 65, 86, 45, 69, 46, 80, 78, 79, 98, 26, 26, 27, 98, 0, 0, 0, 0, 0, 0, 0, 59, 4, 74, 30, 0, 99, 50, 26, 19, 99, 0, 0, 0, 0, 0, 0, 0, 56, 4, 73, 6, 0, 99, 49, 17, 30, 99, 75, 0, 0, 0, 0, 0, 0, 63, 0, 61, 12, 0, 99, 19, 26, 23, 99, 72, 0, 0, 0, 0, 0, 0, 35, 0, 83, 0, 0, 99, 76, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 81, 0, 79, 23, 71, 92, 16, 98, 33, 99, 0, 0, 0, 0, 0, 0, 0, 59, 4, 99, 0, 0, 82, 98, 75, 60, 50, 51, 50, 50, 16, 12, 0, 0, 38, 0, 23, 24, 83, 89, 78, 45, 67, 76, 65, 86, 32, 32, 98, 87, 0, 0, 87, 86, 0, 0, 32, 0, 21, 0, 59, 31, 77, 48, 0, 95, 95, 0, 0, 99, 96, 89, 0, 32, 0, 0, 0, 43, 24, 99, 0, 0, 95, 92, 28, 60, 99, 90, 0, 0, 32, 0, 0, 0, 59, 11, 99, 4, 0, 98, 87, 0, 0, 87, 86, 0, 0, 32, 0, 21, 0, 59, 4, 71, 2, 0, 95, 95, 0, 0, 99, 96, 89, 0, 32, 0, 0, 0, 51, 7, 99, 4, 0, 95, 92, 28, 60, 99, 90, 0, 0, 32, 0, 0, 0, 67, 12, 99, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 2, 13, 50, 0, 0, 0, 11, 24, 67, 76, 65, 86, 73, 78, 69, 84, 32, 32, 94, 1, 33, 12, 4, 19, 0, 0, 53, 0, 38, 0, 58, 4, 67, 10, 0, 98, 20, 6, 2, 91, 90, 0, 0, 36, 0, 0, 15, 58, 4, 75, 2, 0, 70, 30, 23, 50, 99, 85, 0, 0, 32, 0, 0, 0, 60, 12, 99, 2, 0, 94, 21, 33, 12, 74, 19, 0, 0, 38, 0, 20, 0, 59, 28, 92, 6, 0, 98, 36, 6, 32, 91, 90, 0, 0, 50, 22, 50, 3, 58, 4, 72, 2, 0, 70, 30, 23, 50, 99, 85, 0, 0, 32, 0, 0, 0, 60, 12, 99, 2, 0, 0, 0, 0, 0, 50, 50, 50, 50, 2, 14, 30, 0, 0, 0, 32, 24, 80, 73, 65, 78, 79, 32, 32, 32, 53, 32, 97, 27, 20, 50, 99, 85, 0, 0, 41, 21, 90, 3, 67, 8, 71, 10, 0, 97, 27, 10, 25, 99, 86, 48, 0, 0, 0, 0, 0, 51, 8, 78, 2, 0, 88, 25, 28, 50, 99, 86, 0, 0, 0, 0, 99, 8, 58, 8, 99, 2, 0, 81, 25, 25, 14, 99, 99, 99, 0, 35, 17, 60, 3, 58, 8, 69, 8, 0, 99, 0, 25, 0, 99, 75, 0, 0, 0, 0, 14, 0, 74, 0, 89, 2, 0, 88, 25, 24, 48, 99, 93, 0, 0, 0, 0, 99, 8, 42, 8, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 10, 13, 35, 0, 0, 0, 48, 12, 71, 82, 68, 32, 80, 73, 65, 78, 79, 49, 99, 29, 22, 4, 99, 95, 0, 0, 22, 4, 12, 3, 60, 12, 88, 6, 0, 99, 53, 19, 35, 99, 94, 0, 0, 0, 0, 5, 0, 25, 8, 76, 2, 0, 99, 51, 18, 51, 99, 94, 0, 0, 0, 0, 0, 0, 66, 4, 94, 2, 0, 99, 24, 22, 4, 99, 91, 4, 0, 22, 3, 32, 3, 27, 12, 88, 8, 0, 99, 38, 17, 35, 95, 0, 99, 0, 0, 0, 3, 12, 65, 8, 80, 2, 0, 99, 32, 18, 51, 99, 96, 0, 0, 0, 0, 0, 0, 11, 8, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 2, 12, 35, 0, 0, 0, 1, 12, 83, 84, 69, 73, 78, 87, 65, 89, 32, 32, 78, 73, 32, 46, 99, 71, 0, 90, 46, 0, 0, 3, 63, 12, 66, 7, 69, 74, 25, 24, 99, 99, 63, 0, 99, 62, 9, 36, 3, 60, 8, 76, 10, 0, 71, 16, 24, 35, 99, 27, 51, 0, 34, 11, 0, 7, 43, 4, 78, 6, 0, 71, 42, 24, 50, 99, 90, 0, 0, 25, 0, 0, 10, 61, 24, 99, 2, 0, 99, 49, 44, 70, 0, 0, 0, 99, 41, 0, 0, 0, 72, 0, 99, 22, 21, 75, 62, 24, 59, 99, 27, 0, 0, 25, 0, 13, 0, 57, 8, 99, 5, 13, 77, 98, 75, 60, 51, 50, 50, 49, 14, 13, 34, 85, 0, 0, 23, 24, 71, 85, 73, 84, 32, 65, 67, 79, 85, 83, 99, 41, 26, 10, 99, 98, 0, 0, 15, 0, 0, 4, 66, 12, 37, 18, 0, 99, 77, 26, 7, 99, 98, 0, 0, 15, 0, 0, 4, 18, 8, 87, 2, 0, 99, 41, 42, 7, 99, 98, 0, 0, 15, 0, 0, 4, 34, 4, 90, 14, 0, 99, 77, 26, 28, 99, 98, 0, 0, 15, 0, 0, 4, 58, 8, 91, 2, 0, 99, 41, 26, 7, 99, 98, 0, 0, 15, 0, 0, 4, 58, 8, 97, 2, 0, 99, 77, 26, 42, 99, 98, 0, 0, 15, 0, 0, 4, 58, 4, 73, 40, 0, 99, 99, 99, 99, 50, 50, 50, 50, 7, 8, 28, 0, 0, 0, 32, 24, 83, 73, 84, 65, 82, 32, 32, 32, 32, 32, 82, 53, 37, 48, 99, 81, 0, 0, 0, 0, 5, 0, 62, 4, 81, 6, 0, 91, 37, 29, 29, 99, 90, 0, 0, 0, 0, 5, 0, 62, 4, 83, 8, 0, 90, 28, 17, 39, 99, 76, 0, 0, 10, 0, 17, 4, 62, 4, 82, 2, 0, 94, 64, 30, 33, 99, 92, 0, 0, 0, 0, 0, 0, 61, 12, 99, 2, 0, 99, 68, 28, 48, 99, 83, 0, 0, 0, 0, 10, 0, 62, 0, 99, 8, 0, 94, 62, 58, 34, 99, 92, 0, 0, 0, 0, 0, 0, 62, 12, 90, 2, 0, 85, 99, 75, 0, 49, 50, 50, 50, 1, 15, 30, 40, 17, 15, 41, 24, 75, 79, 84, 79, 32, 32, 32, 32, 32, 32, 95, 72, 71, 99, 99, 97, 91, 98, 64, 0, 55, 0, 57, 0, 87, 12, 0, 95, 28, 27, 47, 99, 90, 0, 0, 49, 0, 0, 0, 51, 12, 83, 8, 0, 95, 72, 71, 99, 99, 97, 91, 98, 64, 0, 46, 0, 57, 0, 99, 6, 0, 95, 28, 27, 47, 99, 90, 0, 0, 49, 0, 0, 0, 51, 8, 85, 2, 0, 95, 72, 71, 99, 99, 97, 91, 98, 49, 0, 0, 0, 57, 0, 99, 0, 0, 95, 28, 27, 47, 99, 90, 0, 0, 49, 0, 0, 0, 59, 8, 89, 8, 0, 0, 0, 0, 0, 50, 50, 50, 50, 4, 25, 35, 0, 0, 0, 6, 24, 72, 65, 82, 80, 83, 73, 67, 72, 32, 49, 93, 5, 17, 30, 76, 51, 0, 0, 10, 32, 0, 4, 82, 4, 67, 24, 0, 99, 42, 15, 99, 99, 61, 0, 0, 10, 0, 0, 4, 56, 8, 91, 0, 0, 95, 99, 23, 84, 99, 99, 0, 0, 0, 0, 0, 4, 63, 12, 99, 4, 0, 95, 17, 17, 66, 99, 95, 0, 0, 38, 98, 98, 6, 56, 16, 77, 6, 0, 99, 39, 21, 30, 99, 85, 0, 0, 0, 0, 0, 4, 112, 8, 93, 0, 0, 80, 32, 18, 66, 99, 95, 0, 0, 0, 0, 0, 0, 60, 12, 99, 0, 0, 99, 98, 75, 60, 50, 50, 50, 50, 3, 0, 35, 30, 0, 0, 32, 24, 67, 76, 65, 86, 32, 32, 32, 32, 51, 32, 0, 81, 55, 0, 78, 78, 0, 0, 41, 0, 0, 0, 56, 20, 75, 8, 0, 99, 86, 55, 0, 96, 78, 0, 0, 41, 0, 0, 0, 56, 8, 79, 0, 0, 99, 73, 0, 14, 82, 48, 0, 0, 54, 0, 46, 0, 56, 8, 94, 6, 0, 95, 50, 49, 41, 99, 92, 0, 0, 0, 0, 0, 0, 59, 24, 99, 0, 0, 99, 71, 0, 0, 82, 48, 0, 0, 54, 0, 46, 0, 56, 8, 99, 6, 0, 95, 43, 49, 53, 99, 92, 0, 0, 0, 0, 0, 0, 58, 20, 99, 0, 0, 94, 67, 95, 60, 50, 50, 50, 50, 6, 8, 34, 33, 0, 0, 24, 48, 88, 89, 76, 79, 80, 72, 79, 78, 69, 32, 99, 77, 55, 0, 78, 78, 0, 0, 41, 0, 0, 0, 56, 16, 87, 14, 0, 99, 64, 0, 8, 82, 48, 0, 0, 54, 0, 46, 0, 56, 8, 97, 14, 0, 90, 75, 0, 82, 82, 48, 0, 0, 54, 0, 0, 0, 56, 20, 91, 14, 0, 99, 31, 50, 46, 99, 80, 0, 0, 0, 0, 0, 0, 59, 28, 99, 2, 0, 99, 33, 46, 50, 99, 80, 0, 0, 54, 0, 46, 0, 60, 24, 60, 10, 0, 99, 33, 50, 46, 99, 80, 0, 0, 0, 0, 0, 0, 59, 28, 99, 2, 0, 94, 67, 95, 60, 50, 50, 50, 50, 6, 15, 21, 0, 0, 0, 33, 24, 77, 65, 82, 73, 77, 66, 65, 32, 32, 32, 99, 48, 99, 50, 99, 32, 0, 0, 39, 12, 12, 12, 61, 28, 57, 28, 0, 80, 85, 24, 50, 99, 90, 42, 0, 9, 0, 0, 5, 115, 20, 99, 2, 0, 80, 85, 24, 50, 99, 90, 0, 0, 9, 0, 0, 5, 3, 4, 99, 2, 0, 80, 85, 43, 50, 99, 74, 0, 0, 39, 12, 12, 12, 60, 16, 72, 6, 0, 80, 85, 24, 50, 99, 90, 0, 0, 39, 4, 12, 12, 58, 4, 99, 2, 0, 99, 28, 99, 50, 99, 25, 0, 0, 39, 12, 12, 12, 58, 28, 50, 8, 0, 99, 98, 75, 60, 50, 50, 50, 50, 22, 13, 26, 0, 0, 0, 33, 24, 86, 73, 66, 69, 32, 32, 32, 32, 49, 32, 94, 56, 24, 55, 96, 78, 0, 0, 0, 0, 0, 0, 57, 20, 72, 32, 0, 99, 69, 0, 96, 99, 0, 0, 0, 68, 97, 0, 0, 56, 20, 69, 8, 0, 99, 71, 0, 97, 82, 48, 0, 0, 48, 74, 46, 0, 56, 20, 97, 16, 0, 95, 60, 49, 38, 99, 81, 0, 0, 34, 0, 0, 0, 60, 28, 99, 2, 0, 99, 46, 35, 0, 80, 75, 67, 0, 54, 0, 0, 0, 60, 8, 82, 16, 0, 95, 47, 30, 47, 99, 92, 0, 0, 0, 0, 0, 0, 59, 4, 99, 2, 0, 94, 67, 95, 60, 50, 50, 50, 50, 6, 15, 34, 33, 0, 0, 40, 36, 71, 76, 79, 75, 69, 78, 83, 80, 76, 32, 99, 58, 99, 51, 99, 85, 81, 0, 46, 13, 79, 12, 63, 20, 77, 47, 37, 99, 45, 21, 22, 99, 76, 45, 0, 51, 0, 0, 0, 44, 20, 80, 18, 33, 99, 21, 26, 14, 99, 26, 0, 0, 0, 0, 0, 0, 59, 12, 75, 9, 53, 99, 42, 47, 19, 99, 85, 0, 0, 44, 11, 0, 0, 61, 16, 64, 27, 99, 90, 40, 21, 16, 99, 73, 50, 0, 46, 7, 0, 3, 115, 20, 74, 14, 0, 99, 15, 28, 25, 99, 67, 0, 0, 0, 0, 0, 0, 61, 8, 99, 4, 0, 37, 50, 50, 50, 50, 50, 50, 50, 6, 7, 35, 0, 0, 0, 49, 24, 66, 69, 76, 76, 32, 67, 32, 32, 32, 32, 94, 28, 99, 23, 99, 25, 0, 0, 28, 12, 0, 12, 64, 0, 74, 6, 5, 94, 28, 99, 21, 99, 25, 0, 0, 28, 12, 12, 12, 114, 0, 48, 0, 0, 94, 28, 15, 25, 99, 25, 0, 0, 28, 12, 0, 12, 0, 0, 79, 2, 18, 94, 28, 99, 29, 99, 25, 0, 0, 28, 12, 0, 12, 56, 0, 81, 6, 5, 94, 28, 99, 29, 99, 25, 0, 0, 28, 12, 0, 12, 56, 0, 93, 2, 18, 94, 28, 99, 29, 99, 25, 0, 0, 28, 12, 0, 12, 56, 8, 99, 0, 0, 97, 94, 75, 60, 49, 51, 50, 50, 26, 5, 14, 14, 0, 0, 16, 12, 66, 69, 76, 76, 83, 32, 32, 32, 32, 32, 98, 91, 0, 28, 99, 0, 0, 0, 0, 0, 0, 0, 2, 0, 85, 4, 0, 76, 78, 71, 70, 99, 0, 0, 0, 0, 0, 0, 0, 58, 20, 99, 5, 51, 98, 12, 71, 28, 99, 0, 32, 0, 0, 0, 0, 0, 42, 0, 75, 4, 75, 95, 33, 71, 25, 99, 0, 32, 0, 0, 0, 0, 0, 18, 0, 99, 2, 0, 98, 12, 71, 28, 99, 0, 32, 0, 0, 0, 0, 0, 82, 0, 78, 4, 75, 95, 33, 71, 25, 99, 0, 32, 0, 0, 0, 0, 0, 74, 0, 95, 2, 0, 67, 95, 95, 60, 50, 50, 50, 50, 4, 7, 35, 0, 0, 0, 18, 24, 84, 85, 66, 32, 66, 69, 76, 76, 83, 32, 40, 25, 7, 16, 86, 96, 0, 0, 0, 0, 0, 0, 56, 8, 65, 24, 20, 43, 30, 15, 10, 95, 87, 0, 0, 0, 0, 0, 0, 56, 28, 67, 8, 40, 79, 30, 15, 24, 95, 87, 0, 0, 0, 0, 0, 0, 56, 8, 65, 6, 26, 36, 30, 50, 24, 95, 87, 0, 0, 0, 0, 0, 0, 56, 4, 63, 14, 32, 29, 42, 20, 18, 99, 85, 41, 0, 0, 0, 0, 0, 57, 8, 56, 2, 0, 79, 26, 20, 41, 99, 95, 41, 0, 0, 0, 0, 0, 56, 4, 99, 2, 0, 99, 98, 75, 60, 50, 50, 50, 50, 16, 15, 35, 89, 0, 0, 89, 12, 71, 79, 78, 71, 32, 32, 32, 32, 50, 32, 98, 2, 26, 28, 98, 0, 0, 0, 41, 0, 24, 0, 60, 4, 73, 0, 56, 99, 50, 26, 20, 99, 0, 0, 0, 74, 0, 0, 10, 56, 4, 78, 0, 0, 65, 31, 17, 29, 99, 75, 0, 0, 41, 0, 15, 3, 59, 12, 91, 0, 75, 99, 77, 26, 24, 99, 72, 0, 0, 2, 0, 0, 10, 35, 8, 93, 0, 36, 99, 76, 26, 22, 99, 72, 0, 0, 50, 0, 0, 10, 63, 4, 82, 0, 0, 91, 36, 98, 34, 99, 0, 0, 0, 2, 0, 0, 10, 59, 8, 99, 0, 0, 98, 98, 75, 98, 50, 51, 50, 50, 15, 15, 11, 0, 16, 0, 32, 12, 75, 69, 84, 84, 76, 69, 32, 54, 32, 32, 93, 72, 25, 72, 96, 39, 0, 0, 38, 0, 0, 10, 56, 0, 99, 37, 69, 90, 42, 54, 44, 99, 90, 0, 0, 38, 0, 0, 10, 59, 0, 99, 0, 0, 93, 72, 25, 65, 96, 39, 0, 0, 38, 0, 0, 10, 56, 0, 99, 13, 69, 90, 42, 54, 46, 99, 90, 0, 0, 38, 0, 0, 10, 59, 0, 99, 0, 0, 93, 72, 25, 70, 96, 39, 0, 0, 38, 0, 0, 10, 56, 0, 99, 53, 78, 90, 42, 54, 44, 99, 90, 0, 0, 38, 0, 0, 10, 59, 0, 99, 0, 0, 98, 98, 98, 98, 50, 50, 50, 50, 5, 11, 15, 0, 38, 0, 115, 24, 77, 73, 68, 32, 68, 82, 77, 32, 51, 32, 89, 85, 81, 88, 99, 83, 0, 0, 26, 0, 0, 10, 58, 0, 98, 0, 75, 83, 80, 71, 99, 99, 99, 0, 0, 26, 0, 0, 10, 56, 0, 75, 5, 67, 94, 71, 50, 85, 99, 90, 0, 0, 2, 0, 0, 10, 59, 0, 99, 2, 67, 76, 85, 39, 46, 97, 80, 0, 0, 2, 0, 0, 10, 57, 0, 71, 2, 85, 82, 49, 43, 58, 99, 0, 0, 0, 2, 0, 0, 10, 61, 0, 89, 1, 42, 84, 46, 77, 53, 99, 32, 0, 0, 2, 0, 0, 10, 58, 0, 99, 0, 51, 75, 29, 98, 98, 52, 50, 50, 50, 3, 15, 35, 0, 0, 0, 1, 29, 79, 82, 73, 32, 68, 82, 85, 77, 32, 49, 99, 75, 54, 71, 99, 86, 0, 0, 2, 0, 0, 10, 57, 0, 77, 4, 65, 99, 57, 53, 54, 99, 72, 0, 0, 2, 0, 0, 10, 59, 0, 99, 2, 0, 99, 80, 50, 51, 99, 75, 0, 0, 2, 0, 0, 10, 58, 0, 89, 2, 80, 99, 54, 71, 70, 99, 72, 0, 0, 2, 0, 0, 10, 58, 0, 99, 2, 0, 99, 80, 50, 49, 99, 75, 0, 0, 2, 0, 0, 10, 58, 0, 85, 8, 60, 99, 54, 60, 59, 99, 90, 0, 0, 2, 0, 0, 10, 58, 4, 99, 2, 0, 98, 98, 98, 98, 53, 51, 50, 50, 5, 14, 17, 33, 0, 0, 5, 24, 87, 79, 79, 68, 32, 54, 32, 32, 32, 32, 98, 20, 26, 22, 98, 0, 0, 0, 2, 0, 0, 10, 56, 8, 99, 62, 0, 99, 57, 26, 52, 99, 0, 0, 0, 74, 0, 0, 10, 56, 4, 64, 19, 99, 99, 99, 46, 46, 99, 99, 0, 0, 74, 0, 0, 10, 56, 4, 88, 45, 94, 99, 99, 40, 48, 99, 99, 0, 0, 2, 0, 0, 10, 56, 5, 95, 13, 72, 99, 28, 43, 32, 99, 60, 97, 0, 38, 0, 0, 10, 61, 1, 98, 37, 34, 99, 35, 52, 38, 99, 63, 0, 0, 2, 0, 0, 10, 61, 0, 95, 2, 42, 98, 98, 98, 98, 50, 50, 50, 50, 6, 15, 99, 0, 92, 0, 35, 24, 76, 65, 84, 78, 32, 68, 82, 77, 32, 52, 99, 99, 99, 20, 99, 0, 0, 0, 2, 0, 0, 10, 63, 0, 99, 49, 0, 99, 9, 20, 12, 99, 0, 0, 0, 2, 0, 0, 10, 63, 0, 99, 23, 51, 99, 46, 99, 30, 99, 0, 0, 0, 2, 0, 0, 10, 63, 0, 97, 51, 99, 99, 20, 20, 20, 99, 0, 0, 0, 2, 0, 0, 10, 56, 4, 99, 15, 92, 99, 16, 20, 14, 99, 0, 0, 0, 2, 0, 0, 10, 56, 4, 91, 7, 34, 99, 28, 41, 28, 99, 0, 0, 0, 2, 0, 0, 10, 58, 12, 99, 39, 21, 98, 98, 98, 98, 50, 50, 50, 50, 2, 15, 0, 0, 0, 0, 0, 24, 67, 73, 77, 66, 65, 76, 32, 32, 32, 32, 99, 26, 99, 64, 99, 0, 0, 0, 0, 0, 0, 0, 63, 28, 99, 2, 0, 99, 99, 99, 6, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 99, 62, 0, 99, 99, 99, 11, 99, 99, 99, 0, 0, 0, 0, 0, 58, 0, 99, 15, 60, 99, 53, 99, 53, 99, 0, 0, 0, 0, 0, 0, 0, 58, 28, 96, 1, 0, 99, 77, 91, 40, 99, 82, 0, 0, 0, 0, 0, 0, 63, 12, 99, 20, 0, 99, 26, 99, 55, 99, 0, 0, 0, 0, 0, 0, 0, 63, 28, 99, 2, 0, 99, 87, 99, 1, 50, 0, 0, 50, 27, 15, 35, 0, 0, 0, 49, 12, 83, 89, 78, 68, 77, 32, 50, 53, 46, 56, 99, 99, 99, 0, 99, 99, 99, 0, 32, 0, 0, 8, 56, 0, 99, 55, 57, 99, 78, 60, 50, 99, 89, 0, 0, 80, 0, 0, 7, 56, 4, 90, 0, 0, 95, 50, 42, 45, 99, 80, 0, 0, 56, 98, 98, 12, 59, 12, 99, 21, 20, 99, 80, 35, 57, 99, 90, 0, 0, 48, 0, 0, 4, 32, 4, 94, 33, 83, 95, 57, 0, 0, 99, 0, 0, 0, 41, 0, 0, 4, 80, 0, 98, 3, 0, 90, 50, 33, 62, 99, 0, 0, 0, 51, 98, 98, 3, 59, 0, 99, 27, 91, 99, 99, 75, 60, 50, 50, 50, 50, 2, 15, 55, 0, 0, 0, 6, 24, 66, 46, 68, 82, 77, 45, 83, 78, 65, 82, // }; // const uint8_t syx_bank_2[] FLASHMEM = { 97, 99, 85, 68, 99, 99, 0, 0, 56, 20, 0, 2, 56, 1, 66, 14, 7, 97, 99, 99, 68, 99, 99, 99, 0, 51, 0, 10, 0, 80, 0, 95, 2, 50, 96, 99, 99, 60, 99, 99, 99, 0, 63, 42, 0, 0, 56, 1, 99, 0, 50, 97, 99, 99, 68, 99, 99, 99, 0, 0, 0, 0, 0, 32, 0, 99, 2, 50, 97, 99, 99, 68, 99, 99, 99, 0, 0, 0, 0, 0, 0, 0, 99, 2, 0, 97, 99, 99, 68, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 23, 8, 32, 0, 6, 99, 17, 24, 67, 76, 73, 67, 75, 32, 49, 50, 52, 32, 96, 45, 0, 99, 99, 0, 0, 0, 38, 81, 34, 3, 56, 0, 99, 12, 0, 99, 85, 99, 99, 99, 0, 0, 0, 27, 83, 0, 0, 24, 0, 88, 12, 0, 97, 99, 98, 99, 99, 99, 99, 0, 48, 0, 80, 1, 8, 0, 42, 8, 52, 97, 99, 98, 99, 99, 99, 99, 0, 44, 85, 43, 3, 0, 0, 67, 6, 0, 97, 99, 98, 99, 99, 99, 99, 0, 55, 99, 58, 3, 56, 0, 89, 2, 1, 97, 99, 98, 99, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 99, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 29, 8, 35, 0, 0, 0, 1, 12, 42, 72, 97, 109, 109, 111, 110, 100, 32, 49, 99, 61, 99, 99, 99, 0, 0, 0, 39, 98, 0, 0, 56, 0, 75, 8, 0, 99, 99, 99, 98, 99, 99, 99, 0, 39, 0, 0, 0, 56, 0, 86, 4, 0, 99, 99, 99, 98, 99, 99, 99, 0, 39, 0, 0, 0, 56, 28, 71, 10, 0, 99, 99, 99, 98, 99, 99, 99, 0, 86, 98, 0, 15, 56, 28, 99, 4, 0, 99, 99, 99, 98, 99, 99, 99, 0, 39, 0, 0, 0, 64, 0, 99, 2, 0, 99, 99, 99, 98, 99, 99, 99, 0, 39, 0, 0, 0, 56, 0, 99, 0, 0, 99, 71, 95, 60, 50, 50, 50, 50, 28, 0, 33, 0, 0, 0, 40, 24, 69, 46, 79, 82, 71, 65, 78, 32, 51, 32, 99, 98, 10, 99, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 73, 2, 0, 99, 98, 10, 99, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 89, 6, 0, 99, 98, 10, 99, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 90, 6, 0, 99, 98, 10, 99, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 90, 6, 0, 99, 98, 10, 99, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 90, 4, 0, 99, 98, 10, 99, 99, 99, 99, 0, 0, 0, 0, 0, 56, 0, 91, 0, 100, 75, 80, 75, 60, 50, 50, 50, 50, 28, 14, 35, 14, 22, 0, 25, 24, 54, 48, 45, 83, 32, 79, 82, 71, 65, 78, 87, 90, 99, 99, 99, 0, 0, 0, 0, 0, 0, 0, 58, 11, 99, 18, 38, 99, 77, 30, 89, 99, 62, 99, 99, 38, 10, 56, 12, 56, 24, 68, 7, 32, 99, 68, 16, 57, 99, 90, 99, 0, 44, 0, 44, 0, 8, 8, 90, 8, 0, 96, 50, 16, 62, 99, 97, 99, 0, 0, 0, 0, 0, 58, 19, 99, 1, 21, 99, 68, 16, 90, 99, 87, 99, 94, 38, 0, 8, 0, 42, 8, 95, 2, 0, 96, 50, 16, 66, 99, 97, 99, 0, 0, 0, 0, 0, 74, 7, 99, 1, 1, 99, 99, 99, 99, 50, 50, 50, 49, 27, 14, 35, 0, 11, 0, 49, 12, 79, 80, 84, 73, 67, 32, 50, 56, 32, 32, 72, 25, 25, 70, 99, 99, 99, 0, 46, 10, 1, 12, 59, 8, 76, 20, 0, 61, 25, 25, 61, 99, 99, 93, 0, 0, 0, 0, 0, 59, 0, 97, 4, 0, 61, 25, 25, 50, 99, 99, 97, 0, 60, 10, 10, 0, 59, 0, 88, 8, 0, 99, 97, 62, 47, 99, 99, 90, 0, 46, 17, 40, 3, 61, 0, 75, 2, 0, 99, 97, 62, 47, 99, 99, 90, 0, 0, 0, 0, 0, 60, 0, 90, 0, 0, 45, 25, 25, 36, 99, 99, 98, 0, 41, 0, 50, 0, 61, 0, 99, 0, 0, 94, 67, 95, 60, 50, 50, 50, 50, 18, 15, 34, 33, 0, 0, 40, 12, 80, 73, 80, 69, 83, 32, 32, 32, 49, 32, 89, 80, 22, 65, 99, 99, 99, 0, 0, 0, 60, 4, 56, 0, 58, 8, 1, 88, 68, 22, 75, 60, 99, 99, 0, 0, 0, 50, 4, 56, 0, 80, 16, 1, 73, 80, 22, 50, 79, 99, 99, 0, 0, 0, 20, 0, 48, 0, 98, 4, 1, 76, 80, 22, 63, 99, 99, 99, 0, 35, 13, 15, 0, 60, 0, 87, 2, 1, 99, 99, 57, 64, 57, 52, 99, 0, 0, 0, 30, 0, 56, 0, 99, 8, 1, 77, 80, 74, 48, 99, 97, 99, 0, 35, 13, 10, 3, 58, 0, 99, 0, 0, 94, 3, 95, 60, 50, 50, 50, 50, 24, 3, 35, 63, 0, 0, 24, 24, 80, 73, 80, 69, 83, 32, 32, 32, 51, 32, 89, 80, 22, 65, 99, 99, 99, 0, 0, 0, 60, 4, 56, 0, 58, 8, 1, 88, 68, 22, 75, 70, 70, 70, 0, 78, 0, 5, 8, 56, 0, 84, 16, 1, 62, 80, 22, 50, 99, 99, 99, 0, 0, 0, 20, 0, 48, 0, 98, 4, 1, 47, 80, 22, 63, 99, 99, 99, 0, 35, 13, 15, 0, 60, 0, 97, 2, 1, 85, 30, 57, 64, 57, 75, 99, 0, 0, 0, 30, 0, 56, 0, 99, 8, 1, 53, 80, 41, 48, 99, 97, 99, 0, 35, 13, 10, 3, 58, 0, 99, 0, 0, 94, 3, 95, 60, 50, 50, 50, 50, 24, 3, 35, 63, 0, 0, 24, 24, 80, 73, 80, 69, 83, 32, 32, 32, 50, 32, 99, 99, 99, 0, 99, 99, 99, 99, 20, 0, 99, 0, 104, 29, 50, 1, 88, 52, 99, 99, 0, 98, 97, 97, 0, 48, 0, 20, 0, 40, 5, 90, 2, 1, 99, 99, 35, 0, 99, 85, 96, 90, 46, 90, 2, 14, 40, 5, 68, 2, 1, 50, 99, 99, 46, 99, 99, 99, 0, 26, 0, 6, 0, 104, 4, 99, 2, 0, 90, 90, 82, 40, 80, 94, 85, 80, 44, 76, 78, 3, 72, 14, 95, 2, 0, 52, 99, 99, 46, 99, 99, 99, 0, 15, 0, 33, 4, 104, 14, 99, 0, 99, 86, 90, 99, 99, 53, 52, 50, 50, 0, 7, 40, 30, 6, 8, 40, 24, 74, 88, 45, 51, 51, 45, 80, 32, 32, 32, 50, 76, 10, 20, 99, 92, 0, 0, 0, 0, 0, 0, 0, 3, 70, 12, 0, 42, 73, 10, 35, 98, 92, 0, 0, 0, 0, 0, 0, 112, 3, 65, 8, 0, 52, 74, 10, 20, 99, 98, 36, 0, 0, 0, 0, 0, 80, 0, 75, 4, 0, 42, 15, 15, 35, 99, 92, 32, 0, 0, 0, 0, 0, 104, 0, 99, 8, 0, 43, 13, 0, 20, 99, 92, 28, 0, 0, 0, 0, 0, 8, 3, 75, 4, 0, 70, 56, 10, 35, 98, 98, 35, 0, 0, 0, 0, 0, 32, 0, 99, 8, 0, 99, 99, 99, 99, 50, 50, 50, 50, 1, 15, 35, 0, 11, 0, 48, 12, 83, 79, 85, 78, 68, 84, 82, 65, 67, 75, 99, 38, 25, 41, 99, 71, 72, 0, 39, 0, 1, 15, 112, 4, 82, 6, 0, 99, 39, 25, 33, 99, 71, 64, 0, 39, 0, 0, 15, 112, 0, 76, 4, 0, 99, 76, 99, 47, 99, 88, 96, 0, 39, 0, 0, 15, 112, 0, 99, 2, 0, 99, 39, 25, 33, 99, 71, 64, 0, 39, 0, 1, 15, 56, 4, 83, 4, 0, 99, 38, 25, 36, 99, 72, 72, 0, 39, 0, 0, 15, 56, 0, 82, 2, 0, 99, 76, 99, 47, 99, 88, 96, 0, 39, 0, 0, 15, 56, 0, 99, 2, 0, 84, 95, 95, 60, 50, 50, 50, 50, 2, 14, 37, 0, 0, 0, 64, 24, 73, 67, 69, 32, 80, 65, 68, 32, 32, 50, 51, 22, 31, 41, 99, 92, 0, 0, 0, 0, 0, 11, 113, 7, 98, 4, 0, 91, 37, 36, 41, 99, 99, 0, 0, 0, 0, 0, 1, 3, 9, 83, 4, 0, 99, 22, 36, 40, 99, 91, 0, 0, 0, 0, 0, 1, 44, 16, 85, 0, 98, 91, 20, 8, 40, 99, 94, 0, 0, 0, 0, 0, 0, 93, 5, 99, 0, 98, 99, 43, 29, 37, 99, 86, 0, 0, 0, 0, 0, 12, 60, 16, 78, 22, 0, 92, 49, 6, 40, 99, 89, 0, 0, 0, 0, 0, 0, 26, 4, 99, 2, 0, 94, 67, 95, 60, 50, 50, 50, 50, 27, 2, 31, 11, 21, 63, 25, 24, 77, 49, 32, 80, 65, 68, 83, 32, 32, 32, 37, 32, 24, 28, 99, 96, 92, 0, 54, 0, 0, 0, 51, 4, 72, 22, 0, 37, 32, 24, 28, 99, 96, 92, 0, 54, 0, 0, 0, 57, 8, 59, 14, 0, 37, 32, 24, 28, 99, 96, 92, 0, 54, 0, 0, 0, 43, 8, 99, 2, 0, 99, 34, 20, 35, 99, 92, 84, 0, 49, 0, 0, 0, 2, 0, 61, 8, 0, 99, 46, 0, 28, 99, 93, 87, 0, 54, 0, 0, 0, 9, 8, 90, 4, 0, 47, 33, 20, 35, 99, 92, 84, 0, 49, 0, 0, 0, 2, 4, 99, 1, 28, 94, 67, 95, 60, 50, 50, 50, 50, 2, 7, 38, 33, 17, 71, 40, 12, 67, 65, 82, 76, 79, 83, 32, 32, 32, 50, 30, 41, 49, 40, 99, 0, 0, 0, 51, 99, 0, 0, 65, 3, 96, 2, 2, 79, 41, 99, 32, 99, 0, 0, 0, 51, 99, 0, 0, 57, 28, 99, 4, 0, 35, 99, 99, 40, 99, 99, 99, 0, 41, 0, 38, 5, 25, 0, 90, 8, 1, 35, 99, 99, 40, 99, 99, 99, 0, 41, 0, 38, 5, 25, 0, 97, 2, 1, 35, 99, 99, 40, 99, 99, 99, 0, 41, 0, 38, 5, 73, 0, 90, 8, 0, 35, 99, 99, 40, 99, 99, 99, 0, 41, 0, 38, 5, 57, 0, 94, 2, 0, 99, 99, 99, 99, 50, 50, 50, 50, 30, 5, 35, 50, 16, 10, 40, 24, 83, 79, 70, 84, 32, 84, 79, 85, 67, 72, 36, 25, 49, 31, 99, 68, 0, 0, 0, 0, 0, 0, 56, 8, 62, 32, 75, 37, 22, 22, 50, 99, 22, 15, 0, 0, 0, 0, 0, 104, 12, 99, 10, 0, 36, 36, 22, 44, 99, 42, 37, 0, 0, 0, 0, 0, 88, 1, 44, 56, 0, 42, 16, 33, 41, 99, 32, 0, 0, 0, 0, 5, 0, 48, 0, 99, 10, 0, 25, 24, 22, 27, 99, 66, 0, 0, 0, 0, 0, 0, 88, 0, 36, 30, 0, 35, 18, 22, 35, 99, 80, 43, 0, 0, 0, 0, 0, 0, 0, 99, 10, 0, 75, 80, 75, 60, 50, 50, 50, 50, 4, 12, 39, 0, 6, 38, 24, 19, 42, 80, 108, 97, 110, 101, 116, 115, 32, 32, 80, 25, 26, 12, 85, 99, 81, 0, 0, 0, 0, 0, 56, 0, 81, 2, 0, 45, 20, 95, 30, 70, 99, 99, 0, 0, 0, 0, 0, 56, 0, 99, 57, 13, 80, 16, 26, 25, 85, 99, 81, 0, 0, 0, 0, 0, 112, 0, 81, 2, 0, 45, 20, 95, 30, 70, 99, 99, 0, 0, 0, 0, 0, 56, 0, 99, 1, 8, 80, 16, 26, 25, 85, 99, 81, 0, 0, 0, 0, 0, 0, 0, 81, 2, 0, 45, 20, 95, 30, 70, 99, 99, 0, 0, 0, 0, 0, 56, 0, 99, 33, 0, 99, 99, 99, 99, 50, 50, 50, 50, 4, 8, 35, 0, 0, 0, 49, 12, 67, 73, 82, 82, 85, 83, 32, 32, 32, 32, 29, 22, 0, 37, 99, 0, 0, 0, 2, 0, 0, 10, 56, 0, 98, 2, 0, 50, 21, 0, 37, 99, 0, 0, 0, 2, 0, 0, 10, 56, 0, 99, 2, 0, 98, 12, 71, 29, 99, 0, 32, 0, 2, 0, 0, 10, 42, 0, 0, 4, 75, 95, 33, 71, 26, 99, 0, 32, 0, 2, 0, 0, 10, 18, 0, 0, 2, 0, 98, 12, 71, 29, 99, 0, 32, 1, 2, 0, 0, 10, 82, 0, 0, 4, 75, 95, 33, 71, 26, 99, 0, 32, 0, 2, 0, 0, 10, 74, 0, 0, 2, 0, 67, 95, 95, 60, 50, 50, 50, 50, 4, 4, 35, 0, 0, 0, 98, 24, 69, 78, 84, 82, 73, 88, 32, 32, 32, 32, 94, 28, 0, 99, 99, 99, 99, 0, 0, 0, 0, 0, 88, 0, 78, 0, 0, 28, 88, 0, 99, 99, 99, 0, 0, 0, 0, 0, 0, 112, 2, 99, 1, 0, 99, 28, 0, 99, 99, 99, 0, 0, 0, 0, 0, 0, 40, 0, 77, 0, 0, 28, 88, 0, 99, 99, 99, 99, 0, 0, 0, 0, 0, 72, 2, 99, 1, 0, 94, 28, 0, 99, 99, 99, 99, 0, 0, 0, 0, 0, 0, 0, 75, 0, 0, 28, 88, 0, 0, 99, 99, 99, 0, 0, 0, 0, 0, 24, 2, 99, 1, 0, 99, 99, 99, 99, 50, 50, 50, 50, 4, 5, 35, 35, 0, 0, 16, 24, 77, 65, 76, 32, 80, 79, 76, 89, 32, 32, 99, 16, 20, 20, 0, 75, 0, 86, 55, 0, 40, 0, 56, 4, 99, 4, 0, 65, 99, 21, 26, 99, 99, 99, 0, 43, 99, 0, 3, 113, 0, 94, 1, 0, 99, 25, 14, 24, 40, 83, 60, 99, 55, 0, 0, 0, 40, 4, 99, 0, 1, 70, 70, 50, 30, 99, 99, 99, 0, 43, 99, 0, 3, 56, 0, 92, 1, 37, 97, 10, 26, 20, 40, 99, 0, 86, 55, 0, 20, 0, 72, 4, 99, 2, 50, 50, 99, 16, 29, 99, 99, 35, 0, 43, 99, 0, 3, 57, 0, 92, 1, 21, 9, 4, 19, 62, 50, 50, 50, 50, 4, 3, 23, 0, 9, 50, 56, 24, 84, 101, 120, 116, 117, 114, 101, 115, 32, 54, 60, 45, 3, 35, 46, 91, 99, 91, 12, 0, 5, 0, 88, 4, 84, 2, 0, 67, 17, 7, 37, 99, 93, 28, 0, 31, 0, 7, 0, 80, 4, 99, 2, 0, 68, 64, 14, 50, 99, 78, 0, 73, 0, 0, 0, 0, 40, 8, 89, 18, 41, 55, 57, 35, 46, 99, 81, 0, 0, 0, 0, 4, 0, 48, 20, 92, 16, 0, 60, 45, 4, 34, 46, 89, 99, 89, 12, 0, 7, 0, 24, 4, 87, 2, 50, 61, 17, 7, 37, 99, 93, 28, 0, 31, 0, 11, 0, 32, 8, 99, 2, 50, 73, 67, 99, 99, 52, 49, 50, 50, 4, 14, 26, 32, 25, 0, 16, 24, 69, 116, 104, 101, 114, 105, 97, 108, 53, 97, 38, 11, 6, 21, 99, 82, 70, 0, 53, 0, 8, 0, 56, 12, 70, 8, 0, 39, 12, 14, 23, 99, 83, 0, 0, 60, 0, 14, 0, 56, 8, 68, 1, 65, 37, 13, 20, 25, 99, 83, 82, 0, 53, 0, 6, 0, 56, 12, 74, 2, 0, 38, 15, 15, 28, 99, 85, 0, 0, 53, 0, 13, 0, 56, 8, 68, 1, 51, 30, 17, 8, 30, 92, 80, 99, 0, 58, 0, 20, 0, 40, 0, 87, 0, 0, 58, 0, 0, 32, 99, 97, 95, 0, 0, 0, 0, 0, 56, 4, 99, 1, 0, 9, 4, 19, 62, 50, 50, 50, 50, 15, 7, 10, 0, 3, 0, 57, 36, 39, 65, 105, 114, 121, 39, 32, 32, 32, 32, 70, 27, 16, 51, 90, 99, 91, 0, 2, 0, 9, 10, 11, 0, 89, 4, 0, 70, 27, 16, 50, 90, 99, 91, 0, 2, 0, 4, 10, 11, 0, 73, 0, 0, 70, 27, 16, 47, 90, 99, 91, 0, 2, 0, 0, 10, 110, 0, 80, 0, 0, 64, 40, 23, 40, 99, 97, 94, 0, 2, 0, 0, 10, 119, 0, 99, 0, 0, 50, 26, 9, 40, 94, 99, 93, 0, 26, 0, 5, 10, 115, 0, 85, 0, 0, 65, 99, 99, 40, 99, 99, 99, 0, 2, 0, 0, 10, 44, 0, 99, 0, 0, 98, 98, 98, 98, 50, 50, 50, 50, 20, 14, 40, 0, 13, 0, 49, 24, 66, 79, 82, 79, 78, 32, 65, 32, 32, 32, 35, 0, 0, 0, 99, 99, 99, 0, 39, 60, 0, 6, 7, 3, 84, 0, 0, 32, 42, 71, 34, 99, 99, 99, 0, 51, 99, 0, 6, 59, 0, 99, 1, 0, 10, 0, 0, 0, 99, 99, 99, 0, 39, 99, 0, 6, 59, 0, 71, 0, 0, 35, 42, 71, 34, 99, 99, 99, 0, 51, 99, 0, 6, 59, 0, 99, 1, 0, 61, 99, 20, 0, 99, 98, 85, 0, 39, 99, 0, 6, 61, 0, 74, 0, 0, 37, 42, 71, 34, 99, 99, 99, 0, 51, 99, 0, 6, 59, 0, 99, 1, 0, 99, 99, 99, 99, 50, 50, 50, 50, 4, 15, 9, 0, 35, 0, 16, 24, 86, 65, 78, 71, 69, 76, 73, 83, 32, 49, 70, 27, 16, 31, 90, 99, 91, 0, 0, 0, 17, 0, 119, 0, 94, 4, 0, 70, 27, 16, 40, 90, 99, 91, 0, 0, 0, 0, 0, 8, 0, 74, 0, 0, 70, 27, 16, 39, 90, 99, 99, 0, 0, 0, 0, 0, 104, 0, 75, 0, 0, 64, 40, 23, 51, 99, 97, 94, 0, 0, 0, 0, 0, 112, 0, 99, 0, 0, 50, 26, 9, 36, 94, 99, 93, 0, 24, 0, 7, 0, 112, 0, 86, 0, 0, 65, 99, 99, 50, 99, 99, 99, 0, 0, 0, 0, 0, 40, 0, 99, 0, 0, 99, 99, 99, 99, 50, 50, 50, 50, 8, 14, 14, 0, 0, 0, 11, 24, 83, 84, 82, 73, 78, 71, 83, 32, 67, 32, 53, 64, 44, 54, 99, 92, 56, 0, 55, 25, 0, 3, 58, 8, 54, 28, 0, 53, 67, 38, 54, 86, 92, 74, 0, 0, 0, 0, 0, 58, 4, 84, 6, 0, 96, 19, 20, 54, 99, 92, 89, 0, 0, 0, 0, 0, 58, 8, 75, 2, 0, 50, 52, 35, 41, 99, 92, 91, 0, 51, 98, 60, 3, 58, 4, 99, 2, 0, 99, 71, 35, 51, 82, 92, 87, 0, 54, 0, 0, 0, 57, 0, 86, 2, 0, 52, 30, 25, 43, 99, 92, 90, 0, 0, 0, 0, 0, 58, 4, 99, 2, 0, 94, 67, 95, 60, 50, 50, 50, 50, 14, 15, 28, 46, 30, 0, 24, 12, 83, 84, 82, 73, 78, 71, 83, 32, 51, 32, 72, 76, 10, 32, 99, 92, 0, 0, 0, 0, 0, 0, 56, 0, 70, 16, 0, 76, 73, 10, 28, 99, 92, 0, 0, 0, 0, 0, 0, 56, 0, 66, 4, 0, 49, 74, 10, 32, 98, 98, 36, 0, 98, 0, 0, 0, 56, 0, 76, 4, 0, 51, 15, 10, 47, 99, 92, 0, 0, 0, 0, 0, 0, 104, 0, 92, 4, 0, 81, 13, 7, 25, 99, 92, 28, 0, 0, 0, 0, 0, 8, 0, 74, 4, 0, 48, 56, 10, 47, 98, 98, 36, 0, 98, 0, 0, 0, 56, 0, 92, 4, 0, 84, 95, 95, 60, 50, 50, 50, 50, 1, 15, 30, 81, 8, 0, 40, 12, 83, 84, 82, 73, 78, 71, 83, 32, 50, 32, 94, 31, 98, 20, 98, 1, 78, 0, 35, 10, 0, 0, 33, 4, 68, 2, 50, 46, 60, 40, 40, 87, 87, 93, 0, 0, 0, 0, 0, 56, 0, 79, 6, 0, 79, 68, 62, 40, 99, 99, 99, 0, 41, 87, 81, 5, 58, 4, 73, 2, 50, 48, 33, 40, 47, 99, 87, 89, 0, 0, 0, 0, 0, 80, 4, 96, 2, 50, 79, 68, 62, 40, 99, 99, 99, 0, 36, 98, 47, 5, 42, 4, 78, 2, 0, 56, 33, 40, 47, 99, 87, 89, 0, 0, 0, 0, 0, 80, 0, 99, 2, 0, 84, 95, 95, 60, 50, 50, 50, 50, 1, 7, 33, 35, 15, 0, 32, 24, 83, 84, 82, 73, 78, 71, 83, 32, 55, 32, 46, 25, 25, 36, 99, 96, 96, 0, 46, 0, 50, 0, 56, 0, 67, 10, 0, 46, 25, 25, 41, 99, 96, 96, 0, 0, 0, 0, 0, 56, 0, 67, 0, 0, 46, 25, 25, 35, 99, 96, 96, 0, 0, 0, 0, 0, 56, 0, 78, 2, 0, 46, 25, 25, 43, 99, 96, 96, 0, 0, 0, 0, 0, 114, 0, 99, 41, 32, 98, 0, 0, 0, 99, 99, 99, 0, 0, 0, 1, 0, 7, 0, 75, 4, 0, 41, 42, 71, 34, 99, 99, 99, 0, 0, 0, 0, 0, 115, 0, 99, 4, 0, 99, 99, 99, 99, 50, 50, 50, 50, 1, 15, 35, 0, 0, 0, 32, 12, 70, 85, 76, 76, 32, 83, 84, 82, 73, 78, 46, 25, 25, 35, 99, 96, 96, 0, 46, 0, 50, 0, 56, 0, 67, 10, 0, 46, 25, 25, 41, 99, 96, 96, 0, 0, 0, 0, 0, 56, 0, 67, 0, 98, 46, 25, 25, 43, 99, 96, 96, 0, 0, 0, 0, 0, 56, 0, 78, 2, 0, 46, 25, 25, 43, 99, 96, 96, 0, 0, 0, 0, 0, 114, 0, 99, 25, 32, 60, 25, 25, 28, 99, 96, 90, 0, 27, 10, 5, 0, 112, 0, 80, 4, 0, 80, 25, 25, 48, 99, 96, 90, 0, 46, 0, 10, 0, 48, 0, 99, 49, 1, 99, 99, 99, 99, 50, 50, 50, 50, 1, 7, 35, 33, 8, 0, 39, 12, 83, 89, 78, 45, 79, 82, 67, 72, 32, 32, 49, 99, 28, 68, 98, 98, 91, 0, 39, 54, 50, 5, 60, 8, 82, 2, 0, 77, 36, 41, 71, 99, 98, 98, 0, 39, 0, 0, 15, 64, 8, 98, 2, 0, 77, 36, 41, 71, 99, 98, 98, 0, 39, 0, 0, 15, 56, 8, 99, 2, 0, 77, 76, 82, 71, 99, 98, 98, 0, 39, 0, 0, 15, 40, 8, 99, 2, 0, 62, 51, 29, 71, 82, 95, 96, 0, 27, 0, 7, 7, 112, 0, 86, 0, 0, 72, 76, 99, 71, 99, 88, 96, 0, 39, 0, 14, 15, 112, 0, 98, 0, 0, 84, 95, 95, 60, 50, 50, 50, 50, 21, 15, 37, 0, 5, 0, 56, 24, 66, 82, 65, 83, 83, 32, 32, 32, 49, 32, 60, 61, 19, 70, 99, 98, 97, 0, 0, 0, 0, 0, 57, 7, 83, 2, 0, 68, 20, 20, 70, 99, 95, 95, 0, 0, 0, 0, 0, 58, 7, 99, 2, 0, 68, 20, 20, 70, 99, 95, 95, 0, 0, 0, 0, 0, 58, 7, 97, 2, 0, 68, 20, 20, 70, 99, 96, 95, 0, 0, 0, 0, 0, 58, 7, 99, 2, 0, 60, 15, 15, 70, 99, 90, 80, 0, 0, 0, 0, 0, 58, 7, 89, 2, 0, 68, 20, 20, 70, 99, 95, 95, 0, 0, 0, 0, 0, 58, 7, 99, 2, 0, 94, 67, 95, 60, 50, 50, 50, 50, 21, 15, 34, 33, 0, 0, 56, 24, 66, 82, 65, 83, 83, 32, 54, 32, 66, 67, 42, 56, 20, 70, 99, 0, 0, 0, 0, 0, 0, 0, 63, 12, 99, 14, 21, 48, 12, 22, 50, 99, 61, 61, 0, 0, 0, 0, 0, 53, 0, 50, 12, 4, 66, 76, 22, 50, 99, 61, 61, 0, 63, 0, 0, 0, 61, 16, 74, 2, 0, 41, 12, 22, 50, 99, 61, 61, 0, 0, 0, 0, 0, 61, 4, 79, 2, 0, 99, 12, 22, 50, 85, 0, 0, 0, 68, 0, 96, 4, 58, 28, 50, 4, 5, 70, 24, 19, 55, 99, 86, 86, 0, 0, 0, 0, 0, 58, 16, 99, 2, 0, 86, 67, 95, 60, 52, 50, 50, 50, 17, 15, 34, 45, 5, 0, 32, 24, 66, 82, 32, 84, 82, 85, 77, 80, 69, 84, }; const uint8_t* const fm_patches_table[] FLASHMEM = { syx_bank_0, syx_bank_0 + 4096, syx_bank_0 + 4096 * 2, }; const float lut_sine[] FLASHMEM = { 0.000000000e+00, 1.227153829e-02, 2.454122852e-02, 3.680722294e-02, 4.906767433e-02, 6.132073630e-02, 7.356456360e-02, 8.579731234e-02, 9.801714033e-02, 1.102222073e-01, 1.224106752e-01, 1.345807085e-01, 1.467304745e-01, 1.588581433e-01, 1.709618888e-01, 1.830398880e-01, 1.950903220e-01, 2.071113762e-01, 2.191012402e-01, 2.310581083e-01, 2.429801799e-01, 2.548656596e-01, 2.667127575e-01, 2.785196894e-01, 2.902846773e-01, 3.020059493e-01, 3.136817404e-01, 3.253102922e-01, 3.368898534e-01, 3.484186802e-01, 3.598950365e-01, 3.713171940e-01, 3.826834324e-01, 3.939920401e-01, 4.052413140e-01, 4.164295601e-01, 4.275550934e-01, 4.386162385e-01, 4.496113297e-01, 4.605387110e-01, 4.713967368e-01, 4.821837721e-01, 4.928981922e-01, 5.035383837e-01, 5.141027442e-01, 5.245896827e-01, 5.349976199e-01, 5.453249884e-01, 5.555702330e-01, 5.657318108e-01, 5.758081914e-01, 5.857978575e-01, 5.956993045e-01, 6.055110414e-01, 6.152315906e-01, 6.248594881e-01, 6.343932842e-01, 6.438315429e-01, 6.531728430e-01, 6.624157776e-01, 6.715589548e-01, 6.806009978e-01, 6.895405447e-01, 6.983762494e-01, 7.071067812e-01, 7.157308253e-01, 7.242470830e-01, 7.326542717e-01, 7.409511254e-01, 7.491363945e-01, 7.572088465e-01, 7.651672656e-01, 7.730104534e-01, 7.807372286e-01, 7.883464276e-01, 7.958369046e-01, 8.032075315e-01, 8.104571983e-01, 8.175848132e-01, 8.245893028e-01, 8.314696123e-01, 8.382247056e-01, 8.448535652e-01, 8.513551931e-01, 8.577286100e-01, 8.639728561e-01, 8.700869911e-01, 8.760700942e-01, 8.819212643e-01, 8.876396204e-01, 8.932243012e-01, 8.986744657e-01, 9.039892931e-01, 9.091679831e-01, 9.142097557e-01, 9.191138517e-01, 9.238795325e-01, 9.285060805e-01, 9.329927988e-01, 9.373390119e-01, 9.415440652e-01, 9.456073254e-01, 9.495281806e-01, 9.533060404e-01, 9.569403357e-01, 9.604305194e-01, 9.637760658e-01, 9.669764710e-01, 9.700312532e-01, 9.729399522e-01, 9.757021300e-01, 9.783173707e-01, 9.807852804e-01, 9.831054874e-01, 9.852776424e-01, 9.873014182e-01, 9.891765100e-01, 9.909026354e-01, 9.924795346e-01, 9.939069700e-01, 9.951847267e-01, 9.963126122e-01, 9.972904567e-01, 9.981181129e-01, 9.987954562e-01, 9.993223846e-01, 9.996988187e-01, 9.999247018e-01, 1.000000000e+00, 9.999247018e-01, 9.996988187e-01, 9.993223846e-01, 9.987954562e-01, 9.981181129e-01, 9.972904567e-01, 9.963126122e-01, 9.951847267e-01, 9.939069700e-01, 9.924795346e-01, 9.909026354e-01, 9.891765100e-01, 9.873014182e-01, 9.852776424e-01, 9.831054874e-01, 9.807852804e-01, 9.783173707e-01, 9.757021300e-01, 9.729399522e-01, 9.700312532e-01, 9.669764710e-01, 9.637760658e-01, 9.604305194e-01, 9.569403357e-01, 9.533060404e-01, 9.495281806e-01, 9.456073254e-01, 9.415440652e-01, 9.373390119e-01, 9.329927988e-01, 9.285060805e-01, 9.238795325e-01, 9.191138517e-01, 9.142097557e-01, 9.091679831e-01, 9.039892931e-01, 8.986744657e-01, 8.932243012e-01, 8.876396204e-01, 8.819212643e-01, 8.760700942e-01, 8.700869911e-01, 8.639728561e-01, 8.577286100e-01, 8.513551931e-01, 8.448535652e-01, 8.382247056e-01, 8.314696123e-01, 8.245893028e-01, 8.175848132e-01, 8.104571983e-01, 8.032075315e-01, 7.958369046e-01, 7.883464276e-01, 7.807372286e-01, 7.730104534e-01, 7.651672656e-01, 7.572088465e-01, 7.491363945e-01, 7.409511254e-01, 7.326542717e-01, 7.242470830e-01, 7.157308253e-01, 7.071067812e-01, 6.983762494e-01, 6.895405447e-01, 6.806009978e-01, 6.715589548e-01, 6.624157776e-01, 6.531728430e-01, 6.438315429e-01, 6.343932842e-01, 6.248594881e-01, 6.152315906e-01, 6.055110414e-01, 5.956993045e-01, 5.857978575e-01, 5.758081914e-01, 5.657318108e-01, 5.555702330e-01, 5.453249884e-01, 5.349976199e-01, 5.245896827e-01, 5.141027442e-01, 5.035383837e-01, 4.928981922e-01, 4.821837721e-01, 4.713967368e-01, 4.605387110e-01, 4.496113297e-01, 4.386162385e-01, 4.275550934e-01, 4.164295601e-01, 4.052413140e-01, 3.939920401e-01, 3.826834324e-01, 3.713171940e-01, 3.598950365e-01, 3.484186802e-01, 3.368898534e-01, 3.253102922e-01, 3.136817404e-01, 3.020059493e-01, 2.902846773e-01, 2.785196894e-01, 2.667127575e-01, 2.548656596e-01, 2.429801799e-01, 2.310581083e-01, 2.191012402e-01, 2.071113762e-01, 1.950903220e-01, 1.830398880e-01, 1.709618888e-01, 1.588581433e-01, 1.467304745e-01, 1.345807085e-01, 1.224106752e-01, 1.102222073e-01, 9.801714033e-02, 8.579731234e-02, 7.356456360e-02, 6.132073630e-02, 4.906767433e-02, 3.680722294e-02, 2.454122852e-02, 1.227153829e-02, 1.224646799e-16, -1.227153829e-02, -2.454122852e-02, -3.680722294e-02, -4.906767433e-02, -6.132073630e-02, -7.356456360e-02, -8.579731234e-02, -9.801714033e-02, -1.102222073e-01, -1.224106752e-01, -1.345807085e-01, -1.467304745e-01, -1.588581433e-01, -1.709618888e-01, -1.830398880e-01, -1.950903220e-01, -2.071113762e-01, -2.191012402e-01, -2.310581083e-01, -2.429801799e-01, -2.548656596e-01, -2.667127575e-01, -2.785196894e-01, -2.902846773e-01, -3.020059493e-01, -3.136817404e-01, -3.253102922e-01, -3.368898534e-01, -3.484186802e-01, -3.598950365e-01, -3.713171940e-01, -3.826834324e-01, -3.939920401e-01, -4.052413140e-01, -4.164295601e-01, -4.275550934e-01, -4.386162385e-01, -4.496113297e-01, -4.605387110e-01, -4.713967368e-01, -4.821837721e-01, -4.928981922e-01, -5.035383837e-01, -5.141027442e-01, -5.245896827e-01, -5.349976199e-01, -5.453249884e-01, -5.555702330e-01, -5.657318108e-01, -5.758081914e-01, -5.857978575e-01, -5.956993045e-01, -6.055110414e-01, -6.152315906e-01, -6.248594881e-01, -6.343932842e-01, -6.438315429e-01, -6.531728430e-01, -6.624157776e-01, -6.715589548e-01, -6.806009978e-01, -6.895405447e-01, -6.983762494e-01, -7.071067812e-01, -7.157308253e-01, -7.242470830e-01, -7.326542717e-01, -7.409511254e-01, -7.491363945e-01, -7.572088465e-01, -7.651672656e-01, -7.730104534e-01, -7.807372286e-01, -7.883464276e-01, -7.958369046e-01, -8.032075315e-01, -8.104571983e-01, -8.175848132e-01, -8.245893028e-01, -8.314696123e-01, -8.382247056e-01, -8.448535652e-01, -8.513551931e-01, -8.577286100e-01, -8.639728561e-01, -8.700869911e-01, -8.760700942e-01, -8.819212643e-01, -8.876396204e-01, -8.932243012e-01, -8.986744657e-01, -9.039892931e-01, -9.091679831e-01, -9.142097557e-01, -9.191138517e-01, -9.238795325e-01, -9.285060805e-01, -9.329927988e-01, -9.373390119e-01, -9.415440652e-01, -9.456073254e-01, -9.495281806e-01, -9.533060404e-01, -9.569403357e-01, -9.604305194e-01, -9.637760658e-01, -9.669764710e-01, -9.700312532e-01, -9.729399522e-01, -9.757021300e-01, -9.783173707e-01, -9.807852804e-01, -9.831054874e-01, -9.852776424e-01, -9.873014182e-01, -9.891765100e-01, -9.909026354e-01, -9.924795346e-01, -9.939069700e-01, -9.951847267e-01, -9.963126122e-01, -9.972904567e-01, -9.981181129e-01, -9.987954562e-01, -9.993223846e-01, -9.996988187e-01, -9.999247018e-01, -1.000000000e+00, -9.999247018e-01, -9.996988187e-01, -9.993223846e-01, -9.987954562e-01, -9.981181129e-01, -9.972904567e-01, -9.963126122e-01, -9.951847267e-01, -9.939069700e-01, -9.924795346e-01, -9.909026354e-01, -9.891765100e-01, -9.873014182e-01, -9.852776424e-01, -9.831054874e-01, -9.807852804e-01, -9.783173707e-01, -9.757021300e-01, -9.729399522e-01, -9.700312532e-01, -9.669764710e-01, -9.637760658e-01, -9.604305194e-01, -9.569403357e-01, -9.533060404e-01, -9.495281806e-01, -9.456073254e-01, -9.415440652e-01, -9.373390119e-01, -9.329927988e-01, -9.285060805e-01, -9.238795325e-01, -9.191138517e-01, -9.142097557e-01, -9.091679831e-01, -9.039892931e-01, -8.986744657e-01, -8.932243012e-01, -8.876396204e-01, -8.819212643e-01, -8.760700942e-01, -8.700869911e-01, -8.639728561e-01, -8.577286100e-01, -8.513551931e-01, -8.448535652e-01, -8.382247056e-01, -8.314696123e-01, -8.245893028e-01, -8.175848132e-01, -8.104571983e-01, -8.032075315e-01, -7.958369046e-01, -7.883464276e-01, -7.807372286e-01, -7.730104534e-01, -7.651672656e-01, -7.572088465e-01, -7.491363945e-01, -7.409511254e-01, -7.326542717e-01, -7.242470830e-01, -7.157308253e-01, -7.071067812e-01, -6.983762494e-01, -6.895405447e-01, -6.806009978e-01, -6.715589548e-01, -6.624157776e-01, -6.531728430e-01, -6.438315429e-01, -6.343932842e-01, -6.248594881e-01, -6.152315906e-01, -6.055110414e-01, -5.956993045e-01, -5.857978575e-01, -5.758081914e-01, -5.657318108e-01, -5.555702330e-01, -5.453249884e-01, -5.349976199e-01, -5.245896827e-01, -5.141027442e-01, -5.035383837e-01, -4.928981922e-01, -4.821837721e-01, -4.713967368e-01, -4.605387110e-01, -4.496113297e-01, -4.386162385e-01, -4.275550934e-01, -4.164295601e-01, -4.052413140e-01, -3.939920401e-01, -3.826834324e-01, -3.713171940e-01, -3.598950365e-01, -3.484186802e-01, -3.368898534e-01, -3.253102922e-01, -3.136817404e-01, -3.020059493e-01, -2.902846773e-01, -2.785196894e-01, -2.667127575e-01, -2.548656596e-01, -2.429801799e-01, -2.310581083e-01, -2.191012402e-01, -2.071113762e-01, -1.950903220e-01, -1.830398880e-01, -1.709618888e-01, -1.588581433e-01, -1.467304745e-01, -1.345807085e-01, -1.224106752e-01, -1.102222073e-01, -9.801714033e-02, -8.579731234e-02, -7.356456360e-02, -6.132073630e-02, -4.906767433e-02, -3.680722294e-02, -2.454122852e-02, -1.227153829e-02, -2.449293598e-16, 1.227153829e-02, 2.454122852e-02, 3.680722294e-02, 4.906767433e-02, 6.132073630e-02, 7.356456360e-02, 8.579731234e-02, 9.801714033e-02, 1.102222073e-01, 1.224106752e-01, 1.345807085e-01, 1.467304745e-01, 1.588581433e-01, 1.709618888e-01, 1.830398880e-01, 1.950903220e-01, 2.071113762e-01, 2.191012402e-01, 2.310581083e-01, 2.429801799e-01, 2.548656596e-01, 2.667127575e-01, 2.785196894e-01, 2.902846773e-01, 3.020059493e-01, 3.136817404e-01, 3.253102922e-01, 3.368898534e-01, 3.484186802e-01, 3.598950365e-01, 3.713171940e-01, 3.826834324e-01, 3.939920401e-01, 4.052413140e-01, 4.164295601e-01, 4.275550934e-01, 4.386162385e-01, 4.496113297e-01, 4.605387110e-01, 4.713967368e-01, 4.821837721e-01, 4.928981922e-01, 5.035383837e-01, 5.141027442e-01, 5.245896827e-01, 5.349976199e-01, 5.453249884e-01, 5.555702330e-01, 5.657318108e-01, 5.758081914e-01, 5.857978575e-01, 5.956993045e-01, 6.055110414e-01, 6.152315906e-01, 6.248594881e-01, 6.343932842e-01, 6.438315429e-01, 6.531728430e-01, 6.624157776e-01, 6.715589548e-01, 6.806009978e-01, 6.895405447e-01, 6.983762494e-01, 7.071067812e-01, 7.157308253e-01, 7.242470830e-01, 7.326542717e-01, 7.409511254e-01, 7.491363945e-01, 7.572088465e-01, 7.651672656e-01, 7.730104534e-01, 7.807372286e-01, 7.883464276e-01, 7.958369046e-01, 8.032075315e-01, 8.104571983e-01, 8.175848132e-01, 8.245893028e-01, 8.314696123e-01, 8.382247056e-01, 8.448535652e-01, 8.513551931e-01, 8.577286100e-01, 8.639728561e-01, 8.700869911e-01, 8.760700942e-01, 8.819212643e-01, 8.876396204e-01, 8.932243012e-01, 8.986744657e-01, 9.039892931e-01, 9.091679831e-01, 9.142097557e-01, 9.191138517e-01, 9.238795325e-01, 9.285060805e-01, 9.329927988e-01, 9.373390119e-01, 9.415440652e-01, 9.456073254e-01, 9.495281806e-01, 9.533060404e-01, 9.569403357e-01, 9.604305194e-01, 9.637760658e-01, 9.669764710e-01, 9.700312532e-01, 9.729399522e-01, 9.757021300e-01, 9.783173707e-01, 9.807852804e-01, 9.831054874e-01, 9.852776424e-01, 9.873014182e-01, 9.891765100e-01, 9.909026354e-01, 9.924795346e-01, 9.939069700e-01, 9.951847267e-01, 9.963126122e-01, 9.972904567e-01, 9.981181129e-01, 9.987954562e-01, 9.993223846e-01, 9.996988187e-01, 9.999247018e-01, 1.000000000e+00, }; const float lut_fm_frequency_quantizer[] FLASHMEM = { -1.200000000e+01, -1.200000000e+01, -1.200000000e+01, -1.184000000e+01, -1.184000000e+01, -1.184000000e+01, -1.111000000e+01, -1.038000000e+01, -9.650000000e+00, -8.920000000e+00, -8.190000000e+00, -7.460000000e+00, -6.730000000e+00, -6.000000000e+00, -6.000000000e+00, -6.000000000e+00, -5.545511612e+00, -5.091023223e+00, -4.636534835e+00, -4.182046446e+00, -4.182046446e+00, -4.182046446e+00, -3.659290641e+00, -3.136534835e+00, -2.613779029e+00, -2.091023223e+00, -1.568267417e+00, -1.045511612e+00, -5.227558058e-01, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 1.600000000e-01, 1.600000000e-01, 1.600000000e-01, 8.900000000e-01, 1.620000000e+00, 2.350000000e+00, 3.080000000e+00, 3.810000000e+00, 4.540000000e+00, 5.270000000e+00, 6.000000000e+00, 6.000000000e+00, 6.000000000e+00, 6.454488388e+00, 6.908976777e+00, 7.363465165e+00, 7.817953554e+00, 7.817953554e+00, 7.817953554e+00, 8.285529931e+00, 8.753106309e+00, 9.220682687e+00, 9.688259065e+00, 9.688259065e+00, 9.688259065e+00, 1.026619430e+01, 1.084412953e+01, 1.142206477e+01, 1.200000000e+01, 1.200000000e+01, 1.200000000e+01, 1.216000000e+01, 1.216000000e+01, 1.216000000e+01, 1.262977500e+01, 1.309955001e+01, 1.356932501e+01, 1.403910002e+01, 1.403910002e+01, 1.403910002e+01, 1.490761987e+01, 1.577613972e+01, 1.664465957e+01, 1.751317942e+01, 1.751317942e+01, 1.751317942e+01, 1.800000000e+01, 1.800000000e+01, 1.800000000e+01, 1.850977500e+01, 1.901955001e+01, 1.901955001e+01, 1.901955001e+01, 1.981795355e+01, 1.981795355e+01, 1.981795355e+01, 2.066386428e+01, 2.150977500e+01, 2.150977500e+01, 2.150977500e+01, 2.213233125e+01, 2.275488750e+01, 2.337744375e+01, 2.400000000e+01, 2.400000000e+01, 2.400000000e+01, 2.450977500e+01, 2.501955001e+01, 2.501955001e+01, 2.501955001e+01, 2.547403840e+01, 2.592852679e+01, 2.638301517e+01, 2.683750356e+01, 2.683750356e+01, 2.683750356e+01, 2.735032035e+01, 2.786313714e+01, 2.786313714e+01, 2.786313714e+01, 2.839735285e+01, 2.893156857e+01, 2.946578428e+01, 3.000000000e+01, 3.000000000e+01, 3.000000000e+01, 3.075000000e+01, 3.150000000e+01, 3.225000000e+01, 3.300000000e+01, 3.375000000e+01, 3.450000000e+01, 3.525000000e+01, 3.600000000e+01, 3.600000000e+01, 3.600000000e+01, 3.600000000e+01, 3.600000000e+01, }; const float lut_fold[] FLASHMEM = { -9.980545825e-01, -9.970653772e-01, -9.960649692e-01, -9.950532582e-01, -9.940301939e-01, -9.929957802e-01, -9.919500809e-01, -9.908932239e-01, -9.898254054e-01, -9.887468930e-01, -9.876580288e-01, -9.865592310e-01, -9.854509946e-01, -9.843338912e-01, -9.832085672e-01, -9.820757409e-01, -9.809361977e-01, -9.797907840e-01, -9.786403995e-01, -9.774859869e-01, -9.763285207e-01, -9.751689938e-01, -9.740084017e-01, -9.728477255e-01, -9.716879129e-01, -9.705298570e-01, -9.693743743e-01, -9.682221804e-01, -9.670738649e-01, -9.659298654e-01, -9.647904408e-01, -9.636556431e-01, -9.625252914e-01, -9.613989436e-01, -9.602758714e-01, -9.591550347e-01, -9.580350590e-01, -9.569142144e-01, -9.557903981e-01, -9.546611197e-01, -9.535234911e-01, -9.523742208e-01, -9.512096130e-01, -9.500255727e-01, -9.488176173e-01, -9.475808937e-01, -9.463102039e-01, -9.450000364e-01, -9.436446065e-01, -9.422379038e-01, -9.407737471e-01, -9.392458479e-01, -9.376478811e-01, -9.359735625e-01, -9.342167345e-01, -9.323714562e-01, -9.304321011e-01, -9.283934575e-01, -9.262508342e-01, -9.240001674e-01, -9.216381294e-01, -9.191622368e-01, -9.165709565e-01, -9.138638086e-01, -9.110414630e-01, -9.081058297e-01, -9.050601387e-01, -9.019090092e-01, -8.986585056e-01, -8.953161780e-01, -8.918910851e-01, -8.883937990e-01, -8.848363883e-01, -8.812323792e-01, -8.775966932e-01, -8.739455595e-01, -8.702964016e-01, -8.666676980e-01, -8.630788161e-01, -8.595498195e-01, -8.561012493e-01, -8.527538811e-01, -8.495284571e-01, -8.464453973e-01, -8.435244910e-01, -8.407845708e-01, -8.382431741e-01, -8.359161932e-01, -8.338175206e-01, -8.319586927e-01, -8.303485360e-01, -8.289928229e-01, -8.278939413e-01, -8.270505833e-01, -8.264574602e-01, -8.261050485e-01, -8.259793727e-01, -8.260618323e-01, -8.263290765e-01, -8.267529332e-01, -8.273003972e-01, -8.279336816e-01, -8.286103366e-01, -8.292834393e-01, -8.299018559e-01, -8.304105799e-01, -8.307511441e-01, -8.308621097e-01, -8.306796276e-01, -8.301380721e-01, -8.291707415e-01, -8.277106225e-01, -8.256912103e-01, -8.230473793e-01, -8.197162939e-01, -8.156383519e-01, -8.107581485e-01, -8.050254496e-01, -7.983961624e-01, -7.908332902e-01, -7.823078566e-01, -7.727997861e-01, -7.622987256e-01, -7.508047928e-01, -7.383292372e-01, -7.248949979e-01, -7.105371474e-01, -6.953032052e-01, -6.792533125e-01, -6.624602549e-01, -6.450093250e-01, -6.269980173e-01, -6.085355495e-01, -5.897422068e-01, -5.707485064e-01, -5.516941858e-01, -5.327270153e-01, -5.140014423e-01, -4.956770752e-01, -4.779170191e-01, -4.608860753e-01, -4.447488219e-01, -4.296675951e-01, -4.158003906e-01, -4.032987090e-01, -3.923053718e-01, -3.829523325e-01, -3.753585132e-01, -3.696276948e-01, -3.658464920e-01, -3.640824427e-01, -3.643822430e-01, -3.667701571e-01, -3.712466318e-01, -3.777871433e-01, -3.863413015e-01, -3.968322361e-01, -4.091562858e-01, -4.231830080e-01, -4.387555229e-01, -4.556912047e-01, -4.737827239e-01, -4.927994449e-01, -5.124891750e-01, -5.325802587e-01, -5.527840042e-01, -5.727974254e-01, -5.923062779e-01, -6.109883621e-01, -6.285170609e-01, -6.445650789e-01, -6.588083399e-01, -6.709300033e-01, -6.806245487e-01, -6.876018827e-01, -6.915914142e-01, -6.923460464e-01, -6.896460314e-01, -6.833026329e-01, -6.731615438e-01, -6.591060076e-01, -6.410595911e-01, -6.189885640e-01, -5.929038395e-01, -5.628624373e-01, -5.289684349e-01, -4.913733765e-01, -4.502761195e-01, -4.059220990e-01, -3.586020036e-01, -3.086498600e-01, -2.564405314e-01, -2.023866445e-01, -1.469349657e-01, -9.056225673e-02, -3.377064458e-02, 2.291744737e-02, 7.896475831e-02, 1.338249802e-01, 1.869488164e-01, 2.377902398e-01, 2.858128778e-01, 3.304964479e-01, 3.713431643e-01, 4.078840357e-01, 4.396849726e-01, 4.663526243e-01, 4.875398649e-01, 5.029508548e-01, 5.123456023e-01, 5.155439593e-01, 5.124289894e-01, 5.029496521e-01, 4.871227568e-01, 4.650341465e-01, 4.368390827e-01, 4.027618100e-01, 3.630942908e-01, 3.181941105e-01, 2.684815644e-01, 2.144359470e-01, 1.565910778e-01, 9.553010345e-02, 3.187963220e-02, -3.369674102e-02, -1.005054456e-01, -1.678304053e-01, -2.349408810e-01, -3.010995956e-01, -3.655710438e-01, -4.276298873e-01, -4.865693337e-01, -5.417093944e-01, -5.924049204e-01, -6.380533123e-01, -6.781018093e-01, -7.120542597e-01, -7.394772881e-01, -7.600057749e-01, -7.733475770e-01, -7.792874237e-01, -7.776899338e-01, -7.685017108e-01, -7.517524823e-01, -7.275552655e-01, -6.961055475e-01, -6.576794884e-01, -6.126311602e-01, -5.613888527e-01, -5.044504876e-01, -4.423781911e-01, -3.757920909e-01, -3.053634092e-01, -2.318069348e-01, -1.558729654e-01, -7.833881626e-02, 0.000000000e+00, 7.833881626e-02, 1.558729654e-01, 2.318069348e-01, 3.053634092e-01, 3.757920909e-01, 4.423781911e-01, 5.044504876e-01, 5.613888527e-01, 6.126311602e-01, 6.576794884e-01, 6.961055475e-01, 7.275552655e-01, 7.517524823e-01, 7.685017108e-01, 7.776899338e-01, 7.792874237e-01, 7.733475770e-01, 7.600057749e-01, 7.394772881e-01, 7.120542597e-01, 6.781018093e-01, 6.380533123e-01, 5.924049204e-01, 5.417093944e-01, 4.865693337e-01, 4.276298873e-01, 3.655710438e-01, 3.010995956e-01, 2.349408810e-01, 1.678304053e-01, 1.005054456e-01, 3.369674102e-02, -3.187963220e-02, -9.553010345e-02, -1.565910778e-01, -2.144359470e-01, -2.684815644e-01, -3.181941105e-01, -3.630942908e-01, -4.027618100e-01, -4.368390827e-01, -4.650341465e-01, -4.871227568e-01, -5.029496521e-01, -5.124289894e-01, -5.155439593e-01, -5.123456023e-01, -5.029508548e-01, -4.875398649e-01, -4.663526243e-01, -4.396849726e-01, -4.078840357e-01, -3.713431643e-01, -3.304964479e-01, -2.858128778e-01, -2.377902398e-01, -1.869488164e-01, -1.338249802e-01, -7.896475831e-02, -2.291744737e-02, 3.377064458e-02, 9.056225673e-02, 1.469349657e-01, 2.023866445e-01, 2.564405314e-01, 3.086498600e-01, 3.586020036e-01, 4.059220990e-01, 4.502761195e-01, 4.913733765e-01, 5.289684349e-01, 5.628624373e-01, 5.929038395e-01, 6.189885640e-01, 6.410595911e-01, 6.591060076e-01, 6.731615438e-01, 6.833026329e-01, 6.896460314e-01, 6.923460464e-01, 6.915914142e-01, 6.876018827e-01, 6.806245487e-01, 6.709300033e-01, 6.588083399e-01, 6.445650789e-01, 6.285170609e-01, 6.109883621e-01, 5.923062779e-01, 5.727974254e-01, 5.527840042e-01, 5.325802587e-01, 5.124891750e-01, 4.927994449e-01, 4.737827239e-01, 4.556912047e-01, 4.387555229e-01, 4.231830080e-01, 4.091562858e-01, 3.968322361e-01, 3.863413015e-01, 3.777871433e-01, 3.712466318e-01, 3.667701571e-01, 3.643822430e-01, 3.640824427e-01, 3.658464920e-01, 3.696276948e-01, 3.753585132e-01, 3.829523325e-01, 3.923053718e-01, 4.032987090e-01, 4.158003906e-01, 4.296675951e-01, 4.447488219e-01, 4.608860753e-01, 4.779170191e-01, 4.956770752e-01, 5.140014423e-01, 5.327270153e-01, 5.516941858e-01, 5.707485064e-01, 5.897422068e-01, 6.085355495e-01, 6.269980173e-01, 6.450093250e-01, 6.624602549e-01, 6.792533125e-01, 6.953032052e-01, 7.105371474e-01, 7.248949979e-01, 7.383292372e-01, 7.508047928e-01, 7.622987256e-01, 7.727997861e-01, 7.823078566e-01, 7.908332902e-01, 7.983961624e-01, 8.050254496e-01, 8.107581485e-01, 8.156383519e-01, 8.197162939e-01, 8.230473793e-01, 8.256912103e-01, 8.277106225e-01, 8.291707415e-01, 8.301380721e-01, 8.306796276e-01, 8.308621097e-01, 8.307511441e-01, 8.304105799e-01, 8.299018559e-01, 8.292834393e-01, 8.286103366e-01, 8.279336816e-01, 8.273003972e-01, 8.267529332e-01, 8.263290765e-01, 8.260618323e-01, 8.259793727e-01, 8.261050485e-01, 8.264574602e-01, 8.270505833e-01, 8.278939413e-01, 8.289928229e-01, 8.303485360e-01, 8.319586927e-01, 8.338175206e-01, 8.359161932e-01, 8.382431741e-01, 8.407845708e-01, 8.435244910e-01, 8.464453973e-01, 8.495284571e-01, 8.527538811e-01, 8.561012493e-01, 8.595498195e-01, 8.630788161e-01, 8.666676980e-01, 8.702964016e-01, 8.739455595e-01, 8.775966932e-01, 8.812323792e-01, 8.848363883e-01, 8.883937990e-01, 8.918910851e-01, 8.953161780e-01, 8.986585056e-01, 9.019090092e-01, 9.050601387e-01, 9.081058297e-01, 9.110414630e-01, 9.138638086e-01, 9.165709565e-01, 9.191622368e-01, 9.216381294e-01, 9.240001674e-01, 9.262508342e-01, 9.283934575e-01, 9.304321011e-01, 9.323714562e-01, 9.342167345e-01, 9.359735625e-01, 9.376478811e-01, 9.392458479e-01, 9.407737471e-01, 9.422379038e-01, 9.436446065e-01, 9.450000364e-01, 9.463102039e-01, 9.475808937e-01, 9.488176173e-01, 9.500255727e-01, 9.512096130e-01, 9.523742208e-01, 9.535234911e-01, 9.546611197e-01, 9.557903981e-01, 9.569142144e-01, 9.580350590e-01, 9.591550347e-01, 9.602758714e-01, 9.613989436e-01, 9.625252914e-01, 9.636556431e-01, 9.647904408e-01, 9.659298654e-01, 9.670738649e-01, 9.682221804e-01, 9.693743743e-01, 9.705298570e-01, 9.716879129e-01, 9.728477255e-01, 9.740084017e-01, 9.751689938e-01, 9.763285207e-01, 9.774859869e-01, 9.786403995e-01, 9.797907840e-01, 9.809361977e-01, 9.820757409e-01, 9.832085672e-01, 9.843338912e-01, 9.854509946e-01, 9.865592310e-01, 9.876580288e-01, 9.887468930e-01, 9.898254054e-01, 9.908932239e-01, 9.919500809e-01, 9.929957802e-01, 9.940301939e-01, 9.950532582e-01, 9.960649692e-01, 9.970653772e-01, 9.980545825e-01, 9.990327291e-01, 1.000000000e+00, 1.000000000e+00, }; const float lut_fold_2[] FLASHMEM = { 1.000000000e+00, 9.992967758e-01, 9.985815484e-01, 9.978540078e-01, 9.971138332e-01, 9.963606927e-01, 9.955942426e-01, 9.948141269e-01, 9.940199768e-01, 9.932114103e-01, 9.923880310e-01, 9.915494283e-01, 9.906951760e-01, 9.898248319e-01, 9.889379369e-01, 9.880340145e-01, 9.871125695e-01, 9.861730874e-01, 9.852150334e-01, 9.842378513e-01, 9.832409624e-01, 9.822237646e-01, 9.811856308e-01, 9.801259079e-01, 9.790439155e-01, 9.779389442e-01, 9.768102539e-01, 9.756570727e-01, 9.744785949e-01, 9.732739786e-01, 9.720423447e-01, 9.707827737e-01, 9.694943044e-01, 9.681759305e-01, 9.668265989e-01, 9.654452060e-01, 9.640305956e-01, 9.625815548e-01, 9.610968112e-01, 9.595750288e-01, 9.580148040e-01, 9.564146617e-01, 9.547730501e-01, 9.530883359e-01, 9.513587989e-01, 9.495826263e-01, 9.477579060e-01, 9.458826201e-01, 9.439546371e-01, 9.419717041e-01, 9.399314380e-01, 9.378313157e-01, 9.356686640e-01, 9.334406481e-01, 9.311442591e-01, 9.287763006e-01, 9.263333739e-01, 9.238118615e-01, 9.212079094e-01, 9.185174075e-01, 9.157359677e-01, 9.128589003e-01, 9.098811874e-01, 9.067974538e-01, 9.036019347e-01, 9.002884395e-01, 8.968503119e-01, 8.932803854e-01, 8.895709331e-01, 8.857136124e-01, 8.816994016e-01, 8.775185304e-01, 8.731603996e-01, 8.686134921e-01, 8.638652705e-01, 8.589020627e-01, 8.537089293e-01, 8.482695142e-01, 8.425658723e-01, 8.365782715e-01, 8.302849649e-01, 8.236619269e-01, 8.166825462e-01, 8.093172692e-01, 8.015331811e-01, 7.932935143e-01, 7.845570677e-01, 7.752775176e-01, 7.654025961e-01, 7.548731062e-01, 7.436217337e-01, 7.315716072e-01, 7.186345391e-01, 7.047088637e-01, 6.896767601e-01, 6.734009108e-01, 6.557202943e-01, 6.364448402e-01, 6.153485688e-01, 5.921606903e-01, 5.665539193e-01, 5.381289295e-01, 5.063933787e-01, 4.707331500e-01, 4.303722225e-01, 3.843155503e-01, 3.312659247e-01, 2.694998552e-01, 1.966767932e-01, 1.095358294e-01, 3.393987745e-03, -1.040028802e-01, -1.920923242e-01, -2.656393469e-01, -3.279705091e-01, -3.814696578e-01, -4.278897766e-01, -4.685487258e-01, -5.044563616e-01, -5.363995499e-01, -5.650004958e-01, -5.676277376e-01, -5.456089430e-01, -5.216251172e-01, -4.954009254e-01, -4.666070735e-01, -4.348464092e-01, -3.996354923e-01, -3.603798149e-01, -3.163399611e-01, -2.665845916e-01, -2.099238522e-01, -1.448129904e-01, -6.920937281e-02, 1.895794740e-02, 1.019348852e-01, 1.729075540e-01, 2.343052184e-01, 2.879430943e-01, 3.352048344e-01, 3.771635871e-01, 4.146644691e-01, 4.483820782e-01, 4.788614349e-01, 5.065476686e-01, 5.318078998e-01, 5.549476117e-01, 5.762230650e-01, 5.958508275e-01, 6.140151734e-01, 6.308738858e-01, 6.465628523e-01, 6.611997355e-01, 6.748869294e-01, 6.877139581e-01, 6.925931401e-01, 6.755415987e-01, 6.569329565e-01, 6.365437238e-01, 6.141054921e-01, 5.892930521e-01, 5.617085284e-01, 5.308598832e-01, 4.961313087e-01, 4.567416977e-01, 4.116851906e-01, 3.596440735e-01, 2.988577649e-01, 2.269196964e-01, 1.404511108e-01, 3.455499060e-02, -8.308691439e-02, -1.798594632e-01, -2.595549970e-01, -3.263272740e-01, -3.830839556e-01, -4.319212812e-01, -4.743886570e-01, -5.116560503e-01, -5.446234410e-01, -5.739944533e-01, -6.003271365e-01, -6.109475507e-01, -5.895686806e-01, -5.661619434e-01, -5.404244477e-01, -5.119898195e-01, -4.804106515e-01, -4.451347882e-01, -4.054727657e-01, -3.605522997e-01, -3.092533873e-01, -2.501136501e-01, -1.811866822e-01, -9.982372580e-02, -2.325458569e-03, 9.596728942e-02, 1.779431078e-01, 2.473476588e-01, 3.068667711e-01, 3.584720417e-01, 4.036434517e-01, 4.435136052e-01, 4.789639990e-01, 5.106909591e-01, 5.392518362e-01, 5.650980300e-01, 5.885990231e-01, 6.100601564e-01, 6.297359696e-01, 6.478403436e-01, 6.645543074e-01, 6.585194180e-01, 6.406121537e-01, 6.211278553e-01, 5.998486007e-01, 5.765143776e-01, 5.508124062e-01, 5.223630380e-01, 4.907008769e-01, 4.552491217e-01, 4.152841095e-01, 3.698853971e-01, 3.178639957e-01, 2.576567279e-01, 1.871664560e-01, 1.035128010e-01, 2.628828896e-03, -9.918255595e-02, -1.835455764e-01, -2.545841775e-01, -3.152240342e-01, -3.675927060e-01, -4.132744159e-01, -4.534730876e-01, -4.891200006e-01, -5.209468346e-01, -5.495364245e-01, -5.753587781e-01, -5.987971175e-01, -6.201670260e-01, -6.397307408e-01, -6.255537426e-01, -6.058657960e-01, -5.844073505e-01, -5.609283358e-01, -5.351292603e-01, -5.066483683e-01, -4.750445715e-01, -4.397744409e-01, -4.001606981e-01, -3.553483015e-01, -3.042420289e-01, -2.454157756e-01, -1.769773894e-01, -9.636135435e-02, 0.000000000e+00, 9.636135435e-02, 1.769773894e-01, 2.454157756e-01, 3.042420289e-01, 3.553483015e-01, 4.001606981e-01, 4.397744409e-01, 4.750445715e-01, 5.066483683e-01, 5.351292603e-01, 5.609283358e-01, 5.844073505e-01, 6.058657960e-01, 6.255537426e-01, 6.397307408e-01, 6.201670260e-01, 5.987971175e-01, 5.753587781e-01, 5.495364245e-01, 5.209468346e-01, 4.891200006e-01, 4.534730876e-01, 4.132744159e-01, 3.675927060e-01, 3.152240342e-01, 2.545841775e-01, 1.835455764e-01, 9.918255595e-02, -2.628828896e-03, -1.035128010e-01, -1.871664560e-01, -2.576567279e-01, -3.178639957e-01, -3.698853971e-01, -4.152841095e-01, -4.552491217e-01, -4.907008769e-01, -5.223630380e-01, -5.508124062e-01, -5.765143776e-01, -5.998486007e-01, -6.211278553e-01, -6.406121537e-01, -6.585194180e-01, -6.645543074e-01, -6.478403436e-01, -6.297359696e-01, -6.100601564e-01, -5.885990231e-01, -5.650980300e-01, -5.392518362e-01, -5.106909591e-01, -4.789639990e-01, -4.435136052e-01, -4.036434517e-01, -3.584720417e-01, -3.068667711e-01, -2.473476588e-01, -1.779431078e-01, -9.596728942e-02, 2.325458569e-03, 9.982372580e-02, 1.811866822e-01, 2.501136501e-01, 3.092533873e-01, 3.605522997e-01, 4.054727657e-01, 4.451347882e-01, 4.804106515e-01, 5.119898195e-01, 5.404244477e-01, 5.661619434e-01, 5.895686806e-01, 6.109475507e-01, 6.003271365e-01, 5.739944533e-01, 5.446234410e-01, 5.116560503e-01, 4.743886570e-01, 4.319212812e-01, 3.830839556e-01, 3.263272740e-01, 2.595549970e-01, 1.798594632e-01, 8.308691439e-02, -3.455499060e-02, -1.404511108e-01, -2.269196964e-01, -2.988577649e-01, -3.596440735e-01, -4.116851906e-01, -4.567416977e-01, -4.961313087e-01, -5.308598832e-01, -5.617085284e-01, -5.892930521e-01, -6.141054921e-01, -6.365437238e-01, -6.569329565e-01, -6.755415987e-01, -6.925931401e-01, -6.877139581e-01, -6.748869294e-01, -6.611997355e-01, -6.465628523e-01, -6.308738858e-01, -6.140151734e-01, -5.958508275e-01, -5.762230650e-01, -5.549476117e-01, -5.318078998e-01, -5.065476686e-01, -4.788614349e-01, -4.483820782e-01, -4.146644691e-01, -3.771635871e-01, -3.352048344e-01, -2.879430943e-01, -2.343052184e-01, -1.729075540e-01, -1.019348852e-01, -1.895794740e-02, 6.920937281e-02, 1.448129904e-01, 2.099238522e-01, 2.665845916e-01, 3.163399611e-01, 3.603798149e-01, 3.996354923e-01, 4.348464092e-01, 4.666070735e-01, 4.954009254e-01, 5.216251172e-01, 5.456089430e-01, 5.676277376e-01, 5.650004958e-01, 5.363995499e-01, 5.044563616e-01, 4.685487258e-01, 4.278897766e-01, 3.814696578e-01, 3.279705091e-01, 2.656393469e-01, 1.920923242e-01, 1.040028802e-01, -3.393987745e-03, -1.095358294e-01, -1.966767932e-01, -2.694998552e-01, -3.312659247e-01, -3.843155503e-01, -4.303722225e-01, -4.707331500e-01, -5.063933787e-01, -5.381289295e-01, -5.665539193e-01, -5.921606903e-01, -6.153485688e-01, -6.364448402e-01, -6.557202943e-01, -6.734009108e-01, -6.896767601e-01, -7.047088637e-01, -7.186345391e-01, -7.315716072e-01, -7.436217337e-01, -7.548731062e-01, -7.654025961e-01, -7.752775176e-01, -7.845570677e-01, -7.932935143e-01, -8.015331811e-01, -8.093172692e-01, -8.166825462e-01, -8.236619269e-01, -8.302849649e-01, -8.365782715e-01, -8.425658723e-01, -8.482695142e-01, -8.537089293e-01, -8.589020627e-01, -8.638652705e-01, -8.686134921e-01, -8.731603996e-01, -8.775185304e-01, -8.816994016e-01, -8.857136124e-01, -8.895709331e-01, -8.932803854e-01, -8.968503119e-01, -9.002884395e-01, -9.036019347e-01, -9.067974538e-01, -9.098811874e-01, -9.128589003e-01, -9.157359677e-01, -9.185174075e-01, -9.212079094e-01, -9.238118615e-01, -9.263333739e-01, -9.287763006e-01, -9.311442591e-01, -9.334406481e-01, -9.356686640e-01, -9.378313157e-01, -9.399314380e-01, -9.419717041e-01, -9.439546371e-01, -9.458826201e-01, -9.477579060e-01, -9.495826263e-01, -9.513587989e-01, -9.530883359e-01, -9.547730501e-01, -9.564146617e-01, -9.580148040e-01, -9.595750288e-01, -9.610968112e-01, -9.625815548e-01, -9.640305956e-01, -9.654452060e-01, -9.668265989e-01, -9.681759305e-01, -9.694943044e-01, -9.707827737e-01, -9.720423447e-01, -9.732739786e-01, -9.744785949e-01, -9.756570727e-01, -9.768102539e-01, -9.779389442e-01, -9.790439155e-01, -9.801259079e-01, -9.811856308e-01, -9.822237646e-01, -9.832409624e-01, -9.842378513e-01, -9.852150334e-01, -9.861730874e-01, -9.871125695e-01, -9.880340145e-01, -9.889379369e-01, -9.898248319e-01, -9.906951760e-01, -9.915494283e-01, -9.923880310e-01, -9.932114103e-01, -9.940199768e-01, -9.948141269e-01, -9.955942426e-01, -9.963606927e-01, -9.971138332e-01, -9.978540078e-01, -9.985815484e-01, -9.992967758e-01, -1.000000000e+00, -1.000691521e+00, -1.001371627e+00, -1.001371627e+00, }; const float lut_stiffness[] FLASHMEM = { -6.250000000e-02, -5.859375000e-02, -5.468750000e-02, -5.078125000e-02, -4.687500000e-02, -4.296875000e-02, -3.906250000e-02, -3.515625000e-02, -3.125000000e-02, -2.734375000e-02, -2.343750000e-02, -1.953125000e-02, -1.562500000e-02, -1.171875000e-02, -7.812500000e-03, -3.906250000e-03, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 1.009582073e-03, 2.416076364e-03, 4.002252878e-03, 5.791066350e-03, 7.808404022e-03, 1.008346028e-02, 1.264915914e-02, 1.554263074e-02, 1.880574864e-02, 2.248573583e-02, 2.663584813e-02, 3.131614488e-02, 3.659435812e-02, 4.254687278e-02, 4.925983210e-02, 5.683038428e-02, 6.536808837e-02, 7.499649981e-02, 8.585495846e-02, 9.810060511e-02, 1.119106556e-01, 1.274849653e-01, 1.450489216e-01, 1.648567056e-01, 1.871949702e-01, 2.123869891e-01, 2.407973346e-01, 2.728371538e-01, 3.089701187e-01, 3.497191360e-01, 3.956739150e-01, 4.474995013e-01, 5.059459012e-01, 5.718589358e-01, 6.461924814e-01, 7.300222738e-01, 8.245614757e-01, 9.311782340e-01, 1.000037649e+00, 1.005639154e+00, 1.048005353e+00, 1.183990632e+00, 1.457101344e+00, 2.000000000e+00, 2.000000000e+00, }; const float lut_svf_shift[] FLASHMEM = { 7.500000000e-01, 7.591880421e-01, 7.683455389e-01, 7.774424499e-01, 7.864497239e-01, 7.953397451e-01, 8.040867240e-01, 8.126670211e-01, 8.210593968e-01, 8.292451828e-01, 8.372083767e-01, 8.449356653e-01, 8.524163823e-01, 8.596424124e-01, 8.666080494e-01, 8.733098228e-01, 8.797462999e-01, 8.859178746e-01, 8.918265520e-01, 8.974757332e-01, 9.028700082e-01, 9.080149595e-01, 9.129169800e-01, 9.175831064e-01, 9.220208696e-01, 9.262381615e-01, 9.302431183e-01, 9.340440198e-01, 9.376492031e-01, 9.410669892e-01, 9.443056230e-01, 9.473732226e-01, 9.502777394e-01, 9.530269262e-01, 9.556283121e-01, 9.580891845e-01, 9.604165758e-01, 9.626172547e-01, 9.646977214e-01, 9.666642057e-01, 9.685226683e-01, 9.702788030e-01, 9.719380415e-01, 9.735055596e-01, 9.749862835e-01, 9.763848977e-01, 9.777058532e-01, 9.789533760e-01, 9.801314757e-01, 9.812439545e-01, 9.822944161e-01, 9.832862746e-01, 9.842227627e-01, 9.851069409e-01, 9.859417053e-01, 9.867297957e-01, 9.874738036e-01, 9.881761792e-01, 9.888392394e-01, 9.894651739e-01, 9.900560522e-01, 9.906138300e-01, 9.911403551e-01, 9.916373732e-01, 9.921065333e-01, 9.925493929e-01, 9.929674233e-01, 9.933620136e-01, 9.937344761e-01, 9.940860496e-01, 9.944179041e-01, 9.947311441e-01, 9.950268127e-01, 9.953058946e-01, 9.955693195e-01, 9.958179650e-01, 9.960526598e-01, 9.962741861e-01, 9.964832825e-01, 9.966806459e-01, 9.968669346e-01, 9.970427696e-01, 9.972087374e-01, 9.973653916e-01, 9.975132546e-01, 9.976528197e-01, 9.977845524e-01, 9.979088923e-01, 9.980262540e-01, 9.981370293e-01, 9.982415876e-01, 9.983402778e-01, 9.984334293e-01, 9.985213529e-01, 9.986043419e-01, 9.986826732e-01, 9.987566083e-01, 9.988263939e-01, 9.988922628e-01, 9.989544348e-01, 9.990131175e-01, 9.990685067e-01, 9.991207871e-01, 9.991701333e-01, 9.992167099e-01, 9.992606725e-01, 9.993021676e-01, 9.993413338e-01, 9.993783018e-01, 9.994131950e-01, 9.994461297e-01, 9.994772160e-01, 9.995065576e-01, 9.995342523e-01, 9.995603927e-01, 9.995850659e-01, 9.996083544e-01, 9.996303357e-01, 9.996510834e-01, 9.996706665e-01, 9.996891506e-01, 9.997065972e-01, 9.997230647e-01, 9.997386078e-01, 9.997532786e-01, 9.997671260e-01, 9.997801962e-01, 9.997925329e-01, 9.998041771e-01, 9.998151678e-01, 9.998255416e-01, 9.998353332e-01, 9.998445753e-01, 9.998532986e-01, 9.998615323e-01, 9.998693039e-01, 9.998766393e-01, 9.998835630e-01, 9.998900981e-01, 9.998962664e-01, 9.999020885e-01, 9.999075839e-01, 9.999127708e-01, 9.999176666e-01, 9.999222876e-01, 9.999266493e-01, 9.999307661e-01, 9.999346519e-01, 9.999383196e-01, 9.999417815e-01, 9.999450491e-01, 9.999481332e-01, 9.999510443e-01, 9.999537919e-01, 9.999563854e-01, 9.999588333e-01, 9.999611438e-01, 9.999633246e-01, 9.999653831e-01, 9.999673260e-01, 9.999691598e-01, 9.999708907e-01, 9.999725245e-01, 9.999740666e-01, 9.999755221e-01, 9.999768960e-01, 9.999781927e-01, 9.999794167e-01, 9.999805719e-01, 9.999816623e-01, 9.999826915e-01, 9.999836630e-01, 9.999845799e-01, 9.999854454e-01, 9.999862623e-01, 9.999870333e-01, 9.999877611e-01, 9.999884480e-01, 9.999890964e-01, 9.999897083e-01, 9.999902860e-01, 9.999908312e-01, 9.999913458e-01, 9.999918315e-01, 9.999922900e-01, 9.999927227e-01, 9.999931311e-01, 9.999935167e-01, 9.999938805e-01, 9.999942240e-01, 9.999945482e-01, 9.999948542e-01, 9.999951430e-01, 9.999954156e-01, 9.999956729e-01, 9.999959157e-01, 9.999961450e-01, 9.999963613e-01, 9.999965656e-01, 9.999967583e-01, 9.999969403e-01, 9.999971120e-01, 9.999972741e-01, 9.999974271e-01, 9.999975715e-01, 9.999977078e-01, 9.999978364e-01, 9.999979579e-01, 9.999980725e-01, 9.999981807e-01, 9.999982828e-01, 9.999983792e-01, 9.999984701e-01, 9.999985560e-01, 9.999986370e-01, 9.999987135e-01, 9.999987857e-01, 9.999988539e-01, 9.999989182e-01, 9.999989789e-01, 9.999990362e-01, 9.999990903e-01, 9.999991414e-01, 9.999991896e-01, 9.999992351e-01, 9.999992780e-01, 9.999993185e-01, 9.999993568e-01, 9.999993929e-01, 9.999994269e-01, 9.999994591e-01, 9.999994895e-01, 9.999995181e-01, 9.999995452e-01, 9.999995707e-01, 9.999995948e-01, 9.999996175e-01, 9.999996390e-01, 9.999996593e-01, 9.999996784e-01, 9.999996964e-01, 9.999997135e-01, 9.999997296e-01, 9.999997447e-01, 9.999997591e-01, 9.999997726e-01, 9.999997853e-01, 9.999997974e-01, 9.999998088e-01, 9.999998195e-01, 9.999998296e-01, 9.999998392e-01, 9.999998482e-01, 9.999998567e-01, 9.999998648e-01, 9.999998724e-01, 9.999998795e-01, }; const float lut_4x_downsampler_fir[] FLASHMEM = { 2.442415000e-02, 9.297315000e-02, 1.671293800e-01, 2.154733200e-01, }; const float* const lookup_table_table[] FLASHMEM = { lut_sine, lut_fm_frequency_quantizer, lut_fold, lut_fold_2, lut_stiffness, lut_svf_shift, lut_4x_downsampler_fir, }; const int16_t lut_ws_inverse_tan[] FLASHMEM = { -32767, -26872, -24921, -23661, -22748, -22047, -21486, -21026, -20640, -20310, -20025, -19775, -19554, -19358, -19181, -19021, -18875, -18742, -18620, -18507, -18402, -18304, -18213, -18128, -18047, -17971, -17900, -17832, -17767, -17706, -17647, -17591, -17537, -17485, -17435, -17387, -17341, -17296, -17253, -17211, -17170, -17130, -17092, -17054, -17017, -16981, -16945, -16911, -16877, -16843, -16810, -16778, -16746, -16715, -16683, -16652, -16622, -16592, -16561, -16531, -16502, -16472, -16442, -16413, -16384, -16354, -16325, -16295, -16265, -16236, -16206, -16175, -16145, -16115, -16084, -16052, -16021, -15989, -15957, -15924, -15890, -15856, -15822, -15786, -15750, -15713, -15675, -15637, -15597, -15556, -15514, -15471, -15426, -15380, -15332, -15282, -15230, -15176, -15120, -15061, -15000, -14935, -14867, -14796, -14720, -14639, -14554, -14463, -14365, -14260, -14147, -14025, -13892, -13746, -13586, -13409, -13213, -12992, -12742, -12457, -12127, -11741, -11281, -10720, -10019, -9106, -7846, -5895, 0, 5895, 7846, 9106, 10019, 10720, 11281, 11741, 12127, 12457, 12742, 12992, 13213, 13409, 13586, 13746, 13892, 14025, 14147, 14260, 14365, 14463, 14554, 14639, 14720, 14796, 14867, 14935, 15000, 15061, 15120, 15176, 15230, 15282, 15332, 15380, 15426, 15471, 15514, 15556, 15597, 15637, 15675, 15713, 15750, 15786, 15822, 15856, 15890, 15924, 15957, 15989, 16021, 16052, 16084, 16115, 16145, 16175, 16206, 16236, 16265, 16295, 16325, 16354, 16384, 16413, 16442, 16472, 16502, 16531, 16561, 16592, 16622, 16652, 16683, 16715, 16746, 16778, 16810, 16843, 16877, 16911, 16945, 16981, 17017, 17054, 17092, 17130, 17170, 17211, 17253, 17296, 17341, 17387, 17435, 17485, 17537, 17591, 17647, 17706, 17767, 17832, 17900, 17971, 18047, 18128, 18213, 18304, 18402, 18507, 18620, 18742, 18875, 19021, 19181, 19358, 19554, 19775, 20025, 20310, 20640, 21026, 21486, 22047, 22748, 23661, 24921, 26872, 32767, }; const int16_t lut_ws_inverse_sin[] FLASHMEM = { -32767, -30921, -30153, -29561, -29060, -28617, -28215, -27843, -27496, -27169, -26858, -26561, -26276, -26001, -25736, -25479, -25229, -24986, -24748, -24517, -24290, -24068, -23850, -23636, -23425, -23218, -23014, -22813, -22614, -22419, -22225, -22034, -21845, -21657, -21472, -21288, -21106, -20926, -20747, -20569, -20393, -20218, -20043, -19870, -19698, -19527, -19357, -19188, -19019, -18851, -18684, -18517, -18351, -18185, -18020, -17855, -17691, -17527, -17363, -17199, -17036, -16873, -16709, -16546, -16384, -16221, -16058, -15894, -15731, -15568, -15404, -15240, -15076, -14912, -14747, -14582, -14416, -14250, -14083, -13916, -13748, -13579, -13410, -13240, -13069, -12897, -12724, -12549, -12374, -12198, -12020, -11841, -11661, -11479, -11295, -11110, -10922, -10733, -10542, -10348, -10153, -9954, -9753, -9549, -9342, -9131, -8917, -8699, -8477, -8250, -8019, -7781, -7538, -7288, -7031, -6766, -6491, -6206, -5909, -5598, -5271, -4924, -4552, -4150, -3707, -3206, -2614, -1846, 0, 1846, 2614, 3206, 3707, 4150, 4552, 4924, 5271, 5598, 5909, 6206, 6491, 6766, 7031, 7288, 7538, 7781, 8019, 8250, 8477, 8699, 8917, 9131, 9342, 9549, 9753, 9954, 10153, 10348, 10542, 10733, 10922, 11110, 11295, 11479, 11661, 11841, 12020, 12198, 12374, 12549, 12724, 12897, 13069, 13240, 13410, 13579, 13748, 13916, 14083, 14250, 14416, 14582, 14747, 14912, 15076, 15240, 15404, 15568, 15731, 15894, 16058, 16221, 16384, 16546, 16709, 16873, 17036, 17199, 17363, 17527, 17691, 17855, 18020, 18185, 18351, 18517, 18684, 18851, 19019, 19188, 19357, 19527, 19698, 19870, 20043, 20218, 20393, 20569, 20747, 20926, 21106, 21288, 21472, 21657, 21845, 22034, 22225, 22419, 22614, 22813, 23014, 23218, 23425, 23636, 23850, 24068, 24290, 24517, 24748, 24986, 25229, 25479, 25736, 26001, 26276, 26561, 26858, 27169, 27496, 27843, 28215, 28617, 29060, 29561, 30153, 30921, 32767, }; const int16_t lut_ws_linear[] FLASHMEM = { -32767, -32511, -32255, -31999, -31743, -31487, -31231, -30975, -30719, -30463, -30207, -29951, -29695, -29439, -29183, -28927, -28671, -28415, -28159, -27903, -27647, -27391, -27135, -26879, -26623, -26367, -26111, -25855, -25599, -25343, -25087, -24831, -24575, -24319, -24063, -23807, -23551, -23295, -23039, -22783, -22527, -22271, -22015, -21759, -21503, -21247, -20991, -20735, -20479, -20223, -19967, -19711, -19455, -19199, -18943, -18687, -18431, -18175, -17919, -17663, -17407, -17151, -16895, -16639, -16384, -16128, -15872, -15616, -15360, -15104, -14848, -14592, -14336, -14080, -13824, -13568, -13312, -13056, -12800, -12544, -12288, -12032, -11776, -11520, -11264, -11008, -10752, -10496, -10240, -9984, -9728, -9472, -9216, -8960, -8704, -8448, -8192, -7936, -7680, -7424, -7168, -6912, -6656, -6400, -6144, -5888, -5632, -5376, -5120, -4864, -4608, -4352, -4096, -3840, -3584, -3328, -3072, -2816, -2560, -2304, -2048, -1792, -1536, -1280, -1024, -768, -512, -256, 0, 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632, 5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680, 7936, 8192, 8448, 8704, 8960, 9216, 9472, 9728, 9984, 10240, 10496, 10752, 11008, 11264, 11520, 11776, 12032, 12288, 12544, 12800, 13056, 13312, 13568, 13824, 14080, 14336, 14592, 14848, 15104, 15360, 15616, 15872, 16128, 16384, 16639, 16895, 17151, 17407, 17663, 17919, 18175, 18431, 18687, 18943, 19199, 19455, 19711, 19967, 20223, 20479, 20735, 20991, 21247, 21503, 21759, 22015, 22271, 22527, 22783, 23039, 23295, 23551, 23807, 24063, 24319, 24575, 24831, 25087, 25343, 25599, 25855, 26111, 26367, 26623, 26879, 27135, 27391, 27647, 27903, 28159, 28415, 28671, 28927, 29183, 29439, 29695, 29951, 30207, 30463, 30719, 30975, 31231, 31487, 31743, 31999, 32255, 32511, 32767, }; const int16_t lut_ws_bump[] FLASHMEM = { 0, -36, -150, -348, -636, -1017, -1496, -2074, -2752, -3528, -4401, -5366, -6417, -7548, -8750, -10013, -11327, -12679, -14056, -15444, -16829, -18197, -19530, -20816, -22039, -23185, -24239, -25190, -26025, -26733, -27306, -27736, -28018, -28214, -28391, -28550, -28690, -28810, -28912, -28994, -29056, -29099, -29122, -29125, -29109, -29073, -29017, -28941, -28846, -28732, -28599, -28446, -28275, -28085, -27877, -27651, -27407, -27145, -26867, -26572, -26260, -25933, -25590, -25233, -24861, -24475, -24075, -23663, -23238, -22802, -22354, -21896, -21428, -20951, -20465, -19971, -19469, -18961, -18447, -17928, -17404, -16877, -16346, -15813, -15278, -14742, -14206, -13670, -13136, -12603, -12073, -11547, -11025, -10507, -9995, -9489, -8990, -8499, -8015, -7541, -7076, -6621, -6178, -5745, -5324, -4916, -4521, -4140, -3773, -3420, -3082, -2760, -2454, -2165, -1892, -1636, -1398, -1178, -976, -792, -627, -481, -354, -246, -158, -89, -39, -10, 0, 10, 39, 89, 158, 246, 354, 481, 627, 792, 976, 1178, 1398, 1636, 1892, 2165, 2454, 2760, 3082, 3420, 3773, 4140, 4521, 4916, 5324, 5745, 6178, 6621, 7076, 7541, 8015, 8499, 8990, 9489, 9995, 10507, 11025, 11547, 12073, 12603, 13136, 13670, 14206, 14742, 15278, 15813, 16346, 16877, 17404, 17928, 18447, 18961, 19469, 19971, 20465, 20951, 21428, 21896, 22354, 22802, 23238, 23663, 24075, 24475, 24861, 25233, 25590, 25933, 26260, 26572, 26867, 27145, 27407, 27651, 27877, 28085, 28275, 28446, 28599, 28732, 28846, 28941, 29017, 29073, 29109, 29125, 29122, 29099, 29056, 28994, 28912, 28810, 28690, 28550, 28391, 28214, 28018, 27736, 27306, 26733, 26025, 25190, 24239, 23185, 22039, 20816, 19530, 18197, 16829, 15444, 14056, 12679, 11327, 10013, 8750, 7548, 6417, 5366, 4401, 3528, 2752, 2074, 1496, 1017, 636, 348, 150, 36, 0, }; const int16_t lut_ws_double_bump[] FLASHMEM = { 32767, 32745, 32678, 32567, 32412, 32213, 31971, 31685, 31356, 30985, 30571, 30117, 29621, 29085, 28510, 27896, 27245, 26556, 25832, 25072, 24279, 23452, 22594, 21705, 20787, 19841, 18868, 17869, 16846, 15800, 14732, 13645, 12539, 11417, 10278, 9126, 7962, 6786, 5602, 4410, 3212, 2009, 804, -402, -1608, -2811, -4011, -5205, -6393, -7571, -8739, -9896, -11039, -12167, -13279, -14372, -15446, -16499, -17530, -18537, -19519, -20475, -21403, -22301, -23170, -24007, -24811, -25582, -26319, -27019, -27683, -28310, -28898, -29447, -29956, -30424, -30852, -31237, -31580, -31880, -32137, -32351, -32521, -32646, -32728, -32765, -32757, -32705, -32609, -32469, -32285, -32057, -31785, -31470, -31113, -30714, -30273, -29791, -29268, -28706, -28105, -27466, -26790, -26077, -25329, -24547, -23731, -22884, -22005, -21096, -20159, -19195, -18204, -17189, -16151, -15090, -14010, -12910, -11793, -10659, -9512, -8351, -7179, -5998, -4808, -3612, -2410, -1206, 0, 1206, 2410, 3612, 4808, 5998, 7179, 8351, 9512, 10659, 11793, 12910, 14010, 15090, 16151, 17189, 18204, 19195, 20159, 21096, 22005, 22884, 23731, 24547, 25329, 26077, 26790, 27466, 28105, 28706, 29268, 29791, 30273, 30714, 31113, 31470, 31785, 32057, 32285, 32469, 32609, 32705, 32757, 32765, 32728, 32646, 32521, 32351, 32137, 31880, 31580, 31237, 30852, 30424, 29956, 29447, 28898, 28310, 27683, 27019, 26319, 25582, 24811, 24007, 23170, 22301, 21403, 20475, 19519, 18537, 17530, 16499, 15446, 14372, 13279, 12167, 11039, 9896, 8739, 7571, 6393, 5205, 4011, 2811, 1608, 402, -804, -2009, -3212, -4410, -5602, -6786, -7962, -9126, -10278, -11417, -12539, -13645, -14732, -15800, -16846, -17869, -18868, -19841, -20787, -21705, -22594, -23452, -24279, -25072, -25832, -26556, -27245, -27896, -28510, -29085, -29621, -30117, -30571, -30985, -31356, -31685, -31971, -32213, -32412, -32567, -32678, -32745, -32767, }; const int16_t* const lookup_table_i16_table[] FLASHMEM = { lut_ws_inverse_tan, lut_ws_inverse_sin, lut_ws_linear, lut_ws_bump, lut_ws_double_bump, lut_ws_double_bump, }; // const int32_t* const lookup_table_i32_table[] FLASHMEM = { // }; const int8_t lut_lpc_excitation_pulse[] FLASHMEM = { 0, 0, 0, 0, 1, 1, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 17, 19, 21, 23, 25, 28, 30, 33, 36, 38, 41, 44, 48, 51, 54, 57, 61, 64, 68, 71, 75, 78, 82, 85, 89, 92, 95, 99, 102, 105, 108, 110, 113, 115, 118, 120, 121, 123, 124, 125, 126, 127, 127, 127, 127, 126, 125, 124, 122, 121, 118, 116, 113, 110, 107, 104, 100, 96, 92, 87, 83, 78, 73, 68, 63, 58, 53, 47, 42, 37, 31, 26, 21, 16, 11, 6, 1, -3, -8, -12, -16, -20, -23, -26, -29, -32, -35, -37, -39, -40, -42, -43, -43, -44, -44, -44, -44, -44, -43, -42, -41, -40, -39, -38, -36, -35, -33, -32, -30, -29, -27, -26, -24, -23, -22, -20, -19, -18, -18, -17, -16, -16, -16, -16, -16, -16, -17, -17, -18, -19, -20, -21, -23, -24, -26, -27, -29, -30, -32, -34, -35, -37, -39, -40, -42, -43, -44, -46, -47, -48, -48, -49, -49, -50, -50, -50, -49, -49, -48, -47, -46, -45, -44, -42, -41, -39, -37, -35, -33, -31, -29, -27, -25, -23, -20, -18, -16, -14, -13, -11, -9, -8, -7, -6, -5, -4, -3, -3, -3, -3, -3, -4, -5, -6, -7, -9, -10, -12, -14, -16, -18, -21, -23, -26, -29, -32, -34, -37, -40, -43, -46, -49, -51, -54, -56, -59, -61, -63, -65, -67, -68, -70, -71, -72, -72, -73, -73, -73, -73, -72, -72, -71, -70, -69, -67, -66, -64, -63, -61, -59, -57, -54, -52, -50, -48, -45, -43, -41, -39, -37, -35, -33, -31, -29, -27, -26, -25, -23, -22, -21, -20, -20, -19, -19, -19, -18, -18, -18, -19, -19, -19, -20, -20, -21, -21, -22, -22, -23, -23, -24, -24, -25, -25, -25, -26, -26, -26, -25, -25, -25, -24, -24, -23, -22, -21, -20, -19, -18, -16, -15, -13, -12, -10, -8, -6, -4, -3, -1, 1, 3, 5, 7, 8, 10, 12, 13, 15, 16, 17, 18, 19, 20, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 21, 21, 20, 19, 19, 18, 17, 16, 15, 14, 14, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 33, 34, 35, 35, 35, 36, 36, 36, 36, 35, 35, 35, 34, 34, 33, 33, 32, 31, 30, 30, 29, 28, 27, 26, 25, 25, 24, 23, 22, 22, 21, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 27, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 31, 30, 30, 30, 29, 29, 28, 28, 27, 26, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 15, 14, 13, 12, 12, 11, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 12, 12, 11, 10, 9, 8, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -4, -5, -6, -6, -7, -7, -8, -8, -8, -9, -9, -9, -9, -9, -9, -9, -9, -8, -8, -8, -7, -7, -7, -6, -6, -5, -5, -5, -4, -4, -4, -3, -3, -3, -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, }; const int8_t* const lookup_table_i8_table[] FLASHMEM = { lut_lpc_excitation_pulse, }; const int16_t wav_integrated_waves[] FLASHMEM = { -20556, -20706, -20806, -20857, -20857, -20806, -20706, -20556, -20356, -20107, -19810, -19465, -19073, -18635, -18152, -17626, -17057, -16447, -15798, -15110, -14386, -13627, -12835, -12013, -11162, -10283, -9380, -8454, -7508, -6544, -5564, -4571, -3567, -2554, -1535, -512, 512, 1535, 2554, 3567, 4571, 5564, 6544, 7508, 8454, 9380, 10283, 11162, 12013, 12835, 13627, 14386, 15110, 15798, 16447, 17057, 17626, 18152, 18635, 19073, 19465, 19810, 20107, 20356, 20556, 20706, 20806, 20857, 20857, 20806, 20706, 20556, 20356, 20107, 19810, 19465, 19073, 18635, 18152, 17626, 17057, 16447, 15798, 15110, 14386, 13627, 12835, 12013, 11162, 10283, 9380, 8454, 7508, 6544, 5564, 4571, 3567, 2554, 1535, 512, -512, -1535, -2554, -3567, -4571, -5564, -6544, -7508, -8454, -9380, -10283, -11162, -12013, -12835, -13627, -14386, -15110, -15798, -16447, -17057, -17626, -18152, -18635, -19073, -19465, -19810, -20107, -20356, -20556, -20706, -20806, -20857, -9825, -10122, -10322, -10422, -10422, -10322, -10122, -9825, -9433, -8950, -8381, -7732, -7007, -6216, -5364, -4461, -3515, -2535, -1531, -512, 512, 1531, 2535, 3515, 4461, 5364, 6216, 7007, 7732, 8381, 8950, 9433, 9825, 10122, 10322, 10422, 10422, 10322, 10122, 9825, 9433, 8950, 8381, 7732, 7007, 6216, 5364, 4461, 3515, 2535, 1531, 512, -512, -1531, -2535, -3515, -4461, -5364, -6216, -7007, -7732, -8381, -8950, -9433, -9825, -10122, -10322, -10422, -10422, -10322, -10122, -9825, -9433, -8950, -8381, -7732, -7007, -6216, -5364, -4461, -3515, -2535, -1531, -512, 512, 1531, 2535, 3515, 4461, 5364, 6216, 7007, 7732, 8381, 8950, 9433, 9825, 10122, 10322, 10422, 10422, 10322, 10122, 9825, 9433, 8950, 8381, 7732, 7007, 6216, 5364, 4461, 3515, 2535, 1531, 512, -512, -1531, -2535, -3515, -4461, -5364, -6216, -7007, -7732, -8381, -8950, -9433, -9825, -10122, -10322, -10422, -6056, -6494, -6791, -6941, -6941, -6791, -6494, -6056, -5487, -4799, -4008, -3129, -2183, -1190, -171, 852, 1856, 2820, 3724, 4546, 5270, 5880, 6363, 6708, 6908, 6958, 6857, 6609, 6217, 5690, 5041, 4282, 3431, 2505, 1525, 512, -512, -1525, -2505, -3431, -4282, -5041, -5690, -6217, -6609, -6857, -6958, -6908, -6708, -6363, -5880, -5270, -4546, -3724, -2820, -1856, -852, 171, 1190, 2183, 3129, 4008, 4799, 5487, 6056, 6494, 6791, 6941, 6941, 6791, 6494, 6056, 5487, 4799, 4008, 3129, 2183, 1190, 171, -852, -1856, -2820, -3724, -4546, -5270, -5880, -6363, -6708, -6908, -6958, -6857, -6609, -6217, -5690, -5041, -4282, -3431, -2505, -1525, -512, 512, 1525, 2505, 3431, 4282, 5041, 5690, 6217, 6609, 6857, 6958, 6908, 6708, 6363, 5880, 5270, 4546, 3724, 2820, 1856, 852, -171, -1190, -2183, -3129, -4008, -4799, -5487, -6056, -6494, -6791, -6941, -4038, -4607, -4999, -5198, -5198, -4999, -4607, -4038, -3314, -2462, -1516, -512, 512, 1516, 2462, 3314, 4038, 4607, 4999, 5198, 5198, 4999, 4607, 4038, 3314, 2462, 1516, 512, -512, -1516, -2462, -3314, -4038, -4607, -4999, -5198, -5198, -4999, -4607, -4038, -3314, -2462, -1516, -512, 512, 1516, 2462, 3314, 4038, 4607, 4999, 5198, 5198, 4999, 4607, 4038, 3314, 2462, 1516, 512, -512, -1516, -2462, -3314, -4038, -4607, -4999, -5198, -5198, -4999, -4607, -4038, -3314, -2462, -1516, -512, 512, 1516, 2462, 3314, 4038, 4607, 4999, 5198, 5198, 4999, 4607, 4038, 3314, 2462, 1516, 512, -512, -1516, -2462, -3314, -4038, -4607, -4999, -5198, -5198, -4999, -4607, -4038, -3314, -2462, -1516, -512, 512, 1516, 2462, 3314, 4038, 4607, 4999, 5198, 5198, 4999, 4607, 4038, 3314, 2462, 1516, 512, -512, -1516, -2462, -3314, -4038, -4607, -4999, -5198, -2732, -3420, -3902, -4151, -4151, -3902, -3420, -2732, -1881, -916, 103, 1116, 2062, 2884, 3534, 3972, 4171, 4121, 3824, 3297, 2573, 1695, 715, -308, -1312, -2238, -3029, -3639, -4031, -4181, -4081, -3736, -3167, -2408, -1505, -512, 512, 1505, 2408, 3167, 3736, 4081, 4181, 4031, 3639, 3029, 2238, 1312, 308, -715, -1695, -2573, -3297, -3824, -4121, -4171, -3972, -3534, -2884, -2062, -1116, -103, 916, 1881, 2732, 3420, 3902, 4151, 4151, 3902, 3420, 2732, 1881, 916, -103, -1116, -2062, -2884, -3534, -3972, -4171, -4121, -3824, -3297, -2573, -1695, -715, 308, 1312, 2238, 3029, 3639, 4031, 4181, 4081, 3736, 3167, 2408, 1505, 512, -512, -1505, -2408, -3167, -3736, -4081, -4181, -4031, -3639, -3029, -2238, -1312, -308, 715, 1695, 2573, 3297, 3824, 4121, 4171, 3972, 3534, 2884, 2062, 1116, 103, -916, -1881, -2732, -3420, -3902, -4151, -1794, -2585, -3154, -3452, -3452, -3154, -2585, -1794, -848, 171, 1176, 2079, 2803, 3285, 3485, 3385, 2993, 2343, 1492, 512, -512, -1492, -2343, -2993, -3385, -3485, -3285, -2803, -2079, -1176, -171, 848, 1794, 2585, 3154, 3452, 3452, 3154, 2585, 1794, 848, -171, -1176, -2079, -2803, -3285, -3485, -3385, -2993, -2343, -1492, -512, 512, 1492, 2343, 2993, 3385, 3485, 3285, 2803, 2079, 1176, 171, -848, -1794, -2585, -3154, -3452, -3452, -3154, -2585, -1794, -848, 171, 1176, 2079, 2803, 3285, 3485, 3385, 2993, 2343, 1492, 512, -512, -1492, -2343, -2993, -3385, -3485, -3285, -2803, -2079, -1176, -171, 848, 1794, 2585, 3154, 3452, 3452, 3154, 2585, 1794, 848, -171, -1176, -2079, -2803, -3285, -3485, -3385, -2993, -2343, -1492, -512, 512, 1492, 2343, 2993, 3385, 3485, 3285, 2803, 2079, 1176, 171, -848, -1794, -2585, -3154, -3452, -1078, -1956, -2606, -2951, -2951, -2606, -1956, -1078, -73, 939, 1843, 2530, 2922, 2972, 2675, 2065, 1214, 220, -799, -1724, -2449, -2886, -2987, -2738, -2169, -1347, -367, 656, 1602, 2361, 2844, 2994, 2794, 2268, 1476, 512, -512, -1476, -2268, -2794, -2994, -2844, -2361, -1602, -656, 367, 1347, 2169, 2738, 2987, 2886, 2449, 1724, 799, -220, -1214, -2065, -2675, -2972, -2922, -2530, -1843, -939, 73, 1078, 1956, 2606, 2951, 2951, 2606, 1956, 1078, 73, -939, -1843, -2530, -2922, -2972, -2675, -2065, -1214, -220, 799, 1724, 2449, 2886, 2987, 2738, 2169, 1347, 367, -656, -1602, -2361, -2844, -2994, -2794, -2268, -1476, -512, 512, 1476, 2268, 2794, 2994, 2844, 2361, 1602, 656, -367, -1347, -2169, -2738, -2987, -2886, -2449, -1724, -799, 220, 1214, 2065, 2675, 2972, 2922, 2530, 1843, 939, -73, -1078, -1956, -2606, -2951, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -9825, -10122, -10322, -10422, -10422, -10322, -10122, -9825, -9433, -8950, -8381, -7732, -7007, -6216, -5364, -4461, -3515, -2535, -1531, -512, 512, 1531, 2535, 3515, 4461, 5364, 6216, 7007, 7732, 8381, 8950, 9433, 9825, 10122, 10322, 10422, 10422, 10322, 10122, 9825, 9433, 8950, 8381, 7732, 7007, 6216, 5364, 4461, 3515, 2535, 1531, 512, -512, -1531, -2535, -3515, -4461, -5364, -6216, -7007, -7732, -8381, -8950, -9433, -9825, -10122, -10322, -10422, -10422, -10322, -10122, -9825, -9433, -8950, -8381, -7732, -7007, -6216, -5364, -4461, -3515, -2535, -1531, -512, 512, 1531, 2535, 3515, 4461, 5364, 6216, 7007, 7732, 8381, 8950, 9433, 9825, 10122, 10322, 10422, 10422, 10322, 10122, 9825, 9433, 8950, 8381, 7732, 7007, 6216, 5364, 4461, 3515, 2535, 1531, 512, -512, -1531, -2535, -3515, -4461, -5364, -6216, -7007, -7732, -8381, -8950, -9433, -9825, -10122, -10322, -10422, -6056, -6494, -6791, -6941, -6941, -6791, -6494, -6056, -5487, -4799, -4008, -3129, -2183, -1190, -171, 852, 1856, 2820, 3724, 4546, 5270, 5880, 6363, 6708, 6908, 6958, 6857, 6609, 6217, 5690, 5041, 4282, 3431, 2505, 1525, 512, -512, -1525, -2505, -3431, -4282, -5041, -5690, -6217, -6609, -6857, -6958, -6908, -6708, -6363, -5880, -5270, -4546, -3724, -2820, -1856, -852, 171, 1190, 2183, 3129, 4008, 4799, 5487, 6056, 6494, 6791, 6941, 6941, 6791, 6494, 6056, 5487, 4799, 4008, 3129, 2183, 1190, 171, -852, -1856, -2820, -3724, -4546, -5270, -5880, -6363, -6708, -6908, -6958, -6857, -6609, -6217, -5690, -5041, -4282, -3431, -2505, -1525, -512, 512, 1525, 2505, 3431, 4282, 5041, 5690, 6217, 6609, 6857, 6958, 6908, 6708, 6363, 5880, 5270, 4546, 3724, 2820, 1856, 852, -171, -1190, -2183, -3129, -4008, -4799, -5487, -6056, -6494, -6791, -6941, -4038, -4607, -4999, -5198, -5198, -4999, -4607, -4038, -3314, -2462, -1516, -512, 512, 1516, 2462, 3314, 4038, 4607, 4999, 5198, 5198, 4999, 4607, 4038, 3314, 2462, 1516, 512, -512, -1516, -2462, -3314, -4038, -4607, -4999, -5198, -5198, -4999, -4607, -4038, -3314, -2462, -1516, -512, 512, 1516, 2462, 3314, 4038, 4607, 4999, 5198, 5198, 4999, 4607, 4038, 3314, 2462, 1516, 512, -512, -1516, -2462, -3314, -4038, -4607, -4999, -5198, -5198, -4999, -4607, -4038, -3314, -2462, -1516, -512, 512, 1516, 2462, 3314, 4038, 4607, 4999, 5198, 5198, 4999, 4607, 4038, 3314, 2462, 1516, 512, -512, -1516, -2462, -3314, -4038, -4607, -4999, -5198, -5198, -4999, -4607, -4038, -3314, -2462, -1516, -512, 512, 1516, 2462, 3314, 4038, 4607, 4999, 5198, 5198, 4999, 4607, 4038, 3314, 2462, 1516, 512, -512, -1516, -2462, -3314, -4038, -4607, -4999, -5198, -1794, -2585, -3154, -3452, -3452, -3154, -2585, -1794, -848, 171, 1176, 2079, 2803, 3285, 3485, 3385, 2993, 2343, 1492, 512, -512, -1492, -2343, -2993, -3385, -3485, -3285, -2803, -2079, -1176, -171, 848, 1794, 2585, 3154, 3452, 3452, 3154, 2585, 1794, 848, -171, -1176, -2079, -2803, -3285, -3485, -3385, -2993, -2343, -1492, -512, 512, 1492, 2343, 2993, 3385, 3485, 3285, 2803, 2079, 1176, 171, -848, -1794, -2585, -3154, -3452, -3452, -3154, -2585, -1794, -848, 171, 1176, 2079, 2803, 3285, 3485, 3385, 2993, 2343, 1492, 512, -512, -1492, -2343, -2993, -3385, -3485, -3285, -2803, -2079, -1176, -171, 848, 1794, 2585, 3154, 3452, 3452, 3154, 2585, 1794, 848, -171, -1176, -2079, -2803, -3285, -3485, -3385, -2993, -2343, -1492, -512, 512, 1492, 2343, 2993, 3385, 3485, 3285, 2803, 2079, 1176, 171, -848, -1794, -2585, -3154, -3452, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, -2574, -2182, -1458, -512, 512, 1458, 2182, 2574, 2574, 2182, 1458, 512, -512, -1458, -2182, -2574, 831, -173, -1119, -1688, -1688, -1119, -173, 831, 1556, 1755, 1363, 512, -512, -1363, -1755, -1556, -831, 173, 1119, 1688, 1688, 1119, 173, -831, -1556, -1755, -1363, -512, 512, 1363, 1755, 1556, 831, -173, -1119, -1688, -1688, -1119, -173, 831, 1556, 1755, 1363, 512, -512, -1363, -1755, -1556, -831, 173, 1119, 1688, 1688, 1119, 173, -831, -1556, -1755, -1363, -512, 512, 1363, 1755, 1556, 831, -173, -1119, -1688, -1688, -1119, -173, 831, 1556, 1755, 1363, 512, -512, -1363, -1755, -1556, -831, 173, 1119, 1688, 1688, 1119, 173, -831, -1556, -1755, -1363, -512, 512, 1363, 1755, 1556, 831, -173, -1119, -1688, -1688, -1119, -173, 831, 1556, 1755, 1363, 512, -512, -1363, -1755, -1556, -831, 173, 1119, 1688, 1688, 1119, 173, -831, -1556, -1755, -1363, -512, 512, 1363, 1755, 1556, 831, -173, -1119, -1688, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, -1236, -512, 512, 1236, 1236, 512, -512, -1236, 512, 904, 180, -766, -766, 180, 904, 512, -512, -904, -180, 766, 766, -180, -904, -512, 512, 904, 180, -766, -766, 180, 904, 512, -512, -904, -180, 766, 766, -180, -904, -512, 512, 904, 180, -766, -766, 180, 904, 512, -512, -904, -180, 766, 766, -180, -904, -512, 512, 904, 180, -766, -766, 180, 904, 512, -512, -904, -180, 766, 766, -180, -904, -512, 512, 904, 180, -766, -766, 180, 904, 512, -512, -904, -180, 766, 766, -180, -904, -512, 512, 904, 180, -766, -766, 180, 904, 512, -512, -904, -180, 766, 766, -180, -904, -512, 512, 904, 180, -766, -766, 180, 904, 512, -512, -904, -180, 766, 766, -180, -904, -512, 512, 904, 180, -766, -766, 180, 904, 512, -512, -904, -180, 766, 766, -180, -904, -512, 512, 904, 180, -766, -1114, -2082, -2836, -3249, -3249, -2836, -2082, -1114, -90, 834, 1535, 1940, 2042, 1888, 1567, 1179, 820, 551, 398, 344, 344, 340, 282, 135, -106, -417, -757, -1074, -1320, -1460, -1479, -1379, -1175, -892, -555, -188, 188, 555, 892, 1175, 1379, 1479, 1460, 1320, 1074, 757, 417, 106, -135, -282, -340, -344, -344, -398, -551, -820, -1179, -1567, -1888, -2042, -1940, -1535, -834, 90, 1114, 2082, 2836, 3249, 3249, 2836, 2082, 1114, 90, -834, -1535, -1940, -2042, -1888, -1567, -1179, -820, -551, -398, -344, -344, -340, -282, -135, 106, 417, 757, 1074, 1320, 1460, 1479, 1379, 1175, 892, 555, 188, -188, -555, -892, -1175, -1379, -1479, -1460, -1320, -1074, -757, -417, -106, 135, 282, 340, 344, 344, 398, 551, 820, 1179, 1567, 1888, 2042, 1940, 1535, 834, -90, -1114, -2082, -2836, -3249, -1, -1025, -1892, -2388, -2388, -1892, -1025, -1, 939, 1592, 1848, 1708, 1273, 702, 158, -239, -444, -481, -427, -369, -369, -444, -565, -668, -686, -575, -329, 15, 392, 728, 961, 1053, 998, 811, 526, 182, -182, -526, -811, -998, -1053, -961, -728, -392, -15, 329, 575, 686, 668, 565, 444, 369, 369, 427, 481, 444, 239, -158, -702, -1273, -1708, -1848, -1592, -939, 1, 1025, 1892, 2388, 2388, 1892, 1025, 1, -939, -1592, -1848, -1708, -1273, -702, -158, 239, 444, 481, 427, 369, 369, 444, 565, 668, 686, 575, 329, -15, -392, -728, -961, -1053, -998, -811, -526, -182, 182, 526, 811, 998, 1053, 961, 728, 392, 15, -329, -575, -686, -668, -565, -444, -369, -369, -427, -481, -444, -239, 158, 702, 1273, 1708, 1848, 1592, 939, -1, -1025, -1892, -2388, 657, -367, -1338, -1927, -1927, -1338, -367, 657, 1404, 1662, 1411, 803, 89, -487, -779, -780, -589, -351, -182, -118, -118, -100, 4, 206, 452, 648, 703, 573, 277, -106, -475, -735, -829, -746, -513, -182, 182, 513, 746, 829, 735, 475, 106, -277, -573, -703, -648, -452, -206, -4, 100, 118, 118, 182, 351, 589, 780, 779, 487, -89, -803, -1411, -1662, -1404, -657, 367, 1338, 1927, 1927, 1338, 367, -657, -1404, -1662, -1411, -803, -89, 487, 779, 780, 589, 351, 182, 118, 118, 100, -4, -206, -452, -648, -703, -573, -277, 106, 475, 735, 829, 746, 513, 182, -182, -513, -746, -829, -735, -475, -106, 277, 573, 703, 648, 452, 206, 4, -100, -118, -118, -182, -351, -589, -780, -779, -487, 89, 803, 1411, 1662, 1404, 657, -367, -1338, -1927, 1162, 425, -599, -1324, -1324, -599, 425, 1162, 1225, 644, -191, -796, -890, -532, -18, 342, 416, 286, 128, 58, 58, 27, -103, -289, -400, -320, -45, 298, 526, 513, 260, -111, -428, -558, -457, -175, 175, 457, 558, 428, 111, -260, -513, -526, -298, 45, 320, 400, 289, 103, -27, -58, -58, -128, -286, -416, -342, 18, 532, 890, 796, 191, -644, -1225, -1162, -425, 599, 1324, 1324, 599, -425, -1162, -1225, -644, 191, 796, 890, 532, 18, -342, -416, -286, -128, -58, -58, -27, 103, 289, 400, 320, 45, -298, -526, -513, -260, 111, 428, 558, 457, 175, -175, -457, -558, -428, -111, 260, 513, 526, 298, -45, -320, -400, -289, -103, 27, 58, 58, 128, 286, 416, 342, -18, -532, -890, -796, -191, 644, 1225, 1162, 425, -599, -1324, 1114, 856, -168, -1084, -1084, -168, 856, 1114, 444, -511, -936, -564, 168, 609, 490, 63, -245, -258, -119, -38, -38, 8, 158, 281, 197, -99, -380, -390, -86, 302, 473, 300, -82, -398, -438, -187, 187, 438, 398, 82, -300, -473, -302, 86, 390, 380, 99, -197, -281, -158, -8, 38, 38, 119, 258, 245, -63, -490, -609, -168, 564, 936, 511, -444, -1114, -856, 168, 1084, 1084, 168, -856, -1114, -444, 511, 936, 564, -168, -609, -490, -63, 245, 258, 119, 38, 38, -8, -158, -281, -197, 99, 380, 390, 86, -302, -473, -300, 82, 398, 438, 187, -187, -438, -398, -82, 300, 473, 302, -86, -390, -380, -99, 197, 281, 158, 8, -38, -38, -119, -258, -245, 63, 490, 609, 168, -564, -936, -511, 444, 1114, 856, -168, -1084, -11, 791, 366, -658, -658, 366, 791, -11, -731, -293, 514, 455, -234, -445, -3, 304, 120, -118, -98, -18, -18, 45, 144, 38, -200, -176, 145, 287, 2, -303, -175, 201, 292, -16, -294, -176, 176, 294, 16, -292, -201, 175, 303, -2, -287, -145, 176, 200, -38, -144, -45, 18, 18, 98, 118, -120, -304, 3, 445, 234, -455, -514, 293, 731, 11, -791, -366, 658, 658, -366, -791, 11, 731, 293, -514, -455, 234, 445, 3, -304, -120, 118, 98, 18, 18, -45, -144, -38, 200, 176, -145, -287, -2, 303, 175, -201, -292, 16, 294, 176, -176, -294, -16, 292, 201, -175, -303, 2, 287, 145, -176, -200, 38, 144, 45, -18, -18, -98, -118, 120, 304, -3, -445, -234, 455, 514, -293, -731, -11, 791, 366, -658, -626, 225, 585, -439, -439, 585, 225, -626, 0, 560, -178, -415, 269, 244, -265, -100, 188, 19, -82, -11, -11, 61, 60, -136, -57, 202, 14, -238, 45, 241, -98, -222, 135, 196, -157, -174, 174, 157, -196, -135, 222, 98, -241, -45, 238, -14, -202, 57, 136, -60, -61, 11, 11, 82, -19, -188, 100, 265, -244, -269, 415, 178, -560, 0, 626, -225, -585, 439, 439, -585, -225, 626, 0, -560, 178, 415, -269, -244, 265, 100, -188, -19, 82, 11, 11, -61, -60, 136, 57, -202, -14, 238, -45, -241, 98, 222, -135, -196, 157, 174, -174, -157, 196, 135, -222, -98, 241, 45, -238, 14, 202, -57, -136, 60, 61, -11, -11, -82, 19, 188, -100, -265, 244, 269, -415, -178, 560, 0, -626, 225, 585, -439, 462, -562, 456, -175, -175, 456, -562, 462, -205, -97, 325, -403, 325, -150, -31, 145, -162, 106, -32, -7, -7, 56, -93, 79, -5, -99, 180, -189, 112, 21, -149, 209, -171, 51, 91, -186, 186, -91, -51, 171, -209, 149, -21, -112, 189, -180, 99, 5, -79, 93, -56, 7, 7, 32, -106, 162, -145, 31, 150, -325, 403, -325, 97, 205, -462, 562, -456, 175, 175, -456, 562, -462, 205, 97, -325, 403, -325, 150, 31, -145, 162, -106, 32, 7, 7, -56, 93, -79, 5, 99, -180, 189, -112, -21, 149, -209, 171, -51, -91, 186, -186, 91, 51, -171, 209, -149, 21, 112, -189, 180, -99, -5, 79, -93, 56, -7, -7, -32, 106, -162, 145, -31, -150, 325, -403, 325, -97, -205, 462, -562, 456, -175, -17260, -17514, -17685, -17770, -17770, -17685, -17514, -17260, -16924, -16508, -16016, -15451, -14817, -14119, -13361, -12549, -11688, -10785, -9845, -8875, -7882, -6872, -5852, -4828, -3807, -2795, -1798, -822, 127, 1044, 1923, 2762, 3555, 4300, 4992, 5630, 6212, 6736, 7201, 7608, 7956, 8246, 8480, 8658, 8784, 8861, 8890, 8876, 8822, 8733, 8612, 8464, 8294, 8105, 7904, 7694, 7479, 7265, 7056, 6855, 6666, 6493, 6339, 6206, 6097, 6013, 5957, 5928, 5928, 5957, 6013, 6097, 6206, 6339, 6493, 6666, 6855, 7056, 7265, 7479, 7694, 7904, 8105, 8294, 8464, 8612, 8733, 8822, 8876, 8890, 8861, 8784, 8658, 8480, 8246, 7956, 7608, 7201, 6736, 6212, 5630, 4992, 4300, 3555, 2762, 1923, 1044, 127, -822, -1798, -2795, -3807, -4828, -5852, -6872, -7882, -8875, -9845, -10785, -11688, -12549, -13361, -14119, -14817, -15451, -16016, -16508, -16924, -17260, -17514, -17685, -17770, -14591, -14946, -15185, -15306, -15306, -15185, -14946, -14591, -14127, -13558, -12894, -12144, -11319, -10428, -9486, -8504, -7495, -6472, -5448, -4435, -3445, -2489, -1577, -717, 83, 817, 1479, 2067, 2579, 3014, 3374, 3662, 3880, 4034, 4130, 4174, 4174, 4137, 4073, 3989, 3893, 3794, 3698, 3613, 3545, 3500, 3480, 3490, 3532, 3607, 3716, 3856, 4025, 4222, 4442, 4680, 4931, 5190, 5450, 5706, 5952, 6182, 6390, 6572, 6723, 6839, 6918, 6958, 6958, 6918, 6839, 6723, 6572, 6390, 6182, 5952, 5706, 5450, 5190, 4931, 4680, 4442, 4222, 4025, 3856, 3716, 3607, 3532, 3490, 3480, 3500, 3545, 3613, 3698, 3794, 3893, 3989, 4073, 4137, 4174, 4174, 4130, 4034, 3880, 3662, 3374, 3014, 2579, 2067, 1479, 817, 83, -717, -1577, -2489, -3445, -4435, -5448, -6472, -7495, -8504, -9486, -10428, -11319, -12144, -12894, -13558, -14127, -14591, -14946, -15185, -15306, -10925, -11467, -11839, -12029, -12029, -11839, -11467, -10925, -10234, -9416, -8500, -7516, -6496, -5472, -4474, -3528, -2657, -1880, -1209, -652, -210, 121, 350, 491, 559, 572, 551, 514, 480, 463, 476, 529, 628, 773, 963, 1191, 1450, 1729, 2016, 2299, 2565, 2805, 3009, 3172, 3288, 3359, 3386, 3374, 3329, 3262, 3182, 3098, 3023, 2963, 2927, 2921, 2947, 3006, 3096, 3211, 3347, 3494, 3644, 3787, 3915, 4018, 4091, 4129, 4129, 4091, 4018, 3915, 3787, 3644, 3494, 3347, 3211, 3096, 3006, 2947, 2921, 2927, 2963, 3023, 3098, 3182, 3262, 3329, 3374, 3386, 3359, 3288, 3172, 3009, 2805, 2565, 2299, 2016, 1729, 1450, 1191, 963, 773, 628, 529, 476, 463, 480, 514, 551, 572, 559, 491, 350, 121, -210, -652, -1209, -1880, -2657, -3528, -4474, -5472, -6496, -7516, -8500, -9416, -10234, -10925, -11467, -11839, -12029, -7628, -8407, -8966, -9258, -9258, -8966, -8407, -7628, -6693, -5676, -4652, -3690, -2847, -2161, -1649, -1308, -1115, -1036, -1027, -1042, -1042, -996, -885, -704, -464, -182, 116, 403, 654, 851, 985, 1056, 1074, 1056, 1024, 999, 999, 1037, 1119, 1241, 1393, 1561, 1727, 1872, 1984, 2054, 2081, 2069, 2030, 1979, 1931, 1902, 1902, 1936, 2004, 2099, 2208, 2318, 2413, 2481, 2514, 2510, 2472, 2409, 2334, 2260, 2202, 2170, 2170, 2202, 2260, 2334, 2409, 2472, 2510, 2514, 2481, 2413, 2318, 2208, 2099, 2004, 1936, 1902, 1902, 1931, 1979, 2030, 2069, 2081, 2054, 1984, 1872, 1727, 1561, 1393, 1241, 1119, 1037, 999, 999, 1024, 1056, 1074, 1056, 985, 851, 654, 403, 116, -182, -464, -704, -885, -996, -1042, -1042, -1027, -1036, -1115, -1308, -1649, -2161, -2847, -3690, -4652, -5676, -6693, -7628, -8407, -8966, -9258, -4585, -5604, -6428, -6888, -6888, -6428, -5604, -4585, -3561, -2697, -2092, -1760, -1644, -1637, -1631, -1545, -1351, -1072, -765, -497, -315, -229, -217, -229, -217, -146, -13, 161, 336, 472, 549, 567, 552, 537, 555, 621, 728, 852, 962, 1034, 1058, 1044, 1017, 1005, 1028, 1091, 1179, 1269, 1336, 1365, 1355, 1322, 1291, 1283, 1311, 1369, 1441, 1503, 1535, 1530, 1495, 1450, 1418, 1415, 1446, 1499, 1553, 1588, 1588, 1553, 1499, 1446, 1415, 1418, 1450, 1495, 1530, 1535, 1503, 1441, 1369, 1311, 1283, 1291, 1322, 1355, 1365, 1336, 1269, 1179, 1091, 1028, 1005, 1017, 1044, 1058, 1034, 962, 852, 728, 621, 555, 537, 552, 567, 549, 472, 336, 161, -13, -146, -217, -229, -217, -229, -315, -497, -765, -1072, -1351, -1545, -1631, -1637, -1644, -1760, -2092, -2697, -3561, -4585, -5604, -6428, -6888, -2258, -3160, -4184, -4869, -4869, -4184, -3160, -2258, -1761, -1637, -1639, -1535, -1273, -974, -783, -735, -739, -682, -530, -353, -239, -215, -221, -182, -75, 50, 127, 139, 130, 159, 241, 337, 392, 396, 384, 406, 473, 549, 590, 586, 573, 589, 645, 707, 737, 728, 711, 724, 770, 822, 843, 829, 810, 818, 858, 901, 915, 896, 873, 878, 913, 949, 955, 931, 905, 906, 937, 966, 966, 937, 906, 905, 931, 955, 949, 913, 878, 873, 896, 915, 901, 858, 818, 810, 829, 843, 822, 770, 724, 711, 728, 737, 707, 645, 589, 573, 586, 590, 549, 473, 406, 384, 396, 392, 337, 241, 159, 130, 139, 127, 50, -75, -182, -221, -215, -239, -353, -530, -682, -739, -735, -783, -974, -1273, -1535, -1639, -1637, -1761, -2258, -3160, -4184, -4869, -1529, -1723, -2622, -3646, -3646, -2622, -1723, -1529, -1503, -1217, -952, -923, -874, -683, -562, -563, -497, -358, -305, -307, -230, -132, -116, -107, -29, 35, 33, 55, 128, 163, 156, 191, 252, 264, 260, 303, 348, 345, 350, 396, 423, 413, 428, 471, 481, 470, 494, 529, 524, 518, 549, 571, 558, 560, 592, 600, 583, 594, 622, 616, 602, 621, 639, 623, 615, 638, 644, 623, 623, 644, 638, 615, 623, 639, 621, 602, 616, 622, 594, 583, 600, 592, 560, 558, 571, 549, 518, 524, 529, 494, 470, 481, 471, 428, 413, 423, 396, 350, 345, 348, 303, 260, 264, 252, 191, 156, 163, 128, 55, 33, 35, -29, -107, -116, -132, -230, -307, -305, -358, -497, -563, -562, -683, -874, -923, -952, -1217, -1503, -1529, -1723, -2622, -3646, -935, -1169, -1256, -2280, -2280, -1256, -1169, -935, -788, -735, -574, -574, -442, -432, -352, -311, -280, -213, -212, -141, -141, -89, -72, -48, -10, -8, 39, 35, 74, 81, 102, 124, 127, 160, 155, 187, 187, 206, 219, 222, 246, 240, 266, 262, 279, 285, 289, 306, 300, 321, 314, 330, 330, 335, 345, 339, 356, 346, 361, 356, 362, 367, 361, 374, 362, 376, 367, 372, 372, 367, 376, 362, 374, 361, 367, 362, 356, 361, 346, 356, 339, 345, 335, 330, 330, 314, 321, 300, 306, 289, 285, 279, 262, 266, 240, 246, 222, 219, 206, 187, 187, 155, 160, 127, 124, 102, 81, 74, 35, 39, -8, -10, -48, -72, -89, -141, -141, -212, -213, -280, -311, -352, -432, -442, -574, -574, -735, -788, -935, -1169, -1256, -2280, -11045, -11619, -12033, -12251, -12251, -12033, -11619, -11045, -10360, -9620, -8874, -8167, -7524, -6953, -6446, -5978, -5511, -5006, -4426, -3745, -2951, -2051, -1069, -45, 972, 1930, 2781, 3489, 4034, 4415, 4651, 4776, 4835, 4877, 4947, 5080, 5294, 5589, 5945, 6326, 6688, 6978, 7152, 7174, 7025, 6704, 6231, 5640, 4979, 4299, 3648, 3066, 2575, 2181, 1873, 1623, 1394, 1145, 840, 453, -26, -589, -1210, -1847, -2448, -2959, -3331, -3528, -3528, -3331, -2959, -2448, -1847, -1210, -589, -26, 453, 840, 1145, 1394, 1623, 1873, 2181, 2575, 3066, 3648, 4299, 4979, 5640, 6231, 6704, 7025, 7174, 7152, 6978, 6688, 6326, 5945, 5589, 5294, 5080, 4947, 4877, 4835, 4776, 4651, 4415, 4034, 3489, 2781, 1930, 972, -45, -1069, -2051, -2951, -3745, -4426, -5006, -5511, -5978, -6446, -6953, -7524, -8167, -8874, -9620, -10360, -11045, -11619, -12033, -12251, -6418, -7272, -8015, -8452, -8452, -8015, -7272, -6418, -5623, -4956, -4371, -3750, -2991, -2066, -1042, -42, 822, 1507, 2045, 2514, 2967, 3399, 3741, 3903, 3841, 3587, 3241, 2917, 2675, 2481, 2225, 1790, 1126, 303, -507, -1106, -1356, -1252, -916, -536, -270, -177, -199, -208, -90, 195, 590, 982, 1271, 1420, 1470, 1504, 1582, 1700, 1793, 1773, 1592, 1282, 941, 676, 544, 503, 437, 221, -201, -769, -1318, -1657, -1657, -1318, -769, -201, 221, 437, 503, 544, 676, 941, 1282, 1592, 1773, 1793, 1700, 1582, 1504, 1470, 1420, 1271, 982, 590, 195, -90, -208, -199, -177, -270, -536, -916, -1252, -1356, -1106, -507, 303, 1126, 1790, 2225, 2481, 2675, 2917, 3241, 3587, 3841, 3903, 3741, 3399, 2967, 2514, 2045, 1507, 822, -42, -1042, -2066, -2991, -3750, -4371, -4956, -5623, -6418, -7272, -8015, -8452, -3929, -4693, -5552, -6153, -6153, -5552, -4693, -3929, -3314, -2646, -1759, -735, 194, 892, 1419, 1886, 2273, 2458, 2376, 2120, 1833, 1549, 1192, 728, 264, -47, -181, -259, -374, -439, -285, 99, 475, 567, 370, 187, 329, 784, 1216, 1301, 1029, 662, 432, 330, 193, -50, -289, -377, -311, -216, -171, -114, 53, 312, 532, 624, 645, 710, 816, 827, 655, 398, 255, 272, 251, -41, -571, -1004, -1004, -571, -41, 251, 272, 255, 398, 655, 827, 816, 710, 645, 624, 532, 312, 53, -114, -171, -216, -311, -377, -289, -50, 193, 330, 432, 662, 1029, 1301, 1216, 784, 329, 187, 370, 567, 475, 99, -285, -439, -374, -259, -181, -47, 264, 728, 1192, 1549, 1833, 2120, 2376, 2458, 2273, 1886, 1419, 892, 194, -735, -1759, -2646, -3314, -3929, -4693, -5552, -6153, -2734, -3386, -4247, -5001, -5001, -4247, -3386, -2734, -1987, -963, 27, 725, 1245, 1674, 1845, 1694, 1414, 1116, 717, 256, -66, -212, -307, -331, -156, 131, 336, 499, 740, 913, 829, 670, 675, 602, 100, -539, -673, -282, 23, -23, -51, 181, 425, 476, 487, 569, 559, 386, 218, 130, 0, -174, -229, -158, -109, -70, 90, 295, 371, 380, 470, 515, 345, 153, 180, 178, -215, -723, -723, -215, 178, 180, 153, 345, 515, 470, 380, 371, 295, 90, -70, -109, -158, -229, -174, 0, 130, 218, 386, 559, 569, 487, 476, 425, 181, -51, -23, 23, -282, -673, -539, 100, 602, 675, 670, 829, 913, 740, 499, 336, 131, -156, -331, -307, -212, -66, 256, 717, 1116, 1414, 1694, 1845, 1674, 1245, 725, 27, -963, -1987, -2734, -3386, -4247, -5001, -1834, -2524, -3289, -4139, -4139, -3289, -2524, -1834, -810, 145, 757, 1236, 1450, 1282, 1003, 654, 203, -102, -228, -288, -162, 104, 302, 502, 676, 640, 531, 428, 178, -31, -50, -144, -155, 163, 233, -103, -6, 502, 538, 233, 156, 78, -123, -138, -63, -50, 80, 244, 278, 322, 344, 218, 107, 38, -100, -152, -85, -66, 22, 201, 243, 264, 358, 239, 78, 167, -9, -542, -542, -9, 167, 78, 239, 358, 264, 243, 201, 22, -66, -85, -152, -100, 38, 107, 218, 344, 322, 278, 244, 80, -50, -63, -138, -123, 78, 156, 233, 538, 502, -6, -103, 233, 163, -155, -144, -50, -31, 178, 428, 531, 640, 676, 502, 302, 104, -162, -288, -228, -102, 203, 654, 1003, 1282, 1450, 1236, 757, 145, -810, -1834, -2524, -3289, -4139, -1039, -1925, -2598, -3496, -3496, -2598, -1925, -1039, -15, 613, 1075, 1152, 902, 590, 150, -129, -234, -216, 22, 235, 435, 558, 476, 373, 161, -31, -85, -141, -2, 142, 235, 418, 320, 302, 276, -318, -409, 33, -16, 26, 239, 223, 291, 246, 106, 54, -79, -97, -50, -12, 131, 183, 217, 222, 104, 50, -52, -109, -48, -41, 95, 177, 176, 266, 107, 80, 97, -417, -417, 97, 80, 107, 266, 176, 177, 95, -41, -48, -109, -52, 50, 104, 222, 217, 183, 131, -12, -50, -97, -79, 54, 106, 246, 291, 223, 239, 26, -16, 33, -409, -318, 276, 302, 320, 418, 235, 142, -2, -141, -85, -31, 161, 373, 476, 558, 435, 235, 22, -216, -234, -129, 150, 590, 902, 1152, 1075, 613, -15, -1039, -1925, -2598, -3496, -383, -1407, -2047, -2928, -2928, -2047, -1407, -383, 360, 841, 939, 690, 351, -41, -184, -208, 10, 212, 407, 436, 338, 170, -25, -87, -103, 54, 153, 299, 279, 232, 99, -27, -33, -96, 181, -109, -39, 359, 106, 95, -41, -64, -24, 28, 150, 158, 194, 88, 38, -63, -62, -36, 39, 126, 144, 160, 60, 24, -77, -43, -35, 66, 126, 146, 172, 18, 130, -315, -315, 130, 18, 172, 146, 126, 66, -35, -43, -77, 24, 60, 160, 144, 126, 39, -36, -62, -63, 38, 88, 194, 158, 150, 28, -24, -64, -41, 95, 106, 359, -39, -109, 181, -96, -33, -27, 99, 232, 279, 299, 153, 54, -103, -87, -25, 170, 338, 436, 407, 212, 10, -208, -184, -41, 351, 690, 939, 841, 360, -383, -1407, -2047, -2928, 22, -1002, -1731, -2605, -2605, -1731, -1002, 22, 583, 854, 626, 288, -85, -197, -126, 117, 312, 393, 297, 117, -46, -103, -24, 108, 240, 249, 195, 41, -26, -83, 36, 84, 242, 139, 237, -185, -252, 72, -30, 161, 131, 176, 56, 12, -67, -24, 21, 111, 131, 115, 39, -27, -55, -29, 44, 97, 131, 78, 32, -52, -32, -31, 87, 81, 168, 20, 122, -248, -248, 122, 20, 168, 81, 87, -31, -32, -52, 32, 78, 131, 97, 44, -29, -55, -27, 39, 115, 131, 111, 21, -24, -67, 12, 56, 176, 131, 161, -30, 72, -252, -185, 237, 139, 242, 84, 36, -83, -26, 41, 195, 249, 240, 108, -24, -103, -46, 117, 297, 393, 312, 117, -126, -197, -85, 288, 626, 854, 583, 22, -1002, -1731, -2605, -23288, -23584, -23805, -23935, -23935, -23805, -23584, -23288, -22923, -22499, -22019, -21489, -20914, -20295, -19638, -18943, -18215, -17455, -16665, -15849, -15008, -14143, -13257, -12351, -11427, -10487, -9532, -8564, -7583, -6593, -5594, -4587, -3574, -2556, -1535, -512, 512, 1535, 2556, 3574, 4587, 5594, 6593, 7583, 8564, 9532, 10487, 11427, 12351, 13257, 14143, 15008, 15849, 16665, 17455, 18215, 18943, 19638, 20295, 20914, 21489, 22019, 22499, 22923, 23288, 23584, 23805, 23935, 23935, 23805, 23584, 23288, 22923, 22499, 22019, 21489, 20914, 20295, 19638, 18943, 18215, 17455, 16665, 15849, 15008, 14143, 13257, 12351, 11427, 10487, 9532, 8564, 7583, 6593, 5594, 4587, 3574, 2556, 1535, 512, -512, -1535, -2556, -3574, -4587, -5594, -6593, -7583, -8564, -9532, -10487, -11427, -12351, -13257, -14143, -15008, -15849, -16665, -17455, -18215, -18943, -19638, -20295, -20914, -21489, -22019, -22499, -22923, -23288, -23584, -23805, -23935, -12795, -13401, -13864, -14157, -14157, -13864, -13401, -12795, -12083, -11279, -10406, -9474, -8502, -7498, -6481, -5457, -4444, -3454, -2508, -1621, -852, -205, 360, 844, 1252, 1561, 1754, 1873, 1936, 1956, 1944, 1909, 1859, 1802, 1749, 1708, 1708, 1752, 1817, 1903, 2003, 2120, 2250, 2399, 2565, 2757, 2981, 3274, 3601, 3933, 4246, 4524, 4711, 4805, 4850, 4856, 4834, 4787, 4724, 4645, 4558, 4463, 4366, 4268, 4177, 4093, 4025, 3979, 3979, 4025, 4093, 4177, 4268, 4366, 4463, 4558, 4645, 4724, 4787, 4834, 4856, 4850, 4805, 4711, 4524, 4246, 3933, 3601, 3274, 2981, 2757, 2565, 2399, 2250, 2120, 2003, 1903, 1817, 1752, 1708, 1708, 1749, 1802, 1859, 1909, 1944, 1956, 1936, 1873, 1754, 1561, 1252, 844, 360, -205, -852, -1621, -2508, -3454, -4444, -5457, -6481, -7498, -8502, -9474, -10406, -11279, -12083, -12795, -13401, -13864, -14157, -5039, -5863, -6517, -6952, -6952, -6517, -5863, -5039, -4112, -3114, -2090, -1074, -110, 729, 1387, 1860, 2169, 2322, 2340, 2276, 2119, 1909, 1721, 1615, 1547, 1529, 1563, 1633, 1721, 1834, 1986, 2117, 2144, 2117, 2038, 1920, 1730, 1485, 1218, 956, 722, 574, 447, 292, 138, 12, -65, -23, 72, 155, 146, 62, -92, -303, -525, -721, -864, -1011, -1184, -1285, -1314, -1312, -1286, -1245, -1196, -1144, -1097, -1062, -1062, -1097, -1144, -1196, -1245, -1286, -1312, -1314, -1285, -1184, -1011, -864, -721, -525, -303, -92, 62, 146, 155, 72, -23, -65, 12, 138, 292, 447, 574, 722, 956, 1218, 1485, 1730, 1920, 2038, 2117, 2144, 2117, 1986, 1834, 1721, 1633, 1563, 1529, 1547, 1615, 1721, 1909, 2119, 2276, 2340, 2322, 2169, 1860, 1387, 729, -110, -1074, -2090, -3114, -4112, -5039, -5863, -6517, -6952, -3914, -4821, -5558, -6060, -6060, -5558, -4821, -3914, -2925, -1901, -912, -43, 608, 1045, 1288, 1369, 1333, 1213, 1085, 1029, 1026, 1088, 1203, 1393, 1585, 1746, 1821, 1844, 1773, 1634, 1500, 1355, 1186, 1085, 1019, 982, 979, 1012, 1035, 1032, 947, 867, 752, 575, 319, 28, -214, -284, -250, -194, -175, -182, -183, -185, -264, -373, -469, -584, -740, -854, -959, -1027, -1029, -1011, -973, -931, -889, -856, -856, -889, -931, -973, -1011, -1029, -1027, -959, -854, -740, -584, -469, -373, -264, -185, -183, -182, -175, -194, -250, -284, -214, 28, 319, 575, 752, 867, 947, 1032, 1035, 1012, 979, 982, 1019, 1085, 1186, 1355, 1500, 1634, 1773, 1844, 1821, 1746, 1585, 1393, 1203, 1088, 1026, 1029, 1085, 1213, 1333, 1369, 1288, 1045, 608, -43, -912, -1901, -2925, -3914, -4821, -5558, -6060, -1705, -2714, -3572, -4185, -4185, -3572, -2714, -1705, -681, 255, 913, 1276, 1383, 1306, 1122, 959, 887, 904, 991, 1133, 1227, 1227, 1131, 980, 752, 532, 351, 234, 170, 121, 149, 120, 19, -103, -278, -443, -560, -604, -615, -556, -490, -427, -424, -427, -493, -644, -776, -700, -519, -365, -265, -134, -42, -6, -37, -52, -13, 5, 63, 169, 281, 380, 470, 502, 495, 470, 439, 411, 411, 439, 470, 495, 502, 470, 380, 281, 169, 63, 5, -13, -52, -37, -6, -42, -134, -265, -365, -519, -700, -776, -644, -493, -427, -424, -427, -490, -556, -615, -604, -560, -443, -278, -103, 19, 120, 149, 121, 170, 234, 351, 532, 752, 980, 1131, 1227, 1227, 1133, 991, 904, 887, 959, 1122, 1306, 1383, 1276, 913, 255, -681, -1705, -2714, -3572, -4185, -477, -1501, -2421, -3111, -3111, -2421, -1501, -477, 430, 1008, 1213, 1156, 938, 752, 679, 710, 805, 857, 791, 633, 385, 139, -39, -115, -132, -119, -148, -220, -339, -491, -529, -515, -461, -359, -296, -261, -264, -278, -262, -188, -96, 67, 182, 245, 283, 210, 87, 162, 298, 353, 387, 412, 341, 263, 154, 62, 71, 69, 59, 48, -8, -101, -185, -264, -291, -281, -260, -236, -236, -260, -281, -291, -264, -185, -101, -8, 48, 59, 69, 71, 62, 154, 263, 341, 412, 387, 353, 298, 162, 87, 210, 283, 245, 182, 67, -96, -188, -262, -278, -264, -261, -296, -359, -461, -515, -529, -491, -339, -220, -148, -119, -132, -115, -39, 139, 385, 633, 791, 857, 805, 710, 679, 752, 938, 1156, 1213, 1008, 430, -477, -1501, -2421, -3111, -198, -1222, -2181, -2924, -2924, -2181, -1222, -198, 570, 930, 953, 787, 640, 624, 714, 838, 863, 762, 554, 341, 194, 126, 113, 99, 9, -127, -281, -375, -401, -388, -310, -284, -315, -368, -403, -375, -300, -176, -95, -35, -33, -14, 40, 104, 214, 257, 177, 233, 277, 239, 255, 286, 293, 288, 198, 110, 58, 16, 5, 4, -2, -61, -134, -209, -255, -255, -236, -214, -214, -236, -255, -255, -209, -134, -61, -2, 4, 5, 16, 58, 110, 198, 288, 293, 286, 255, 239, 277, 233, 177, 257, 214, 104, 40, -14, -33, -35, -95, -176, -300, -375, -403, -368, -315, -284, -310, -388, -401, -375, -281, -127, 9, 99, 113, 126, 194, 341, 554, 762, 863, 838, 714, 624, 640, 787, 953, 930, 570, -198, -1222, -2181, -2924, 391, -571, -1595, -2428, -2428, -1595, -571, 391, 866, 914, 704, 551, 548, 653, 689, 572, 336, 104, -27, -50, -50, -109, -238, -356, -406, -362, -271, -217, -215, -265, -219, -126, -5, 94, 133, 127, 125, 156, 217, 263, 250, 206, 151, 129, 126, 124, -36, -31, -63, -129, -134, -138, -140, -173, -216, -238, -164, -101, -46, -30, -26, -24, 27, 94, 159, 179, 167, 147, 147, 167, 179, 159, 94, 27, -24, -26, -30, -46, -101, -164, -238, -216, -173, -140, -138, -134, -129, -63, -31, -36, 124, 126, 129, 151, 206, 250, 263, 217, 156, 125, 127, 133, 94, -5, -126, -219, -265, -215, -217, -271, -362, -406, -356, -238, -109, -50, -50, -27, 104, 336, 572, 689, 653, 548, 551, 704, 914, 866, 391, -571, -1595, -2428, -11878, -12319, -12618, -12770, -12770, -12618, -12319, -11878, -11306, -10615, -9822, -8943, -7997, -7005, -5987, -4963, -3953, -2974, -2044, -1176, -384, 325, 944, 1468, 1897, 2234, 2483, 2650, 2745, 2777, 2758, 2699, 2613, 2511, 2404, 2302, 2213, 2145, 2103, 2090, 2109, 2158, 2236, 2340, 2465, 2606, 2756, 2910, 3061, 3202, 3329, 3436, 3520, 3579, 3611, 3616, 3596, 3553, 3491, 3413, 3326, 3234, 3143, 3057, 2983, 2923, 2881, 2859, 2859, 2881, 2923, 2983, 3057, 3143, 3234, 3326, 3413, 3491, 3553, 3596, 3616, 3611, 3579, 3520, 3436, 3329, 3202, 3061, 2910, 2756, 2606, 2465, 2340, 2236, 2158, 2109, 2090, 2103, 2145, 2213, 2302, 2404, 2511, 2613, 2699, 2758, 2777, 2745, 2650, 2483, 2234, 1897, 1468, 944, 325, -384, -1176, -2044, -2974, -3953, -4963, -5987, -7005, -7997, -8943, -9822, -10615, -11306, -11878, -12319, -12618, -12770, -14120, -14675, -15058, -15253, -15253, -15058, -14675, -14120, -13414, -12585, -11663, -10677, -9658, -8634, -7628, -6657, -5734, -4864, -4049, -3283, -2560, -1870, -1203, -552, 90, 725, 1349, 1957, 2538, 3077, 3558, 3966, 4283, 4498, 4602, 4591, 4470, 4247, 3938, 3566, 3155, 2735, 2334, 1982, 1703, 1518, 1441, 1480, 1634, 1896, 2252, 2681, 3161, 3667, 4171, 4651, 5087, 5462, 5767, 5998, 6157, 6252, 6292, 6294, 6271, 6238, 6209, 6192, 6192, 6209, 6238, 6271, 6294, 6292, 6252, 6157, 5998, 5767, 5462, 5087, 4651, 4171, 3667, 3161, 2681, 2252, 1896, 1634, 1480, 1441, 1518, 1703, 1982, 2334, 2735, 3155, 3566, 3938, 4247, 4470, 4591, 4602, 4498, 4283, 3966, 3558, 3077, 2538, 1957, 1349, 725, 90, -552, -1203, -1870, -2560, -3283, -4049, -4864, -5734, -6657, -7628, -8634, -9658, -10677, -11663, -12585, -13414, -14120, -14675, -15058, -15253, -11898, -12626, -13145, -13414, -13414, -13145, -12626, -11898, -11013, -10029, -9005, -7992, -7029, -6138, -5325, -4583, -3891, -3226, -2564, -1888, -1194, -487, 210, 866, 1444, 1906, 2220, 2366, 2342, 2161, 1855, 1472, 1066, 695, 412, 258, 258, 417, 722, 1143, 1635, 2150, 2641, 3068, 3404, 3638, 3775, 3835, 3849, 3849, 3868, 3931, 4050, 4223, 4434, 4654, 4847, 4975, 5007, 4920, 4709, 4384, 3972, 3514, 3061, 2664, 2369, 2212, 2212, 2369, 2664, 3061, 3514, 3972, 4384, 4709, 4920, 5007, 4975, 4847, 4654, 4434, 4223, 4050, 3931, 3868, 3849, 3849, 3835, 3775, 3638, 3404, 3068, 2641, 2150, 1635, 1143, 722, 417, 258, 258, 412, 695, 1066, 1472, 1855, 2161, 2342, 2366, 2220, 1906, 1444, 866, 210, -487, -1194, -1888, -2564, -3226, -3891, -4583, -5325, -6138, -7029, -7992, -9005, -10029, -11013, -11898, -12626, -13145, -13414, -11438, -12308, -12954, -13299, -13299, -12954, -12308, -11438, -10442, -9418, -8447, -7578, -6828, -6176, -5582, -4995, -4375, -3700, -2976, -2238, -1536, -929, -462, -161, -16, 10, -19, -30, 44, 249, 595, 1058, 1581, 2086, 2495, 2741, 2792, 2652, 2365, 2004, 1657, 1409, 1324, 1433, 1729, 2168, 2686, 3209, 3672, 4032, 4278, 4427, 4517, 4598, 4711, 4879, 5098, 5334, 5534, 5638, 5591, 5366, 4965, 4432, 3838, 3275, 2837, 2596, 2596, 2837, 3275, 3838, 4432, 4965, 5366, 5591, 5638, 5534, 5334, 5098, 4879, 4711, 4598, 4517, 4427, 4278, 4032, 3672, 3209, 2686, 2168, 1729, 1433, 1324, 1409, 1657, 2004, 2365, 2652, 2792, 2741, 2495, 2086, 1581, 1058, 595, 249, 44, -30, -19, 10, -16, -161, -462, -929, -1536, -2238, -2976, -3700, -4375, -4995, -5582, -6176, -6828, -7578, -8447, -9418, -10442, -11438, -12308, -12954, -13299, -11893, -12837, -13568, -13969, -13969, -13568, -12837, -11893, -10869, -9876, -8975, -8169, -7410, -6632, -5779, -4833, -3831, -2853, -1998, -1355, -967, -814, -818, -862, -825, -621, -221, 336, 960, 1536, 1966, 2193, 2222, 2115, 1964, 1859, 1859, 1970, 2145, 2305, 2368, 2284, 2056, 1745, 1458, 1312, 1400, 1761, 2363, 3117, 3895, 4575, 5067, 5342, 5432, 5410, 5364, 5360, 5420, 5512, 5567, 5504, 5265, 4842, 4285, 3698, 3209, 2931, 2931, 3209, 3698, 4285, 4842, 5265, 5504, 5567, 5512, 5420, 5360, 5364, 5410, 5432, 5342, 5067, 4575, 3895, 3117, 2363, 1761, 1400, 1312, 1458, 1745, 2056, 2284, 2368, 2305, 2145, 1970, 1859, 1859, 1964, 2115, 2222, 2193, 1966, 1536, 960, 336, -221, -621, -825, -862, -818, -814, -967, -1355, -1998, -2853, -3831, -4833, -5779, -6632, -7410, -8169, -8975, -9876, -10869, -11893, -12837, -13568, -13969, -8150, -9174, -10117, -10684, -10684, -10117, -9174, -8150, -7312, -6790, -6541, -6401, -6179, -5756, -5120, -4347, -3527, -2714, -1902, -1065, -206, 606, 1249, 1614, 1670, 1505, 1298, 1235, 1417, 1805, 2240, 2528, 2544, 2302, 1944, 1664, 1598, 1751, 1996, 2152, 2085, 1790, 1399, 1113, 1096, 1390, 1896, 2428, 2807, 2941, 2856, 2655, 2453, 2309, 2219, 2142, 2065, 2026, 2106, 2368, 2789, 3238, 3515, 3446, 2981, 2242, 1492, 1022, 1022, 1492, 2242, 2981, 3446, 3515, 3238, 2789, 2368, 2106, 2026, 2065, 2142, 2219, 2309, 2453, 2655, 2856, 2941, 2807, 2428, 1896, 1390, 1096, 1113, 1399, 1790, 2085, 2152, 1996, 1751, 1598, 1664, 1944, 2302, 2544, 2528, 2240, 1805, 1417, 1235, 1298, 1505, 1670, 1614, 1249, 606, -206, -1065, -1902, -2714, -3527, -4347, -5120, -5756, -6179, -6401, -6541, -6790, -7312, -8150, -9174, -10117, -10684, -5646, -6670, -7672, -8291, -8291, -7672, -6670, -5646, -4925, -4659, -4787, -5094, -5333, -5344, -5102, -4686, -4201, -3699, -3168, -2564, -1886, -1217, -702, -478, -584, -911, -1243, -1354, -1124, -608, -10, 424, 532, 325, -25, -283, -283, -20, 349, 598, 563, 243, -197, -502, -465, -28, 691, 1466, 2077, 2416, 2515, 2505, 2525, 2649, 2865, 3122, 3394, 3725, 4206, 4906, 5790, 6686, 7339, 7524, 7173, 6432, 5622, 5100, 5100, 5622, 6432, 7173, 7524, 7339, 6686, 5790, 4906, 4206, 3725, 3394, 3122, 2865, 2649, 2525, 2505, 2515, 2416, 2077, 1466, 691, -28, -465, -502, -197, 243, 563, 598, 349, -20, -283, -283, -25, 325, 532, 424, -10, -608, -1124, -1354, -1243, -911, -584, -478, -702, -1217, -1886, -2564, -3168, -3699, -4201, -4686, -5102, -5344, -5333, -5094, -4787, -4659, -4925, -5646, -6670, -7672, -8291, -1658, -2370, -3128, -3616, -3616, -3128, -2370, -1658, -1249, -1211, -1403, -1564, -1462, -1015, -322, 409, 986, 1340, 1538, 1724, 2005, 2376, 2717, 2872, 2762, 2448, 2113, 1955, 2069, 2366, 2613, 2548, 2029, 1128, 104, -719, -1117, -1082, -819, -637, -781, -1305, -2057, -2764, -3182, -3218, -2960, -2607, -2342, -2229, -2194, -2091, -1810, -1356, -852, -456, -254, -189, -90, 235, 868, 1712, 2519, 3016, 3050, 2678, 2150, 1780, 1780, 2150, 2678, 3050, 3016, 2519, 1712, 868, 235, -90, -189, -254, -456, -852, -1356, -1810, -2091, -2194, -2229, -2342, -2607, -2960, -3218, -3182, -2764, -2057, -1305, -781, -637, -819, -1082, -1117, -719, 104, 1128, 2029, 2548, 2613, 2366, 2069, 1955, 2113, 2448, 2762, 2872, 2717, 2376, 2005, 1724, 1538, 1340, 986, 409, -322, -1015, -1462, -1564, -1403, -1211, -1249, -1658, -2370, -3128, -3616, -11982, -12450, -12913, -13204, -13204, -12913, -12450, -11982, -11627, -11392, -11165, -10789, -10154, -9270, -8261, -7300, -6514, -5911, -5386, -4781, -3990, -3021, -1997, -1089, -421, 5, 299, 624, 1094, 1709, 2352, 2860, 3119, 3132, 3019, 2949, 3042, 3305, 3626, 3846, 3854, 3656, 3374, 3175, 3182, 3398, 3709, 3953, 4017, 3900, 3720, 3640, 3776, 4125, 4570, 4942, 5123, 5109, 5011, 4992, 5163, 5521, 5945, 6269, 6373, 6254, 6028, 5856, 5856, 6028, 6254, 6373, 6269, 5945, 5521, 5163, 4992, 5011, 5109, 5123, 4942, 4570, 4125, 3776, 3640, 3720, 3900, 4017, 3953, 3709, 3398, 3182, 3175, 3374, 3656, 3854, 3846, 3626, 3305, 3042, 2949, 3019, 3132, 3119, 2860, 2352, 1709, 1094, 624, 299, 5, -421, -1089, -1997, -3021, -3990, -4781, -5386, -5911, -6514, -7300, -8261, -9270, -10154, -10789, -11165, -11392, -11627, -11982, -12450, -12913, -13204, -7496, -8520, -9407, -9925, -9925, -9407, -8520, -7496, -6555, -5823, -5302, -4905, -4519, -4076, -3574, -3062, -2592, -2178, -1789, -1375, -913, -433, -10, 276, 394, 391, 375, 459, 698, 1052, 1404, 1617, 1614, 1420, 1154, 968, 968, 1158, 1438, 1665, 1725, 1600, 1372, 1181, 1149, 1318, 1634, 1984, 2259, 2411, 2464, 2496, 2575, 2726, 2918, 3093, 3211, 3278, 3338, 3430, 3545, 3605, 3491, 3109, 2456, 1652, 913, 470, 470, 913, 1652, 2456, 3109, 3491, 3605, 3545, 3430, 3338, 3278, 3211, 3093, 2918, 2726, 2575, 2496, 2464, 2411, 2259, 1984, 1634, 1318, 1149, 1181, 1372, 1600, 1725, 1665, 1438, 1158, 968, 968, 1154, 1420, 1614, 1617, 1404, 1052, 698, 459, 375, 391, 394, 276, -10, -433, -913, -1375, -1789, -2178, -2592, -3062, -3574, -4076, -4519, -4905, -5302, -5823, -6555, -7496, -8520, -9407, -9925, -9783, -10807, -11664, -12155, -12155, -11664, -10807, -9783, -8783, -7923, -7218, -6603, -5992, -5329, -4612, -3883, -3188, -2551, -1957, -1376, -792, -226, 271, 647, 888, 1033, 1164, 1358, 1645, 1980, 2263, 2390, 2313, 2071, 1784, 1592, 1592, 1788, 2093, 2373, 2518, 2495, 2358, 2216, 2174, 2278, 2502, 2767, 2991, 3130, 3196, 3235, 3291, 3377, 3469, 3527, 3528, 3483, 3429, 3399, 3379, 3304, 3080, 2634, 1974, 1210, 528, 125, 125, 528, 1210, 1974, 2634, 3080, 3304, 3379, 3399, 3429, 3483, 3528, 3527, 3469, 3377, 3291, 3235, 3196, 3130, 2991, 2767, 2502, 2278, 2174, 2216, 2358, 2495, 2518, 2373, 2093, 1788, 1592, 1592, 1784, 2071, 2313, 2390, 2263, 1980, 1645, 1358, 1164, 1033, 888, 647, 271, -226, -792, -1376, -1957, -2551, -3188, -3883, -4612, -5329, -5992, -6603, -7218, -7923, -8783, -9783, -10807, -11664, -12155, -9318, -10342, -11211, -11714, -11714, -11211, -10342, -9318, -8336, -7505, -6818, -6189, -5518, -4758, -3933, -3122, -2402, -1811, -1325, -886, -446, 5, 433, 796, 1078, 1315, 1578, 1928, 2368, 2818, 3146, 3230, 3028, 2618, 2171, 1883, 1883, 2174, 2635, 3077, 3333, 3333, 3122, 2828, 2585, 2476, 2499, 2593, 2685, 2738, 2762, 2799, 2874, 2974, 3040, 3009, 2850, 2590, 2300, 2049, 1855, 1661, 1361, 863, 156, -659, -1387, -1818, -1818, -1387, -659, 156, 863, 1361, 1661, 1855, 2049, 2300, 2590, 2850, 3009, 3040, 2974, 2874, 2799, 2762, 2738, 2685, 2593, 2499, 2476, 2585, 2828, 3122, 3333, 3333, 3077, 2635, 2174, 1883, 1883, 2171, 2618, 3028, 3230, 3146, 2818, 2368, 1928, 1578, 1315, 1078, 796, 433, 5, -446, -886, -1325, -1811, -2402, -3122, -3933, -4758, -5518, -6189, -6818, -7505, -8336, -9318, -10342, -11211, -11714, -8348, -9330, -10117, -10557, -10557, -10117, -9330, -8348, -7324, -6368, -5525, -4787, -4122, -3509, -2947, -2452, -2031, -1668, -1323, -951, -527, -61, 403, 810, 1128, 1364, 1555, 1748, 1966, 2188, 2362, 2431, 2374, 2222, 2055, 1965, 2015, 2206, 2479, 2747, 2932, 3004, 2990, 2947, 2929, 2957, 3010, 3040, 3009, 2909, 2770, 2644, 2571, 2559, 2580, 2582, 2523, 2380, 2157, 1864, 1498, 1031, 428, -321, -1176, -2030, -2729, -3125, -3125, -2729, -2030, -1176, -321, 428, 1031, 1498, 1864, 2157, 2380, 2523, 2582, 2580, 2559, 2571, 2644, 2770, 2909, 3009, 3040, 3010, 2957, 2929, 2947, 2990, 3004, 2932, 2747, 2479, 2206, 2015, 1965, 2055, 2222, 2374, 2431, 2362, 2188, 1966, 1748, 1555, 1364, 1128, 810, 403, -61, -527, -951, -1323, -1668, -2031, -2452, -2947, -3509, -4122, -4787, -5525, -6368, -7324, -8348, -9330, -10117, -10557, -5699, -6574, -7222, -7566, -7566, -7222, -6574, -5699, -4697, -3673, -2724, -1923, -1313, -903, -672, -577, -566, -587, -597, -571, -501, -396, -270, -144, -31, 61, 134, 201, 275, 370, 493, 644, 816, 992, 1155, 1290, 1388, 1449, 1482, 1500, 1521, 1560, 1625, 1716, 1823, 1934, 2033, 2110, 2161, 2192, 2219, 2259, 2328, 2434, 2569, 2706, 2804, 2811, 2673, 2347, 1812, 1077, 184, -792, -1756, -2601, -3230, -3565, -3565, -3230, -2601, -1756, -792, 184, 1077, 1812, 2347, 2673, 2811, 2804, 2706, 2569, 2434, 2328, 2259, 2219, 2192, 2161, 2110, 2033, 1934, 1823, 1716, 1625, 1560, 1521, 1500, 1482, 1449, 1388, 1290, 1155, 992, 816, 644, 493, 370, 275, 201, 134, 61, -31, -144, -270, -396, -501, -571, -597, -587, -566, -577, -672, -903, -1313, -1923, -2724, -3673, -4697, -5699, -6574, -7222, -7566, -2245, -3174, -3879, -4260, -4260, -3879, -3174, -2245, -1221, -236, 590, 1176, 1484, 1526, 1353, 1043, 686, 360, 125, 9, 9, 98, 236, 377, 487, 545, 548, 512, 459, 415, 396, 413, 459, 520, 577, 610, 610, 577, 520, 459, 413, 396, 415, 459, 512, 548, 545, 487, 377, 236, 98, 9, 9, 125, 360, 686, 1043, 1353, 1526, 1484, 1176, 590, -236, -1221, -2245, -3174, -3879, -4260, -4260, -3879, -3174, -2245, -1221, -236, 590, 1176, 1484, 1526, 1353, 1043, 686, 360, 125, 9, 9, 98, 236, 377, 487, 545, 548, 512, 459, 415, 396, 413, 459, 520, 577, 610, 610, 577, 520, 459, 413, 396, 415, 459, 512, 548, 545, 487, 377, 236, 98, 9, 9, 125, 360, 686, 1043, 1353, 1526, 1484, 1176, 590, -236, -1221, -2245, -3174, -3879, -4260, -2455, -3479, -4342, -4836, -4836, -4342, -3479, -2455, -1484, -723, -233, 14, 98, 106, 99, 104, 124, 154, 186, 212, 212, 156, 16, -209, -475, -692, -747, -545, -56, 672, 1520, 2345, 3029, 3512, 3797, 3923, 3923, 3797, 3512, 3029, 2345, 1520, 672, -56, -545, -747, -692, -475, -209, 16, 156, 212, 212, 186, 154, 124, 104, 99, 106, 98, 14, -233, -723, -1484, -2455, -3479, -4342, -4836, -4836, -4342, -3479, -2455, -1484, -723, -233, 14, 98, 106, 99, 104, 124, 154, 186, 212, 212, 156, 16, -209, -475, -692, -747, -545, -56, 672, 1520, 2345, 3029, 3512, 3797, 3923, 3923, 3797, 3512, 3029, 2345, 1520, 672, -56, -545, -747, -692, -475, -209, 16, 156, 212, 212, 186, 154, 124, 104, 99, 106, 98, 14, -233, -723, -1484, -2455, -3479, -4342, -4836, -24465, -24934, -25303, -25650, -25650, -25303, -24934, -24465, -23963, -23391, -22788, -22130, -21445, -20715, -19962, -19170, -18359, -17515, -16655, -15767, -14865, -13941, -13004, -12049, -11085, -10106, -9119, -8121, -7118, -6106, -5092, -4071, -3051, -2027, -1006, 17, 1035, 2051, 3060, 4066, 5062, 6051, 7028, 7997, 8951, 9893, 10819, 11729, 12621, 13494, 14346, 15176, 15981, 16762, 17514, 18238, 18929, 19588, 20209, 20793, 21335, 21833, 22282, 22680, 23019, 23296, 23499, 23620, 23620, 23499, 23296, 23019, 22680, 22282, 21833, 21335, 20793, 20209, 19588, 18929, 18238, 17514, 16762, 15981, 15176, 14346, 13494, 12621, 11729, 10819, 9893, 8951, 7997, 7028, 6051, 5062, 4066, 3060, 2051, 1035, 17, -1006, -2027, -3051, -4071, -5092, -6106, -7118, -8121, -9119, -10106, -11085, -12049, -13004, -13941, -14865, -15767, -16655, -17515, -18359, -19170, -19962, -20715, -21445, -22130, -22788, -23391, -23963, -24465, -24934, -25303, -25650, -13219, -13414, -13578, -13708, -13781, -13269, -12847, -12321, -11825, -11266, -10725, -10139, -9565, -8958, -8361, -7738, -7125, -6491, -5866, -5225, -4594, -3950, -3316, -2673, -2041, -1401, -773, -141, 479, 1102, 1710, 2320, 2915, 3509, 4087, 4663, 5221, 5776, 6312, 6842, 7354, 7858, 8341, 8815, 9268, 9710, 10129, 10535, 10917, 11285, 11626, 11952, 12250, 12530, 12780, 13010, 13208, 13384, 13524, 13640, 13718, 13767, 13775, 13750, 13677, 13566, 13398, 13181, 12880, 12508, 12074, 11596, 11066, 10502, 9893, 9255, 8574, 7870, 7126, 6363, 5561, 4745, 3889, 3025, 2118, 1212, 256, -681, -1705, -2536, -2635, -2789, -2931, -3110, -3287, -3492, -3699, -3930, -4163, -4416, -4673, -4947, -5224, -5515, -5809, -6116, -6425, -6743, -7064, -7391, -7720, -8055, -8389, -8727, -9063, -9400, -9735, -10069, -10397, -10723, -11042, -11355, -11659, -11955, -12238, -12509, -12764, -13002, -13219, -13414, -13578, -13708, -23535, -24447, -25205, -26106, -26106, -25205, -24447, -23535, -22674, -21723, -20801, -19819, -18859, -17855, -16869, -15851, -14851, -13827, -12819, -11796, -10789, -9772, -8772, -7767, -6779, -5792, -4822, -3856, -2909, -1970, -1051, -143, 745, 1617, 2468, 3300, 4111, 4899, 5665, 6405, 7121, 7808, 8471, 9101, 9706, 10275, 10817, 11319, 11794, 12224, 12627, 12980, 13305, 13575, 13817, 13997, 14150, 14232, 14288, 14264, 14214, 14072, 13909, 13632, 13346, 12906, 12495, 11801, 11801, 12495, 12906, 13346, 13632, 13909, 14072, 14214, 14264, 14288, 14232, 14150, 13997, 13817, 13575, 13305, 12980, 12627, 12224, 11794, 11319, 10817, 10275, 9706, 9101, 8471, 7808, 7121, 6405, 5665, 4899, 4111, 3300, 2468, 1617, 745, -143, -1051, -1970, -2909, -3856, -4822, -5792, -6779, -7767, -8772, -9772, -10789, -11796, -12819, -13827, -14851, -15851, -16869, -17855, -18859, -19819, -20801, -21723, -22674, -23535, -24447, -25205, -26106, -14958, -15580, -16101, -16732, -16732, -16101, -15580, -14958, -14379, -13744, -13138, -12496, -11879, -11236, -10616, -9979, -9365, -8738, -8134, -7523, -6935, -6344, -5777, -5209, -4666, -4125, -3612, -3101, -2619, -2142, -1696, -1256, -848, -448, -82, 275, 596, 908, 1180, 1444, 1664, 1877, 2041, 2203, 2305, 2416, 2449, 3279, 4303, 5226, 6153, 7019, 7868, 8665, 9436, 10157, 10846, 11486, 12088, 12640, 13149, 13606, 14014, 14367, 14664, 14900, 15069, 15165, 15165, 15069, 14900, 14664, 14367, 14014, 13606, 13149, 12640, 12088, 11486, 10846, 10157, 9436, 8665, 7868, 7019, 6153, 5226, 4303, 3279, 2449, 2416, 2305, 2203, 2041, 1877, 1664, 1444, 1180, 908, 596, 275, -82, -448, -848, -1256, -1696, -2142, -2619, -3101, -3612, -4125, -4666, -5209, -5777, -6344, -6935, -7523, -8134, -8738, -9365, -9979, -10616, -11236, -11879, -12496, -13138, -13744, -14379, -14958, -15580, -16101, -16732, -12888, -13434, -13895, -14463, -14463, -13895, -13434, -12888, -12387, -11844, -11332, -10798, -10288, -9768, -9269, -8769, -8288, -7813, -7355, -6909, -6479, -6065, -5667, -5290, -4927, -4591, -4265, -3973, -3688, -3445, -3201, -3011, -2809, -2682, -2510, -2487, -1964, -940, -68, 846, 1679, 2519, 3297, 4067, 4784, 5482, 6133, 6759, 7340, 7890, 8397, 8868, 9298, 9687, 10036, 10338, 10602, 10812, 10986, 11098, 11177, 11185, 11162, 11055, 10925, 10684, 10446, 10012, 10012, 10446, 10684, 10925, 11055, 11162, 11185, 11177, 11098, 10986, 10812, 10602, 10338, 10036, 9687, 9298, 8868, 8397, 7890, 7340, 6759, 6133, 5482, 4784, 4067, 3297, 2519, 1679, 846, -68, -940, -1964, -2487, -2510, -2682, -2809, -3011, -3201, -3445, -3688, -3973, -4265, -4591, -4927, -5290, -5667, -6065, -6479, -6909, -7355, -7813, -8288, -8769, -9269, -9768, -10288, -10798, -11332, -11844, -12387, -12888, -13434, -13895, -14463, -13569, -13655, -13735, -13799, -13825, -13236, -12767, -12209, -11706, -11158, -10651, -10119, -9623, -9114, -8639, -8158, -7711, -7264, -6849, -6441, -6065, -5700, -5367, -5048, -4762, -4494, -4258, -4044, -3861, -3707, -3576, -3497, -3340, -2353, -1381, -428, 474, 1359, 2191, 3003, 3762, 4500, 5182, 5842, 6445, 7025, 7544, 8040, 8473, 8881, 9223, 9542, 9789, 10014, 10160, 10289, 10327, 10358, 10276, 10218, 9971, 10347, 11118, 11702, 12289, 12756, 13181, 13494, 13724, 13826, 13862, 13805, 13689, 13494, 13245, 12924, 12550, 12113, 11624, 11077, 10478, 9828, 9125, 8376, 7572, 6733, 5828, 4909, 3885, 3036, 2973, 2815, 2661, 2429, 2191, 1885, 1567, 1189, 797, 347, -115, -633, -1164, -1747, -2341, -2988, -3643, -4350, -5061, -5826, -6591, -7411, -8224, -9097, -9953, -10881, -11764, -12770, -13027, -12966, -13018, -13031, -13094, -13144, -13223, -13297, -13388, -13475, -13569, -13655, -13735, -13799, -13405, -13971, -14453, -15057, -15057, -14453, -13971, -13405, -12897, -12349, -11845, -11321, -10835, -10340, -9882, -9423, -9000, -8582, -8199, -7827, -7490, -7168, -6880, -6612, -6378, -6168, -5991, -5843, -5725, -5627, -4745, -3721, -2795, -1862, -998, -141, 651, 1430, 2147, 2847, 3483, 4102, 4656, 5190, 5657, 6105, 6481, 6839, 7121, 7388, 7568, 7744, 7814, 7906, 7828, 8069, 8984, 9749, 10509, 11175, 11805, 12352, 12849, 13267, 13622, 13896, 14094, 14203, 14203, 14094, 13896, 13622, 13267, 12849, 12352, 11805, 11175, 10509, 9749, 8984, 8069, 7828, 7906, 7814, 7744, 7568, 7388, 7121, 6839, 6481, 6105, 5657, 5190, 4656, 4102, 3483, 2847, 2147, 1430, 651, -141, -998, -1862, -2795, -3721, -4745, -5627, -5725, -5843, -5991, -6168, -6378, -6612, -6880, -7168, -7490, -7827, -8199, -8582, -9000, -9423, -9882, -10340, -10835, -11321, -11845, -12349, -12897, -13405, -13971, -14453, -15057, -12208, -12681, -13100, -13654, -13654, -13100, -12681, -12208, -11804, -11395, -11035, -10695, -10392, -10128, -9890, -9710, -9539, -9455, -9344, -9400, -8957, -8016, -7246, -6454, -5755, -5075, -4465, -3894, -3378, -2918, -2501, -2156, -1836, -1616, -1383, -1330, -791, 233, 1074, 1925, 2671, 3386, 4019, 4602, 5118, 5566, 5960, 6270, 6543, 6704, 6866, 6836, 7278, 8194, 8913, 9628, 10224, 10775, 11229, 11616, 11919, 12136, 12280, 12319, 12297, 12138, 11950, 11533, 11533, 11950, 12138, 12297, 12319, 12280, 12136, 11919, 11616, 11229, 10775, 10224, 9628, 8913, 8194, 7278, 6836, 6866, 6704, 6543, 6270, 5960, 5566, 5118, 4602, 4019, 3386, 2671, 1925, 1074, 233, -791, -1330, -1383, -1616, -1836, -2156, -2501, -2918, -3378, -3894, -4465, -5075, -5755, -6454, -7246, -8016, -8957, -9400, -9344, -9455, -9539, -9710, -9890, -10128, -10392, -10695, -11035, -11395, -11804, -12208, -12681, -13100, -13654, -20923, -21864, -22661, -23685, -23685, -22661, -21864, -20923, -20077, -19154, -18293, -17380, -16516, -15613, -14751, -13861, -13005, -12128, -11282, -10419, -9586, -8740, -7921, -7092, -6290, -5481, -4696, -3908, -3143, -2377, -1633, -890, -170, 549, 1245, 1938, 2609, 3274, 3918, 4556, 5171, 5779, 6365, 6942, 7497, 8041, 8564, 9074, 9563, 10038, 10491, 10930, 11346, 11745, 12122, 12481, 12817, 13133, 13425, 13696, 13942, 14165, 14360, 14531, 14672, 14785, 14864, 14910, 14910, 14864, 14785, 14672, 14531, 14360, 14165, 13942, 13696, 13425, 13133, 12817, 12481, 12122, 11745, 11346, 10930, 10491, 10038, 9563, 9074, 8564, 8041, 7497, 6942, 6365, 5779, 5171, 4556, 3918, 3274, 2609, 1938, 1245, 549, -170, -890, -1633, -2377, -3143, -3908, -4696, -5481, -6290, -7092, -7921, -8740, -9586, -10419, -11282, -12128, -13005, -13861, -14751, -15613, -16516, -17380, -18293, -19154, -20077, -20923, -21864, -22661, -23685, -11488, -12034, -12560, -13357, -13539, -12843, -12250, -11488, -10751, -9911, -9081, -8179, -7283, -6333, -5390, -4405, -3428, -2420, -1423, -402, 606, 1630, 2638, 3656, 4656, 5659, 6641, 7620, 8575, 9522, 10440, 11346, 12219, 13073, 13891, 14683, 15434, 16152, 16824, 17456, 18032, 18560, 19024, 19425, 19748, 19989, 20119, 20100, 19954, 19723, 19408, 19029, 18585, 18088, 17537, 16942, 16302, 15625, 14910, 14164, 13386, 12582, 11751, 10899, 10026, 9136, 8229, 7310, 6379, 5440, 4494, 3543, 2590, 1637, 687, -258, -1196, -2124, -3038, -3937, -4816, -5674, -6503, -7303, -8066, -8789, -9461, -10077, -10620, -11064, -11371, -11596, -11750, -11855, -11908, -11926, -11906, -11861, -11786, -11695, -11579, -11456, -11313, -11168, -11009, -10854, -10689, -10533, -10371, -10224, -10074, -9945, -9816, -9713, -9614, -9547, -9486, -9465, -9452, -9486, -9531, -9632, -9747, -9928, -10124, -10401, -10691, -11086, -11488, -12034, -12560, -13357, -15902, -16725, -17398, -18143, -18143, -17398, -16725, -15902, -15093, -14194, -13301, -12346, -11397, -10404, -9420, -8404, -7401, -6377, -5369, -4349, -3350, -2348, -1371, -399, 543, 1472, 2364, 3234, 4061, 4857, 5600, 6301, 6936, 7514, 8006, 8414, 8674, 8796, 8824, 8776, 8660, 8489, 8266, 8000, 7693, 7353, 6980, 6582, 6159, 5718, 5259, 4789, 4307, 3821, 3329, 2839, 2351, 1870, 1400, 944, 506, 92, -294, -647, -958, -1221, -1421, -1547, -1547, -1421, -1221, -958, -647, -294, 92, 506, 944, 1400, 1870, 2351, 2839, 3329, 3821, 4307, 4789, 5259, 5718, 6159, 6582, 6980, 7353, 7693, 8000, 8266, 8489, 8660, 8776, 8824, 8796, 8674, 8414, 8006, 7514, 6936, 6301, 5600, 4857, 4061, 3234, 2364, 1472, 543, -399, -1371, -2348, -3350, -4349, -5369, -6377, -7401, -8404, -9420, -10404, -11397, -12346, -13301, -14194, -15093, -15902, -16725, -17398, -18143, -12797, -13668, -14382, -15143, -15143, -14382, -13668, -12797, -11932, -10976, -10027, -9022, -8030, -7006, -6004, -4989, -4005, -3026, -2089, -1176, -320, 493, 1229, 1892, 2446, 2857, 3057, 3141, 3121, 3034, 2875, 2674, 2423, 2146, 1836, 1515, 1175, 838, 497, 172, -141, -423, -674, -873, -1018, -1078, -1033, -798, -431, 24, 543, 1115, 1724, 2364, 3022, 3695, 4371, 5047, 5712, 6362, 6988, 7584, 8140, 8650, 9099, 9480, 9769, 9951, 9951, 9769, 9480, 9099, 8650, 8140, 7584, 6988, 6362, 5712, 5047, 4371, 3695, 3022, 2364, 1724, 1115, 543, 24, -431, -798, -1033, -1078, -1018, -873, -674, -423, -141, 172, 497, 838, 1175, 1515, 1836, 2146, 2423, 2674, 2875, 3034, 3121, 3141, 3057, 2857, 2446, 1892, 1229, 493, -320, -1176, -2089, -3026, -4005, -4989, -6004, -7006, -8030, -9022, -10027, -10976, -11932, -12797, -13668, -14382, -15143, -11230, -12144, -12895, -13678, -13678, -12895, -12144, -11230, -10321, -9326, -8346, -7322, -6328, -5323, -4367, -3429, -2565, -1753, -1053, -460, -96, 63, 91, 32, -105, -290, -520, -770, -1040, -1306, -1566, -1798, -1995, -2134, -2195, -2148, -1903, -1453, -903, -266, 419, 1150, 1898, 2663, 3420, 4170, 4887, 5571, 6195, 6755, 7213, 7554, 7677, 7584, 7370, 7060, 6680, 6245, 5772, 5272, 4759, 4242, 3739, 3257, 2816, 2428, 2123, 1921, 1921, 2123, 2428, 2816, 3257, 3739, 4242, 4759, 5272, 5772, 6245, 6680, 7060, 7370, 7584, 7677, 7554, 7213, 6755, 6195, 5571, 4887, 4170, 3420, 2663, 1898, 1150, 419, -266, -903, -1453, -1903, -2148, -2195, -2134, -1995, -1798, -1566, -1306, -1040, -770, -520, -290, -105, 32, 91, 63, -96, -460, -1053, -1753, -2565, -3429, -4367, -5323, -6328, -7322, -8346, -9326, -10321, -11230, -12144, -12895, -13678, -10073, -10189, -10326, -10735, -10783, -9998, -9240, -8309, -7385, -6375, -5388, -4364, -3385, -2409, -1506, -648, 94, 733, 1141, 1296, 1292, 1190, 1001, 763, 480, 182, -128, -420, -691, -909, -1060, -1106, -989, -606, -74, 562, 1260, 2008, 2778, 3560, 4332, 5084, 5793, 6446, 7015, 7476, 7776, 7805, 7632, 7344, 6960, 6515, 6020, 5500, 4964, 4435, 3922, 3453, 3038, 2715, 2514, 2553, 2807, 3169, 3617, 4115, 4651, 5200, 5752, 6285, 6789, 7239, 7623, 7904, 8062, 7989, 7660, 7192, 6618, 5970, 5266, 4527, 3768, 3006, 2256, 1536, 866, 271, -221, -531, -582, -493, -306, -57, 238, 553, 880, 1193, 1486, 1731, 1921, 2022, 2014, 1830, 1375, 729, -25, -876, -1781, -2739, -3714, -4711, -5691, -6661, -7577, -8445, -9207, -9851, -10231, -10426, -10502, -10512, -10456, -10385, -10278, -10198, -10107, -10085, -10073, -10189, -10326, -10735, -10338, -11294, -12084, -12896, -12896, -12084, -11294, -10338, -9390, -8366, -7371, -6353, -5391, -4455, -3611, -2854, -2259, -1919, -1817, -1819, -1930, -2087, -2299, -2519, -2753, -2958, -3137, -3242, -3262, -3122, -2723, -2137, -1462, -707, 81, 899, 1710, 2513, 3270, 3978, 4593, 5102, 5410, 5442, 5301, 5056, 4727, 4351, 3936, 3514, 3092, 2701, 2350, 2083, 1915, 1959, 2255, 2683, 3199, 3773, 4380, 5002, 5616, 6208, 6752, 7232, 7611, 7861, 7861, 7611, 7232, 6752, 6208, 5616, 5002, 4380, 3773, 3199, 2683, 2255, 1959, 1915, 2083, 2350, 2701, 3092, 3514, 3936, 4351, 4727, 5056, 5301, 5442, 5410, 5102, 4593, 3978, 3270, 2513, 1710, 899, 81, -707, -1462, -2137, -2723, -3122, -3262, -3242, -3137, -2958, -2753, -2519, -2299, -2087, -1930, -1819, -1817, -1919, -2259, -2854, -3611, -4455, -5391, -6353, -7371, -8366, -9390, -10338, -11294, -12084, -12896, -8818, -9842, -10709, -11586, -11586, -10709, -9842, -8818, -7842, -6846, -5978, -5217, -4811, -4713, -4771, -4905, -5077, -5227, -5313, -5263, -4911, -4233, -3444, -2566, -1690, -828, -67, 564, 859, 831, 660, 401, 115, -159, -360, -433, -197, 358, 1031, 1787, 2546, 3287, 3930, 4441, 4618, 4469, 4180, 3800, 3396, 3001, 2683, 2489, 2607, 3042, 3597, 4232, 4873, 5493, 6019, 6408, 6468, 6198, 5791, 5291, 4769, 4253, 3817, 3502, 3502, 3817, 4253, 4769, 5291, 5791, 6198, 6468, 6408, 6019, 5493, 4873, 4232, 3597, 3042, 2607, 2489, 2683, 3001, 3396, 3800, 4180, 4469, 4618, 4441, 3930, 3287, 2546, 1787, 1031, 358, -197, -433, -360, -159, 115, 401, 660, 831, 859, 564, -67, -828, -1690, -2566, -3444, -4233, -4911, -5263, -5313, -5227, -5077, -4905, -4771, -4713, -4811, -5217, -5978, -6846, -7842, -8818, -9842, -10709, -11586, -2052, -2183, -2314, -2533, -2664, -2708, -2665, -2537, -2327, -2037, -1673, -1238, -738, -179, 432, 1088, 1782, 2505, 3249, 4006, 4768, 5525, 6269, 6992, 7686, 8342, 8953, 9512, 10012, 10447, 10812, 11101, 11312, 11439, 11482, 11439, 11307, 11089, 10783, 10393, 9920, 9368, 8741, 8043, 7280, 6459, 5585, 4667, 3711, 2725, 1718, 699, -325, -1345, -2352, -3337, -4293, -5212, -6086, -6907, -7669, -8367, -8994, -9546, -10019, -10410, -10715, -10934, -11065, -11109, -11066, -10938, -10728, -10438, -10073, -9638, -9138, -8579, -7968, -7312, -6619, -5896, -5152, -4394, -3633, -2876, -2131, -1408, -715, -59, 552, 1111, 1611, 2046, 2411, 2280, 2148, 2017, 1886, 1755, 1623, 1492, 1361, 1230, 1098, 967, 836, 705, 573, 442, 311, 180, 48, -83, -214, -346, -477, -608, -739, -871, -1002, -1133, -1264, -1396, -1527, -1658, -1789, -1921, -2052, -2183, -2314, -2533, -2730, -2842, -2953, -2952, -3064, -3063, -2952, -2735, -2415, -2000, -1498, -917, -269, 436, 1185, 1965, 2764, 3566, 4358, 5128, 5861, 6545, 7167, 7718, 8186, 8564, 8843, 9019, 9086, 9042, 8885, 8618, 8241, 7760, 7179, 6505, 5748, 4916, 4021, 3074, 2089, 1077, 53, -970, -1977, -2956, -3894, -4777, -5595, -6336, -6992, -7553, -8014, -8369, -8615, -8748, -8770, -8681, -8485, -8185, -7789, -7303, -6737, -6102, -5407, -4666, -3890, -3095, -2292, -1497, -722, 20, 714, 1350, 1916, 2402, 2798, 3098, 3294, 3383, 3361, 3228, 2982, 2627, 2166, 2055, 1944, 1832, 1721, 1610, 1499, 1387, 1276, 1165, 1053, 942, 831, 720, 608, 497, 386, 274, 163, 52, -60, -171, -282, -393, -505, -616, -727, -839, -950, -1061, -1172, -1284, -1395, -1506, -1618, -1729, -1840, -1951, -2063, -2174, -2285, -2397, -2508, -2619, -2730, -2842, -2953, -2952, -3253, -3312, -3370, -3571, -3629, -3547, -3325, -2971, -2494, -1904, -1217, -448, 385, 1263, 2164, 3070, 3958, 4808, 5600, 6317, 6940, 7457, 7853, 8119, 8249, 8237, 8084, 7791, 7363, 6808, 6137, 5363, 4501, 3570, 2587, 1574, 550, -464, -1446, -2377, -3239, -4013, -4684, -5239, -5667, -5960, -6114, -6125, -5995, -5729, -5333, -4817, -4193, -3476, -2684, -1834, -946, -41, 861, 1739, 2572, 3341, 4028, 4618, 5095, 5449, 5670, 5753, 5695, 5494, 5155, 4684, 4089, 3382, 2577, 1690, 740, -255, -314, -373, -432, -491, -549, -608, -667, -726, -784, -843, -902, -961, -1019, -1078, -1137, -1196, -1255, -1313, -1372, -1431, -1490, -1548, -1607, -1666, -1725, -1784, -1842, -1901, -1960, -2019, -2077, -2136, -2195, -2254, -2312, -2371, -2430, -2489, -2548, -2606, -2665, -2724, -2783, -2841, -2900, -2959, -3018, -3076, -3135, -3194, -3253, -3312, -3370, -3571, -2499, -2498, -2496, -2694, -2693, -2492, -2099, -1529, -805, 47, 993, 1998, 3022, 4026, 4972, 5824, 6548, 7118, 7511, 7712, 7713, 7515, 7126, 6559, 5838, 4989, 4046, 3045, 2024, 1023, 80, -769, -1490, -2057, -2446, -2644, -2643, -2442, -2049, -1479, -755, 97, 1043, 2047, 3071, 4076, 5022, 5874, 6598, 7168, 7561, 7762, 7763, 7565, 7176, 6609, 5888, 5039, 4096, 3095, 2074, 1073, 130, -719, -1440, -2007, -2397, -2594, -2593, -2591, -2590, -2588, -2587, -2585, -2584, -2582, -2580, -2579, -2577, -2576, -2574, -2573, -2571, -2570, -2568, -2566, -2565, -2563, -2562, -2560, -2559, -2557, -2556, -2554, -2552, -2551, -2549, -2548, -2546, -2545, -2543, -2541, -2540, -2538, -2537, -2535, -2534, -2532, -2531, -2529, -2527, -2526, -2524, -2523, -2521, -2520, -2518, -2517, -2515, -2513, -2512, -2510, -2509, -2507, -2506, -2504, -2503, -2501, -2499, -2498, -2496, -2694, -1662, -1690, -1719, -1990, -2019, -1806, -1365, -725, 75, 984, 1946, 2903, 3795, 4566, 5169, 5566, 5732, 5654, 5336, 4795, 4061, 3178, 2196, 1172, 166, -764, -1563, -2185, -2596, -2771, -2702, -2395, -1870, -1161, -311, 626, 1594, 2531, 3381, 4090, 4615, 4922, 4991, 4816, 4405, 3783, 2984, 2054, 1048, 24, -958, -1841, -2575, -3116, -3434, -3512, -3346, -2949, -2346, -1575, -683, 274, 245, 216, 187, 158, 129, 100, 71, 43, 14, -15, -44, -73, -102, -131, -160, -189, -217, -246, -275, -304, -333, -362, -391, -420, -448, -477, -506, -535, -564, -593, -622, -651, -680, -708, -737, -766, -795, -824, -853, -882, -911, -939, -968, -997, -1026, -1055, -1084, -1113, -1142, -1171, -1199, -1228, -1257, -1286, -1315, -1344, -1373, -1402, -1430, -1459, -1488, -1517, -1546, -1575, -1604, -1633, -1662, -1690, -1719, -1990, -895, -901, -907, -1302, -1308, -924, -209, 726, 1739, 2674, 3389, 3773, 3767, 3372, 2646, 1700, 676, -271, -997, -1392, -1398, -1014, -299, 636, 1649, 2584, 3299, 3683, 3677, 3282, 2556, 1610, 586, -361, -1087, -1482, -1488, -1104, -389, 546, 1559, 2494, 3209, 3593, 3587, 3192, 2466, 1520, 496, -451, -457, -462, -468, -473, -479, -485, -490, -496, -502, -507, -513, -518, -524, -530, -535, -541, -547, -552, -558, -563, -569, -575, -580, -586, -592, -597, -603, -608, -614, -620, -625, -631, -637, -642, -648, -653, -659, -665, -670, -676, -682, -687, -693, -698, -704, -710, -715, -721, -727, -732, -738, -743, -749, -755, -760, -766, -772, -777, -783, -788, -794, -800, -805, -811, -817, -822, -828, -833, -839, -845, -850, -856, -862, -867, -873, -878, -884, -890, -895, -901, -907, -1302, 39, 44, 50, -665, -659, 67, 1091, 1817, 1822, 1108, 95, -620, -614, 112, 1136, 1862, 1867, 1153, 140, -575, -569, 157, 1181, 1907, 1912, 1198, 185, -530, -524, 202, 1226, 1952, 1957, 1243, 230, -485, -479, -473, -468, -462, -456, -451, -445, -440, -434, -428, -423, -417, -411, -406, -400, -395, -389, -383, -378, -372, -366, -361, -355, -350, -344, -338, -333, -327, -321, -316, -310, -305, -299, -293, -288, -282, -276, -271, -265, -260, -254, -248, -243, -237, -231, -226, -220, -214, -209, -203, -198, -192, -186, -181, -175, -169, -164, -158, -153, -147, -141, -136, -130, -124, -119, -113, -108, -102, -96, -91, -85, -79, -74, -68, -63, -57, -51, -46, -40, -34, -29, -23, -18, -12, -6, -1, 5, 11, 16, 22, 27, 33, 39, 44, 50, -665, 96, 96, 96, -928, -928, 96, 96, -928, -928, 96, 96, -928, -928, 96, 96, -928, -928, 96, 96, -928, -928, 96, 96, -928, -928, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, -928, -3776, -3851, -3919, -3983, -4046, -3936, -3660, -3229, -2654, -1952, -1142, -244, 719, 1724, 2748, 3767, 4757, 5696, 6564, 7341, 8011, 8561, 8978, 9255, 9387, 9373, 9214, 8915, 8484, 7931, 7270, 6515, 5683, 4792, 3861, 2910, 1959, 1027, 132, -709, -1480, -2166, -2757, -3244, -3618, -3876, -4017, -4041, -3952, -3756, -3461, -3077, -2617, -2092, -1518, -910, -283, 347, 966, 1559, 2112, 2612, 3050, 3417, 3703, 3906, 4020, 4046, 3983, 3835, 3606, 3302, 2930, 2501, 2023, 1508, 967, 410, -150, -702, -1237, -1744, -2215, -2642, -3019, -3341, -3604, -3807, -3949, -4031, -4056, -4027, -3948, -3825, -3665, -3474, -3259, -3029, -2791, -2551, -2318, -2097, -1894, -1714, -1561, -1439, -1349, -1293, -1271, -1282, -1324, -1397, -1496, -1618, -1759, -1915, -2083, -2257, -2434, -2610, -2782, -2946, -3101, -3244, -3375, -3494, -3599, -3693, -3776, -3851, -3919, -3983, -2399, -2422, -2454, -2492, -2532, -2327, -1893, -1256, -453, 474, 1475, 2499, 3494, 4411, 5205, 5837, 6278, 6508, 6518, 6308, 5892, 5290, 4534, 3660, 2712, 1734, 772, -129, -929, -1593, -2094, -2412, -2538, -2471, -2220, -1804, -1246, -580, 158, 930, 1696, 2416, 3055, 3582, 3972, 4208, 4279, 4185, 3931, 3531, 3007, 2385, 1696, 972, 247, -445, -1074, -1613, -2040, -2340, -2503, -2528, -2418, -2184, -1845, -1420, -935, -417, 106, 607, 1060, 1443, 1738, 1932, 2016, 1989, 1853, 1618, 1295, 903, 460, -12, -491, -955, -1385, -1762, -2073, -2308, -2460, -2528, -2513, -2423, -2267, -2058, -1812, -1542, -1267, -1001, -759, -554, -394, -288, -239, -247, -311, -425, -582, -774, -989, -1217, -1448, -1672, -1880, -2065, -2222, -2348, -2441, -2503, -2537, -2546, -2536, -2512, -2481, -2449, -2419, -2397, -2386, -2386, -2399, -2422, -2454, -2492, -1722, -1771, -1810, -1841, -1870, -1582, -1009, -207, 750, 1774, 2774, 3663, 4364, 4818, 4987, 4859, 4448, 3792, 2947, 1988, 995, 53, -763, -1387, -1771, -1891, -1742, -1345, -741, 11, 843, 1678, 2444, 3073, 3513, 3726, 3697, 3431, 2953, 2305, 1545, 737, -51, -756, -1320, -1702, -1875, -1832, -1585, -1161, -603, 34, 694, 1315, 1844, 2235, 2456, 2491, 2337, 2012, 1545, 978, 358, -262, -831, -1306, -1650, -1841, -1870, -1742, -1475, -1098, -650, -174, 286, 690, 1001, 1195, 1257, 1183, 983, 676, 289, -143, -585, -1001, -1359, -1633, -1807, -1873, -1831, -1694, -1480, -1213, -921, -633, -376, -172, -39, 14, -14, -121, -293, -515, -767, -1027, -1275, -1494, -1669, -1791, -1857, -1868, -1831, -1757, -1657, -1546, -1437, -1343, -1272, -1230, -1219, -1239, -1285, -1350, -1428, -1510, -1590, -1661, -1722, -1771, -1810, -1841, -1113, -1158, -1190, -1213, -1232, -785, 31, 1052, 2076, 2904, 3378, 3410, 2997, 2222, 1234, 223, -624, -1150, -1265, -957, -297, 580, 1500, 2283, 2778, 2894, 2611, 1987, 1144, 242, -548, -1084, -1270, -1083, -569, 164, 969, 1686, 2178, 2353, 2180, 1696, 996, 215, -502, -1022, -1255, -1167, -786, -195, 486, 1121, 1587, 1796, 1712, 1353, 792, 137, -490, -973, -1228, -1217, -953, -497, 56, 594, 1013, 1232, 1213, 963, 532, 6, -518, -944, -1197, -1240, -1076, -745, -321, 110, 461, 667, 690, 529, 219, -180, -591, -941, -1170, -1243, -1158, -941, -643, -328, -60, 110, 151, 59, -145, -420, -713, -973, -1155, -1235, -1207, -1088, -910, -715, -544, -431, -395, -441, -555, -714, -887, -1043, -1159, -1222, -1229, -1191, -1124, -1050, -987, -949, -942, -964, -1007, -1061, -1113, -1158, -1190, -1213, -794, -833, -862, -881, -895, -315, 651, 1669, 2393, 2582, 2175, 1314, 290, -557, -951, -773, -96, 840, 1712, 2227, 2213, 1680, 811, -103, -760, -949, -622, 99, 961, 1668, 1983, 1803, 1194, 362, -414, -881, -895, -465, 253, 1007, 1540, 1676, 1372, 735, -19, -642, -933, -807, -321, 350, 974, 1339, 1325, 942, 321, -328, -795, -932, -707, -210, 382, 865, 1077, 950, 531, -36, -563, -881, -895, -614, -146, 344, 687, 770, 569, 157, -329, -727, -915, -842, -547, -139, 236, 451, 437, 203, -168, -554, -829, -914, -792, -519, -197, 63, 171, 96, -132, -435, -713, -881, -895, -764, -544, -319, -166, -136, -233, -422, -638, -813, -898, -877, -772, -629, -503, -437, -451, -535, -658, -779, -864, -896, -878, -829, -775, -740, -735, -757, -794, -833, -862, -881, -781, -770, -766, -773, -785, -142, 870, 1816, 2294, 2106, 1336, 312, -537, -862, -541, 276, 1231, 1917, 2046, 1566, 687, -223, -784, -774, -212, 651, 1443, 1826, 1644, 978, 112, -593, -849, -562, 131, 926, 1483, 1568, 1151, 411, -340, -791, -766, -291, 420, 1060, 1356, 1188, 631, -77, -641, -835, -590, -26, 609, 1042, 1092, 743, 147, -446, -794, -762, -380, 177, 668, 884, 737, 295, -254, -682, -821, -626, -194, 281, 595, 618, 345, -105, -543, -793, -763, -480, -77, 268, 410, 292, -30, -419, -716, -808, -669, -374, -58, 144, 147, -43, -345, -631, -789, -768, -590, -344, -141, -65, -146, -343, -573, -744, -795, -721, -566, -407, -312, -321, -423, -572, -708, -783, -778, -711, -623, -557, -541, -577, -645, -716, -765, -784, -781, -770, -766, -773, -605, -636, -663, -679, -690, 3, 1027, 1845, 2034, 1501, 527, -386, -776, -455, 393, 1318, 1839, 1690, 952, 10, -654, -710, -145, 734, 1464, 1668, 1245, 419, -385, -759, -525, 179, 977, 1453, 1363, 760, -43, -635, -721, -275, 459, 1092, 1297, 972, 291, -396, -741, -581, -16, 651, 1070, 1026, 549, -113, -621, -725, -388, 202, 730, 922, 684, 144, -420, -723, -624, -191, 340, 690, 679, 319, -200, -615, -723, -483, -36, 379, 545, 381, -22, -457, -706, -655, -347, 46, 315, 324, 72, -306, -618, -715, -563, -255, 39, 166, 65, -208, -510, -693, -676, -485, -232, -53, -39, -192, -430, -631, -704, -627, -455, -287, -212, -265, -412, -578, -683, -687, -604, -491, -413, -408, -473, -572, -656, -691, -677, -635, -599, -588, -605, -636, -663, -679, -362, -359, -376, -390, -396, 561, 1286, 887, -137, -529, 173, 1084, 1078, 169, -522, -160, 786, 1141, 473, -390, -396, 439, 1072, 723, -169, -512, 97, 888, 881, 94, -504, -193, 622, 927, 352, -390, -396, 318, 858, 559, -202, -494, 22, 691, 685, 19, -486, -225, 458, 712, 230, -390, -396, 197, 643, 395, -235, -476, -53, 494, 488, -56, -469, -258, 294, 498, 109, -390, -396, 75, 429, 231, -267, -459, -128, 298, 292, -131, -451, -291, 130, 284, -12, -390, -396, -46, 215, 67, -300, -441, -203, 101, 95, -207, -433, -323, -34, 70, -134, -390, -396, -167, 1, -96, -332, -423, -279, -95, -101, -282, -416, -356, -198, -144, -255, -390, -396, -289, -213, -260, -365, -406, -354, -292, -298, -357, -398, -389, -362, -359, -376, -390, -5054, -5064, -5079, -5103, -5185, -5080, -4798, -4355, -3766, -3051, -2229, -1324, -356, 651, 1675, 2694, 3689, 4639, 5528, 6341, 7065, 7689, 8206, 8611, 8901, 9076, 9138, 9091, 8942, 8700, 8372, 7971, 7507, 6992, 6440, 5861, 5269, 4673, 4086, 3516, 2971, 2460, 1988, 1559, 1177, 844, 559, 323, 133, -13, -119, -189, -227, -240, -230, -205, -169, -127, -82, -40, -3, 26, 44, 52, 46, 29, -1, -42, -93, -153, -219, -289, -361, -433, -503, -570, -631, -684, -731, -768, -797, -818, -832, -838, -839, -836, -832, -827, -825, -827, -835, -853, -881, -921, -975, -1044, -1128, -1229, -1345, -1478, -1625, -1786, -1960, -2144, -2337, -2537, -2741, -2947, -3152, -3354, -3550, -3739, -3918, -4086, -4241, -4383, -4509, -4621, -4717, -4798, -4865, -4919, -4960, -4991, -5013, -5028, -5039, -5046, -5054, -5064, -5079, -5103, -1700, -1736, -1781, -1830, -1860, -1471, -740, 212, 1236, 2183, 2924, 3370, 3485, 3286, 2837, 2242, 1617, 1078, 716, 588, 705, 1037, 1514, 2044, 2525, 2868, 3005, 2904, 2572, 2051, 1412, 744, 136, -334, -611, -674, -532, -225, 186, 628, 1029, 1330, 1490, 1498, 1364, 1124, 825, 524, 270, 104, 48, 102, 249, 456, 682, 883, 1021, 1072, 1022, 879, 662, 400, 129, -117, -311, -435, -482, -458, -381, -272, -156, -57, 7, 28, 3, -60, -150, -250, -346, -423, -473, -494, -489, -465, -433, -403, -385, -386, -410, -454, -514, -585, -659, -728, -789, -839, -878, -908, -934, -958, -984, -1014, -1049, -1086, -1123, -1156, -1183, -1203, -1214, -1220, -1222, -1226, -1236, -1254, -1284, -1325, -1375, -1430, -1486, -1538, -1582, -1615, -1636, -1647, -1652, -1655, -1661, -1676, -1700, -1736, -1781, -1830, -1133, -1152, -1199, -1256, -1276, -703, 256, 1280, 2054, 2371, 2199, 1675, 1052, 599, 502, 801, 1384, 2026, 2481, 2564, 2221, 1543, 729, 17, -400, -435, -129, 368, 859, 1168, 1203, 979, 607, 247, 45, 85, 358, 771, 1182, 1453, 1498, 1306, 946, 534, 191, 3, -3, 133, 328, 488, 543, 469, 295, 86, -85, -158, -114, 27, 214, 382, 480, 486, 407, 278, 144, 43, -8, -11, 11, 30, 23, -20, -90, -171, -241, -285, -300, -292, -274, -260, -259, -268, -282, -292, -291, -282, -273, -276, -301, -350, -417, -487, -543, -574, -577, -560, -541, -538, -563, -618, -693, -766, -817, -832, -808, -759, -705, -672, -677, -724, -804, -893, -968, -1009, -1009, -977, -933, -902, -904, -945, -1020, -1108, -1187, -1236, -1246, -1222, -1182, -1146, -1133, -1152, -1199, -1256, -1365, -1391, -1419, -1445, -1468, -1004, -169, 855, 1862, 2670, 3154, 3270, 3054, 2602, 2041, 1494, 1050, 748, 582, 509, 473, 430, 361, 283, 237, 272, 429, 718, 1109, 1536, 1910, 2139, 2155, 1933, 1496, 920, 311, -217, -565, -677, -545, -215, 230, 690, 1069, 1300, 1355, 1247, 1023, 747, 484, 279, 155, 105, 103, 115, 108, 70, 3, -70, -119, -115, -41, 96, 272, 445, 567, 600, 521, 337, 75, -215, -477, -662, -738, -696, -556, -357, -148, 22, 118, 124, 46, -92, -255, -409, -526, -594, -616, -605, -583, -570, -577, -608, -653, -697, -726, -726, -696, -644, -587, -546, -540, -581, -669, -792, -931, -1059, -1154, -1200, -1192, -1139, -1058, -973, -906, -874, -886, -938, -1019, -1112, -1201, -1272, -1318, -1340, -1345, -1342, -1341, -1348, -1365, -1391, -1419, -1445, -5683, -5796, -5904, -6002, -6095, -5744, -5033, -4089, -3065, -2115, -1370, -921, -805, -1006, -1456, -2051, -2665, -3177, -3480, -3504, -3222, -2652, -1854, -917, 54, 954, 1695, 2216, 2492, 2537, 2397, 2143, 1858, 1628, 1522, 1589, 1847, 2284, 2863, 3521, 4191, 4800, 5289, 5618, 5767, 5745, 5583, 5328, 5036, 4766, 4566, 4471, 4496, 4637, 4868, 5153, 5445, 5697, 5868, 5929, 5866, 5684, 5400, 5045, 4659, 4280, 3944, 3676, 3490, 3385, 3348, 3356, 3378, 3382, 3341, 3233, 3046, 2782, 2450, 2070, 1668, 1271, 903, 584, 325, 129, -12, -112, -190, -268, -366, -500, -680, -908, -1179, -1480, -1796, -2108, -2400, -2656, -2868, -3032, -3153, -3238, -3300, -3354, -3415, -3495, -3601, -3736, -3900, -4084, -4279, -4474, -4656, -4816, -4946, -5046, -5114, -5159, -5186, -5206, -5229, -5263, -5313, -5383, -5470, -5573, -5683, -5796, -5904, -6002, -1269, -1284, -1283, -1281, -1300, -750, 180, 1204, 2042, 2511, 2572, 2322, 1933, 1580, 1363, 1285, 1267, 1195, 989, 643, 235, -107, -258, -150, 194, 667, 1123, 1426, 1510, 1391, 1161, 938, 818, 833, 938, 1037, 1024, 835, 480, 45, -339, -548, -505, -219, 226, 699, 1066, 1242, 1208, 1015, 751, 505, 335, 246, 201, 146, 42, -114, -286, -409, -425, -304, -66, 227, 489, 643, 648, 513, 290, 53, -129, -223, -232, -198, -174, -200, -286, -409, -520, -568, -524, -389, -203, -24, 91, 107, 21, -136, -315, -470, -569, -611, -615, -612, -627, -669, -724, -767, -770, -719, -621, -503, -406, -364, -396, -497, -641, -790, -908, -976, -991, -973, -945, -932, -942, -971, -1003, -1021, -1012, -977, -930, -892, -883, -914, -981, -1069, -1157, -1227, -1269, -1284, -1283, -1281, -600, -621, -601, -582, -591, 433, 1242, 1029, 394, 386, 1048, 1414, 875, -15, -310, 132, 603, 575, 312, 352, 719, 956, 791, 444, 241, 203, 171, 138, 230, 418, 505, 430, 394, 532, 641, 440, 29, -150, 106, 449, 426, 105, -5, 327, 694, 583, 78, -227, -12, 362, 360, -1, -200, 63, 463, 496, 142, -145, -58, 191, 215, -21, -193, -84, 149, 221, 94, -34, -31, 24, 4, -76, -116, -97, -83, -92, -69, -7, 6, -87, -197, -192, -95, -71, -191, -315, -267, -94, -23, -156, -327, -322, -169, -102, -237, -413, -410, -244, -142, -233, -391, -413, -295, -220, -300, -439, -472, -386, -315, -351, -435, -460, -415, -383, -413, -468, -492, -484, -481, -494, -503, -500, -508, -533, -550, -541, -531, -554, -600, -621, -601, -582, -420, -374, -394, -443, -450, 574, 805, 203, 361, 1154, 994, 33, -148, 412, 358, -184, 25, 778, 839, 319, 274, 587, 382, -129, -100, 309, 376, 210, 337, 574, 465, 183, 111, 148, 87, 59, 174, 277, 305, 340, 322, 174, 69, 114, 108, -12, 33, 266, 311, 118, 90, 256, 186, -105, -112, 159, 175, -54, -2, 282, 233, -91, -107, 141, 89, -191, -131, 176, 156, -115, -89, 147, 69, -216, -188, 56, 24, -187, -131, 84, 29, -191, -176, -18, -73, -239, -193, -38, -67, -195, -171, -78, -130, -241, -225, -154, -177, -231, -206, -165, -191, -233, -235, -235, -257, -264, -258, -266, -270, -253, -259, -300, -311, -286, -301, -351, -347, -299, -310, -368, -364, -317, -340, -408, -403, -352, -371, -430, -420, -374, -394, -443, -6257, -6312, -6374, -6443, -6550, -5920, -5032, -4051, -3036, -2012, -992, 16, 1008, 1982, 2934, 3864, 4770, 5650, 6504, 7328, 8117, 8863, 9534, 10022, 10293, 10480, 10618, 10704, 10711, 10559, 10240, 9794, 9192, 8502, 7783, 7057, 6334, 5619, 4917, 4232, 3571, 2952, 2445, 2095, 1802, 1532, 1276, 1032, 797, 571, 355, 150, -39, -198, -295, -332, -343, -337, -303, -210, -60, 59, 79, 64, 37, 5, -31, -70, -112, -156, -202, -251, -301, -354, -410, -467, -527, -590, -660, -744, -816, -820, -800, -776, -757, -750, -770, -840, -946, -1066, -1192, -1321, -1452, -1584, -1716, -1850, -1985, -2123, -2268, -2433, -2650, -2888, -3128, -3365, -3590, -3804, -4013, -4217, -4418, -4615, -4809, -4997, -5179, -5350, -5499, -5619, -5723, -5818, -5899, -5946, -5978, -6005, -6033, -6063, -6095, -6130, -6168, -6210, -6257, -6312, -6374, -6443, -2471, -2554, -2630, -2678, -2719, -1835, -832, 192, 1207, 2198, 3140, 3896, 3934, 3714, 3455, 3181, 2901, 2621, 2381, 2458, 2616, 2830, 3038, 3238, 3425, 3573, 3398, 3102, 2517, 1838, 1161, 501, -120, -522, -707, -724, -349, 122, 601, 1066, 1438, 1567, 1662, 1714, 1528, 1291, 1053, 849, 871, 915, 939, 899, 1024, 1170, 1296, 1231, 1113, 988, 856, 694, 361, 20, -200, -318, -421, -508, -550, -511, -319, -160, -134, -121, -112, -107, -108, -144, -281, -300, -305, -311, -320, -339, -388, -426, -477, -546, -617, -688, -758, -827, -894, -929, -991, -1054, -1117, -1178, -1237, -1286, -1345, -1430, -1461, -1487, -1512, -1536, -1559, -1570, -1514, -1494, -1516, -1543, -1573, -1606, -1649, -1759, -1883, -1967, -2022, -2074, -2123, -2168, -2177, -2163, -2153, -2180, -2224, -2271, -2320, -2383, -2471, -2554, -2630, -2678, -1639, -1713, -1777, -1781, -1808, -857, 167, 1187, 2158, 2601, 2410, 2173, 1925, 1695, 1905, 2485, 2766, 2986, 3156, 2879, 2190, 1407, 636, -76, -364, -417, -146, 389, 933, 1123, 1230, 1007, 769, 600, 732, 898, 1356, 1806, 1984, 1844, 1666, 1254, 768, 452, 290, 150, 111, 266, 235, 202, 250, 277, 92, 111, 169, 231, 304, 563, 636, 677, 681, 599, 378, 274, 182, 94, 9, -48, -127, -206, -280, -339, -325, -304, -287, -271, -259, -296, -307, -299, -291, -281, -198, -166, -215, -271, -333, -494, -660, -721, -774, -819, -759, -690, -710, -721, -737, -851, -969, -1001, -1012, -1012, -924, -835, -794, -812, -861, -991, -1123, -1238, -1281, -1302, -1259, -1215, -1179, -1208, -1269, -1364, -1455, -1541, -1575, -1559, -1517, -1477, -1442, -1430, -1490, -1563, -1639, -1713, -1777, -1781, -1772, -1783, -1769, -1762, -1790, -848, 173, 1197, 2198, 3138, 3592, 3912, 4091, 3492, 2638, 1829, 1442, 1099, 775, 470, 196, -24, 64, 256, 463, 675, 904, 1442, 2037, 2572, 2766, 2623, 2378, 1809, 1218, 634, 70, -453, -739, -538, -117, 330, 773, 1193, 1377, 1469, 1518, 1354, 1077, 698, 542, 412, 288, 171, 61, -37, -149, -188, -152, -106, -50, 151, 415, 661, 759, 791, 733, 466, 176, -114, -395, -660, -843, -756, -636, -459, -267, -84, 2, 13, 7, -95, -243, -392, -464, -523, -580, -635, -687, -734, -795, -849, -892, -903, -906, -854, -747, -646, -607, -611, -628, -738, -884, -1032, -1176, -1314, -1422, -1390, -1342, -1290, -1231, -1165, -1130, -1146, -1169, -1228, -1317, -1404, -1441, -1472, -1507, -1542, -1575, -1607, -1646, -1681, -1715, -1747, -1772, -1783, -1769, -1762, -5427, -5514, -5568, -5621, -5708, -4878, -3911, -2896, -1872, -863, 97, 825, 582, 103, -397, -889, -1362, -1802, -2147, -1946, -1281, -507, 270, 1031, 1767, 2448, 2769, 2892, 2642, 2329, 2011, 1702, 1417, 1290, 1398, 1591, 2085, 2608, 3123, 3619, 4047, 4232, 4372, 4415, 4212, 3988, 3765, 3566, 3552, 3577, 3617, 3773, 4091, 4413, 4716, 4897, 4997, 5075, 5119, 4994, 4736, 4435, 4138, 3912, 3679, 3443, 3218, 3146, 3126, 3093, 2971, 2836, 2699, 2556, 2395, 2088, 1758, 1490, 1243, 1000, 761, 528, 321, 242, 150, 30, -92, -212, -334, -459, -610, -854, -1070, -1282, -1493, -1700, -1904, -2102, -2263, -2375, -2484, -2590, -2695, -2800, -2904, -3011, -3144, -3318, -3493, -3667, -3838, -4007, -4171, -4334, -4452, -4538, -4615, -4682, -4737, -4781, -4817, -4842, -4914, -4998, -5082, -5167, -5251, -5336, -5427, -5514, -5568, -5621, -1380, -1399, -1418, -1437, -1459, -493, 531, 1545, 2500, 2914, 3058, 2695, 2278, 1671, 1328, 1006, 776, 988, 866, 637, 409, 217, 307, 509, 707, 904, 1092, 1122, 927, 1013, 1122, 989, 1117, 1272, 1406, 1329, 1098, 576, 58, -400, -599, -426, -3, 430, 854, 1243, 1350, 1376, 1191, 815, 500, 374, 261, 172, 210, 52, -130, -250, -221, -158, -3, 145, 289, 424, 427, 342, 261, 99, -58, -45, -19, 4, -26, -132, -363, -513, -589, -645, -543, -365, -185, -12, 137, 140, 38, -151, -343, -467, -520, -567, -608, -615, -714, -746, -752, -754, -737, -659, -584, -513, -450, -478, -597, -712, -819, -916, -931, -940, -949, -969, -1019, -1063, -1099, -1132, -1160, -1120, -1060, -1002, -950, -923, -993, -1072, -1161, -1247, -1294, -1323, -1350, -1374, -1380, -1399, -1418, -1437, -649, -707, -760, -745, -756, 268, 1253, 1090, 876, 1158, 1393, 1354, 590, -276, -571, 112, 429, 649, 597, 852, 1314, 1071, 797, 522, 281, 58, 225, 433, 663, 846, 657, 556, 461, 514, 322, -205, -325, 125, 588, 659, 446, 434, 645, 825, 426, -13, -355, -55, 318, 184, -12, 43, 359, 502, 363, 17, -78, 60, 135, 183, 39, 95, 204, 210, 139, 49, -20, -94, -150, -114, 13, 49, -63, -44, -62, 48, -5, -221, -313, -217, -38, -22, -156, -267, -111, 0, -118, -298, -460, -365, -238, -249, -365, -399, -280, -166, -200, -341, -377, -363, -341, -342, -429, -427, -418, -412, -423, -464, -488, -514, -540, -559, -494, -494, -525, -542, -542, -491, -509, -590, -664, -663, -617, -618, -679, -736, -696, -655, -649, -707, -760, -745, -503, -465, -469, -506, -514, 510, 730, 529, 1093, 1415, 845, -71, -233, 5, 99, -90, 355, 1062, 1099, 600, 446, 249, -99, -126, 177, 406, 538, 715, 636, 439, 198, 8, -145, -8, 285, 439, 321, 406, 549, 398, -33, -162, 123, 223, 56, 181, 546, 423, 49, 86, 239, -84, -263, 66, 382, 206, 16, 181, 317, 1, -277, -50, 182, 16, -23, 234, 205, -60, -122, 15, -38, -192, -148, 65, 92, -57, -94, 3, -50, -169, -166, -121, -102, -87, -63, -88, -127, -163, -196, -225, -208, -192, -193, -181, -116, -142, -266, -294, -218, -222, -315, -306, -201, -197, -310, -327, -258, -291, -396, -349, -263, -330, -406, -336, -278, -367, -454, -402, -343, -408, -468, -408, -361, -430, -468, -430, -437, -496, -503, -465, -469, -506, -30208, -31232, -32256, -31264, -30271, -29279, -28286, -27294, -26301, -25309, -24316, -23324, -22331, -21339, -20346, -19354, -18361, -17369, -16376, -15384, -14391, -13399, -12406, -11414, -10421, -9429, -8436, -7444, -6451, -5459, -4466, -3474, -2481, -1489, -496, 496, 1489, 2481, 3474, 4466, 5459, 6451, 7444, 8436, 9429, 10421, 11414, 12406, 13399, 14391, 15384, 16376, 17369, 18361, 19354, 20346, 21339, 22331, 23324, 24316, 25309, 26301, 27294, 28286, 29279, 30271, 31264, 32256, 31232, 30208, 29184, 28160, 27136, 26112, 25088, 24064, 23040, 22016, 20992, 19968, 18944, 17920, 16896, 15872, 14848, 13824, 12800, 11776, 10752, 9728, 8704, 7680, 6656, 5632, 4608, 3584, 2560, 1536, 512, -512, -1536, -2560, -3584, -4608, -5632, -6656, -7680, -8704, -9728, -10752, -11776, -12800, -13824, -14848, -15872, -16896, -17920, -18944, -19968, -20992, -22016, -23040, -24064, -25088, -26112, -27136, -28160, -29184, -30208, -31232, -32256, -31264, -25689, -26412, -27136, -26112, -25088, -24064, -23040, -22016, -20992, -19968, -18944, -17920, -16896, -15872, -14848, -13824, -12800, -11776, -10752, -9728, -8704, -7680, -6656, -5632, -4608, -3584, -2560, -1536, -512, 512, 1536, 2560, 3584, 4608, 5632, 6656, 7680, 8704, 9728, 10752, 11776, 12800, 13824, 14848, 15872, 16896, 17920, 18944, 19968, 20992, 22016, 23040, 24064, 25088, 26112, 27136, 26412, 25689, 24965, 24241, 23518, 22794, 22071, 21347, 20623, 19900, 19176, 18452, 17729, 17005, 16282, 15558, 14834, 14111, 13387, 12663, 11940, 11216, 10493, 9769, 9045, 8322, 7598, 6874, 6151, 5427, 4704, 3980, 3256, 2533, 1809, 1085, 362, -362, -1085, -1809, -2533, -3256, -3980, -4704, -5427, -6151, -6874, -7598, -8322, -9045, -9769, -10493, -11216, -11940, -12663, -13387, -14111, -14834, -15558, -16282, -17005, -17729, -18452, -19176, -19900, -20623, -21347, -22071, -22794, -23518, -24241, -24965, -25689, -26412, -27136, -26112, -21455, -21992, -22528, -21504, -20480, -19456, -18432, -17408, -16384, -15360, -14336, -13312, -12288, -11264, -10240, -9216, -8192, -7168, -6144, -5120, -4096, -3072, -2048, -1024, 0, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360, 16384, 17408, 18432, 19456, 20480, 21504, 22528, 21992, 21455, 20919, 20382, 19846, 19310, 18773, 18237, 17701, 17164, 16628, 16091, 15555, 15019, 14482, 13946, 13410, 12873, 12337, 11800, 11264, 10728, 10191, 9655, 9118, 8582, 8046, 7509, 6973, 6437, 5900, 5364, 4827, 4291, 3755, 3218, 2682, 2146, 1609, 1073, 536, 0, -536, -1073, -1609, -2146, -2682, -3218, -3755, -4291, -4827, -5364, -5900, -6437, -6973, -7509, -8046, -8582, -9118, -9655, -10191, -10728, -11264, -11800, -12337, -12873, -13410, -13946, -14482, -15019, -15555, -16091, -16628, -17164, -17701, -18237, -18773, -19310, -19846, -20382, -20919, -21455, -21992, -22528, -21504, -16185, -16540, -16896, -15872, -14848, -13824, -12800, -11776, -10752, -9728, -8704, -7680, -6656, -5632, -4608, -3584, -2560, -1536, -512, 512, 1536, 2560, 3584, 4608, 5632, 6656, 7680, 8704, 9728, 10752, 11776, 12800, 13824, 14848, 15872, 16896, 16540, 16185, 15829, 15473, 15117, 14762, 14406, 14050, 13695, 13339, 12983, 12628, 12272, 11916, 11560, 11205, 10849, 10493, 10138, 9782, 9426, 9070, 8715, 8359, 8003, 7648, 7292, 6936, 6581, 6225, 5869, 5513, 5158, 4802, 4446, 4091, 3735, 3379, 3023, 2668, 2312, 1956, 1601, 1245, 889, 534, 178, -178, -534, -889, -1245, -1601, -1956, -2312, -2668, -3023, -3379, -3735, -4091, -4446, -4802, -5158, -5513, -5869, -6225, -6581, -6936, -7292, -7648, -8003, -8359, -8715, -9070, -9426, -9782, -10138, -10493, -10849, -11205, -11560, -11916, -12272, -12628, -12983, -13339, -13695, -14050, -14406, -14762, -15117, -15473, -15829, -16185, -16540, -16896, -15872, -13277, -13550, -13824, -12800, -11776, -10752, -9728, -8704, -7680, -6656, -5632, -4608, -3584, -2560, -1536, -512, 512, 1536, 2560, 3584, 4608, 5632, 6656, 7680, 8704, 9728, 10752, 11776, 12800, 13824, 13550, 13277, 13003, 12729, 12455, 12182, 11908, 11634, 11360, 11087, 10813, 10539, 10265, 9992, 9718, 9444, 9170, 8897, 8623, 8349, 8075, 7802, 7528, 7254, 6980, 6707, 6433, 6159, 5885, 5612, 5338, 5064, 4790, 4517, 4243, 3969, 3696, 3422, 3148, 2874, 2601, 2327, 2053, 1779, 1506, 1232, 958, 684, 411, 137, -137, -411, -684, -958, -1232, -1506, -1779, -2053, -2327, -2601, -2874, -3148, -3422, -3696, -3969, -4243, -4517, -4790, -5064, -5338, -5612, -5885, -6159, -6433, -6707, -6980, -7254, -7528, -7802, -8075, -8349, -8623, -8897, -9170, -9444, -9718, -9992, -10265, -10539, -10813, -11087, -11360, -11634, -11908, -12182, -12455, -12729, -13003, -13277, -13550, -13824, -12800, -8390, -8547, -8704, -7680, -6656, -5632, -4608, -3584, -2560, -1536, -512, 512, 1536, 2560, 3584, 4608, 5632, 6656, 7680, 8704, 8547, 8390, 8234, 8077, 7920, 7763, 7606, 7449, 7293, 7136, 6979, 6822, 6665, 6508, 6352, 6195, 6038, 5881, 5724, 5567, 5411, 5254, 5097, 4940, 4783, 4626, 4470, 4313, 4156, 3999, 3842, 3685, 3529, 3372, 3215, 3058, 2901, 2745, 2588, 2431, 2274, 2117, 1960, 1804, 1647, 1490, 1333, 1176, 1019, 863, 706, 549, 392, 235, 78, -78, -235, -392, -549, -706, -863, -1019, -1176, -1333, -1490, -1647, -1804, -1960, -2117, -2274, -2431, -2588, -2745, -2901, -3058, -3215, -3372, -3529, -3685, -3842, -3999, -4156, -4313, -4470, -4626, -4783, -4940, -5097, -5254, -5411, -5567, -5724, -5881, -6038, -6195, -6352, -6508, -6665, -6822, -6979, -7136, -7293, -7449, -7606, -7763, -7920, -8077, -8234, -8390, -8547, -8704, -7680, -4453, -4531, -4608, -3584, -2560, -1536, -512, 512, 1536, 2560, 3584, 4608, 4531, 4453, 4376, 4298, 4221, 4143, 4066, 3988, 3911, 3834, 3756, 3679, 3601, 3524, 3446, 3369, 3291, 3214, 3137, 3059, 2982, 2904, 2827, 2749, 2672, 2594, 2517, 2440, 2362, 2285, 2207, 2130, 2052, 1975, 1897, 1820, 1743, 1665, 1588, 1510, 1433, 1355, 1278, 1200, 1123, 1046, 968, 891, 813, 736, 658, 581, 503, 426, 349, 271, 194, 116, 39, -39, -116, -194, -271, -349, -426, -503, -581, -658, -736, -813, -891, -968, -1046, -1123, -1200, -1278, -1355, -1433, -1510, -1588, -1665, -1743, -1820, -1897, -1975, -2052, -2130, -2207, -2285, -2362, -2440, -2517, -2594, -2672, -2749, -2827, -2904, -2982, -3059, -3137, -3214, -3291, -3369, -3446, -3524, -3601, -3679, -3756, -3834, -3911, -3988, -4066, -4143, -4221, -4298, -4376, -4453, -4531, -4608, -3584, -2477, -2518, -2560, -1536, -512, 512, 1536, 2560, 2518, 2477, 2435, 2393, 2352, 2310, 2269, 2227, 2185, 2144, 2102, 2060, 2019, 1977, 1936, 1894, 1852, 1811, 1769, 1727, 1686, 1644, 1603, 1561, 1519, 1478, 1436, 1394, 1353, 1311, 1270, 1228, 1186, 1145, 1103, 1061, 1020, 978, 937, 895, 853, 812, 770, 728, 687, 645, 604, 562, 520, 479, 437, 395, 354, 312, 271, 229, 187, 146, 104, 62, 21, -21, -62, -104, -146, -187, -229, -271, -312, -354, -395, -437, -479, -520, -562, -604, -645, -687, -728, -770, -812, -853, -895, -937, -978, -1020, -1061, -1103, -1145, -1186, -1228, -1270, -1311, -1353, -1394, -1436, -1478, -1519, -1561, -1603, -1644, -1686, -1727, -1769, -1811, -1852, -1894, -1936, -1977, -2019, -2060, -2102, -2144, -2185, -2227, -2269, -2310, -2352, -2393, -2435, -2477, -2518, -2560, -1536, -25205, -26158, -26912, -27331, -27331, -26912, -26158, -25205, -24192, -23221, -22326, -21487, -20652, -19773, -18831, -17840, -16836, -15849, -14893, -13957, -13016, -12048, -11045, -10021, -8998, -7993, -7013, -6048, -5082, -4101, -3104, -2102, -1113, -150, 786, 1703, 2615, 3530, 4445, 5350, 6230, 7077, 7891, 8680, 9456, 10223, 10978, 11709, 12405, 13060, 13675, 14261, 14826, 15373, 15898, 16388, 16835, 17234, 17591, 17915, 18212, 18486, 18729, 18932, 19086, 19190, 19251, 19278, 19278, 19251, 19190, 19086, 18932, 18729, 18486, 18212, 17915, 17591, 17234, 16835, 16388, 15898, 15373, 14826, 14261, 13675, 13060, 12405, 11709, 10978, 10223, 9456, 8680, 7891, 7077, 6230, 5350, 4445, 3530, 2615, 1703, 786, -150, -1113, -2102, -3104, -4101, -5082, -6048, -7013, -7993, -8998, -10021, -11045, -12048, -13016, -13957, -14893, -15849, -16836, -17840, -18831, -19773, -20652, -21487, -22326, -23221, -24192, -25205, -26158, -26912, -27331, -22542, -23430, -23985, -24156, -24156, -23985, -23430, -22542, -21541, -20619, -19838, -19151, -18470, -17715, -16848, -15889, -14904, -13953, -13061, -12206, -11341, -10424, -9444, -8420, -7396, -6411, -5473, -4564, -3652, -2712, -1741, -761, 193, 1100, 1955, 2777, 3589, 4406, 5224, 6024, 6781, 7481, 8128, 8736, 9324, 9898, 10454, 10977, 11450, 11868, 12239, 12574, 12886, 13178, 13446, 13681, 13876, 14032, 14156, 14258, 14345, 14418, 14476, 14516, 14539, 14550, 14553, 14554, 14554, 14553, 14550, 14539, 14516, 14476, 14418, 14345, 14258, 14156, 14032, 13876, 13681, 13446, 13178, 12886, 12574, 12239, 11868, 11450, 10977, 10454, 9898, 9324, 8736, 8128, 7481, 6781, 6024, 5224, 4406, 3589, 2777, 1955, 1100, 193, -761, -1741, -2712, -3652, -4564, -5473, -6411, -7396, -8420, -9444, -10424, -11341, -12206, -13061, -13953, -14904, -15889, -16848, -17715, -18470, -19151, -19838, -20619, -21541, -22542, -23430, -23985, -24156, -18887, -19656, -19957, -19986, -19986, -19957, -19656, -18887, -17908, -17078, -16482, -16021, -15568, -15012, -14277, -13380, -12432, -11550, -10773, -10058, -9327, -8507, -7567, -6543, -5521, -4572, -3714, -2907, -2094, -1231, -311, 626, 1516, 2319, 3033, 3693, 4337, 4989, 5643, 6267, 6827, 7305, 7714, 8075, 8412, 8735, 9037, 9303, 9522, 9693, 9827, 9936, 10031, 10115, 10185, 10239, 10276, 10300, 10315, 10325, 10332, 10338, 10341, 10342, 10343, 10343, 10343, 10343, 10343, 10343, 10343, 10343, 10342, 10341, 10338, 10332, 10325, 10315, 10300, 10276, 10239, 10185, 10115, 10031, 9936, 9827, 9693, 9522, 9303, 9037, 8735, 8412, 8075, 7714, 7305, 6827, 6267, 5643, 4989, 4337, 3693, 3033, 2319, 1516, 626, -311, -1231, -2094, -2907, -3714, -4572, -5521, -6543, -7567, -8507, -9327, -10058, -10773, -11550, -12432, -13380, -14277, -15012, -15568, -16021, -16482, -17078, -17908, -18887, -19656, -19957, -19986, -14425, -15003, -15092, -15092, -15092, -15092, -15003, -14425, -13489, -12816, -12470, -12262, -12062, -11759, -11233, -10447, -9568, -8808, -8219, -7719, -7198, -6542, -5679, -4655, -3634, -2756, -2035, -1400, -755, -28, 800, 1657, 2431, 3059, 3558, 3983, 4388, 4803, 5221, 5602, 5907, 6131, 6294, 6421, 6532, 6634, 6723, 6792, 6839, 6867, 6885, 6897, 6906, 6912, 6917, 6920, 6921, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6922, 6921, 6920, 6917, 6912, 6906, 6897, 6885, 6867, 6839, 6792, 6723, 6634, 6532, 6421, 6294, 6131, 5907, 5602, 5221, 4803, 4388, 3983, 3558, 3059, 2431, 1657, 800, -28, -755, -1400, -2035, -2756, -3634, -4655, -5679, -6542, -7198, -7719, -8219, -8808, -9568, -10447, -11233, -11759, -12062, -12262, -12470, -12816, -13489, -14425, -15003, -15092, -15092, -9768, -10095, -10103, -10103, -10103, -10103, -10095, -9768, -8913, -8471, -8354, -8312, -8273, -8183, -7913, -7310, -6555, -5992, -5652, -5409, -5143, -4723, -3997, -2973, -1953, -1200, -693, -299, 107, 624, 1292, 2010, 2595, 2981, 3224, 3400, 3560, 3728, 3899, 4040, 4131, 4180, 4206, 4222, 4234, 4244, 4252, 4257, 4259, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4260, 4259, 4257, 4252, 4244, 4234, 4222, 4206, 4180, 4131, 4040, 3899, 3728, 3560, 3400, 3224, 2981, 2595, 2010, 1292, 624, 107, -299, -693, -1200, -1953, -2973, -3997, -4723, -5143, -5409, -5652, -5992, -6555, -7310, -7913, -8183, -8273, -8312, -8354, -8471, -8913, -9768, -10095, -10103, -10103, -5824, -5928, -5928, -5928, -5928, -5928, -5928, -5824, -5110, -4920, -4906, -4904, -4903, -4895, -4824, -4468, -3912, -3602, -3489, -3432, -3363, -3190, -2675, -1651, -637, -82, 168, 320, 481, 742, 1178, 1681, 2016, 2161, 2218, 2249, 2274, 2301, 2330, 2349, 2357, 2360, 2360, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2361, 2360, 2360, 2357, 2349, 2330, 2301, 2274, 2249, 2218, 2161, 2016, 1681, 1178, 742, 481, 320, 168, -82, -637, -1651, -2675, -3190, -3363, -3432, -3489, -3602, -3912, -4468, -4824, -4895, -4903, -4904, -4906, -4920, -5110, -5824, -5928, -5928, -5928, -3202, -3212, -3212, -3212, -3212, -3212, -3212, -3202, -2704, -2669, -2668, -2668, -2668, -2668, -2663, -2540, -2238, -2144, -2132, -2128, -2124, -2095, -1836, -812, 194, 494, 555, 577, 603, 669, 855, 1102, 1211, 1232, 1235, 1236, 1237, 1237, 1238, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1238, 1237, 1237, 1236, 1235, 1232, 1211, 1102, 855, 669, 603, 577, 555, 494, 194, -812, -1836, -2095, -2124, -2128, -2132, -2144, -2238, -2540, -2663, -2668, -2668, -2668, -2668, -2669, -2704, -3202, -3212, -3212, -3212, -1892, -1892, -1892, -1892, -1892, -1892, -1892, -1892, -1650, -1649, -1649, -1649, -1649, -1649, -1649, -1634, -1545, -1536, -1536, -1536, -1536, -1535, -1470, -446, 541, 629, 633, 633, 634, 638, 672, 732, 743, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, 743, 732, 672, 638, 634, 633, 633, 629, 541, -446, -1470, -1535, -1536, -1536, -1536, -1536, -1545, -1634, -1649, -1649, -1649, -1649, -1649, -1649, -1650, -1892, -1892, -1892, -1892, -11705, -12211, -12571, -12800, -12800, -12571, -12211, -11705, -11057, -10270, -9392, -8442, -7445, -6425, -5401, -4380, -3391, -2459, -1602, -806, -89, 544, 1088, 1548, 1915, 2207, 2433, 2592, 2676, 2714, 2726, 2710, 2656, 2581, 2500, 2412, 2308, 2200, 2096, 1996, 1902, 1823, 1750, 1694, 1664, 1665, 1686, 1729, 1814, 1920, 2043, 2185, 2350, 2520, 2695, 2879, 3067, 3238, 3405, 3574, 3736, 3877, 4005, 4119, 4217, 4286, 4336, 4364, 4364, 4336, 4286, 4217, 4119, 4005, 3877, 3736, 3574, 3405, 3238, 3067, 2879, 2695, 2520, 2350, 2185, 2043, 1920, 1814, 1729, 1686, 1665, 1664, 1694, 1750, 1823, 1902, 1996, 2096, 2200, 2308, 2412, 2500, 2581, 2656, 2710, 2726, 2714, 2676, 2592, 2433, 2207, 1915, 1548, 1088, 544, -89, -806, -1602, -2459, -3391, -4380, -5401, -6425, -7445, -8442, -9392, -10270, -11057, -11705, -12211, -12571, -12800, -11513, -12026, -12383, -12626, -12626, -12383, -12026, -11513, -10829, -10015, -9148, -8205, -7190, -6166, -5166, -4159, -3169, -2238, -1364, -516, 277, 1003, 1671, 2293, 2855, 3353, 3803, 4205, 4543, 4836, 5080, 5269, 5396, 5472, 5491, 5437, 5336, 5181, 4957, 4697, 4402, 4079, 3738, 3402, 3074, 2755, 2461, 2199, 1964, 1741, 1552, 1387, 1225, 1070, 926, 786, 637, 487, 345, 192, 36, -102, -224, -353, -462, -540, -592, -628, -628, -592, -540, -462, -353, -224, -102, 36, 192, 345, 487, 637, 786, 926, 1070, 1225, 1387, 1552, 1741, 1964, 2199, 2461, 2755, 3074, 3402, 3738, 4079, 4402, 4697, 4957, 5181, 5336, 5437, 5491, 5472, 5396, 5269, 5080, 4836, 4543, 4205, 3803, 3353, 2855, 2293, 1671, 1003, 277, -516, -1364, -2238, -3169, -4159, -5166, -6166, -7190, -8205, -9148, -10015, -10829, -11513, -12026, -12383, -12626, -7753, -8376, -8825, -9124, -9124, -8825, -8376, -7753, -6945, -5994, -4994, -3970, -2946, -1961, -1056, -240, 476, 1077, 1566, 1961, 2248, 2431, 2536, 2576, 2546, 2459, 2327, 2151, 1937, 1712, 1470, 1209, 942, 708, 503, 318, 171, 88, 79, 121, 216, 386, 613, 887, 1187, 1507, 1835, 2143, 2416, 2628, 2770, 2840, 2828, 2715, 2513, 2245, 1916, 1533, 1122, 703, 282, -123, -489, -806, -1079, -1288, -1426, -1499, -1499, -1426, -1288, -1079, -806, -489, -123, 282, 703, 1122, 1533, 1916, 2245, 2513, 2715, 2828, 2840, 2770, 2628, 2416, 2143, 1835, 1507, 1187, 887, 613, 386, 216, 121, 79, 88, 171, 318, 503, 708, 942, 1209, 1470, 1712, 1937, 2151, 2327, 2459, 2546, 2576, 2536, 2431, 2248, 1961, 1566, 1077, 476, -240, -1056, -1961, -2946, -3970, -4994, -5994, -6945, -7753, -8376, -8825, -9124, -12891, -13248, -13449, -13716, -13716, -13449, -13248, -12891, -12367, -11747, -11092, -10321, -9457, -8546, -7619, -6626, -5605, -4601, -3577, -2562, -1603, -662, 227, 1052, 1794, 2489, 3125, 3661, 4102, 4508, 4849, 5019, 5171, 5305, 5327, 5253, 5173, 5083, 4894, 4679, 4474, 4247, 3974, 3716, 3488, 3245, 3017, 2817, 2649, 2520, 2392, 2306, 2251, 2198, 2181, 2189, 2205, 2242, 2310, 2363, 2421, 2508, 2598, 2650, 2678, 2752, 2802, 2784, 2784, 2802, 2752, 2678, 2650, 2598, 2508, 2421, 2363, 2310, 2242, 2205, 2189, 2181, 2198, 2251, 2306, 2392, 2520, 2649, 2817, 3017, 3245, 3488, 3716, 3974, 4247, 4474, 4679, 4894, 5083, 5173, 5253, 5327, 5305, 5171, 5019, 4849, 4508, 4102, 3661, 3125, 2489, 1794, 1052, 227, -662, -1603, -2562, -3577, -4601, -5605, -6626, -7619, -8546, -9457, -10321, -11092, -11747, -12367, -12891, -13248, -13449, -13716, -7156, -7842, -8581, -9416, -9416, -8581, -7842, -7156, -6232, -5208, -4489, -4058, -3664, -3378, -3251, -3293, -3466, -3628, -3691, -3617, -3496, -3309, -2884, -2204, -1525, -931, -299, 348, 822, 1122, 1386, 1591, 1657, 1626, 1547, 1494, 1522, 1604, 1695, 1862, 2101, 2324, 2532, 2748, 2982, 3229, 3410, 3492, 3523, 3566, 3565, 3417, 3161, 2916, 2696, 2413, 2064, 1892, 1911, 1925, 1948, 2120, 2408, 2677, 2870, 3020, 3164, 3266, 3266, 3164, 3020, 2870, 2677, 2408, 2120, 1948, 1925, 1911, 1892, 2064, 2413, 2696, 2916, 3161, 3417, 3565, 3566, 3523, 3492, 3410, 3229, 2982, 2748, 2532, 2324, 2101, 1862, 1695, 1604, 1522, 1494, 1547, 1626, 1657, 1591, 1386, 1122, 822, 348, -299, -931, -1525, -2204, -2884, -3309, -3496, -3617, -3691, -3628, -3466, -3293, -3251, -3378, -3664, -4058, -4489, -5208, -6232, -7156, -7842, -8581, -9416, -8028, -8537, -9395, -10253, -10253, -9395, -8537, -8028, -7592, -7001, -6338, -5533, -4512, -3488, -2736, -2212, -1727, -1256, -856, -473, -49, 372, 677, 778, 732, 756, 977, 1295, 1547, 1683, 1725, 1728, 1779, 1980, 2243, 2420, 2522, 2674, 2858, 2959, 3007, 3106, 3283, 3421, 3405, 3281, 3145, 2989, 2802, 2634, 2461, 2178, 1788, 1448, 1213, 985, 710, 512, 460, 443, 400, 417, 528, 638, 688, 723, 781, 831, 831, 781, 723, 688, 638, 528, 417, 400, 443, 460, 512, 710, 985, 1213, 1448, 1788, 2178, 2461, 2634, 2802, 2989, 3145, 3281, 3405, 3421, 3283, 3106, 3007, 2959, 2858, 2674, 2522, 2420, 2243, 1980, 1779, 1728, 1725, 1683, 1547, 1295, 977, 756, 732, 778, 677, 372, -49, -473, -856, -1256, -1727, -2212, -2736, -3488, -4512, -5533, -6338, -7001, -7592, -8028, -8537, -9395, -10253, -12194, -12261, -12614, -13177, -13177, -12614, -12261, -12194, -11954, -11353, -10698, -10033, -9318, -8483, -7689, -6925, -6123, -5159, -4135, -3204, -2494, -1766, -838, 129, 871, 1524, 2216, 2882, 3481, 4105, 4700, 5182, 5531, 5871, 6251, 6594, 6836, 6988, 7053, 7059, 7091, 7083, 6991, 6812, 6541, 6205, 5935, 5682, 5288, 4764, 4267, 3830, 3378, 2881, 2386, 1878, 1327, 832, 449, 57, -374, -754, -1090, -1384, -1546, -1633, -1789, -1959, -1959, -1789, -1633, -1546, -1384, -1090, -754, -374, 57, 449, 832, 1327, 1878, 2386, 2881, 3378, 3830, 4267, 4764, 5288, 5682, 5935, 6205, 6541, 6812, 6991, 7083, 7091, 7059, 7053, 6988, 6836, 6594, 6251, 5871, 5531, 5182, 4700, 4105, 3481, 2882, 2216, 1524, 871, 129, -838, -1766, -2494, -3204, -4135, -5159, -6123, -6925, -7689, -8483, -9318, -10033, -10698, -11353, -11954, -12194, -12261, -12614, -13177, -11519, -11750, -11930, -12347, -12347, -11930, -11750, -11519, -10983, -10334, -9753, -9002, -8145, -7265, -6386, -5433, -4455, -3460, -2436, -1460, -544, 393, 1362, 2182, 2927, 3742, 4457, 5011, 5601, 6161, 6555, 6908, 7272, 7536, 7667, 7824, 7913, 7860, 7777, 7698, 7482, 7170, 6875, 6521, 6083, 5628, 5134, 4558, 3962, 3376, 2734, 2093, 1443, 774, 99, -531, -1110, -1709, -2306, -2801, -3272, -3744, -4104, -4374, -4667, -4888, -5007, -5063, -5063, -5007, -4888, -4667, -4374, -4104, -3744, -3272, -2801, -2306, -1709, -1110, -531, 99, 774, 1443, 2093, 2734, 3376, 3962, 4558, 5134, 5628, 6083, 6521, 6875, 7170, 7482, 7698, 7777, 7860, 7913, 7824, 7667, 7536, 7272, 6908, 6555, 6161, 5601, 5011, 4457, 3742, 2927, 2182, 1362, 393, -544, -1460, -2436, -3460, -4455, -5433, -6386, -7265, -8145, -9002, -9753, -10334, -10983, -11519, -11750, -11930, -12347, -1683, -2437, -3315, -4339, -4339, -3315, -2437, -1683, -1014, -241, 521, 1283, 1859, 2101, 1996, 1708, 1385, 1047, 613, 261, 39, 27, 131, 222, 231, 236, 215, 172, 149, -6, -243, -433, -495, -556, -716, -867, -859, -648, -424, -227, -124, -24, 130, 269, 401, 553, 688, 750, 773, 835, 815, 809, 827, 736, 642, 596, 565, 455, 214, -13, -147, -284, -500, -692, -800, -906, -1060, -1202, -1202, -1060, -906, -800, -692, -500, -284, -147, -13, 214, 455, 565, 596, 642, 736, 827, 809, 815, 835, 773, 750, 688, 553, 401, 269, 130, -24, -124, -227, -424, -648, -859, -867, -716, -556, -495, -433, -243, -6, 149, 172, 215, 236, 231, 222, 131, 27, 39, 261, 613, 1047, 1385, 1708, 1996, 2101, 1859, 1283, 521, -241, -1014, -1683, -2437, -3315, -4339, -2160, -2663, -3352, -4376, -4376, -3352, -2663, -2160, -1750, -1288, -920, -592, 32, 953, 1457, 1668, 1638, 1566, 1394, 1310, 1310, 1297, 1149, 905, 581, 273, -83, -348, -487, -501, -527, -503, -418, -317, -310, -334, -223, 45, 285, 433, 497, 574, 637, 691, 758, 912, 1096, 1247, 1243, 1177, 1024, 927, 844, 675, 506, 382, 238, 13, -294, -533, -666, -765, -891, -953, -960, -1016, -1179, -1329, -1329, -1179, -1016, -960, -953, -891, -765, -666, -533, -294, 13, 238, 382, 506, 675, 844, 927, 1024, 1177, 1243, 1247, 1096, 912, 758, 691, 637, 574, 497, 433, 285, 45, -223, -334, -310, -317, -418, -503, -527, -501, -487, -348, -83, 273, 581, 905, 1149, 1297, 1310, 1310, 1394, 1566, 1638, 1668, 1457, 953, 32, -592, -920, -1288, -1750, -2160, -2663, -3352, -4376, -1003, -1766, -2700, -3724, -3724, -2700, -1766, -1003, -358, 332, 964, 1474, 1724, 1688, 1318, 797, 272, -258, -896, -1514, -1719, -1289, -802, -398, -109, 206, 523, 838, 1057, 1110, 991, 829, 675, 476, 191, -64, -138, -10, 184, 350, 421, 487, 589, 679, 697, 640, 578, 520, 436, 252, -21, -248, -388, -410, -377, -319, -292, -290, -267, -236, -171, -143, -156, -144, -136, -176, -323, -456, -456, -323, -176, -136, -144, -156, -143, -171, -236, -267, -290, -292, -319, -377, -410, -388, -248, -21, 252, 436, 520, 578, 640, 697, 679, 589, 487, 421, 350, 184, -10, -138, -64, 191, 476, 675, 829, 991, 1110, 1057, 838, 523, 206, -109, -398, -802, -1289, -1719, -1514, -896, -258, 272, 797, 1318, 1688, 1724, 1474, 964, 332, -358, -1003, -1766, -2700, -3724, -1955, -2748, -3711, -4735, -4735, -3711, -2748, -1955, -1262, -537, 168, 915, 1660, 2186, 2318, 2129, 1867, 1690, 1423, 1031, 624, 366, 153, -116, -401, -635, -868, -1189, -1412, -1245, -983, -697, -426, -228, -117, -14, 204, 473, 665, 718, 657, 569, 516, 526, 572, 666, 780, 849, 860, 767, 612, 468, 358, 200, -18, -202, -343, -455, -521, -552, -524, -454, -353, -211, -57, 30, -3, -49, -49, -3, 30, -57, -211, -353, -454, -524, -552, -521, -455, -343, -202, -18, 200, 358, 468, 612, 767, 860, 849, 780, 666, 572, 526, 516, 569, 657, 718, 665, 473, 204, -14, -117, -228, -426, -697, -983, -1245, -1412, -1189, -868, -635, -401, -116, 153, 366, 624, 1031, 1423, 1690, 1867, 2129, 2318, 2186, 1660, 915, 168, -537, -1262, -1955, -2748, -3711, -4735, -1483, -2328, -3352, -4340, -4340, -3352, -2328, -1483, -839, -136, 651, 1428, 2030, 2312, 2217, 1860, 1429, 1030, 632, 295, 105, 121, 239, 317, 353, 488, 627, 635, 376, -68, -504, -828, -1049, -1301, -1688, -2095, -2239, -1831, -1196, -644, -200, 186, 587, 977, 1280, 1465, 1533, 1450, 1240, 952, 632, 375, 210, 117, 77, 38, -19, -67, -62, -27, -8, -67, -164, -244, -277, -301, -396, -512, -512, -396, -301, -277, -244, -164, -67, -8, -27, -62, -67, -19, 38, 77, 117, 210, 375, 632, 952, 1240, 1450, 1533, 1465, 1280, 977, 587, 186, -200, -644, -1196, -1831, -2239, -2095, -1688, -1301, -1049, -828, -504, -68, 376, 635, 627, 488, 353, 317, 239, 121, 105, 295, 632, 1030, 1429, 1860, 2217, 2312, 2030, 1428, 651, -136, -839, -1483, -2328, -3352, -4340, -1307, -2045, -2957, -3981, -3981, -2957, -2045, -1307, -764, -182, 446, 1073, 1592, 1872, 1811, 1511, 1099, 711, 355, 87, -70, -81, -76, -98, -146, -108, -11, 52, 19, -62, -121, -76, 43, 159, 115, -44, -195, -259, -259, -287, -348, -361, -371, -422, -527, -373, 130, 607, 901, 996, 952, 923, 955, 991, 935, 728, 399, 50, -200, -318, -347, -408, -501, -520, -449, -383, -404, -450, -450, -404, -383, -449, -520, -501, -408, -347, -318, -200, 50, 399, 728, 935, 991, 955, 923, 952, 996, 901, 607, 130, -373, -527, -422, -371, -361, -348, -287, -259, -259, -195, -44, 115, 159, 43, -76, -121, -62, 19, 52, -11, -108, -146, -98, -76, -81, -70, 87, 355, 711, 1099, 1511, 1811, 1872, 1592, 1073, 446, -182, -764, -1307, -2045, -2957, -3981, -1435, -2272, -3217, -4241, -4241, -3217, -2272, -1435, -782, -129, 552, 1232, 1754, 1965, 1787, 1398, 936, 484, 21, -371, -581, -546, -447, -379, -331, -215, -41, 111, 158, 99, 7, -16, 38, 61, -46, -165, -114, 163, 544, 861, 1061, 1264, 1503, 1658, 1607, 1385, 1131, 829, 414, -80, -613, -1090, -1517, -1724, -1481, -1137, -815, -522, -239, 33, 304, 477, 510, 435, 275, 49, -200, -361, -361, -200, 49, 275, 435, 510, 477, 304, 33, -239, -522, -815, -1137, -1481, -1724, -1517, -1090, -613, -80, 414, 829, 1131, 1385, 1607, 1658, 1503, 1264, 1061, 861, 544, 163, -114, -165, -46, 61, 38, -16, 7, 99, 158, 111, -41, -215, -331, -379, -447, -546, -581, -371, 21, 484, 936, 1398, 1787, 1965, 1754, 1232, 552, -129, -782, -1435, -2272, -3217, -4241, -2191, -3081, -4105, -5066, -5066, -4105, -3081, -2191, -1420, -674, 111, 939, 1686, 2110, 2117, 1897, 1599, 1224, 768, 362, 152, 128, 163, 176, 179, 222, 275, 285, 256, 203, 129, 79, 37, -46, -169, -259, -210, -20, 233, 421, 504, 587, 718, 878, 1023, 1146, 1274, 1398, 1432, 1347, 1212, 1026, 734, 325, -113, -505, -889, -1217, -1458, -1630, -1795, -1840, -1457, -827, -286, -11, -10, -75, -75, -10, -11, -286, -827, -1457, -1840, -1795, -1630, -1458, -1217, -889, -505, -113, 325, 734, 1026, 1212, 1347, 1432, 1398, 1274, 1146, 1023, 878, 718, 587, 504, 421, 233, -20, -210, -259, -169, -46, 37, 79, 129, 203, 256, 285, 275, 222, 179, 176, 163, 128, 152, 362, 768, 1224, 1599, 1897, 2117, 2110, 1686, 939, 111, -674, -1420, -2191, -3081, -4105, -5066, -20598, -20751, -20852, -20913, -20913, -20852, -20751, -20598, -20397, -20146, -19847, -19499, -19107, -18668, -18183, -17651, -17081, -16469, -15819, -15130, -14404, -13643, -12852, -12029, -11174, -10295, -9392, -8464, -7517, -6552, -5570, -4577, -3571, -2557, -1536, -512, 512, 1536, 2557, 3571, 4577, 5570, 6552, 7517, 8464, 9392, 10295, 11174, 12029, 12852, 13643, 14404, 15130, 15819, 16469, 17081, 17651, 18183, 18668, 19107, 19499, 19847, 20146, 20397, 20598, 20751, 20852, 20913, 20913, 20852, 20751, 20598, 20397, 20146, 19847, 19499, 19107, 18668, 18183, 17651, 17081, 16469, 15819, 15130, 14404, 13643, 12852, 12029, 11174, 10295, 9392, 8464, 7517, 6552, 5570, 4577, 3571, 2557, 1536, 512, -512, -1536, -2557, -3571, -4577, -5570, -6552, -7517, -8464, -9392, -10295, -11174, -12029, -12852, -13643, -14404, -15130, -15819, -16469, -17081, -17651, -18183, -18668, -19107, -19499, -19847, -20146, -20397, -20598, -20751, -20852, -20913, -10108, -10547, -10853, -11035, -11035, -10853, -10547, -10108, -9554, -8873, -8091, -7223, -6289, -5304, -4289, -3270, -2261, -1274, -324, 564, 1369, 2077, 2683, 3175, 3539, 3780, 3899, 3898, 3775, 3536, 3192, 2756, 2243, 1667, 1044, 389, -278, -945, -1587, -2184, -2714, -3164, -3524, -3779, -3919, -3931, -3819, -3572, -3196, -2697, -2079, -1359, -547, 343, 1297, 2295, 3315, 4339, 5345, 6314, 7230, 8076, 8839, 9496, 10042, 10460, 10738, 10877, 10877, 10738, 10460, 10042, 9496, 8839, 8076, 7230, 6314, 5345, 4339, 3315, 2295, 1297, 343, -547, -1359, -2079, -2697, -3196, -3572, -3819, -3931, -3919, -3779, -3524, -3164, -2714, -2184, -1587, -945, -278, 389, 1044, 1667, 2243, 2756, 3192, 3536, 3775, 3898, 3899, 3780, 3539, 3175, 2683, 2077, 1369, 564, -324, -1274, -2261, -3270, -4289, -5304, -6289, -7223, -8091, -8873, -9554, -10108, -10547, -10853, -11035, -17901, -18342, -18803, -19228, -19228, -18803, -18342, -17901, -17436, -16807, -16103, -15368, -14576, -13653, -12677, -11766, -10847, -9864, -8852, -7914, -7046, -6187, -5363, -4604, -3924, -3270, -2658, -2141, -1729, -1316, -893, -564, -341, -167, 21, 189, 289, 342, 424, 557, 739, 993, 1345, 1737, 2141, 2603, 3154, 3801, 4514, 5292, 6129, 7038, 8004, 8994, 10018, 11020, 11963, 12861, 13752, 14589, 15337, 16041, 16670, 17218, 17648, 18012, 18331, 18573, 18573, 18331, 18012, 17648, 17218, 16670, 16041, 15337, 14589, 13752, 12861, 11963, 11020, 10018, 8994, 8004, 7038, 6129, 5292, 4514, 3801, 3154, 2603, 2141, 1737, 1345, 993, 739, 557, 424, 342, 289, 189, 21, -167, -341, -564, -893, -1316, -1729, -2141, -2658, -3270, -3924, -4604, -5363, -6187, -7046, -7914, -8852, -9864, -10847, -11766, -12677, -13653, -14576, -15368, -16103, -16807, -17436, -17901, -18342, -18803, -19228, -10200, -11150, -12174, -12991, -12991, -12174, -11150, -10200, -9660, -9444, -9418, -9382, -9147, -8662, -8047, -7405, -6810, -6198, -5604, -5052, -4567, -4162, -3802, -3460, -3049, -2455, -1773, -1132, -642, -353, -146, 61, 414, 969, 1665, 2333, 2828, 3133, 3303, 3452, 3594, 3753, 3928, 4099, 4328, 4645, 5102, 5588, 5940, 6054, 5899, 5579, 5265, 5107, 5173, 5445, 5789, 6021, 6074, 5935, 5688, 5499, 5447, 5525, 5646, 5765, 5869, 5972, 5972, 5869, 5765, 5646, 5525, 5447, 5499, 5688, 5935, 6074, 6021, 5789, 5445, 5173, 5107, 5265, 5579, 5899, 6054, 5940, 5588, 5102, 4645, 4328, 4099, 3928, 3753, 3594, 3452, 3303, 3133, 2828, 2333, 1665, 969, 414, 61, -146, -353, -642, -1132, -1773, -2455, -3049, -3460, -3802, -4162, -4567, -5052, -5604, -6198, -6810, -7405, -8047, -8662, -9147, -9382, -9418, -9444, -9660, -10200, -11150, -12174, -12991, -15200, -16184, -16972, -17454, -17454, -16972, -16184, -15200, -14223, -13348, -12651, -12132, -11807, -11610, -11515, -11442, -11333, -11125, -10771, -10226, -9508, -8637, -7661, -6642, -5618, -4630, -3711, -2895, -2200, -1626, -1161, -764, -400, -34, 377, 864, 1447, 2132, 2906, 3750, 4618, 5450, 6185, 6800, 7276, 7631, 7884, 8056, 8163, 8242, 8320, 8439, 8627, 8920, 9309, 9776, 10278, 10735, 11089, 11301, 11354, 11268, 11072, 10788, 10480, 10180, 9942, 9820, 9820, 9942, 10180, 10480, 10788, 11072, 11268, 11354, 11301, 11089, 10735, 10278, 9776, 9309, 8920, 8627, 8439, 8320, 8242, 8163, 8056, 7884, 7631, 7276, 6800, 6185, 5450, 4618, 3750, 2906, 2132, 1447, 864, 377, -34, -400, -764, -1161, -1626, -2200, -2895, -3711, -4630, -5618, -6642, -7661, -8637, -9508, -10226, -10771, -11125, -11333, -11442, -11515, -11610, -11807, -12132, -12651, -13348, -14223, -15200, -16184, -16972, -17454, -7131, -8003, -9027, -9971, -9971, -9027, -8003, -7131, -6349, -5525, -4667, -4002, -3565, -3119, -2739, -2513, -2332, -2056, -1686, -1265, -807, -245, 326, 786, 1296, 1841, 2262, 2516, 2564, 2518, 2473, 2332, 2117, 1960, 1826, 1646, 1503, 1512, 1588, 1716, 1917, 2093, 2207, 2209, 2047, 1910, 1873, 1803, 1673, 1586, 1523, 1483, 1486, 1497, 1537, 1601, 1650, 1707, 1723, 1715, 1707, 1568, 1361, 1044, 611, 312, 213, 167, 167, 213, 312, 611, 1044, 1361, 1568, 1707, 1715, 1723, 1707, 1650, 1601, 1537, 1497, 1486, 1483, 1523, 1586, 1673, 1803, 1873, 1910, 2047, 2209, 2207, 2093, 1917, 1716, 1588, 1512, 1503, 1646, 1826, 1960, 2117, 2332, 2473, 2518, 2564, 2516, 2262, 1841, 1296, 786, 326, -245, -807, -1265, -1686, -2056, -2332, -2513, -2739, -3119, -3565, -4002, -4667, -5525, -6349, -7131, -8003, -9027, -9971, -9368, -9777, -9731, -10755, -10755, -9731, -9777, -9368, -8645, -8247, -7761, -6955, -6090, -5586, -4752, -3823, -3293, -2598, -1795, -1143, -541, 215, 815, 1291, 1854, 2358, 2883, 3295, 3683, 4064, 4329, 4621, 4761, 4908, 5046, 5074, 5120, 5046, 4898, 4746, 4638, 4367, 4061, 3937, 3655, 3286, 3079, 2969, 2591, 2278, 2269, 1876, 1542, 1473, 1100, 728, 462, 100, -262, -537, -753, -1039, -1244, -1448, -1680, -1817, -1897, -1882, -1882, -1897, -1817, -1680, -1448, -1244, -1039, -753, -537, -262, 100, 462, 728, 1100, 1473, 1542, 1876, 2269, 2278, 2591, 2969, 3079, 3286, 3655, 3937, 4061, 4367, 4638, 4746, 4898, 5046, 5120, 5074, 5046, 4908, 4761, 4621, 4329, 4064, 3683, 3295, 2883, 2358, 1854, 1291, 815, 215, -541, -1143, -1795, -2598, -3293, -3823, -4752, -5586, -6090, -6955, -7761, -8247, -8645, -9368, -9777, -9731, -10755, -4414, -4670, -4246, -5270, -5270, -4246, -4670, -4414, -3907, -3762, -3598, -3200, -2765, -2558, -2357, -1914, -1737, -1558, -1158, -990, -860, -494, -248, -147, 211, 509, 593, 887, 1181, 1219, 1380, 1642, 1778, 1765, 1910, 2089, 2091, 1993, 2041, 2079, 1841, 1872, 1892, 1636, 1509, 1561, 1414, 1291, 1330, 1201, 1194, 1056, 1071, 1198, 919, 899, 861, 721, 660, 599, 451, 394, 287, 161, 175, 94, 111, 86, 86, 111, 94, 175, 161, 287, 394, 451, 599, 660, 721, 861, 899, 919, 1198, 1071, 1056, 1194, 1201, 1330, 1291, 1414, 1561, 1509, 1636, 1892, 1872, 1841, 2079, 2041, 1993, 2091, 2089, 1910, 1765, 1778, 1642, 1380, 1219, 1181, 887, 593, 509, 211, -147, -248, -494, -860, -990, -1158, -1558, -1737, -1914, -2357, -2558, -2765, -3200, -3598, -3762, -3907, -4414, -4670, -4246, -5270, -19825, -20072, -20279, -20427, -20427, -20279, -20072, -19825, -19569, -19291, -19004, -18698, -18373, -17994, -17552, -17029, -16430, -15773, -15078, -14370, -13675, -12982, -12278, -11541, -10757, -9915, -9023, -8084, -7125, -6151, -5180, -4232, -3312, -2394, -1451, -479, 523, 1540, 2564, 3585, 4583, 5544, 6456, 7317, 8147, 8973, 9808, 10658, 11512, 12356, 13166, 13925, 14619, 15244, 15807, 16330, 16820, 17290, 17745, 18195, 18623, 19003, 19311, 19539, 19694, 19786, 19831, 19844, 19844, 19831, 19786, 19694, 19539, 19311, 19003, 18623, 18195, 17745, 17290, 16820, 16330, 15807, 15244, 14619, 13925, 13166, 12356, 11512, 10658, 9808, 8973, 8147, 7317, 6456, 5544, 4583, 3585, 2564, 1540, 523, -479, -1451, -2394, -3312, -4232, -5180, -6151, -7125, -8084, -9023, -9915, -10757, -11541, -12278, -12982, -13675, -14370, -15078, -15773, -16430, -17029, -17552, -17994, -18373, -18698, -19004, -19291, -19569, -19825, -20072, -20279, -20427, -10881, -11316, -11665, -11893, -11893, -11665, -11316, -10881, -10406, -9886, -9317, -8655, -7888, -7006, -6041, -5025, -4001, -2993, -2023, -1079, -143, 814, 1786, 2741, 3645, 4466, 5187, 5814, 6363, 6851, 7284, 7663, 7970, 8190, 8290, 8266, 8134, 7934, 7702, 7445, 7145, 6786, 6338, 5802, 5197, 4569, 3941, 3329, 2738, 2157, 1579, 976, 346, -293, -910, -1469, -1961, -2393, -2780, -3137, -3486, -3821, -4121, -4356, -4523, -4619, -4671, -4692, -4692, -4671, -4619, -4523, -4356, -4121, -3821, -3486, -3137, -2780, -2393, -1961, -1469, -910, -293, 346, 976, 1579, 2157, 2738, 3329, 3941, 4569, 5197, 5802, 6338, 6786, 7145, 7445, 7702, 7934, 8134, 8266, 8290, 8190, 7970, 7663, 7284, 6851, 6363, 5814, 5187, 4466, 3645, 2741, 1786, 814, -143, -1079, -2023, -2993, -4001, -5025, -6041, -7006, -7888, -8655, -9317, -9886, -10406, -10881, -11316, -11665, -11893, -19536, -19886, -20149, -20318, -20318, -20149, -19886, -19536, -19137, -18680, -18164, -17566, -16878, -16098, -15244, -14343, -13417, -12486, -11554, -10616, -9657, -8663, -7649, -6625, -5622, -4659, -3750, -2885, -2053, -1235, -424, 371, 1133, 1849, 2511, 3116, 3676, 4207, 4730, 5248, 5754, 6241, 6685, 7083, 7443, 7791, 8148, 8520, 8901, 9285, 9655, 10003, 10323, 10612, 10895, 11181, 11476, 11779, 12074, 12332, 12548, 12722, 12867, 13004, 13132, 13251, 13347, 13403, 13403, 13347, 13251, 13132, 13004, 12867, 12722, 12548, 12332, 12074, 11779, 11476, 11181, 10895, 10612, 10323, 10003, 9655, 9285, 8901, 8520, 8148, 7791, 7443, 7083, 6685, 6241, 5754, 5248, 4730, 4207, 3676, 3116, 2511, 1849, 1133, 371, -424, -1235, -2053, -2885, -3750, -4659, -5622, -6625, -7649, -8663, -9657, -10616, -11554, -12486, -13417, -14343, -15244, -16098, -16878, -17566, -18164, -18680, -19137, -19536, -19886, -20149, -20318, -18344, -19191, -19841, -20219, -20219, -19841, -19191, -18344, -17385, -16364, -15340, -14354, -13445, -12607, -11830, -11087, -10365, -9658, -8965, -8282, -7598, -6907, -6215, -5525, -4842, -4148, -3435, -2702, -1976, -1284, -643, -60, 465, 942, 1385, 1805, 2214, 2638, 3095, 3575, 4063, 4554, 5055, 5574, 6103, 6635, 7167, 7711, 8266, 8820, 9336, 9780, 10120, 10356, 10500, 10582, 10629, 10655, 10676, 10715, 10787, 10886, 10995, 11108, 11220, 11327, 11414, 11464, 11464, 11414, 11327, 11220, 11108, 10995, 10886, 10787, 10715, 10676, 10655, 10629, 10582, 10500, 10356, 10120, 9780, 9336, 8820, 8266, 7711, 7167, 6635, 6103, 5574, 5055, 4554, 4063, 3575, 3095, 2638, 2214, 1805, 1385, 942, 465, -60, -643, -1284, -1976, -2702, -3435, -4148, -4842, -5525, -6215, -6907, -7598, -8282, -8965, -9658, -10365, -11087, -11830, -12607, -13445, -14354, -15340, -16364, -17385, -18344, -19191, -19841, -20219, -9058, -9967, -10703, -11149, -11149, -10703, -9967, -9058, -8069, -7045, -6056, -5162, -4375, -3664, -3009, -2411, -1865, -1356, -875, -415, 11, 390, 705, 955, 1167, 1394, 1655, 1938, 2213, 2443, 2593, 2631, 2557, 2403, 2217, 2034, 1870, 1752, 1686, 1656, 1652, 1671, 1725, 1808, 1898, 1988, 2087, 2209, 2354, 2519, 2674, 2777, 2786, 2684, 2489, 2235, 1959, 1703, 1502, 1368, 1270, 1180, 1091, 1038, 1033, 1055, 1072, 1077, 1077, 1072, 1055, 1033, 1038, 1091, 1180, 1270, 1368, 1502, 1703, 1959, 2235, 2489, 2684, 2786, 2777, 2674, 2519, 2354, 2209, 2087, 1988, 1898, 1808, 1725, 1671, 1652, 1656, 1686, 1752, 1870, 2034, 2217, 2403, 2557, 2631, 2593, 2443, 2213, 1938, 1655, 1394, 1167, 955, 705, 390, 11, -415, -875, -1356, -1865, -2411, -3009, -3664, -4375, -5162, -6056, -7045, -8069, -9058, -9967, -10703, -11149, -4016, -4483, -5507, -6477, -6477, -5507, -4483, -4016, -3874, -3602, -3269, -3158, -3175, -2979, -2523, -2053, -1686, -1282, -778, -301, 53, 294, 382, 227, -96, -318, -262, 13, 364, 716, 943, 859, 421, -119, -443, -462, -287, -21, 268, 501, 627, 731, 915, 1131, 1229, 1160, 1052, 1068, 1267, 1630, 2077, 2453, 2613, 2549, 2351, 2073, 1729, 1462, 1509, 1903, 2320, 2376, 2057, 1702, 1567, 1576, 1543, 1465, 1465, 1543, 1576, 1567, 1702, 2057, 2376, 2320, 1903, 1509, 1462, 1729, 2073, 2351, 2549, 2613, 2453, 2077, 1630, 1267, 1068, 1052, 1160, 1229, 1131, 915, 731, 627, 501, 268, -21, -287, -462, -443, -119, 421, 859, 943, 716, 364, 13, -262, -318, -96, 227, 382, 294, 53, -301, -778, -1282, -1686, -2053, -2523, -2979, -3175, -3158, -3269, -3602, -3874, -4016, -4483, -5507, -6477, -6317, -6712, -7736, -8749, -8749, -7736, -6712, -6317, -6229, -5932, -5543, -5412, -5426, -5175, -4621, -4083, -3689, -3239, -2632, -2037, -1604, -1313, -1150, -1191, -1388, -1502, -1363, -1008, -556, -78, 290, 333, 8, -420, -624, -524, -242, 120, 514, 859, 1101, 1323, 1632, 1983, 2208, 2250, 2251, 2378, 2681, 3121, 3610, 4025, 4265, 4322, 4242, 4050, 3780, 3605, 3743, 4190, 4618, 4689, 4414, 4100, 3969, 3968, 3950, 3901, 3901, 3950, 3968, 3969, 4100, 4414, 4689, 4618, 4190, 3743, 3605, 3780, 4050, 4242, 4322, 4265, 4025, 3610, 3121, 2681, 2378, 2251, 2250, 2208, 1983, 1632, 1323, 1101, 859, 514, 120, -242, -524, -624, -420, 8, 333, 290, -78, -556, -1008, -1363, -1502, -1388, -1191, -1150, -1313, -1604, -2037, -2632, -3239, -3689, -4083, -4621, -5175, -5426, -5412, -5543, -5932, -6229, -6317, -6712, -7736, -8749, -19345, -19701, -20465, -21212, -21212, -20465, -19701, -19345, -19158, -18760, -18247, -17889, -17619, -17145, -16438, -15715, -15058, -14324, -13457, -12580, -11793, -11054, -10335, -9704, -9167, -8587, -7836, -6922, -5928, -4904, -3941, -3173, -2617, -2101, -1443, -617, 295, 1259, 2267, 3257, 4160, 5022, 5937, 6885, 7745, 8462, 9117, 9831, 10653, 11549, 12446, 13265, 13943, 14481, 14919, 15266, 15525, 15793, 16205, 16774, 17317, 17634, 17715, 17723, 17795, 17921, 18018, 18058, 18058, 18018, 17921, 17795, 17723, 17715, 17634, 17317, 16774, 16205, 15793, 15525, 15266, 14919, 14481, 13943, 13265, 12446, 11549, 10653, 9831, 9117, 8462, 7745, 6885, 5937, 5022, 4160, 3257, 2267, 1259, 295, -617, -1443, -2101, -2617, -3173, -3941, -4904, -5928, -6922, -7836, -8587, -9167, -9704, -10335, -11054, -11793, -12580, -13457, -14324, -15058, -15715, -16438, -17145, -17619, -17889, -18247, -18760, -19158, -19345, -19701, -20465, -21212, -10337, -11101, -11660, -11984, -11984, -11660, -11101, -10337, -9445, -8463, -7453, -6429, -5433, -4469, -3560, -2700, -1902, -1159, -483, 132, 668, 1119, 1476, 1725, 1852, 1841, 1698, 1442, 1097, 699, 272, -160, -576, -961, -1304, -1591, -1809, -1953, -2033, -2036, -1973, -1851, -1677, -1449, -1157, -787, -317, 254, 904, 1598, 2304, 2988, 3625, 4197, 4709, 5158, 5541, 5857, 6115, 6328, 6492, 6623, 6730, 6821, 6903, 6971, 7023, 7052, 7052, 7023, 6971, 6903, 6821, 6730, 6623, 6492, 6328, 6115, 5857, 5541, 5158, 4709, 4197, 3625, 2988, 2304, 1598, 904, 254, -317, -787, -1157, -1449, -1677, -1851, -1973, -2036, -2033, -1953, -1809, -1591, -1304, -961, -576, -160, 272, 699, 1097, 1442, 1698, 1841, 1852, 1725, 1476, 1119, 668, 132, -483, -1159, -1902, -2700, -3560, -4469, -5433, -6429, -7453, -8463, -9445, -10337, -11101, -11660, -11984, -7356, -8142, -8738, -9147, -9147, -8738, -8142, -7356, -6493, -5642, -4760, -3808, -2841, -1817, -820, 24, 708, 1223, 1560, 1842, 2128, 2370, 2598, 2753, 2764, 2708, 2609, 2473, 2397, 2358, 2252, 2088, 1794, 1337, 809, 262, -298, -789, -1254, -1765, -2292, -2837, -3366, -3751, -3953, -3975, -3763, -3405, -2965, -2418, -1799, -1103, -286, 599, 1471, 2299, 2994, 3533, 3988, 4364, 4676, 4985, 5225, 5347, 5384, 5318, 5198, 5143, 5143, 5198, 5318, 5384, 5347, 5225, 4985, 4676, 4364, 3988, 3533, 2994, 2299, 1471, 599, -286, -1103, -1799, -2418, -2965, -3405, -3763, -3975, -3953, -3751, -3366, -2837, -2292, -1765, -1254, -789, -298, 262, 809, 1337, 1794, 2088, 2252, 2358, 2397, 2473, 2609, 2708, 2764, 2753, 2598, 2370, 2128, 1842, 1560, 1223, 708, 24, -820, -1817, -2841, -3808, -4760, -5642, -6493, -7356, -8142, -8738, -9147, -7261, -8135, -8813, -9271, -9271, -8813, -8135, -7261, -6313, -5388, -4450, -3459, -2474, -1450, -463, 395, 1136, 1760, 2253, 2728, 3233, 3713, 4177, 4563, 4779, 4897, 4948, 4939, 4953, 4986, 4963, 4906, 4757, 4476, 4154, 3801, 3404, 3017, 2589, 2017, 1313, 473, -458, -1316, -2042, -2607, -2969, -3195, -3345, -3368, -3292, -3121, -2824, -2456, -2088, -1744, -1496, -1333, -1145, -905, -599, -182, 233, 562, 824, 965, 1006, 1041, 1041, 1006, 965, 824, 562, 233, -182, -599, -905, -1145, -1333, -1496, -1744, -2088, -2456, -2824, -3121, -3292, -3368, -3345, -3195, -2969, -2607, -2042, -1316, -458, 473, 1313, 2017, 2589, 3017, 3404, 3801, 4154, 4476, 4757, 4906, 4963, 4986, 4953, 4939, 4948, 4897, 4779, 4563, 4177, 3713, 3233, 2728, 2253, 1760, 1136, 395, -463, -1450, -2474, -3459, -4450, -5388, -6313, -7261, -8135, -8813, -9271, -9051, -10030, -10829, -11318, -11318, -10829, -10030, -9051, -8034, -7037, -6098, -5215, -4405, -3660, -2971, -2315, -1672, -1028, -357, 357, 1116, 1901, 2660, 3334, 3890, 4331, 4675, 4952, 5191, 5427, 5683, 5986, 6353, 6793, 7283, 7791, 8289, 8741, 9085, 9219, 9058, 8582, 7851, 6975, 6052, 5139, 4246, 3372, 2522, 1694, 878, 53, -801, -1701, -2650, -3653, -4677, -5629, -6410, -6921, -7141, -7124, -6961, -6737, -6509, -6313, -6160, -6072, -6072, -6160, -6313, -6509, -6737, -6961, -7124, -7141, -6921, -6410, -5629, -4677, -3653, -2650, -1701, -801, 53, 878, 1694, 2522, 3372, 4246, 5139, 6052, 6975, 7851, 8582, 9058, 9219, 9085, 8741, 8289, 7791, 7283, 6793, 6353, 5986, 5683, 5427, 5191, 4952, 4675, 4331, 3890, 3334, 2660, 1901, 1116, 357, -357, -1028, -1672, -2315, -2971, -3660, -4405, -5215, -6098, -7037, -8034, -9051, -10030, -10829, -11318, -7729, -8753, -9617, -10144, -10144, -9617, -8753, -7729, -6746, -5902, -5234, -4703, -4260, -3845, -3410, -2917, -2366, -1755, -1106, -434, 226, 873, 1509, 2139, 2774, 3402, 3988, 4516, 4961, 5326, 5625, 5892, 6147, 6392, 6616, 6814, 6994, 7166, 7301, 7333, 7184, 6815, 6254, 5584, 4884, 4222, 3625, 3086, 2578, 2073, 1546, 955, 275, -520, -1441, -2447, -3460, -4362, -5062, -5497, -5677, -5675, -5584, -5466, -5360, -5264, -5193, -5145, -5145, -5193, -5264, -5360, -5466, -5584, -5675, -5677, -5497, -5062, -4362, -3460, -2447, -1441, -520, 275, 955, 1546, 2073, 2578, 3086, 3625, 4222, 4884, 5584, 6254, 6815, 7184, 7333, 7301, 7166, 6994, 6814, 6616, 6392, 6147, 5892, 5625, 5326, 4961, 4516, 3988, 3402, 2774, 2139, 1509, 873, 226, -434, -1106, -1755, -2366, -2917, -3410, -3845, -4260, -4703, -5234, -5902, -6746, -7729, -8753, -9617, -10144, -8206, -9230, -10123, -10694, -10694, -10123, -9230, -8206, -7241, -6436, -5866, -5474, -5142, -4767, -4322, -3788, -3170, -2517, -1943, -1503, -1219, -1049, -931, -770, -476, -30, 501, 1052, 1596, 2091, 2500, 2834, 3129, 3409, 3665, 3922, 4228, 4585, 4933, 5209, 5391, 5436, 5317, 5058, 4742, 4434, 4147, 3865, 3592, 3298, 2945, 2515, 2024, 1478, 873, 254, -288, -680, -909, -961, -841, -622, -394, -191, -10, 159, 276, 334, 334, 276, 159, -10, -191, -394, -622, -841, -961, -909, -680, -288, 254, 873, 1478, 2024, 2515, 2945, 3298, 3592, 3865, 4147, 4434, 4742, 5058, 5317, 5436, 5391, 5209, 4933, 4585, 4228, 3922, 3665, 3409, 3129, 2834, 2500, 2091, 1596, 1052, 501, -30, -476, -770, -931, -1049, -1219, -1503, -1943, -2517, -3170, -3788, -4322, -4767, -5142, -5474, -5866, -6436, -7241, -8206, -9230, -10123, -10694, -6999, -7755, -8427, -8923, -8923, -8427, -7755, -6999, -6118, -5094, -4086, -3121, -2127, -1104, -204, 526, 1157, 1668, 1948, 1972, 1817, 1533, 1118, 654, 260, -19, -265, -447, -486, -374, -188, 82, 526, 1140, 1816, 2525, 3306, 4077, 4676, 5055, 5294, 5407, 5317, 5008, 4591, 4099, 3476, 2713, 1889, 1049, 164, -707, -1444, -1984, -2361, -2588, -2607, -2466, -2256, -1999, -1619, -1139, -659, -216, 231, 658, 951, 1076, 1076, 951, 658, 231, -216, -659, -1139, -1619, -1999, -2256, -2466, -2607, -2588, -2361, -1984, -1444, -707, 164, 1049, 1889, 2713, 3476, 4099, 4591, 5008, 5317, 5407, 5294, 5055, 4676, 4077, 3306, 2525, 1816, 1140, 526, 82, -188, -374, -486, -447, -265, -19, 260, 654, 1118, 1533, 1817, 1972, 1948, 1668, 1157, 526, -204, -1104, -2127, -3121, -4086, -5094, -6118, -6999, -7755, -8427, -8923, -2844, -3638, -4433, -5141, -5141, -4433, -3638, -2844, -2286, -2185, -2159, -1939, -1471, -570, 454, 1130, 1448, 1363, 942, 666, 711, 995, 1454, 1747, 1597, 1157, 548, 19, -43, 303, 769, 1194, 1308, 1049, 713, 495, 590, 1109, 1695, 1990, 1934, 1443, 671, 67, -210, -168, 117, 237, -22, -527, -1178, -1705, -1751, -1383, -850, -355, -189, -395, -666, -809, -609, 54, 835, 1409, 1696, 1564, 1160, 893, 893, 1160, 1564, 1696, 1409, 835, 54, -609, -809, -666, -395, -189, -355, -850, -1383, -1751, -1705, -1178, -527, -22, 237, 117, -168, -210, 67, 671, 1443, 1934, 1990, 1695, 1109, 590, 495, 713, 1049, 1308, 1194, 769, 303, -43, 19, 548, 1157, 1597, 1747, 1454, 995, 711, 666, 942, 1363, 1448, 1130, 454, -570, -1471, -1939, -2159, -2185, -2286, -2844, -3638, -4433, -5141, -3499, -4234, -4919, -5676, -5676, -4919, -4234, -3499, -2475, -1776, -1488, -959, -283, 199, 783, 1452, 1692, 1531, 1241, 699, -19, -516, -798, -1050, -1165, -1178, -1340, -1552, -1559, -1425, -1161, -577, 185, 797, 1288, 1711, 1874, 1855, 1947, 2103, 2167, 2218, 2222, 1990, 1571, 1144, 753, 432, 247, 176, 147, 106, 26, -67, -112, -103, -45, 77, 244, 379, 448, 492, 531, 546, 576, 659, 731, 740, 740, 731, 659, 576, 546, 531, 492, 448, 379, 244, 77, -45, -103, -112, -67, 26, 106, 147, 176, 247, 432, 753, 1144, 1571, 1990, 2222, 2218, 2167, 2103, 1947, 1855, 1874, 1711, 1288, 797, 185, -577, -1161, -1425, -1559, -1552, -1340, -1178, -1165, -1050, -798, -516, -19, 699, 1241, 1531, 1692, 1452, 783, 199, -283, -959, -1488, -1776, -2475, -3499, -4234, -4919, -5676, -4975, -5929, -6953, -7814, -7814, -6953, -5929, -4975, -4095, -3498, -3165, -2801, -2343, -1748, -927, -112, 395, 584, 450, -12, -578, -1043, -1379, -1546, -1586, -1698, -1954, -2271, -2634, -2948, -2988, -2659, -2114, -1492, -828, -194, 358, 871, 1396, 1929, 2462, 2997, 3446, 3673, 3624, 3342, 2905, 2395, 1885, 1466, 1177, 951, 760, 672, 671, 659, 687, 866, 1188, 1607, 2136, 2736, 3302, 3774, 4108, 4264, 4286, 4264, 4264, 4286, 4264, 4108, 3774, 3302, 2736, 2136, 1607, 1188, 866, 687, 659, 671, 672, 760, 951, 1177, 1466, 1885, 2395, 2905, 3342, 3624, 3673, 3446, 2997, 2462, 1929, 1396, 871, 358, -194, -828, -1492, -2114, -2659, -2988, -2948, -2634, -2271, -1954, -1698, -1586, -1546, -1379, -1043, -578, -12, 450, 584, 395, -112, -927, -1748, -2343, -2801, -3165, -3498, -4095, -4975, -5929, -6953, -7814, -6928, -7860, -8704, -9384, -9384, -8704, -7860, -6928, -5904, -5106, -4608, -4076, -3452, -2844, -2190, -1562, -1224, -1218, -1480, -2002, -2616, -3085, -3386, -3549, -3533, -3452, -3467, -3486, -3391, -3193, -2836, -2175, -1312, -460, 348, 1088, 1612, 1978, 2362, 2729, 3004, 3255, 3424, 3353, 3132, 2921, 2677, 2440, 2383, 2450, 2502, 2616, 2798, 2901, 2971, 3153, 3379, 3584, 3866, 4166, 4329, 4425, 4553, 4635, 4687, 4827, 4956, 4976, 4976, 4956, 4827, 4687, 4635, 4553, 4425, 4329, 4166, 3866, 3584, 3379, 3153, 2971, 2901, 2798, 2616, 2502, 2450, 2383, 2440, 2677, 2921, 3132, 3353, 3424, 3255, 3004, 2729, 2362, 1978, 1612, 1088, 348, -460, -1312, -2175, -2836, -3193, -3391, -3486, -3467, -3452, -3533, -3549, -3386, -3085, -2616, -2002, -1480, -1218, -1224, -1562, -2190, -2844, -3452, -4076, -4608, -5106, -5904, -6928, -7860, -8704, -9384, -16974, -17487, -18008, -18713, -18713, -18008, -17487, -16974, -16042, -15133, -14387, -13406, -12486, -11909, -11228, -10449, -10067, -9866, -9521, -9345, -9338, -9127, -8879, -8780, -8488, -7965, -7559, -7106, -6363, -5571, -4792, -3797, -2773, -1907, -960, 50, 849, 1600, 2486, 3281, 3952, 4678, 5332, 5869, 6481, 7088, 7518, 7957, 8497, 8957, 9359, 9825, 10269, 10667, 11118, 11588, 12039, 12540, 13063, 13524, 13951, 14353, 14672, 14945, 15225, 15455, 15590, 15649, 15649, 15590, 15455, 15225, 14945, 14672, 14353, 13951, 13524, 13063, 12540, 12039, 11588, 11118, 10667, 10269, 9825, 9359, 8957, 8497, 7957, 7518, 7088, 6481, 5869, 5332, 4678, 3952, 3281, 2486, 1600, 849, 50, -960, -1907, -2773, -3797, -4792, -5571, -6363, -7106, -7559, -7965, -8488, -8780, -8879, -9127, -9338, -9345, -9521, -9866, -10067, -10449, -11228, -11909, -12486, -13406, -14387, -15133, -16042, -16974, -17487, -18008, -18713, -14011, -14613, -15136, -15657, -15657, -15136, -14613, -14011, -13172, -12423, -11878, -11211, -10454, -9817, -9210, -8588, -8172, -7972, -7850, -7817, -7880, -7863, -7734, -7569, -7307, -6891, -6456, -5988, -5364, -4639, -3897, -2997, -1973, -1043, -164, 744, 1491, 2053, 2645, 3209, 3628, 4073, 4584, 4979, 5296, 5667, 5992, 6248, 6603, 7042, 7464, 7948, 8491, 8953, 9374, 9835, 10235, 10536, 10889, 11248, 11476, 11698, 11981, 12136, 12182, 12314, 12400, 12336, 12336, 12400, 12314, 12182, 12136, 11981, 11698, 11476, 11248, 10889, 10536, 10235, 9835, 9374, 8953, 8491, 7948, 7464, 7042, 6603, 6248, 5992, 5667, 5296, 4979, 4584, 4073, 3628, 3209, 2645, 2053, 1491, 744, -164, -1043, -1973, -2997, -3897, -4639, -5364, -5988, -6456, -6891, -7307, -7569, -7734, -7863, -7880, -7817, -7850, -7972, -8172, -8588, -9210, -9817, -10454, -11211, -11878, -12423, -13172, -14011, -14613, -15136, -15657, -17928, -18524, -19085, -19500, -19500, -19085, -18524, -17928, -17359, -16925, -16636, -16302, -15809, -15174, -14445, -13676, -12968, -12408, -11990, -11619, -11197, -10706, -10120, -9401, -8619, -7877, -7183, -6488, -5787, -5039, -4187, -3219, -2195, -1182, -203, 726, 1573, 2351, 3147, 3977, 4790, 5583, 6365, 7080, 7685, 8235, 8766, 9280, 9800, 10358, 10922, 11453, 11934, 12372, 12789, 13180, 13559, 13954, 14351, 14698, 14992, 15255, 15465, 15614, 15738, 15860, 15938, 15964, 15964, 15938, 15860, 15738, 15614, 15465, 15255, 14992, 14698, 14351, 13954, 13559, 13180, 12789, 12372, 11934, 11453, 10922, 10358, 9800, 9280, 8766, 8235, 7685, 7080, 6365, 5583, 4790, 3977, 3147, 2351, 1573, 726, -203, -1182, -2195, -3219, -4187, -5039, -5787, -6488, -7183, -7877, -8619, -9401, -10120, -10706, -11197, -11619, -11990, -12408, -12968, -13676, -14445, -15174, -15809, -16302, -16636, -16925, -17359, -17928, -18524, -19085, -19500, -19438, -19943, -20335, -20614, -20614, -20335, -19943, -19438, -18847, -18248, -17664, -17032, -16358, -15675, -14985, -14302, -13663, -13078, -12560, -12073, -11570, -11033, -10445, -9775, -9040, -8285, -7516, -6706, -5865, -4995, -4071, -3080, -2056, -1035, -22, 966, 1890, 2764, 3623, 4465, 5266, 6042, 6801, 7504, 8139, 8741, 9313, 9859, 10398, 10947, 11492, 12010, 12497, 12955, 13393, 13805, 14184, 14556, 14907, 15205, 15471, 15724, 15928, 16083, 16223, 16333, 16398, 16430, 16430, 16398, 16333, 16223, 16083, 15928, 15724, 15471, 15205, 14907, 14556, 14184, 13805, 13393, 12955, 12497, 12010, 11492, 10947, 10398, 9859, 9313, 8741, 8139, 7504, 6801, 6042, 5266, 4465, 3623, 2764, 1890, 966, -22, -1035, -2056, -3080, -4071, -4995, -5865, -6706, -7516, -8285, -9040, -9775, -10445, -11033, -11570, -12073, -12560, -13078, -13663, -14302, -14985, -15675, -16358, -17032, -17664, -18248, -18847, -19438, -19943, -20335, -20614, -19700, -20124, -20524, -20851, -20851, -20524, -20124, -19700, -19248, -18865, -18582, -18231, -17721, -17077, -16326, -15483, -14628, -13844, -13139, -12453, -11728, -10929, -10037, -9045, -8021, -7054, -6156, -5281, -4421, -3564, -2645, -1651, -674, 240, 1136, 1993, 2753, 3471, 4225, 4990, 5728, 6461, 7173, 7802, 8352, 8868, 9379, 9902, 10436, 10966, 11475, 11934, 12325, 12680, 13038, 13382, 13710, 14048, 14371, 14634, 14848, 15035, 15177, 15283, 15394, 15519, 15615, 15660, 15660, 15615, 15519, 15394, 15283, 15177, 15035, 14848, 14634, 14371, 14048, 13710, 13382, 13038, 12680, 12325, 11934, 11475, 10966, 10436, 9902, 9379, 8868, 8352, 7802, 7173, 6461, 5728, 4990, 4225, 3471, 2753, 1993, 1136, 240, -674, -1651, -2645, -3564, -4421, -5281, -6156, -7054, -8021, -9045, -10037, -10929, -11728, -12453, -13139, -13844, -14628, -15483, -16326, -17077, -17721, -18231, -18582, -18865, -19248, -19700, -20124, -20524, -20851, 16913, 17897, 18905, 19929, 19097, 18274, 17466, 16667, 15875, 15100, 14333, 13573, 12822, 12087, 11360, 10641, 9938, 9243, 8556, 7885, 7222, 6575, 5936, 5305, 4691, 4084, 3493, 2911, 2344, 1786, 1243, 709, 191, -319, -814, -1300, -1770, -2232, -2678, -3116, -3538, -3952, -4350, -4731, -5105, -5463, -5812, -6146, -6463, -6773, -7066, -7344, -7613, -7866, -8103, -8332, -8545, -8742, -8931, -9104, -9261, -9402, -9535, -9651, -9752, -9836, -9905, -9965, -10010, -10038, -10050, -10046, -10026, -9999, -9955, -9894, -9818, -9726, -9618, -9494, -9353, -9197, -9024, -8836, -8631, -8418, -8190, -7945, -7684, -7407, -7114, -6797, -6464, -6114, -5749, -5368, -4970, -4557, -4127, -3682, -3220, -2742, -2248, -1730, -1196, -646, -80, 502, 1100, 1723, 2361, 3016, 3686, 4373, 5083, 5810, 6553, 7312, 8095, 8894, 9709, 10548, 11404, 12275, 13163, 14074, 15002, 15945, 16913, 17897, 18905, 19929, 29437, 30461, 31485, 32509, 31501, 30493, 29485, 28477, 27469, 26461, 25453, 24445, 23436, 22428, 21420, 20412, 19404, 18396, 17388, 16380, 15372, 14364, 13356, 12348, 11340, 10332, 9324, 8316, 7307, 6299, 5291, 4283, 3275, 2267, 1259, 251, -757, -1765, -2773, -3781, -4789, -5797, -6805, -7813, -8822, -9830, -10838, -11846, -12854, -13862, -14870, -15878, -16886, -17894, -18902, -19910, -20918, -21926, -22934, -23942, -24951, -25959, -26967, -27975, -28983, -29991, -30999, -32007, -32003, -30979, -29955, -28931, -27907, -26883, -25859, -24835, -23811, -22787, -21763, -20739, -19715, -18691, -17667, -16643, -15619, -14595, -13571, -12547, -11523, -10499, -9475, -8451, -7427, -6403, -5379, -4355, -3331, -2307, -1283, -259, 765, 1789, 2813, 3837, 4861, 5885, 6909, 7933, 8957, 9981, 11005, 12029, 13053, 14077, 15101, 16125, 17149, 18173, 19197, 20221, 21245, 22269, 23293, 24317, 25341, 26365, 27389, 28413, 29437, 30461, 31485, 32509, 9219, 10122, 11074, 12083, 11059, 10083, 9163, 8292, 7469, 6694, 5975, 5304, 4682, 4100, 3566, 3080, 2634, 2229, 1863, 1538, 1253, 1000, 779, 591, 434, 302, 194, 109, 49, 5, -23, -35, -39, -34, -22, -10, 10, 22, 34, 39, 35, 23, -5, -49, -109, -194, -302, -434, -591, -779, -1000, -1253, -1538, -1863, -2229, -2634, -3080, -3566, -4100, -4682, -5304, -5975, -6694, -7469, -8292, -9163, -10083, -11059, -12083, -11074, -10122, -9219, -8363, -7556, -6805, -6102, -5447, -4832, -4266, -3748, -3270, -2832, -2434, -2076, -1759, -1474, -1221, -1000, -811, -646, -505, -389, -296, -220, -159, -115, -79, -51, -30, -10, 10, 30, 51, 79, 115, 159, 220, 296, 389, 505, 646, 811, 1000, 1221, 1474, 1759, 2076, 2434, 2832, 3270, 3748, 4266, 4832, 5447, 6102, 6805, 7556, 8363, 9219, 10122, 11074, 12083, -19411, -19801, -20191, -20580, -20577, -20573, -20570, -20566, -20563, -20559, -20556, -20552, -20163, -19775, -19386, -18997, -18608, -18219, -17830, -17442, -16716, -15990, -15264, -14538, -13812, -13086, -12360, -11634, -10691, -9748, -8806, -7863, -6920, -5977, -5035, -4092, -3069, -2046, -1023, 0, 1023, 2046, 3069, 4092, 5035, 5977, 6920, 7863, 8806, 9748, 10691, 11634, 12360, 13086, 13812, 14538, 15264, 15990, 16716, 17442, 17830, 18219, 18608, 18997, 19386, 19775, 20163, 20552, 20556, 20559, 20563, 20566, 20570, 20573, 20577, 20580, 20191, 19801, 19411, 19021, 18631, 18241, 17852, 17462, 16735, 16008, 15281, 14554, 13827, 13100, 12373, 11646, 10702, 9758, 8815, 7871, 6927, 5983, 5040, 4096, 3072, 2048, 1024, 0, -1024, -2048, -3072, -4096, -5040, -5983, -6927, -7871, -8815, -9758, -10702, -11646, -12373, -13100, -13827, -14554, -15281, -16008, -16735, -17462, -17852, -18241, -18631, -19021, -19411, -19801, -20191, -20580, -20556, -20705, -20805, -20857, -20861, -20809, -20709, -20560, -20364, -20119, -19817, -19476, -19087, -18649, -18163, -17637, -17071, -16464, -15818, -15131, -14404, -13645, -12854, -12031, -11176, -10296, -9393, -8465, -7521, -6554, -5570, -4578, -3570, -2554, -1538, -514, 510, 1534, 2550, 3566, 4574, 5566, 6550, 7517, 8461, 9389, 10292, 11172, 12027, 12850, 13641, 14400, 15127, 15814, 16460, 17067, 17633, 18159, 18645, 19083, 19472, 19813, 20115, 20360, 20556, 20705, 20805, 20857, 20861, 20809, 20709, 20560, 20364, 20119, 19817, 19476, 19087, 18649, 18163, 17637, 17071, 16464, 15818, 15131, 14404, 13645, 12854, 12031, 11176, 10296, 9393, 8465, 7521, 6554, 5570, 4578, 3570, 2554, 1538, 514, -510, -1534, -2550, -3566, -4574, -5566, -6550, -7517, -8461, -9389, -10292, -11172, -12027, -12850, -13641, -14400, -15127, -15814, -16460, -17067, -17633, -18159, -18645, -19083, -19472, -19813, -20115, -20360, -20556, -20705, -20805, -20857, -13901, -13905, -13909, -13913, -13910, -13906, -13902, -13898, -13894, -13882, -13854, -13818, -13757, -13681, -13573, -13432, -13260, -13047, -12786, -12477, -12112, -11698, -11228, -10694, -10104, -9458, -8755, -7996, -7189, -6334, -5439, -4503, -3535, -2544, -1536, -512, 512, 1536, 2544, 3535, 4503, 5439, 6334, 7189, 7996, 8755, 9458, 10104, 10694, 11228, 11698, 12112, 12477, 12786, 13047, 13260, 13432, 13573, 13681, 13757, 13818, 13854, 13882, 13894, 13898, 13902, 13906, 13910, 13913, 13909, 13905, 13901, 13897, 13885, 13857, 13821, 13760, 13684, 13576, 13435, 13262, 13049, 12788, 12479, 12114, 11700, 11230, 10696, 10106, 9459, 8756, 7997, 7190, 6335, 5439, 4504, 3536, 2544, 1536, 512, -512, -1536, -2544, -3536, -4504, -5439, -6335, -7190, -7997, -8756, -9459, -10106, -10696, -11230, -11700, -12114, -12479, -12788, -13049, -13262, -13435, -13576, -13684, -13760, -13821, -13857, -13885, -13897, -13901, -13905, -13909, -13913, -11131, -11135, -11139, -11143, -11139, -11135, -11131, -11127, -11123, -11119, -11115, -11111, -11099, -11087, -11067, -11031, -10979, -10903, -10794, -10654, -10473, -10244, -9959, -9618, -9213, -8735, -8185, -7571, -6884, -6125, -5302, -4423, -3495, -2528, -1528, -512, 512, 1528, 2528, 3495, 4423, 5302, 6125, 6884, 7571, 8185, 8735, 9213, 9618, 9959, 10244, 10473, 10654, 10794, 10903, 10979, 11031, 11067, 11087, 11099, 11111, 11115, 11119, 11123, 11127, 11131, 11135, 11139, 11143, 11139, 11135, 11131, 11127, 11122, 11118, 11114, 11102, 11090, 11070, 11034, 10981, 10905, 10797, 10656, 10475, 10246, 9961, 9620, 9214, 8736, 8186, 7572, 6885, 6126, 5303, 4423, 3496, 2528, 1528, 512, -512, -1528, -2528, -3496, -4423, -5303, -6126, -6885, -7572, -8186, -8736, -9214, -9620, -9961, -10246, -10475, -10656, -10797, -10905, -10981, -11034, -11070, -11090, -11102, -11114, -11118, -11122, -11127, -11131, -11135, -11139, -11143, 2976, 2016, 1024, 0, -1024, -2016, -2976, -3903, -4799, -5662, -6493, -7292, -8059, -8794, -9497, -10160, -10790, -11388, -11955, -12489, -12991, -13461, -13898, -14304, -14677, -15019, -15328, -15605, -15850, -16063, -16243, -16392, -16508, -16593, -16645, -16665, -16645, -16593, -16508, -16392, -16243, -16063, -15850, -15605, -15328, -15019, -14677, -14304, -13898, -13461, -12991, -12489, -11955, -11388, -10790, -10160, -9497, -8794, -8059, -7292, -6493, -5662, -4799, -3903, -2976, -2016, -1024, 0, 1024, 2016, 2976, 3903, 4799, 5662, 6493, 7292, 8059, 8794, 9497, 10160, 10790, 11388, 11955, 12489, 12991, 13461, 13898, 14304, 14677, 15019, 15328, 15605, 15850, 16063, 16243, 16392, 16508, 16593, 16645, 16665, 16645, 16593, 16508, 16392, 16243, 16063, 15850, 15605, 15328, 15019, 14677, 14304, 13898, 13461, 12991, 12489, 11955, 11388, 10790, 10160, 9497, 8794, 8059, 7292, 6493, 5662, 4799, 3903, 2976, 2016, 1024, 0, 7102, 8045, 9029, 10053, 9222, 8406, 7614, 6847, 6096, 5368, 4665, 3978, 3315, 2676, 2061, 1471, 904, 362, -157, -651, -1121, -1568, -1990, -2387, -2761, -3103, -3420, -3714, -3975, -4212, -4418, -4599, -4747, -4872, -4965, -5033, -5070, -5074, -5046, -4994, -4910, -4794, -4646, -4465, -4252, -4008, -3731, -3422, -3081, -2707, -2302, -1864, -1387, -877, -335, 248, 862, 1516, 2203, 2930, 3689, 4488, 5319, 6190, 7102, 8045, 9029, 10053, 9222, 8406, 7614, 6847, 6096, 5368, 4665, 3978, 3315, 2676, 2061, 1471, 904, 362, -157, -651, -1121, -1568, -1990, -2387, -2761, -3103, -3420, -3714, -3975, -4212, -4418, -4599, -4747, -4872, -4965, -5033, -5070, -5074, -5046, -4994, -4910, -4794, -4646, -4465, -4252, -4008, -3731, -3422, -3081, -2707, -2302, -1864, -1387, -877, -335, 248, 862, 1516, 2203, 2930, 3689, 4488, 5319, 6190, 7102, 8045, 9029, 10053, 13051, 14075, 15099, 16123, 15131, 14138, 13146, 12154, 11161, 10169, 9176, 8184, 7192, 6199, 5207, 4215, 3222, 2230, 1238, 245, -747, -1740, -2732, -3724, -4717, -5709, -6701, -7694, -8686, -9679, -10671, -11663, -12656, -13648, -14640, -15633, -15621, -14597, -13573, -12549, -11525, -10501, -9477, -8453, -7429, -6405, -5381, -4357, -3333, -2309, -1285, -261, 763, 1787, 2811, 3835, 4859, 5883, 6907, 7931, 8955, 9979, 11003, 12027, 13051, 14075, 15099, 16123, 15131, 14138, 13146, 12154, 11161, 10169, 9176, 8184, 7192, 6199, 5207, 4215, 3222, 2230, 1238, 245, -747, -1740, -2732, -3724, -4717, -5709, -6701, -7694, -8686, -9679, -10671, -11663, -12656, -13648, -14640, -15633, -15621, -14597, -13573, -12549, -11525, -10501, -9477, -8453, -7429, -6405, -5381, -4357, -3333, -2309, -1285, -261, 763, 1787, 2811, 3835, 4859, 5883, 6907, 7931, 8955, 9979, 11003, 12027, 13051, 14075, 15099, 16123, 3484, 4267, 5155, 6139, 5115, 4196, 3381, 2662, 2040, 1514, 1076, 719, 442, 237, 89, -3, -47, -59, -47, -18, 18, 47, 59, 47, 3, -89, -237, -442, -719, -1076, -1514, -2040, -2662, -3381, -4196, -5115, -6139, -5155, -4267, -3484, -2796, -2206, -1703, -1281, -940, -670, -457, -300, -184, -107, -55, -18, 18, 55, 107, 184, 300, 457, 670, 940, 1281, 1703, 2206, 2796, 3484, 4267, 5155, 6139, 5115, 4196, 3381, 2662, 2040, 1514, 1076, 719, 442, 237, 89, -3, -47, -59, -47, -18, 18, 47, 59, 47, 3, -89, -237, -442, -719, -1076, -1514, -2040, -2662, -3381, -4196, -5115, -6139, -5155, -4267, -3484, -2796, -2206, -1703, -1281, -940, -670, -457, -300, -184, -107, -55, -18, 18, 55, 107, 184, 300, 457, 670, 940, 1281, 1703, 2206, 2796, 3484, 4267, 5155, 6139, -9121, -9511, -9900, -10290, -10287, -10283, -10280, -10276, -9887, -9498, -9110, -8721, -7995, -7269, -6543, -5817, -4874, -3931, -2989, -2046, -1023, 0, 1023, 2046, 2989, 3931, 4874, 5817, 6543, 7269, 7995, 8721, 9110, 9498, 9887, 10276, 10280, 10283, 10287, 10290, 9900, 9511, 9121, 8731, 8004, 7277, 6550, 5823, 4879, 3935, 2992, 2048, 1024, 0, -1024, -2048, -2992, -3935, -4879, -5823, -6550, -7277, -8004, -8731, -9121, -9511, -9900, -10290, -10287, -10283, -10280, -10276, -9887, -9498, -9110, -8721, -7995, -7269, -6543, -5817, -4874, -3931, -2989, -2046, -1023, 0, 1023, 2046, 2989, 3931, 4874, 5817, 6543, 7269, 7995, 8721, 9110, 9498, 9887, 10276, 10280, 10283, 10287, 10290, 9900, 9511, 9121, 8731, 8004, 7277, 6550, 5823, 4879, 3935, 2992, 2048, 1024, 0, -1024, -2048, -2992, -3935, -4879, -5823, -6550, -7277, -8004, -8731, -9121, -9511, -9900, -10290, -9829, -10130, -10327, -10427, -10424, -10323, -10127, -9826, -9436, -8951, -8385, -7738, -7012, -6221, -5366, -4462, -3519, -2535, -1528, -512, 512, 1528, 2535, 3519, 4462, 5366, 6221, 7012, 7738, 8385, 8951, 9436, 9826, 10127, 10323, 10424, 10427, 10327, 10130, 9829, 9439, 8953, 8387, 7740, 7013, 6222, 5367, 4463, 3520, 2536, 1528, 512, -512, -1528, -2536, -3520, -4463, -5367, -6222, -7013, -7740, -8387, -8953, -9439, -9829, -10130, -10327, -10427, -10424, -10323, -10127, -9826, -9436, -8951, -8385, -7738, -7012, -6221, -5366, -4462, -3519, -2535, -1528, -512, 512, 1528, 2535, 3519, 4462, 5366, 6221, 7012, 7738, 8385, 8951, 9436, 9826, 10127, 10323, 10424, 10427, 10327, 10130, 9829, 9439, 8953, 8387, 7740, 7013, 6222, 5367, 4463, 3520, 2536, 1528, 512, -512, -1528, -2536, -3520, -4463, -5367, -6222, -7013, -7740, -8387, -8953, -9439, -9829, -10130, -10327, -10427, -6922, -6950, -6954, -6958, -6954, -6950, -6947, -6919, -6859, -6750, -6578, -6317, -5952, -5482, -4892, -4189, -3382, -2487, -1520, -512, 512, 1520, 2487, 3382, 4189, 4892, 5482, 5952, 6317, 6578, 6750, 6859, 6919, 6947, 6950, 6954, 6958, 6954, 6950, 6922, 6861, 6753, 6580, 6319, 5953, 5484, 4893, 4190, 3383, 2488, 1520, 512, -512, -1520, -2488, -3383, -4190, -4893, -5484, -5953, -6319, -6580, -6753, -6861, -6922, -6950, -6954, -6958, -6954, -6950, -6947, -6919, -6859, -6750, -6578, -6317, -5952, -5482, -4892, -4189, -3382, -2487, -1520, -512, 512, 1520, 2487, 3382, 4189, 4892, 5482, 5952, 6317, 6578, 6750, 6859, 6919, 6947, 6950, 6954, 6958, 6954, 6950, 6922, 6861, 6753, 6580, 6319, 5953, 5484, 4893, 4190, 3383, 2488, 1520, 512, -512, -1520, -2488, -3383, -4190, -4893, -5484, -5953, -6319, -6580, -6753, -6861, -6922, -6950, -6954, -6958, -5565, -5569, -5573, -5577, -5573, -5569, -5565, -5561, -5550, -5530, -5478, -5369, -5189, -4904, -4498, -3948, -3262, -2439, -1512, -512, 512, 1512, 2439, 3262, 3948, 4498, 4904, 5189, 5369, 5478, 5530, 5550, 5561, 5565, 5569, 5573, 5577, 5573, 5569, 5565, 5552, 5532, 5480, 5371, 5191, 4905, 4500, 3950, 3263, 2440, 1512, 512, -512, -1512, -2440, -3263, -3950, -4500, -4905, -5191, -5371, -5480, -5532, -5552, -5565, -5569, -5573, -5577, -5573, -5569, -5565, -5561, -5550, -5530, -5478, -5369, -5189, -4904, -4498, -3948, -3262, -2439, -1512, -512, 512, 1512, 2439, 3262, 3948, 4498, 4904, 5189, 5369, 5478, 5530, 5550, 5561, 5565, 5569, 5573, 5577, 5573, 5569, 5565, 5552, 5532, 5480, 5371, 5191, 4905, 4500, 3950, 3263, 2440, 1512, 512, -512, -1512, -2440, -3263, -3950, -4500, -4905, -5191, -5371, -5480, -5532, -5552, -5565, -5569, -5573, -5577, 3044, 2181, 1253, 261, -763, -1723, -2618, -3449, -4216, -4919, -5550, -6116, -6618, -7056, -7429, -7738, -7983, -8164, -8280, -8333, -8312, -8228, -8080, -7867, -7590, -7248, -6843, -6373, -5839, -5240, -4578, -3843, -3044, -2181, -1253, -261, 763, 1723, 2618, 3449, 4216, 4919, 5550, 6116, 6618, 7056, 7429, 7738, 7983, 8164, 8280, 8333, 8312, 8228, 8080, 7867, 7590, 7248, 6843, 6373, 5839, 5240, 4578, 3843, 3044, 2181, 1253, 261, -763, -1723, -2618, -3449, -4216, -4919, -5550, -6116, -6618, -7056, -7429, -7738, -7983, -8164, -8280, -8333, -8312, -8228, -8080, -7867, -7590, -7248, -6843, -6373, -5839, -5240, -4578, -3843, -3044, -2181, -1253, -261, 763, 1723, 2618, 3449, 4216, 4919, 5550, 6116, 6618, 7056, 7429, 7738, 7983, 8164, 8280, 8333, 8312, 8228, 8080, 7867, 7590, 7248, 6843, 6373, 5839, 5240, 4578, 3843, 3044, 2181, 1253, 261, }; const int16_t* const wavetables_table[] FLASHMEM = { wav_integrated_waves, }; } // namespace plaits ================================================ FILE: lib/plaits/resources.h ================================================ // Copyright 2016 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resources definitions. // // Automatically generated with: // make resources #ifndef PLAITS_RESOURCES_H_ #define PLAITS_RESOURCES_H_ #include "stmlib/stmlib.h" namespace plaits { typedef uint8_t ResourceId; extern const uint8_t* const fm_patches_table[]; extern const float* const lookup_table_table[]; extern const int16_t* const lookup_table_i16_table[]; extern const int32_t* const lookup_table_i32_table[]; extern const int8_t* const lookup_table_i8_table[]; extern const int16_t* const wavetables_table[]; extern const uint8_t syx_bank_0[]; extern const uint8_t syx_bank_1[]; extern const uint8_t syx_bank_2[]; extern const float lut_sine[]; extern const float lut_fm_frequency_quantizer[]; extern const float lut_fold[]; extern const float lut_fold_2[]; extern const float lut_stiffness[]; extern const float lut_svf_shift[]; extern const float lut_4x_downsampler_fir[]; extern const int16_t lut_ws_inverse_tan[]; extern const int16_t lut_ws_inverse_sin[]; extern const int16_t lut_ws_linear[]; extern const int16_t lut_ws_bump[]; extern const int16_t lut_ws_double_bump[]; extern const int8_t lut_lpc_excitation_pulse[]; extern const int16_t wav_integrated_waves[]; #define SYX_BANK_0 0 #define SYX_BANK_0_SIZE 4096 #define SYX_BANK_1 1 #define SYX_BANK_1_SIZE 4096 #define SYX_BANK_2 2 #define SYX_BANK_2_SIZE 4096 #define LUT_SINE 0 #define LUT_SINE_SIZE 641 #define LUT_FM_FREQUENCY_QUANTIZER 1 #define LUT_FM_FREQUENCY_QUANTIZER_SIZE 130 #define LUT_FOLD 2 #define LUT_FOLD_SIZE 516 #define LUT_FOLD_2 3 #define LUT_FOLD_2_SIZE 516 #define LUT_STIFFNESS 4 #define LUT_STIFFNESS_SIZE 65 #define LUT_SVF_SHIFT 5 #define LUT_SVF_SHIFT_SIZE 257 #define LUT_4X_DOWNSAMPLER_FIR 6 #define LUT_4X_DOWNSAMPLER_FIR_SIZE 4 #define LUT_WS_INVERSE_TAN 0 #define LUT_WS_INVERSE_TAN_SIZE 257 #define LUT_WS_INVERSE_SIN 1 #define LUT_WS_INVERSE_SIN_SIZE 257 #define LUT_WS_LINEAR 2 #define LUT_WS_LINEAR_SIZE 257 #define LUT_WS_BUMP 3 #define LUT_WS_BUMP_SIZE 257 #define LUT_WS_DOUBLE_BUMP 4 #define LUT_WS_DOUBLE_BUMP_SIZE 257 #define LUT_WS_DOUBLE_BUMP_SENTINEL 5 #define LUT_WS_DOUBLE_BUMP_SENTINEL_SIZE 257 #define LUT_LPC_EXCITATION_PULSE 0 #define LUT_LPC_EXCITATION_PULSE_SIZE 640 #define WAV_INTEGRATED_WAVES 0 #define WAV_INTEGRATED_WAVES_SIZE 25344 } // namespace plaits #endif // PLAITS_RESOURCES_H_ ================================================ FILE: lib/rings/dsp/dsp.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Utility DSP routines. #ifndef RINGS_DSP_DSP_H_ #define RINGS_DSP_DSP_H_ #include "stmlib/stmlib.h" // #define MIC_W #define BRYAN_CHORDS namespace rings { static const float kSampleRate = 48000.0f; const float a3 = 440.0f / kSampleRate; const size_t kMaxBlockSize = 24; } // namespace rings #endif // RINGS_DSP_DSP_H_ ================================================ FILE: lib/rings/dsp/fm_voice.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // FM Voice. #include "rings/dsp/fm_voice.h" #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/units.h" #include "rings/resources.h" namespace rings { using namespace stmlib; void FMVoice::Init() { set_frequency(220.0f / kSampleRate); set_ratio(0.5f); set_brightness(0.5f); set_damping(0.5f); set_position(0.5f); set_feedback_amount(0.0f); previous_carrier_frequency_ = carrier_frequency_; previous_modulator_frequency_ = carrier_frequency_; previous_brightness_ = brightness_; previous_damping_ = damping_; previous_feedback_amount_ = feedback_amount_; amplitude_envelope_ = 0.0f; brightness_envelope_ = 0.0f; carrier_phase_ = 0; modulator_phase_ = 0; gain_ = 0.0f; fm_amount_ = 0.0f; follower_.Init( 8.0f / kSampleRate, 160.0f / kSampleRate, 1600.0f / kSampleRate); } void FMVoice::Process(const float* in, float* out, float* aux, size_t size) { // Interpolate between the "oscillator" behaviour and the "FMLPGed thing" // behaviour. float envelope_amount = damping_ < 0.9f ? 1.0f : (1.0f - damping_) * 10.0f; float amplitude_rt60 = 0.1f * SemitonesToRatio(damping_ * 96.0f) * kSampleRate; float amplitude_decay = 1.0f - powf(0.001f, 1.0f / amplitude_rt60); float brightness_rt60 = 0.1f * SemitonesToRatio(damping_ * 84.0f) * kSampleRate; float brightness_decay = 1.0f - powf(0.001f, 1.0f / brightness_rt60); float ratio = Interpolate(lut_fm_frequency_quantizer, ratio_, 128.0f); float modulator_frequency = carrier_frequency_ * SemitonesToRatio(ratio); if (modulator_frequency > 0.5f) { modulator_frequency = 0.5f; } float feedback = (feedback_amount_ - 0.5f) * 2.0f; ParameterInterpolator carrier_increment( &previous_carrier_frequency_, carrier_frequency_, size); ParameterInterpolator modulator_increment( &previous_modulator_frequency_, modulator_frequency, size); ParameterInterpolator brightness( &previous_brightness_, brightness_, size); ParameterInterpolator feedback_amount( &previous_feedback_amount_, feedback, size); uint32_t carrier_phase = carrier_phase_; uint32_t modulator_phase = modulator_phase_; float previous_sample = previous_sample_; while (size--) { // Envelope follower and internal envelope. float amplitude_envelope, brightness_envelope; follower_.Process( *in++, &litude_envelope, &brightness_envelope); brightness_envelope *= 2.0f * amplitude_envelope * (2.0f - amplitude_envelope); SLOPE(amplitude_envelope_, amplitude_envelope, 0.05f, amplitude_decay); SLOPE(brightness_envelope_, brightness_envelope, 0.01f, brightness_decay); // Compute envelopes. float brightness_value = brightness.Next(); brightness_value *= brightness_value; float fm_amount_min = brightness_value < 0.5f ? 0.0f : brightness_value * 2.0f - 1.0f; float fm_amount_max = brightness_value < 0.5f ? 2.0f * brightness_value : 1.0f; float fm_envelope = 0.5f + envelope_amount * (brightness_envelope_ - 0.5f); float fm_amount = (fm_amount_min + fm_amount_max * fm_envelope) * 2.0f; SLEW(fm_amount_, fm_amount, 0.005f + fm_amount_max * 0.015f); // FM synthesis in itself float phase_feedback = feedback < 0.0f ? 0.5f * feedback * feedback : 0.0f; modulator_phase += static_cast(4294967296.0f * \ modulator_increment.Next() * (1.0f + previous_sample * phase_feedback)); carrier_phase += static_cast(4294967296.0f * \ carrier_increment.Next()); float feedback = feedback_amount.Next(); float modulator_fb = feedback > 0.0f ? 0.25f * feedback * feedback : 0.0f; float modulator = SineFm(modulator_phase, modulator_fb * previous_sample); float carrier = SineFm(carrier_phase, fm_amount_ * modulator); ONE_POLE(previous_sample, carrier, 0.1f); // Compute amplitude envelope. float gain = 1.0f + envelope_amount * (amplitude_envelope_ - 1.0f); ONE_POLE(gain_, gain, 0.005f + 0.045f * fm_amount_); *out++ = (carrier + 0.5f * modulator) * gain_; *aux++ = 0.5f * modulator * gain_; } carrier_phase_ = carrier_phase; modulator_phase_ = modulator_phase; previous_sample_ = previous_sample; } } // namespace rings ================================================ FILE: lib/rings/dsp/fm_voice.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // FM Voice. #ifndef RINGS_DSP_FM_VOICE_H_ #define RINGS_DSP_FM_VOICE_H_ #include "stmlib/stmlib.h" #include #include "stmlib/dsp/filter.h" #include "rings/dsp/dsp.h" #include "rings/dsp/follower.h" #include "rings/resources.h" namespace rings { using namespace stmlib; class FMVoice { public: FMVoice() { } ~FMVoice() { } void Init(); void Process( const float* in, float* out, float* aux, size_t size); inline void set_frequency(float frequency) { carrier_frequency_ = frequency; } inline void set_ratio(float ratio) { ratio_ = ratio; } inline void set_brightness(float brightness) { brightness_ = brightness; } inline void set_damping(float damping) { damping_ = damping; } inline void set_position(float position) { position_ = position; } inline void set_feedback_amount(float feedback_amount) { feedback_amount_ = feedback_amount; } inline void TriggerInternalEnvelope() { amplitude_envelope_ = 1.0f; brightness_envelope_ = 1.0f; } inline float SineFm(uint32_t phase, float fm) const { phase += (static_cast((fm + 4.0f) * 536870912.0f)) << 3; uint32_t integral = phase >> 20; float fractional = static_cast(phase << 12) / 4294967296.0f; float a = lut_sine[integral]; float b = lut_sine[integral + 1]; return a + (b - a) * fractional; } private: float carrier_frequency_; float ratio_; float brightness_; float damping_; float position_; float feedback_amount_; float previous_carrier_frequency_; float previous_modulator_frequency_; float previous_brightness_; float previous_damping_; float previous_feedback_amount_; float amplitude_envelope_; float brightness_envelope_; float gain_; float fm_amount_; uint32_t carrier_phase_; uint32_t modulator_phase_; float previous_sample_; Follower follower_; DISALLOW_COPY_AND_ASSIGN(FMVoice); }; } // namespace rings #endif // RINGS_DSP_FM_VOICE_H_ ================================================ FILE: lib/rings/dsp/follower.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Envelope / centroid follower for FM voice. #ifndef RINGS_DSP_FOLLOWER_H_ #define RINGS_DSP_FOLLOWER_H_ #include "stmlib/stmlib.h" #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/filter.h" namespace rings { using namespace stmlib; class Follower { public: Follower() { } ~Follower() { } void Init(float low, float low_mid, float mid_high) { low_mid_filter_.Init(); mid_high_filter_.Init(); low_mid_filter_.set_f_q(low_mid, 0.5f); mid_high_filter_.set_f_q(mid_high, 0.5f); attack_[0] = low_mid; decay_[0] = Sqrt(low_mid * low); attack_[1] = Sqrt(low_mid * mid_high); decay_[1] = low_mid; attack_[2] = Sqrt(mid_high * 0.5f); decay_[2] = Sqrt(mid_high * low_mid); std::fill(&detector_[0], &detector_[3], 0.0f); centroid_ = 0.0f; } void Process( float sample, float* envelope, float* centroid) { float bands[3] = { 0.0f, 0.0f, 0.0f }; bands[2] = mid_high_filter_.Process(sample); bands[1] = low_mid_filter_.Process( mid_high_filter_.lp()); bands[0] = low_mid_filter_.lp(); float weighted = 0.0f; float total = 0.0f; float frequency = 0.0f; for (int32_t i = 0; i < 3; ++i) { SLOPE(detector_[i], fabsf(bands[i]), attack_[i], decay_[i]); weighted += detector_[i] * frequency; total += detector_[i]; frequency += 0.5f; } float error = weighted / (total + 0.001f) - centroid_; float coefficient = error > 0.0f ? 0.05f : 0.001f; centroid_ += error * coefficient; *envelope = total; *centroid = centroid_; } private: NaiveSvf low_mid_filter_; NaiveSvf mid_high_filter_; float attack_[3]; float decay_[3]; float detector_[3]; float centroid_; DISALLOW_COPY_AND_ASSIGN(Follower); }; } // namespace rings #endif // RINGS_DSP_FOLLOWER_H_ ================================================ FILE: lib/rings/dsp/fx/chorus.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Chorus. #ifndef RINGS_DSP_FX_CHORUS_H_ #define RINGS_DSP_FX_CHORUS_H_ #include "stmlib/stmlib.h" #include "stmlib/dsp/dsp.h" #include "rings/dsp/fx/fx_engine.h" #include "rings/resources.h" namespace rings { class Chorus { public: Chorus() { } ~Chorus() { } void Init(uint16_t* buffer) { engine_.Init(buffer); phase_1_ = 0; phase_2_ = 0; } void Process(float* left, float* right, size_t size) { typedef E::Reserve<2047> Memory; E::DelayLine line; E::Context c; while (size--) { engine_.Start(&c); float dry_amount = 1.0f - amount_ * 0.5f; // Update LFO. phase_1_ += 4.17e-06f; if (phase_1_ >= 1.0f) { phase_1_ -= 1.0f; } phase_2_ += 5.417e-06f; if (phase_2_ >= 1.0f) { phase_2_ -= 1.0f; } float sin_1 = stmlib::Interpolate(lut_sine, phase_1_, 4096.0f); float cos_1 = stmlib::Interpolate(lut_sine, phase_1_ + 0.25f, 4096.0f); float sin_2 = stmlib::Interpolate(lut_sine, phase_2_, 4096.0f); float cos_2 = stmlib::Interpolate(lut_sine, phase_2_ + 0.25f, 4096.0f); float wet; // Sum L & R channel to send to chorus line. c.Read(*left, 0.5f); c.Read(*right, 0.5f); c.Write(line, 0.0f); c.Interpolate(line, sin_1 * depth_ + 1200, 0.5f); c.Interpolate(line, sin_2 * depth_ + 800, 0.5f); c.Write(wet, 0.0f); *left = wet * amount_ + *left * dry_amount; c.Interpolate(line, cos_1 * depth_ + 800 + cos_2 * 0, 0.5f); c.Interpolate(line, cos_2 * depth_ + 1200, 0.5f); c.Write(wet, 0.0f); *right = wet * amount_ + *right * dry_amount; left++; right++; } } inline void set_amount(float amount) { amount_ = amount; } inline void set_depth(float depth) { depth_ = depth * 384.0f; } private: typedef FxEngine<2048, FORMAT_16_BIT> E; E engine_; float amount_; float depth_; float phase_1_; float phase_2_; DISALLOW_COPY_AND_ASSIGN(Chorus); }; } // namespace rings #endif // RINGS_DSP_FX_CHORUS_H_ ================================================ FILE: lib/rings/dsp/fx/ensemble.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Ensemble FX. #ifndef RINGS_DSP_FX_ENSEMBLE_H_ #define RINGS_DSP_FX_ENSEMBLE_H_ #include "stmlib/stmlib.h" #include "stmlib/dsp/dsp.h" #include "rings/dsp/fx/fx_engine.h" #include "rings/resources.h" namespace rings { class Ensemble { public: Ensemble() { } ~Ensemble() { } void Init(uint16_t* buffer) { engine_.Init(buffer); phase_1_ = 0; phase_2_ = 0; } void Process(float* left, float* right, size_t size) { typedef E::Reserve<2047, E::Reserve<2047> > Memory; E::DelayLine line_l; E::DelayLine line_r; E::Context c; while (size--) { engine_.Start(&c); float dry_amount = 1.0f - amount_ * 0.5f; // Update LFO. phase_1_ += 1.57e-05f; if (phase_1_ >= 1.0f) { phase_1_ -= 1.0f; } phase_2_ += 1.37e-04f; if (phase_2_ >= 1.0f) { phase_2_ -= 1.0f; } int32_t phi_1 = (phase_1_ * 4096.0f); float slow_0 = lut_sine[phi_1 & 4095]; float slow_120 = lut_sine[(phi_1 + 1365) & 4095]; float slow_240 = lut_sine[(phi_1 + 2730) & 4095]; int32_t phi_2 = (phase_2_ * 4096.0f); float fast_0 = lut_sine[phi_2 & 4095]; float fast_120 = lut_sine[(phi_2 + 1365) & 4095]; float fast_240 = lut_sine[(phi_2 + 2730) & 4095]; float a = depth_ * 1.0f; float b = depth_ * 0.1f; float mod_1 = slow_0 * a + fast_0 * b; float mod_2 = slow_120 * a + fast_120 * b; float mod_3 = slow_240 * a + fast_240 * b; float wet = 0.0f; // Sum L & R channel to send to chorus line. c.Read(*left, 1.0f); c.Write(line_l, 0.0f); c.Read(*right, 1.0f); c.Write(line_r, 0.0f); c.Interpolate(line_l, mod_1 + 1024, 0.33f); c.Interpolate(line_l, mod_2 + 1024, 0.33f); c.Interpolate(line_r, mod_3 + 1024, 0.33f); c.Write(wet, 0.0f); *left = wet * amount_ + *left * dry_amount; c.Interpolate(line_r, mod_1 + 1024, 0.33f); c.Interpolate(line_r, mod_2 + 1024, 0.33f); c.Interpolate(line_l, mod_3 + 1024, 0.33f); c.Write(wet, 0.0f); *right = wet * amount_ + *right * dry_amount; left++; right++; } } inline void set_amount(float amount) { amount_ = amount; } inline void set_depth(float depth) { depth_ = depth * 128.0f; } private: typedef FxEngine<4096, FORMAT_16_BIT> E; E engine_; float amount_; float depth_; float phase_1_; float phase_2_; DISALLOW_COPY_AND_ASSIGN(Ensemble); }; } // namespace rings #endif // RINGS_DSP_FX_ENSEMBLE_H_ ================================================ FILE: lib/rings/dsp/fx/fx_engine.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Base class for building reverb. #ifndef RINGS_DSP_FX_FX_ENGINE_H_ #define RINGS_DSP_FX_FX_ENGINE_H_ #include #include "stmlib/stmlib.h" #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/cosine_oscillator.h" namespace rings { #define TAIL , -1 enum Format { FORMAT_12_BIT, FORMAT_16_BIT, FORMAT_32_BIT }; enum LFOIndex { LFO_1, LFO_2 }; template struct DataType { }; template<> struct DataType { typedef uint16_t T; static inline float Decompress(T value) { return static_cast(static_cast(value)) / 4096.0f; } static inline T Compress(float value) { return static_cast( stmlib::Clip16(static_cast(value * 4096.0f))); } }; template<> struct DataType { typedef uint16_t T; static inline float Decompress(T value) { return static_cast(static_cast(value)) / 32768.0f; } static inline T Compress(float value) { return static_cast( stmlib::Clip16(static_cast(value * 32768.0f))); } }; template<> struct DataType { typedef float T; static inline float Decompress(T value) { return value;; } static inline T Compress(float value) { return value; } }; template< size_t size, Format format = FORMAT_12_BIT> class FxEngine { public: typedef typename DataType::T T; FxEngine() { } ~FxEngine() { } void Init(T* buffer) { buffer_ = buffer; Clear(); } void Clear() { std::fill(&buffer_[0], &buffer_[size], 0); write_ptr_ = 0; } struct Empty { }; template struct Reserve { typedef T Tail; enum { length = l }; }; template struct DelayLine { enum { length = DelayLine::length, base = DelayLine::base + DelayLine::length + 1 }; }; template struct DelayLine { enum { length = Memory::length, base = 0 }; }; class Context { friend class FxEngine; public: Context() { } ~Context() { } inline void Load(float value) { accumulator_ = value; } inline void Read(float value, float scale) { accumulator_ += value * scale; } inline void Read(float value) { accumulator_ += value; } inline void Write(float& value) { value = accumulator_; } inline void Write(float& value, float scale) { value = accumulator_; accumulator_ *= scale; } template inline void Write(D& d, int32_t offset, float scale) { STATIC_ASSERT(D::base + D::length <= size, delay_memory_full); T w = DataType::Compress(accumulator_); if (offset == -1) { buffer_[(write_ptr_ + D::base + D::length - 1) & MASK] = w; } else { buffer_[(write_ptr_ + D::base + offset) & MASK] = w; } accumulator_ *= scale; } template inline void Write(D& d, float scale) { Write(d, 0, scale); } template inline void WriteAllPass(D& d, int32_t offset, float scale) { Write(d, offset, scale); accumulator_ += previous_read_; } template inline void WriteAllPass(D& d, float scale) { WriteAllPass(d, 0, scale); } template inline void Read(D& d, int32_t offset, float scale) { STATIC_ASSERT(D::base + D::length <= size, delay_memory_full); T r; if (offset == -1) { r = buffer_[(write_ptr_ + D::base + D::length - 1) & MASK]; } else { r = buffer_[(write_ptr_ + D::base + offset) & MASK]; } float r_f = DataType::Decompress(r); previous_read_ = r_f; accumulator_ += r_f * scale; } template inline void Read(D& d, float scale) { Read(d, 0, scale); } inline void Lp(float& state, float coefficient) { state += coefficient * (accumulator_ - state); accumulator_ = state; } inline void Hp(float& state, float coefficient) { state += coefficient * (accumulator_ - state); accumulator_ -= state; } template inline void Interpolate(D& d, float offset, float scale) { STATIC_ASSERT(D::base + D::length <= size, delay_memory_full); MAKE_INTEGRAL_FRACTIONAL(offset); float a = DataType::Decompress( buffer_[(write_ptr_ + offset_integral + D::base) & MASK]); float b = DataType::Decompress( buffer_[(write_ptr_ + offset_integral + D::base + 1) & MASK]); float x = a + (b - a) * offset_fractional; previous_read_ = x; accumulator_ += x * scale; } template inline void Interpolate( D& d, float offset, LFOIndex index, float amplitude, float scale) { STATIC_ASSERT(D::base + D::length <= size, delay_memory_full); offset += amplitude * lfo_value_[index]; MAKE_INTEGRAL_FRACTIONAL(offset); float a = DataType::Decompress( buffer_[(write_ptr_ + offset_integral + D::base) & MASK]); float b = DataType::Decompress( buffer_[(write_ptr_ + offset_integral + D::base + 1) & MASK]); float x = a + (b - a) * offset_fractional; previous_read_ = x; accumulator_ += x * scale; } private: float accumulator_; float previous_read_; float lfo_value_[2]; T* buffer_; int32_t write_ptr_; DISALLOW_COPY_AND_ASSIGN(Context); }; inline void SetLFOFrequency(LFOIndex index, float frequency) { lfo_[index].template Init(frequency * 32.0f); } inline void Start(Context* c) { --write_ptr_; if (write_ptr_ < 0) { write_ptr_ += size; } c->accumulator_ = 0.0f; c->previous_read_ = 0.0f; c->buffer_ = buffer_; c->write_ptr_ = write_ptr_; if ((write_ptr_ & 31) == 0) { c->lfo_value_[0] = lfo_[0].Next(); c->lfo_value_[1] = lfo_[1].Next(); } else { c->lfo_value_[0] = lfo_[0].value(); c->lfo_value_[1] = lfo_[1].value(); } } private: enum { MASK = size - 1 }; int32_t write_ptr_; T* buffer_; stmlib::CosineOscillator lfo_[2]; DISALLOW_COPY_AND_ASSIGN(FxEngine); }; } // namespace rings #endif // RINGS_DSP_FX_FX_ENGINE_H_ ================================================ FILE: lib/rings/dsp/fx/reverb.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Reverb. #ifndef RINGS_DSP_FX_REVERB_H_ #define RINGS_DSP_FX_REVERB_H_ #include "stmlib/stmlib.h" #include "rings/dsp/fx/fx_engine.h" namespace rings { class Reverb { public: Reverb() { } ~Reverb() { } void Init(uint16_t* buffer) { engine_.Init(buffer); engine_.SetLFOFrequency(LFO_1, 0.5f / 48000.0f); engine_.SetLFOFrequency(LFO_2, 0.3f / 48000.0f); lp_ = 0.7f; diffusion_ = 0.625f; } void Process(float* left, float* right, size_t size) { // This is the Griesinger topology described in the Dattorro paper // (4 AP diffusers on the input, then a loop of 2x 2AP+1Delay). // Modulation is applied in the loop of the first diffuser AP for additional // smearing; and to the two long delays for a slow shimmer/chorus effect. typedef E::Reserve<150, E::Reserve<214, E::Reserve<319, E::Reserve<527, E::Reserve<2182, E::Reserve<2690, E::Reserve<4501, E::Reserve<2525, E::Reserve<2197, E::Reserve<6312> > > > > > > > > > Memory; E::DelayLine ap1; E::DelayLine ap2; E::DelayLine ap3; E::DelayLine ap4; E::DelayLine dap1a; E::DelayLine dap1b; E::DelayLine del1; E::DelayLine dap2a; E::DelayLine dap2b; E::DelayLine del2; E::Context c; const float kap = diffusion_; const float klp = lp_; const float krt = reverb_time_; const float amount = amount_; const float gain = input_gain_; float lp_1 = lp_decay_1_; float lp_2 = lp_decay_2_; while (size--) { float wet; float apout = 0.0f; engine_.Start(&c); // Smear AP1 inside the loop. //c.Interpolate(ap1, 10.0f, LFO_1, 80.0f, 1.0f); //c.Write(ap1, 100, 0.0f); c.Read(*left + *right, gain); // Diffuse through 4 allpasses. c.Read(ap1 TAIL, kap); c.WriteAllPass(ap1, -kap); c.Read(ap2 TAIL, kap); c.WriteAllPass(ap2, -kap); c.Read(ap3 TAIL, kap); c.WriteAllPass(ap3, -kap); c.Read(ap4 TAIL, kap); c.WriteAllPass(ap4, -kap); c.Write(apout); // Main reverb loop. c.Load(apout); c.Interpolate(del2, 6261.0f, LFO_2, 50.0f, krt); c.Lp(lp_1, klp); c.Read(dap1a TAIL, -kap); c.WriteAllPass(dap1a, kap); c.Read(dap1b TAIL, kap); c.WriteAllPass(dap1b, -kap); c.Write(del1, 2.0f); c.Write(wet, 0.0f); *left += (wet - *left) * amount; c.Load(apout); c.Interpolate(del1, 4460.0f, LFO_1, 40.0f, krt); c.Lp(lp_2, klp); c.Read(dap2a TAIL, kap); c.WriteAllPass(dap2a, -kap); c.Read(dap2b TAIL, -kap); c.WriteAllPass(dap2b, kap); c.Write(del2, 2.0f); c.Write(wet, 0.0f); *right += (wet - *right) * amount; ++left; ++right; } lp_decay_1_ = lp_1; lp_decay_2_ = lp_2; } inline void set_amount(float amount) { amount_ = amount; } inline void set_input_gain(float input_gain) { input_gain_ = input_gain; } inline void set_time(float reverb_time) { reverb_time_ = reverb_time; } inline void set_diffusion(float diffusion) { diffusion_ = diffusion; } inline void set_lp(float lp) { lp_ = lp; } inline void Clear() { engine_.Clear(); } private: typedef FxEngine<32768, FORMAT_16_BIT> E; E engine_; float amount_; float input_gain_; float reverb_time_; float diffusion_; float lp_; float lp_decay_1_; float lp_decay_2_; DISALLOW_COPY_AND_ASSIGN(Reverb); }; } // namespace rings #endif // RINGS_DSP_FX_REVERB_H_ ================================================ FILE: lib/rings/dsp/limiter.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Limiter. #ifndef RINGS_DSP_LIMITER_H_ #define RINGS_DSP_LIMITER_H_ #include "stmlib/stmlib.h" #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/filter.h" namespace rings { class Limiter { public: Limiter() { } ~Limiter() { } void Init() { peak_ = 0.5f; } void Process( float* l, float* r, size_t size, float pre_gain) { while (size--) { float l_pre = *l * pre_gain; float r_pre = *r * pre_gain; float l_peak = fabsf(l_pre); float r_peak = fabsf(r_pre); float s_peak = fabsf(r_pre - l_pre); float peak = std::max(std::max(l_peak, r_peak), s_peak); SLOPE(peak_, peak, 0.05f, 0.00002f); // Clamp to 8Vpp, clipping softly towards 10Vpp float gain = (peak_ <= 1.0f ? 1.0f : 1.0f / peak_); *l++ = stmlib::SoftLimit(l_pre * gain * 0.8f); *r++ = stmlib::SoftLimit(r_pre * gain * 0.8f); } } private: float peak_; DISALLOW_COPY_AND_ASSIGN(Limiter); }; } // namespace rings #endif // RINGS_DSP_LIMITER_H_ ================================================ FILE: lib/rings/dsp/note_filter.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Low pass filter for getting stable pitch data. #ifndef RINGS_DSP_NOTE_FILTER_H_ #define RINGS_DSP_NOTE_FILTER_H_ #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/delay_line.h" namespace rings { class NoteFilter { public: enum { N = 4 // Median filter order }; NoteFilter() { } ~NoteFilter() { } void Init( float sample_rate, float time_constant_fast_edge, float time_constant_steady_part, float edge_recovery_time, float edge_avoidance_delay) { fast_coefficient_ = 1.0f / (time_constant_fast_edge * sample_rate); slow_coefficient_ = 1.0f / (time_constant_steady_part * sample_rate); lag_coefficient_ = 1.0f / (edge_recovery_time * sample_rate); delayed_stable_note_.Init(); delayed_stable_note_.set_delay( std::min(size_t(15), size_t(edge_avoidance_delay * sample_rate))); stable_note_ = note_ = 69.0f; coefficient_ = fast_coefficient_; stable_coefficient_ = slow_coefficient_; std::fill(&previous_values_[0], &previous_values_[N], note_); } inline float Process(float note, bool strum) { // If there is a sharp change, follow it instantly. if (fabsf(note - note_) > 0.4f || strum) { stable_note_ = note_ = note; coefficient_ = fast_coefficient_; stable_coefficient_ = slow_coefficient_; std::fill(&previous_values_[0], &previous_values_[N], note); } else { // Median filtering of the raw ADC value. float sorted_values[N]; std::rotate( &previous_values_[0], &previous_values_[1], &previous_values_[N]); previous_values_[N - 1] = note; std::copy(&previous_values_[0], &previous_values_[N], &sorted_values[0]); std::sort(&sorted_values[0], &sorted_values[N]); float median = 0.5f * (sorted_values[(N - 1) / 2] + sorted_values[N / 2]); // Adaptive lag processor. note_ += coefficient_ * (median - note_); stable_note_ += stable_coefficient_ * (note_ - stable_note_); coefficient_ += lag_coefficient_ * (slow_coefficient_ - coefficient_); stable_coefficient_ += lag_coefficient_ * \ (lag_coefficient_ - stable_coefficient_); delayed_stable_note_.Write(stable_note_); } return note_; } inline float note() const { return note_; } inline float stable_note() const { return delayed_stable_note_.Read(); } private: float previous_values_[N]; float note_; float stable_note_; stmlib::DelayLine delayed_stable_note_; float coefficient_; float stable_coefficient_; float fast_coefficient_; float slow_coefficient_; float lag_coefficient_; }; } // namespace rings #endif // RINGS_DSP_NOTE_FILTER_H_ ================================================ FILE: lib/rings/dsp/onset_detector.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Onset detector. #ifndef RINGS_DSP_ONSET_DETECTOR_H_ #define RINGS_DSP_ONSET_DETECTOR_H_ #include "stmlib/stmlib.h" #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/filter.h" namespace rings { using namespace std; using namespace stmlib; class ZScorer { public: ZScorer() { } ~ZScorer() { } void Init(float cutoff) { coefficient_ = cutoff; mean_ = 0.0f; variance_ = 0.00f; } inline float Normalize(float sample) { return Update(sample) / Sqrt(variance_); } inline bool Test(float sample, float threshold) { float value = Update(sample); return value > Sqrt(variance_) * threshold; } inline bool Test(float sample, float threshold, float absolute_threshold) { float value = Update(sample); return value > Sqrt(variance_) * threshold && value > absolute_threshold; } private: inline float Update(float sample) { float centered = sample - mean_; mean_ += coefficient_ * centered; variance_ += coefficient_ * (centered * centered - variance_); return centered; } float coefficient_; float mean_; float variance_; DISALLOW_COPY_AND_ASSIGN(ZScorer); }; class Compressor { public: Compressor() { } ~Compressor() { } void Init(float attack, float decay, float max_gain) { attack_ = attack; decay_ = decay; level_ = 0.0f; skew_ = 1.0f / max_gain; } void Process(const float* in, float* out, size_t size) { float level = level_; while (size--) { SLOPE(level, fabsf(*in), attack_, decay_); *out++ = *in++ / (skew_ + level); } level_ = level; } private: float attack_; float decay_; float level_; float skew_; DISALLOW_COPY_AND_ASSIGN(Compressor); }; class OnsetDetector { public: OnsetDetector() { } ~OnsetDetector() { } void Init( float low, float low_mid, float mid_high, float decimated_sr, float ioi_time) { float ioi_f = 1.0f / (ioi_time * decimated_sr); compressor_.Init(ioi_f * 10.0f, ioi_f * 0.05f, 40.0f); low_mid_filter_.Init(); mid_high_filter_.Init(); low_mid_filter_.set_f_q(low_mid, 0.5f); mid_high_filter_.set_f_q(mid_high, 0.5f); attack_[0] = low_mid; decay_[0] = low * 0.25f; attack_[1] = low_mid; decay_[1] = low * 0.25f; attack_[2] = low_mid; decay_[2] = low * 0.25f; fill(&envelope_[0], &envelope_[3], 0.0f); fill(&energy_[0], &energy_[3], 0.0f); z_df_.Init(ioi_f * 0.05f); inhibit_time_ = static_cast(ioi_time * decimated_sr); inhibit_decay_ = 1.0f / (ioi_time * decimated_sr); inhibit_threshold_ = 0.0f; inhibit_counter_ = 0; onset_df_ = 0.0f; } bool Process(const float* samples, size_t size) { // Automatic gain control. compressor_.Process(samples, bands_[0], size); // Quick and dirty filter bank - split the signal in three bands. mid_high_filter_.Split(bands_[0], bands_[1], bands_[2], size); low_mid_filter_.Split(bands_[1], bands_[0], bands_[1], size); // Compute low-pass energy and onset detection function // (derivative of energy) in each band. float onset_df = 0.0f; float total_energy = 0.0f; for (int32_t i = 0; i < 3; ++i) { float* s = bands_[i]; float energy = 0.0f; float envelope = envelope_[i]; size_t increment = 4 >> i; for (size_t j = 0; j < size; j += increment) { SLOPE(envelope, s[j] * s[j], attack_[i], decay_[i]); energy += envelope; } energy = Sqrt(energy) * float(increment); envelope_[i] = envelope; float derivative = energy - energy_[i]; onset_df += derivative + fabsf(derivative); energy_[i] = energy; total_energy += energy; } onset_df_ += 0.05f * (onset_df - onset_df_); bool outlier_in_df = z_df_.Test(onset_df_, 1.0f, 0.01f); bool exceeds_energy_threshold = total_energy >= inhibit_threshold_; bool not_inhibited = !inhibit_counter_; bool has_onset = outlier_in_df && exceeds_energy_threshold && not_inhibited; if (has_onset) { inhibit_threshold_ = total_energy * 1.5f; inhibit_counter_ = inhibit_time_; } else { inhibit_threshold_ -= inhibit_decay_ * inhibit_threshold_; if (inhibit_counter_) { --inhibit_counter_; } } return has_onset; } private: Compressor compressor_; NaiveSvf low_mid_filter_; NaiveSvf mid_high_filter_; float attack_[3]; float decay_[3]; float energy_[3]; float envelope_[3]; float onset_df_; float bands_[3][32]; ZScorer z_df_; float inhibit_threshold_; float inhibit_decay_; int32_t inhibit_time_; int32_t inhibit_counter_; DISALLOW_COPY_AND_ASSIGN(OnsetDetector); }; } // namespace rings #endif // RINGS_DSP_ONSET_DETECTOR_H_ ================================================ FILE: lib/rings/dsp/part.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Group of voices. //[eh2k] Reverb + RESONATOR_MODEL_STRING_AND_REVERB removed! #include "rings/dsp/part.h" #include "stmlib/dsp/units.h" #include "rings/resources.h" #ifndef FLASHMEM #include "pgmspace.h" #endif namespace rings { using namespace std; using namespace stmlib; void Part::Init() { active_voice_ = 0; fill(¬e_[0], ¬e_[kMaxPolyphony], 0.0f); bypass_ = false; polyphony_ = 1; model_ = RESONATOR_MODEL_MODAL; dirty_ = true; for (int32_t i = 0; i < kMaxPolyphony; ++i) { excitation_filter_[i].Init(); plucker_[i].Init(); dc_blocker_[i].Init(1.0f - 10.0f / kSampleRate); } limiter_.Init(); note_filter_.Init( kSampleRate / kMaxBlockSize, 0.001f, // Lag time with a sharp edge on the V/Oct input or trigger. 0.010f, // Lag time after the trigger has been received. 0.050f, // Time to transition from reactive to filtered. 0.004f); // Prevent a sharp edge to partly leak on the previous voice. } void Part::ConfigureResonators() { if (!dirty_) { return; } switch (model_) { case RESONATOR_MODEL_MODAL: { int32_t resolution = 64 / polyphony_ - 4; for (int32_t i = 0; i < polyphony_; ++i) { resonator_[i].Init(); resonator_[i].set_resolution(resolution); } } break; case RESONATOR_MODEL_SYMPATHETIC_STRING: case RESONATOR_MODEL_STRING: case RESONATOR_MODEL_SYMPATHETIC_STRING_QUANTIZED: { float lfo_frequencies[kNumStrings] = { 0.5f, 0.4f, 0.35f, 0.23f, 0.211f, 0.2f, 0.171f }; for (int32_t i = 0; i < kNumStrings; ++i) { bool has_dispersion = model_ == RESONATOR_MODEL_STRING; string_[i].Init(has_dispersion); float f_lfo = float(kMaxBlockSize) / float(kSampleRate); f_lfo *= lfo_frequencies[i]; lfo_[i].Init(f_lfo); } for (int32_t i = 0; i < polyphony_; ++i) { plucker_[i].Init(); } } break; case RESONATOR_MODEL_FM_VOICE: { for (int32_t i = 0; i < polyphony_; ++i) { fm_voice_[i].Init(); } } break; default: break; } if (active_voice_ >= polyphony_) { active_voice_ = 0; } dirty_ = false; } #ifdef BRYAN_CHORDS // Chord table by Bryan Noll: const float part_chords[][11][8] FLASHMEM = { { { -12.0f, -0.01f, 0.0f, 0.01f, 0.02f, 11.98f, 11.99f, 12.0f }, // OCT { -12.0f, -5.0f, 0.0f, 6.99f, 7.0f, 11.99f, 12.0f, 19.0f }, // 5 { -12.0f, -5.0f, 0.0f, 5.0f, 7.0f, 11.99f, 12.0f, 17.0f }, // sus4 { -12.0f, -5.0f, 0.0f, 3.0f, 7.0f, 3.01f, 12.0f, 19.0f }, // m { -12.0f, -5.0f, 0.0f, 3.0f, 7.0f, 3.01f, 10.0f, 19.0f }, // m7 { -12.0f, -5.0f, 0.0f, 3.0f, 14.0f, 3.01f, 10.0f, 19.0f }, // m9 { -12.0f, -5.0f, 0.0f, 3.0f, 7.0f, 3.01f, 10.0f, 17.0f }, // m11 { -12.0f, -5.0f, 0.0f, 2.0f, 7.0f, 9.0f, 16.0f, 19.0f }, // 69 { -12.0f, -5.0f, 0.0f, 4.0f, 7.0f, 11.0f, 14.0f, 19.0f }, // M9 { -12.0f, -5.0f, 0.0f, 4.0f, 7.0f, 11.0f, 10.99f, 19.0f }, // M7 { -12.0f, -5.0f, 0.0f, 4.0f, 7.0f, 11.99f, 12.0f, 19.0f } // M }, { { -12.0f, 0.0f, 0.01f, 12.0f }, // OCT { -12.0f, 6.99f, 7.0f, 12.0f }, // 5 { -12.0f, 5.0f, 7.0f, 12.0f }, // sus4 { -12.0f, 3.0f, 11.99f, 12.0f }, // m { -12.0f, 3.0f, 10.0f, 12.0f }, // m7 { -12.0f, 3.0f, 10.0f, 14.0f }, // m9 { -12.0f, 3.0f, 10.0f, 17.0f }, // m11 { -12.0f, 2.0f, 9.0f, 16.0f }, // 69 { -12.0f, 4.0f, 11.0f, 14.0f }, // M9 { -12.0f, 4.0f, 7.0f, 11.0f }, // M7 { -12.0f, 4.0f, 7.0f, 12.0f }, // M }, { { 0.0f, -12.0f }, { 0.0f, 2.0f }, { 0.0f, 3.0f }, { 0.0f, 4.0f }, { 0.0f, 5.0f }, { 0.0f, 7.0f }, { 0.0f, 9.0f }, { 0.0f, 10.0f }, { 0.0f, 11.0f }, { 0.0f, 12.0f }, { -12.0f, 12.0f } }, { { 0.0f, -12.0f }, { 0.0f, 2.0f }, { 0.0f, 3.0f }, { 0.0f, 4.0f }, { 0.0f, 5.0f }, { 0.0f, 7.0f }, { 0.0f, 9.0f }, { 0.0f, 10.0f }, { 0.0f, 11.0f }, { 0.0f, 12.0f }, { -12.0f, 12.0f } } }; #else // Original chord table const float part_chords[kMaxPolyphony][11][8] FLASHMEM = { { { -12.0f, 0.0f, 0.01f, 0.02f, 0.03f, 11.98f, 11.99f, 12.0f }, { -12.0f, 0.0f, 3.0f, 3.01f, 7.0f, 9.99f, 10.0f, 19.0f }, { -12.0f, 0.0f, 3.0f, 3.01f, 7.0f, 11.99f, 12.0f, 19.0f }, { -12.0f, 0.0f, 3.0f, 3.01f, 7.0f, 13.99f, 14.0f, 19.0f }, { -12.0f, 0.0f, 3.0f, 3.01f, 7.0f, 16.99f, 17.0f, 19.0f }, { -12.0f, 0.0f, 6.98f, 6.99f, 7.0f, 12.00f, 18.99f, 19.0f }, { -12.0f, 0.0f, 3.99f, 4.0f, 7.0f, 16.99f, 17.0f, 19.0f }, { -12.0f, 0.0f, 3.99f, 4.0f, 7.0f, 13.99f, 14.0f, 19.0f }, { -12.0f, 0.0f, 3.99f, 4.0f, 7.0f, 11.99f, 12.0f, 19.0f }, { -12.0f, 0.0f, 3.99f, 4.0f, 7.0f, 10.99f, 11.0f, 19.0f }, { -12.0f, 0.0f, 4.99f, 5.0f, 7.0f, 11.99f, 12.0f, 17.0f } }, { { -12.0f, 0.0f, 0.01f, 12.0f }, { -12.0f, 3.0f, 7.0f, 10.0f }, { -12.0f, 3.0f, 7.0f, 12.0f }, { -12.0f, 3.0f, 7.0f, 14.0f }, { -12.0f, 3.0f, 7.0f, 17.0f }, { -12.0f, 7.0f, 12.0f, 19.0f }, { -12.0f, 4.0f, 7.0f, 17.0f }, { -12.0f, 4.0f, 7.0f, 14.0f }, { -12.0f, 4.0f, 7.0f, 12.0f }, { -12.0f, 4.0f, 7.0f, 11.0f }, { -12.0f, 5.0f, 7.0f, 12.0f }, }, { { 0.0f, -12.0f }, { 0.0f, 0.01f }, { 0.0f, 2.0f }, { 0.0f, 3.0f }, { 0.0f, 4.0f }, { 0.0f, 5.0f }, { 0.0f, 7.0f }, { 0.0f, 10.0f }, { 0.0f, 11.0f }, { 0.0f, 12.0f }, { -12.0f, 12.0f } }, { { 0.0f, -12.0f }, { 0.0f, 0.01f }, { 0.0f, 2.0f }, { 0.0f, 3.0f }, { 0.0f, 4.0f }, { 0.0f, 5.0f }, { 0.0f, 7.0f }, { 0.0f, 10.0f }, { 0.0f, 11.0f }, { 0.0f, 12.0f }, { -12.0f, 12.0f } } }; #endif // BRYAN_CHORDS void Part::ComputeSympatheticStringsNotes( float tonic, float note, float parameter, float* destination, size_t num_strings) { float notes[9] = { tonic, note - 12.0f, note - 7.01955f, note, note + 7.01955f, note + 12.0f, note + 19.01955f, note + 24.0f, note + 24.0f }; const float detunings[4] = { 0.013f, 0.011f, 0.007f, 0.017f }; if (parameter >= 2.0f) { // Quantized chords int32_t chord_index = parameter - 2.0f; const float* chord = part_chords[polyphony_ - 1][chord_index]; for (size_t i = 0; i < num_strings; ++i) { destination[i] = chord[i] + note; } return; } size_t num_detuned_strings = (num_strings - 1) >> 1; size_t first_detuned_string = num_strings - num_detuned_strings; for (size_t i = 0; i < first_detuned_string; ++i) { float note = 3.0f; if (i != 0) { note = parameter * 7.0f; parameter += (1.0f - parameter) * 0.2f; } MAKE_INTEGRAL_FRACTIONAL(note); note_fractional = Squash(note_fractional); float a = notes[note_integral]; float b = notes[note_integral + 1]; note = a + (b - a) * note_fractional; destination[i] = note; if (i + first_detuned_string < num_strings) { destination[i + first_detuned_string] = destination[i] + detunings[i & 3]; } } } void Part::RenderModalVoice( int32_t voice, const PerformanceState& performance_state, const Patch& patch, float frequency, float filter_cutoff, size_t size) { // Internal exciter is a pulse, pre-filter. if (performance_state.internal_exciter && voice == active_voice_ && performance_state.strum) { resonator_input_[0] += 0.25f * SemitonesToRatio( filter_cutoff * filter_cutoff * 24.0f) / filter_cutoff; } // Process through filter. excitation_filter_[voice].Process( resonator_input_, resonator_input_, size); Resonator& r = resonator_[voice]; r.set_frequency(frequency); r.set_structure(patch.structure); r.set_brightness(patch.brightness * patch.brightness); r.set_position(patch.position); r.set_damping(patch.damping); r.Process(resonator_input_, out_buffer_, aux_buffer_, size); } void Part::RenderFMVoice( int32_t voice, const PerformanceState& performance_state, const Patch& patch, float frequency, float filter_cutoff, size_t size) { FMVoice& v = fm_voice_[voice]; if (performance_state.internal_exciter && voice == active_voice_ && performance_state.strum) { v.TriggerInternalEnvelope(); } v.set_frequency(frequency); v.set_ratio(patch.structure); v.set_brightness(patch.brightness); v.set_feedback_amount(patch.position); v.set_position(/*patch.position*/ 0.0f); v.set_damping(patch.damping); v.Process(resonator_input_, out_buffer_, aux_buffer_, size); } void Part::RenderStringVoice( int32_t voice, const PerformanceState& performance_state, const Patch& patch, float frequency, float filter_cutoff, size_t size) { // Compute number of strings and frequency. int32_t num_strings = 1; float frequencies[kNumStrings]; if (model_ == RESONATOR_MODEL_SYMPATHETIC_STRING || model_ == RESONATOR_MODEL_SYMPATHETIC_STRING_QUANTIZED) { num_strings = 2 * kMaxPolyphony / polyphony_; float parameter = model_ == RESONATOR_MODEL_SYMPATHETIC_STRING ? patch.structure : 2.0f + performance_state.chord; ComputeSympatheticStringsNotes( performance_state.tonic + performance_state.fm, performance_state.tonic + note_[voice] + performance_state.fm, parameter, frequencies, num_strings); for (int32_t i = 0; i < num_strings; ++i) { frequencies[i] = SemitonesToRatio(frequencies[i] - 69.0f) * a3; } } else { frequencies[0] = frequency; } if (voice == active_voice_) { const float gain = 1.0f / Sqrt(static_cast(num_strings) * 2.0f); for (size_t i = 0; i < size; ++i) { resonator_input_[i] *= gain; } } // Process external input. excitation_filter_[voice].Process( resonator_input_, resonator_input_, size); // Add noise burst. if (performance_state.internal_exciter) { if (voice == active_voice_ && performance_state.strum) { plucker_[voice].Trigger(frequency, filter_cutoff * 8.0f, patch.position); } plucker_[voice].Process(noise_burst_buffer_, size); for (size_t i = 0; i < size; ++i) { resonator_input_[i] += noise_burst_buffer_[i]; } } dc_blocker_[voice].Process(resonator_input_, size); fill(&out_buffer_[0], &out_buffer_[size], 0.0f); fill(&aux_buffer_[0], &aux_buffer_[size], 0.0f); float structure = patch.structure; float dispersion = structure < 0.24f ? (structure - 0.24f) * 4.166f : (structure > 0.26f ? (structure - 0.26f) * 1.35135f : 0.0f); for (int32_t string = 0; string < num_strings; ++string) { int32_t i = voice + string * polyphony_; String& s = string_[i]; float lfo_value = lfo_[i].Next(); float brightness = patch.brightness; float damping = patch.damping; float position = patch.position; float glide = 1.0f; float string_index = static_cast(string) / static_cast(num_strings); const float* input = resonator_input_; // When the internal exciter is used, string 0 is the main // source, the other strings are vibrating by sympathetic resonance. // When the internal exciter is not used, all strings are vibrating // by sympathetic resonance. if (string > 0 && performance_state.internal_exciter) { brightness *= (2.0f - brightness); brightness *= (2.0f - brightness); damping = 0.7f + patch.damping * 0.27f; float amount = (0.5f - fabsf(0.5f - patch.position)) * 0.9f; position = patch.position + lfo_value * amount; glide = SemitonesToRatio((brightness - 1.0f) * 36.0f); input = sympathetic_resonator_input_; } s.set_dispersion(dispersion); s.set_frequency(frequencies[string], glide); s.set_brightness(brightness); s.set_position(position); s.set_damping(damping + string_index * (0.95f - damping)); s.Process(input, out_buffer_, aux_buffer_, size); if (string == 0) { // Was 0.1f, Ben Wilson -> 0.2f float gain = 0.2f / static_cast(num_strings); for (size_t i = 0; i < size; ++i) { float sum = out_buffer_[i] - aux_buffer_[i]; sympathetic_resonator_input_[i] = gain * sum; } } } } const int32_t kPingPattern[] = { 1, 0, 2, 1, 0, 2, 1, 0 }; void Part::Process( const PerformanceState& performance_state, const Patch& patch, const float* in, float* out, float* aux, size_t size) { // Copy inputs to outputs when bypass mode is enabled. if (bypass_) { copy(&in[0], &in[size], &out[0]); copy(&in[0], &in[size], &aux[0]); return; } ConfigureResonators(); note_filter_.Process( performance_state.note, performance_state.strum); if (performance_state.strum) { note_[active_voice_] = note_filter_.stable_note(); if (polyphony_ > 1 && polyphony_ & 1) { active_voice_ = kPingPattern[step_counter_ % 8]; step_counter_ = (step_counter_ + 1) % 8; } else { active_voice_ = (active_voice_ + 1) % polyphony_; } } note_[active_voice_] = note_filter_.note(); fill(&out[0], &out[size], 0.0f); fill(&aux[0], &aux[size], 0.0f); for (int32_t voice = 0; voice < polyphony_; ++voice) { // Compute MIDI note value, frequency, and cutoff frequency for excitation // filter. float cutoff = patch.brightness * (2.0f - patch.brightness); float note = note_[voice] + performance_state.tonic + performance_state.fm; float frequency = SemitonesToRatio(note - 69.0f) * a3; float filter_cutoff_range = performance_state.internal_exciter ? frequency * SemitonesToRatio((cutoff - 0.5f) * 96.0f) : 0.4f * SemitonesToRatio((cutoff - 1.0f) * 108.0f); float filter_cutoff = min(voice == active_voice_ ? filter_cutoff_range : (10.0f / kSampleRate), 0.499f); float filter_q = performance_state.internal_exciter ? 1.5f : 0.8f; // Process input with excitation filter. Inactive voices receive silence. excitation_filter_[voice].set_f_q(filter_cutoff, filter_q); if (voice == active_voice_) { copy(&in[0], &in[size], &resonator_input_[0]); } else { fill(&resonator_input_[0], &resonator_input_[size], 0.0f); } if (model_ == RESONATOR_MODEL_MODAL) { RenderModalVoice( voice, performance_state, patch, frequency, filter_cutoff, size); } else if (model_ == RESONATOR_MODEL_FM_VOICE) { RenderFMVoice( voice, performance_state, patch, frequency, filter_cutoff, size); } else { RenderStringVoice( voice, performance_state, patch, frequency, filter_cutoff, size); } if (polyphony_ == 1) { // Send the two sets of harmonics / pickups to individual outputs. for (size_t i = 0; i < size; ++i) { out[i] += out_buffer_[i]; aux[i] += aux_buffer_[i]; } } else { // Dispatch odd/even voices to individual outputs. float* destination = voice & 1 ? aux : out; for (size_t i = 0; i < size; ++i) { destination[i] += out_buffer_[i] - aux_buffer_[i]; } } } // Apply limiter to string output. limiter_.Process(out, aux, size, model_gains_[model_]); } /* static */ float Part::model_gains_[] = { 1.4f, // RESONATOR_MODEL_MODAL 1.0f, // RESONATOR_MODEL_SYMPATHETIC_STRING 1.4f, // RESONATOR_MODEL_STRING 0.7f, // RESONATOR_MODEL_FM_VOICE, 1.0f, // RESONATOR_MODEL_SYMPATHETIC_STRING_QUANTIZED }; } // namespace rings ================================================ FILE: lib/rings/dsp/part.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Group of voices. //[eh2k] Reverb + RESONATOR_MODEL_STRING_AND_REVERB removed! #ifndef RINGS_DSP_PART_H_ #define RINGS_DSP_PART_H_ #include #include "stmlib/stmlib.h" #include "stmlib/dsp/cosine_oscillator.h" #include "stmlib/dsp/delay_line.h" #include "rings/dsp/dsp.h" #include "rings/dsp/fm_voice.h" #include "rings/dsp/fx/reverb.h" #include "rings/dsp/limiter.h" #include "rings/dsp/note_filter.h" #include "rings/dsp/patch.h" #include "rings/dsp/performance_state.h" #include "rings/dsp/plucker.h" #include "rings/dsp/resonator.h" #include "rings/dsp/string.h" namespace rings { enum ResonatorModel { RESONATOR_MODEL_MODAL, RESONATOR_MODEL_SYMPATHETIC_STRING, RESONATOR_MODEL_STRING, // Bonus! RESONATOR_MODEL_FM_VOICE, RESONATOR_MODEL_SYMPATHETIC_STRING_QUANTIZED, RESONATOR_MODEL_LAST }; const int32_t kMaxPolyphony = 4; const int32_t kNumStrings = kMaxPolyphony * 2; class Part { public: Part() { } ~Part() { } void Init(); void Process( const PerformanceState& performance_state, const Patch& patch, const float* in, float* out, float* aux, size_t size); inline bool bypass() const { return bypass_; } inline void set_bypass(bool bypass) { bypass_ = bypass; } inline int32_t polyphony() const { return polyphony_; } inline void set_polyphony(int32_t polyphony) { int32_t old_polyphony = polyphony_; polyphony_ = std::min(polyphony, kMaxPolyphony); for (int32_t i = old_polyphony; i < polyphony_; ++i) { note_[i] = note_[0] + i * 0.05f; } dirty_ = true; } inline ResonatorModel model() const { return model_; } inline void set_model(ResonatorModel model) { if (model != model_) { model_ = model; dirty_ = true; } } private: void ConfigureResonators(); void RenderModalVoice( int32_t voice, const PerformanceState& performance_state, const Patch& patch, float frequency, float filter_cutoff, size_t size); void RenderStringVoice( int32_t voice, const PerformanceState& performance_state, const Patch& patch, float frequency, float filter_cutoff, size_t size); void RenderFMVoice( int32_t voice, const PerformanceState& performance_state, const Patch& patch, float frequency, float filter_cutoff, size_t size); inline float Squash(float x) const { if (x < 0.5f) { x *= 2.0f; x *= x; x *= x; x *= x; x *= x; x *= 0.5f; } else { x = 2.0f - 2.0f * x; x *= x; x *= x; x *= x; x *= x; x = 1.0f - 0.5f * x; } return x; } void ComputeSympatheticStringsNotes( float tonic, float note, float parameter, float* destination, size_t num_strings); bool bypass_; bool dirty_; ResonatorModel model_; int32_t num_voices_; int32_t active_voice_; uint32_t step_counter_; int32_t polyphony_; Resonator resonator_[kMaxPolyphony]; String string_[kNumStrings]; stmlib::CosineOscillator lfo_[kNumStrings]; FMVoice fm_voice_[kMaxPolyphony]; stmlib::Svf excitation_filter_[kMaxPolyphony]; stmlib::DCBlocker dc_blocker_[kMaxPolyphony]; Plucker plucker_[kMaxPolyphony]; float note_[kMaxPolyphony]; NoteFilter note_filter_; float resonator_input_[kMaxBlockSize]; float sympathetic_resonator_input_[kMaxBlockSize]; float noise_burst_buffer_[kMaxBlockSize]; float out_buffer_[kMaxBlockSize]; float aux_buffer_[kMaxBlockSize]; Limiter limiter_; static float model_gains_[RESONATOR_MODEL_LAST]; DISALLOW_COPY_AND_ASSIGN(Part); }; } // namespace rings #endif // RINGS_DSP_PART_H_ ================================================ FILE: lib/rings/dsp/patch.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Patch parameters. #ifndef RINGS_DSP_PATCH_H_ #define RINGS_DSP_PATCH_H_ namespace rings { struct Patch { float structure; float brightness; float damping; float position; }; } // namespace rings #endif // RINGS_DSP_PATCH_H_ ================================================ FILE: lib/rings/dsp/performance_state.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Note triggering state. #ifndef RINGS_DSP_PERFORMANCE_STATE_H_ #define RINGS_DSP_PERFORMANCE_STATE_H_ namespace rings { const int32_t kNumChords = 11; struct PerformanceState { bool strum; bool internal_exciter; bool internal_strum; bool internal_note; float tonic; float note; float fm; int32_t chord; }; } // namespace rings #endif // RINGS_DSP_PERFORMANCE_STATE_H_ ================================================ FILE: lib/rings/dsp/plucker.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Noise burst generator for Karplus-Strong synthesis. #ifndef RINGS_DSP_PLUCKER_H_ #define RINGS_DSP_PLUCKER_H_ #include "stmlib/stmlib.h" #include #include "stmlib/dsp/filter.h" #include "stmlib/dsp/delay_line.h" #include "stmlib/utils/random.h" namespace rings { class Plucker { public: Plucker() { } ~Plucker() { } void Init() { svf_.Init(); comb_filter_.Init(); remaining_samples_ = 0; comb_filter_period_ = 0.0f; } void Trigger(float frequency, float cutoff, float position) { float ratio = position * 0.9f + 0.05f; float comb_period = 1.0f / frequency * ratio; remaining_samples_ = static_cast(comb_period); while (comb_period >= 255.0f) { comb_period *= 0.5f; } comb_filter_period_ = comb_period; comb_filter_gain_ = (1.0f - position) * 0.8f; svf_.set_f_q(std::min(cutoff, 0.499f), 1.0f); } void Process(float* out, size_t size) { const float comb_gain = comb_filter_gain_; const float comb_delay = comb_filter_period_; for (size_t i = 0; i < size; ++i) { float in = 0.0f; if (remaining_samples_) { in = 2.0f * Random::GetFloat() - 1.0f; --remaining_samples_; } out[i] = in + comb_gain * comb_filter_.Read(comb_delay); comb_filter_.Write(out[i]); } svf_.Process(out, out, size); } private: stmlib::Svf svf_; stmlib::DelayLine comb_filter_; size_t remaining_samples_; float comb_filter_period_; float comb_filter_gain_; DISALLOW_COPY_AND_ASSIGN(Plucker); }; } // namespace rings #endif // RINGS_DSP_PLUCKER_H_ ================================================ FILE: lib/rings/dsp/resonator.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resonator. #include "rings/dsp/resonator.h" #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/cosine_oscillator.h" #include "stmlib/dsp/parameter_interpolator.h" #include "rings/resources.h" namespace rings { using namespace std; using namespace stmlib; void Resonator::Init() { for (int32_t i = 0; i < kMaxModes; ++i) { f_[i].Init(); } set_frequency(220.0f / kSampleRate); set_structure(0.25f); set_brightness(0.5f); set_damping(0.3f); set_position(0.999f); previous_position_ = 0.0f; set_resolution(kMaxModes); } int32_t Resonator::ComputeFilters() { float stiffness = Interpolate(lut_stiffness, structure_, 256.0f); float harmonic = frequency_; float stretch_factor = 1.0f; float q = 500.0f * Interpolate( lut_4_decades, damping_, 256.0f); float brightness_attenuation = 1.0f - structure_; // Reduces the range of brightness when structure is very low, to prevent // clipping. brightness_attenuation *= brightness_attenuation; brightness_attenuation *= brightness_attenuation; brightness_attenuation *= brightness_attenuation; float brightness = brightness_ * (1.0f - 0.2f * brightness_attenuation); float q_loss = brightness * (2.0f - brightness) * 0.85f + 0.15f; float q_loss_damping_rate = structure_ * (2.0f - structure_) * 0.1f; int32_t num_modes = 0; for (int32_t i = 0; i < min(kMaxModes, resolution_); ++i) { float partial_frequency = harmonic * stretch_factor; if (partial_frequency >= 0.49f) { partial_frequency = 0.49f; } else { num_modes = i + 1; } f_[i].set_f_q( partial_frequency, 1.0f + partial_frequency * q); stretch_factor += stiffness; if (stiffness < 0.0f) { // Make sure that the partials do not fold back into negative frequencies. stiffness *= 0.93f; } else { // This helps adding a few extra partials in the highest frequencies. stiffness *= 0.98f; } // This prevents the highest partials from decaying too fast. q_loss += q_loss_damping_rate * (1.0f - q_loss); harmonic += frequency_; q *= q_loss; } return num_modes; } void Resonator::Process(const float* in, float* out, float* aux, size_t size) { int32_t num_modes = ComputeFilters(); ParameterInterpolator position(&previous_position_, position_, size); while (size--) { CosineOscillator amplitudes; amplitudes.Init(position.Next()); float input = *in++ * 0.125f; float odd = 0.0f; float even = 0.0f; amplitudes.Start(); for (int32_t i = 0; i < num_modes;) { odd += amplitudes.Next() * f_[i++].Process(input); even += amplitudes.Next() * f_[i++].Process(input); } *out++ = odd; *aux++ = even; } } } // namespace rings ================================================ FILE: lib/rings/dsp/resonator.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resonator. #ifndef RINGS_DSP_RESONATOR_H_ #define RINGS_DSP_RESONATOR_H_ #include "stmlib/stmlib.h" #include #include "rings/dsp/dsp.h" #include "stmlib/dsp/filter.h" #include "stmlib/dsp/delay_line.h" namespace rings { const int32_t kMaxModes = 64; class Resonator { public: Resonator() { } ~Resonator() { } void Init(); void Process( const float* in, float* out, float* aux, size_t size); inline void set_frequency(float frequency) { frequency_ = frequency; } inline void set_structure(float structure) { structure_ = structure; } inline void set_brightness(float brightness) { brightness_ = brightness; } inline void set_damping(float damping) { damping_ = damping; } inline void set_position(float position) { position_ = position; } inline void set_resolution(int32_t resolution) { resolution -= resolution & 1; // Must be even! resolution_ = std::min(resolution, kMaxModes); } private: int32_t ComputeFilters(); float frequency_; float structure_; float brightness_; float position_; float previous_position_; float damping_; int32_t resolution_; stmlib::Svf f_[kMaxModes]; DISALLOW_COPY_AND_ASSIGN(Resonator); }; } // namespace rings #endif // RINGS_DSP_RESONATOR_H_ ================================================ FILE: lib/rings/dsp/string.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Comb filter / KS string. #include "rings/dsp/string.h" #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/units.h" #include "stmlib/utils/random.h" #include "rings/resources.h" namespace rings { using namespace std; using namespace stmlib; void String::Init(bool enable_dispersion) { enable_dispersion_ = enable_dispersion; string_.Init(); stretch_.Init(); fir_damping_filter_.Init(); iir_damping_filter_.Init(); set_frequency(220.0f / kSampleRate); set_dispersion(0.25f); set_brightness(0.5f); set_damping(0.3f); set_position(0.8f); delay_ = 1.0f / frequency_; clamped_position_ = 0.0f; previous_dispersion_ = 0.0f; dispersion_noise_ = 0.0f; curved_bridge_ = 0.0f; previous_damping_compensation_ = 0.0f; out_sample_[0] = out_sample_[1] = 0.0f; aux_sample_[0] = aux_sample_[1] = 0.0f; dc_blocker_.Init(1.0f - 20.0f / kSampleRate); } template void String::ProcessInternal( const float* in, float* out, float* aux, size_t size) { float delay = 1.0f / frequency_; CONSTRAIN(delay, 4.0f, kDelayLineSize - 4.0f); // If there is not enough delay time in the delay line, we play at the // lowest possible note and we upsample on the fly with a shitty linear // interpolator. We don't care because it's a corner case (f0 < 11.7Hz) float src_ratio = delay * frequency_; if (src_ratio >= 0.9999f) { // When we are above 11.7 Hz, we make sure that the linear interpolator // does not get in the way. src_phase_ = 1.0f; src_ratio = 1.0f; } float clamped_position = 0.5f - 0.98f * fabsf(position_ - 0.5f); // Linearly interpolate all comb-related CV parameters for each sample. ParameterInterpolator delay_modulation( &delay_, delay, size); ParameterInterpolator position_modulation( &clamped_position_, clamped_position, size); ParameterInterpolator dispersion_modulation( &previous_dispersion_, dispersion_, size); // For damping/absorption, the interpolation is done in the filter code. float lf_damping = damping_ * (2.0f - damping_); float rt60 = 0.07f * SemitonesToRatio(lf_damping * 96.0f) * kSampleRate; float rt60_base_2_12 = max(-120.0f * delay / src_ratio / rt60, -127.0f); float damping_coefficient = SemitonesToRatio(rt60_base_2_12); float brightness = brightness_ * brightness_; float noise_filter = SemitonesToRatio((brightness_ - 1.0f) * 48.0f); float damping_cutoff = min( 24.0f + damping_ * damping_ * 48.0f + brightness_ * brightness_ * 24.0f, 84.0f); float damping_f = min(frequency_ * SemitonesToRatio(damping_cutoff), 0.499f); // Crossfade to infinite decay. if (damping_ >= 0.95f) { float to_infinite = 20.0f * (damping_ - 0.95f); damping_coefficient += to_infinite * (1.0f - damping_coefficient); brightness += to_infinite * (1.0f - brightness); damping_f += to_infinite * (0.4999f - damping_f); damping_cutoff += to_infinite * (128.0f - damping_cutoff); } fir_damping_filter_.Configure(damping_coefficient, brightness, size); iir_damping_filter_.set_f_q(damping_f, 0.5f); ParameterInterpolator damping_compensation_modulation( &previous_damping_compensation_, 1.0f - Interpolate(lut_svf_shift, damping_cutoff, 1.0f), size); while (size--) { src_phase_ += src_ratio; if (src_phase_ > 1.0f) { src_phase_ -= 1.0f; float delay = delay_modulation.Next(); float comb_delay = delay * position_modulation.Next(); #ifndef MIC_W delay *= damping_compensation_modulation.Next(); // IIR delay. #endif // MIC_W delay -= 1.0f; // FIR delay. float s = 0.0f; if (enable_dispersion) { float noise = 2.0f * Random::GetFloat() - 1.0f; noise *= 1.0f / (0.2f + noise_filter); dispersion_noise_ += noise_filter * (noise - dispersion_noise_); float dispersion = dispersion_modulation.Next(); float stretch_point = dispersion <= 0.0f ? 0.0f : dispersion * (2.0f - dispersion) * 0.475f; float noise_amount = dispersion > 0.75f ? 4.0f * (dispersion - 0.75f) : 0.0f; float bridge_curving = dispersion < 0.0f ? -dispersion : 0.0f; noise_amount = noise_amount * noise_amount * 0.025f; float ac_blocking_amount = bridge_curving; bridge_curving = bridge_curving * bridge_curving * 0.01f; float ap_gain = -0.618f * dispersion / (0.15f + fabsf(dispersion)); float delay_fm = 1.0f; delay_fm += dispersion_noise_ * noise_amount; delay_fm -= curved_bridge_ * bridge_curving; delay *= delay_fm; float ap_delay = delay * stretch_point; float main_delay = delay - ap_delay; if (ap_delay >= 4.0f && main_delay >= 4.0f) { s = string_.ReadHermite(main_delay); s = stretch_.Allpass(s, ap_delay, ap_gain); } else { s = string_.ReadHermite(delay); } float s_ac = s; dc_blocker_.Process(&s_ac, 1); s += ac_blocking_amount * (s_ac - s); float value = fabsf(s) - 0.025f; float sign = s > 0.0f ? 1.0f : -1.5f; curved_bridge_ = (fabsf(value) + value) * sign; } else { s = string_.ReadHermite(delay); } s += *in; // When f0 < 11.7 Hz, causes ugly bitcrushing on the input! s = fir_damping_filter_.Process(s); #ifndef MIC_W s = iir_damping_filter_.Process(s); #endif // MIC_W string_.Write(s); out_sample_[1] = out_sample_[0]; aux_sample_[1] = aux_sample_[0]; out_sample_[0] = s; aux_sample_[0] = string_.Read(comb_delay); } *out++ += Crossfade(out_sample_[1], out_sample_[0], src_phase_); *aux++ += Crossfade(aux_sample_[1], aux_sample_[0], src_phase_); in++; } } void String::Process(const float* in, float* out, float* aux, size_t size) { if (enable_dispersion_) { ProcessInternal(in, out, aux, size); } else { ProcessInternal(in, out, aux, size); } } } // namespace rings ================================================ FILE: lib/rings/dsp/string.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Comb filter / KS string. #ifndef RINGS_DSP_STRING_H_ #define RINGS_DSP_STRING_H_ #include "stmlib/stmlib.h" #include #include "stmlib/dsp/delay_line.h" #include "stmlib/dsp/filter.h" #include "rings/dsp/dsp.h" namespace rings { const size_t kDelayLineSize = 2048; class DampingFilter { public: DampingFilter() { } ~DampingFilter() { } void Init() { x_ = 0.0f; x__ = 0.0f; brightness_ = 0.0f; brightness_increment_ = 0.0f; damping_ = 0.0f; damping_increment_ = 0.0f; } inline void Configure(float damping, float brightness, size_t size) { if (!size) { damping_ = damping; brightness_ = brightness; damping_increment_ = 0.0f; brightness_increment_ = 0.0f; } else { float step = 1.0f / static_cast(size); damping_increment_ = (damping - damping_) * step; brightness_increment_ = (brightness - brightness_) * step; } } inline float Process(float x) { float h0 = (1.0f + brightness_) * 0.5f; float h1 = (1.0f - brightness_) * 0.25f; float y = damping_ * (h0 * x_ + h1 * (x + x__)); x__ = x_; x_ = x; brightness_ += brightness_increment_; damping_ += damping_increment_; return y; } private: float x_; float x__; float brightness_; float brightness_increment_; float damping_; float damping_increment_; DISALLOW_COPY_AND_ASSIGN(DampingFilter); }; typedef stmlib::DelayLine StringDelayLine; typedef stmlib::DelayLine StiffnessDelayLine; class String { public: String() { } ~String() { } void Init(bool enable_dispersion); void Process(const float* in, float* out, float* aux, size_t size); inline void set_frequency(float frequency) { frequency_ = frequency; } inline void set_frequency(float frequency, float coefficient) { frequency_ += coefficient * (frequency - frequency_); } inline void set_dispersion(float dispersion) { dispersion_ = dispersion; } inline void set_brightness(float brightness) { brightness_ = brightness; } inline void set_damping(float damping) { damping_ = damping; } inline void set_position(float position) { position_ = position; } inline StringDelayLine* mutable_string() { return &string_; } private: template void ProcessInternal(const float* in, float* out, float* aux, size_t size); float frequency_; float dispersion_; float brightness_; float damping_; float position_; float delay_; float clamped_position_; float previous_dispersion_; float previous_damping_compensation_; bool enable_dispersion_; bool enable_iir_damping_; float dispersion_noise_; // Very crappy linear interpolation upsampler used for low pitches that // do not fit the delay line. Rarely used. float src_phase_; float out_sample_[2]; float aux_sample_[2]; float curved_bridge_; StringDelayLine string_; StiffnessDelayLine stretch_; DampingFilter fir_damping_filter_; stmlib::Svf iir_damping_filter_; stmlib::DCBlocker dc_blocker_; DISALLOW_COPY_AND_ASSIGN(String); }; } // namespace rings #endif // RINGS_DSP_STRING_H_ ================================================ FILE: lib/rings/dsp/string_synth_envelope.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // AD envelope for the string synth. #ifndef ELEMENTS_DSP_STRING_SYNTH_ENVELOPE_H_ #define ELEMENTS_DSP_STRING_SYNTH_ENVELOPE_H_ #include "stmlib/stmlib.h" namespace rings { enum EnvelopeShape { ENVELOPE_SHAPE_LINEAR, ENVELOPE_SHAPE_QUARTIC }; enum EnvelopeFlags { ENVELOPE_FLAG_RISING_EDGE = 1, ENVELOPE_FLAG_FALLING_EDGE = 2, ENVELOPE_FLAG_GATE = 4 }; class StringSynthEnvelope { public: StringSynthEnvelope() { } ~StringSynthEnvelope() { } void Init() { set_ad(0.1f, 0.001f); segment_ = num_segments_; phase_ = 0.0f; start_value_ = 0.0f; value_ = 0.0f; } inline float Process(uint8_t flags) { if (flags & ENVELOPE_FLAG_RISING_EDGE) { start_value_ = segment_ == num_segments_ ? level_[0] : value_; segment_ = 0; phase_ = 0.0f; } else if (flags & ENVELOPE_FLAG_FALLING_EDGE && sustain_point_) { start_value_ = value_; segment_ = sustain_point_; phase_ = 0.0f; } else if (phase_ >= 1.0f) { start_value_ = level_[segment_ + 1]; ++segment_; phase_ = 0.0f; } bool done = segment_ == num_segments_; bool sustained = sustain_point_ && segment_ == sustain_point_ && flags & ENVELOPE_FLAG_GATE; float phase_increment = 0.0f; if (!sustained && !done) { phase_increment = rate_[segment_]; } float t = phase_; if (shape_[segment_] == ENVELOPE_SHAPE_QUARTIC) { t = 1.0f - t; t *= t; t *= t; t = 1.0f - t; } phase_ += phase_increment; value_ = start_value_ + (level_[segment_ + 1] - start_value_) * t; return value_; } inline void set_ad(float attack, float decay) { num_segments_ = 2; sustain_point_ = 0; level_[0] = 0.0f; level_[1] = 1.0f; level_[2] = 0.0f; rate_[0] = attack; rate_[1] = decay; shape_[0] = ENVELOPE_SHAPE_LINEAR; shape_[1] = ENVELOPE_SHAPE_QUARTIC; } inline void set_ar(float attack, float decay) { num_segments_ = 2; sustain_point_ = 1; level_[0] = 0.0f; level_[1] = 1.0f; level_[2] = 0.0f; rate_[0] = attack; rate_[1] = decay; shape_[0] = ENVELOPE_SHAPE_LINEAR; shape_[1] = ENVELOPE_SHAPE_LINEAR; } private: float level_[4]; float rate_[4]; EnvelopeShape shape_[4]; int16_t segment_; float start_value_; float value_; float phase_; uint16_t num_segments_; uint16_t sustain_point_; DISALLOW_COPY_AND_ASSIGN(StringSynthEnvelope); }; } // namespace rings #endif // ELEMENTS_DSP_STRING_SYNTH_ENVELOPE_H_ ================================================ FILE: lib/rings/dsp/string_synth_oscillator.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Polyblep oscillator used for string synth synthesis. #ifndef RINGS_DSP_STRING_SYNTH_OSCILLATOR_H_ #define RINGS_DSP_STRING_SYNTH_OSCILLATOR_H_ #include "stmlib/stmlib.h" #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/parameter_interpolator.h" #include "stmlib/dsp/units.h" namespace rings { using namespace stmlib; enum OscillatorShape { OSCILLATOR_SHAPE_BRIGHT_SQUARE, OSCILLATOR_SHAPE_SQUARE, OSCILLATOR_SHAPE_DARK_SQUARE, OSCILLATOR_SHAPE_TRIANGLE, }; class StringSynthOscillator { public: StringSynthOscillator() { } ~StringSynthOscillator() { } inline void Init() { phase_ = 0.0f; phase_increment_ = 0.01f; filter_state_ = 0.0f; high_ = false; next_sample_ = 0.0f; next_sample_saw_ = 0.0f; gain_ = 0.0f; gain_saw_ = 0.0f; } template inline void Render( float target_increment, float target_gain, float target_gain_saw, float* out, size_t size) { // Cut harmonics above 12kHz, and low-pass harmonics above 8kHz to clear // highs if (target_increment >= 0.17f) { target_gain *= 1.0f - (target_increment - 0.17f) * 12.5f; if (target_increment >= 0.25f) { return; } } float phase = phase_; ParameterInterpolator phase_increment( &phase_increment_, target_increment, size); ParameterInterpolator gain(&gain_, target_gain, size); ParameterInterpolator gain_saw(&gain_saw_, target_gain_saw, size); float next_sample = next_sample_; float next_sample_saw = next_sample_saw_; float filter_state = filter_state_; bool high = high_; while (size--) { float this_sample = next_sample; float this_sample_saw = next_sample_saw; next_sample = 0.0f; next_sample_saw = 0.0f; float increment = interpolate_pitch ? phase_increment.Next() : target_increment; phase += increment; float sample = 0.0f; const float pw = 0.5f; if (!high && phase >= pw) { float t = (phase - pw) / increment; this_sample += ThisBlepSample(t); next_sample += NextBlepSample(t); high = true; } if (phase >= 1.0f) { phase -= 1.0f; float t = phase / increment; float a = ThisBlepSample(t); float b = NextBlepSample(t); this_sample -= a; next_sample -= b; this_sample_saw -= a; next_sample_saw -= b; high = false; } next_sample += phase < pw ? 0.0f : 1.0f; next_sample_saw += phase; if (shape == OSCILLATOR_SHAPE_TRIANGLE) { const float integrator_coefficient = increment * 0.125f; this_sample = 64.0f * (this_sample - 0.5f); filter_state += integrator_coefficient * (this_sample - filter_state); sample = filter_state; } else if (shape == OSCILLATOR_SHAPE_DARK_SQUARE) { const float integrator_coefficient = increment * 2.0f; this_sample = 4.0f * (this_sample - 0.5f); filter_state += integrator_coefficient * (this_sample - filter_state); sample = filter_state; } else if (shape == OSCILLATOR_SHAPE_BRIGHT_SQUARE) { const float integrator_coefficient = increment * 2.0f; this_sample = 2.0f * this_sample - 1.0f; filter_state += integrator_coefficient * (this_sample - filter_state); sample = (this_sample - filter_state) * 0.5f; } else { this_sample = 2.0f * this_sample - 1.0f; sample = this_sample; } this_sample_saw = 2.0f * this_sample_saw - 1.0f; *out++ += sample * gain.Next() + this_sample_saw * gain_saw.Next(); } high_ = high; phase_ = phase; next_sample_ = next_sample; next_sample_saw_ = next_sample_saw; filter_state_ = filter_state; } private: static inline float ThisBlepSample(float t) { return 0.5f * t * t; } static inline float NextBlepSample(float t) { t = 1.0f - t; return -0.5f * t * t; } bool high_; float phase_; float phase_increment_; float next_sample_; float next_sample_saw_; float filter_state_; float gain_; float gain_saw_; DISALLOW_COPY_AND_ASSIGN(StringSynthOscillator); }; } // namespace rings #endif // RINGS_DSP_STRING_SYNTH_OSCILLATOR_H_ ================================================ FILE: lib/rings/dsp/string_synth_part.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // String synth part. #include "rings/dsp/string_synth_part.h" #include "rings/dsp/dsp.h" namespace rings { using namespace std; using namespace stmlib; void StringSynthPart::Init(uint16_t* reverb_buffer) { active_group_ = 0; acquisition_delay_ = 0; polyphony_ = 1; fx_type_ = FX_ENSEMBLE; for (int32_t i = 0; i < kStringSynthVoices; ++i) { voice_[i].Init(); } for (int32_t i = 0; i < kMaxStringSynthPolyphony; ++i) { group_[i].tonic = 0.0f; group_[i].envelope.Init(); } for (int32_t i = 0; i < kNumFormants; ++i) { formant_filter_[i].Init(); } limiter_.Init(); reverb_.Init(reverb_buffer); chorus_.Init(reverb_buffer); ensemble_.Init(reverb_buffer); note_filter_.Init( kSampleRate / kMaxBlockSize, 0.001f, // Lag time with a sharp edge on the V/Oct input or trigger. 0.005f, // Lag time after the trigger has been received. 0.050f, // Time to transition from reactive to filtered. 0.004f); // Prevent a sharp edge to partly leak on the previous voice. } const int32_t kRegistrationTableSize = 11; const float registrations[kRegistrationTableSize][kNumHarmonics * 2] = { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f }, { 1.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f }, { 1.0f, 0.5f, 1.0f, 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, { 0.0f, 0.5f, 1.0f, 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, }; void StringSynthPart::ComputeRegistration( float gain, float registration, float* amplitudes) { registration *= (kRegistrationTableSize - 1.001f); MAKE_INTEGRAL_FRACTIONAL(registration); float total = 0.0f; for (int32_t i = 0; i < kNumHarmonics * 2; ++i) { float a = registrations[registration_integral][i]; float b = registrations[registration_integral + 1][i]; amplitudes[i] = a + (b - a) * registration_fractional; total += amplitudes[i]; } for (int32_t i = 0; i < kNumHarmonics * 2; ++i) { amplitudes[i] = gain * amplitudes[i] / total; } } #ifdef BRYAN_CHORDS // Chord table by Bryan Noll: // - more compact, leaving room for a bass // - more frequent note changes between adjacent chords. // - dropped fifth. const float chords[kMaxStringSynthPolyphony][kNumChords][kMaxChordSize] = { { { -12.0f, -0.01f, 0.0f, 0.01f, 0.02f, 11.99f, 12.0f, 24.0f }, // OCT { -12.0f, -5.01f, -5.0f, 0.0f, 7.0f, 12.0f, 19.0f, 24.0f }, // 5 { -12.0f, -5.0f, 0.0f, 5.0f, 7.0f, 12.0f, 17.0f, 24.0f }, // sus4 { -12.0f, -5.0f, 0.0f, 0.01f, 3.0f, 12.0f, 19.0f, 24.0f }, // m { -12.0f, -5.01f, -5.0f, 0.0f, 3.0f, 10.0f, 19.0f, 24.0f }, // m7 { -12.0f, -5.0f, 0.0f, 3.0f, 10.0f, 14.0f, 19.0f, 24.0f }, // m9 { -12.0f, -5.01f, -5.0f, 0.0f, 3.0f, 10.0f, 17.0f, 24.0f }, // m11 { -12.0f, -5.0f, 0.0f, 2.0f, 9.0f, 16.0f, 19.0f, 24.0f }, // 69 { -12.0f, -5.0f, 0.0f, 4.0f, 11.0f, 14.0f, 19.0f, 24.0f }, // M9 { -12.0f, -5.0f, 0.0f, 4.0f, 7.0f, 11.0f, 19.0f, 24.0f }, // M7 { -12.0f, -5.0f, 0.0f, 4.0f, 7.0f, 12.0f, 19.0f, 24.0f }, // M }, { { -12.0f, -0.01f, 0.0f, 0.01f, 12.0f, 12.01f }, // OCT { -12.0f, -5.01f, -5.0f, 0.0f, 7.0f, 12.0f }, // 5 { -12.0f, -5.0f, 0.0f, 5.0f, 7.0f, 12.0f }, // sus4 { -12.0f, -5.0f, 0.0f, 0.01f, 3.0f, 12.0f }, // m { -12.0f, -5.01f, -5.0f, 0.0f, 3.0f, 10.0f }, // m7 { -12.0f, -5.0f, 0.0f, 3.0f, 10.0f, 14.0f }, // m9 { -12.0f, -5.0f, 0.0f, 3.0f, 10.0f, 17.0f }, // m11 { -12.0f, -5.0f, 0.0f, 2.0f, 9.0f, 16.0f }, // 69 { -12.0f, -5.0f, 0.0f, 4.0f, 11.0f, 14.0f }, // M9 { -12.0f, -5.0f, 0.0f, 4.0f, 7.0f, 11.0f }, // M7 { -12.0f, -5.0f, 0.0f, 4.0f, 7.0f, 12.0f }, // M }, { { -12.0f, 0.0f, 0.01f, 12.0f }, // OCT { -12.0f, 6.99f, 7.0f, 12.0f }, // 5 { -12.0f, 5.0f, 7.0f, 12.0f }, // sus4 { -12.0f, 3.0f, 11.99f, 12.0f }, // m { -12.0f, 3.0f, 9.99f, 10.0f }, // m7 { -12.0f, 3.0f, 10.0f, 14.0f }, // m9 { -12.0f, 3.0f, 10.0f, 17.0f }, // m11 { -12.0f, 2.0f, 9.0f, 16.0f }, // 69 { -12.0f, 4.0f, 11.0f, 14.0f }, // M9 { -12.0f, 4.0f, 7.0f, 11.0f }, // M7 { -12.0f, 4.0f, 7.0f, 12.0f }, // M }, { { 0.0f, 0.01f, 12.0f }, // OCT { 0.0f, 7.0f, 12.0f }, // 5 { 5.0f, 7.0f, 12.0f }, // sus4 { 0.0f, 3.0f, 12.0f }, // m { 0.0f, 3.0f, 10.0f }, // m7 { 3.0f, 10.0f, 14.0f }, // m9 { 3.0f, 10.0f, 17.0f }, // m11 { 2.0f, 9.0f, 16.0f }, // 69 { 4.0f, 11.0f, 14.0f }, // M9 { 4.0f, 7.0f, 11.0f }, // M7 { 4.0f, 7.0f, 12.0f }, // M } }; #else // Original chord table: // - wider, occupies more room in the spectrum. // - minimum number of note changes between adjacent chords. // - consistant with the chord table used for the sympathetic strings model. const float chords[kMaxStringSynthPolyphony][kNumChords][kMaxChordSize] = { { { -24.0f, -12.0f, 0.0f, 0.01f, 0.02f, 11.99f, 12.0f, 24.0f }, { -24.0f, -12.0f, 0.0f, 3.0f, 7.0f, 10.0f, 19.0f, 24.0f }, { -24.0f, -12.0f, 0.0f, 3.0f, 7.0f, 12.0f, 19.0f, 24.0f }, { -24.0f, -12.0f, 0.0f, 3.0f, 7.0f, 14.0f, 19.0f, 24.0f }, { -24.0f, -12.0f, 0.0f, 3.0f, 7.0f, 17.0f, 19.0f, 24.0f }, { -24.0f, -12.0f, 0.0f, 6.99f, 7.0f, 18.99f, 19.0f, 24.0f }, { -24.0f, -12.0f, 0.0f, 4.0f, 7.0f, 17.0f, 19.0f, 24.0f }, { -24.0f, -12.0f, 0.0f, 4.0f, 7.0f, 14.0f, 19.0f, 24.0f }, { -24.0f, -12.0f, 0.0f, 4.0f, 7.0f, 12.0f, 19.0f, 24.0f }, { -24.0f, -12.0f, 0.0f, 4.0f, 7.0f, 11.0f, 19.0f, 24.0f }, { -24.0f, -12.0f, 0.0f, 5.0f, 7.0f, 12.0f, 17.0f, 24.0f }, }, { { -24.0f, -12.0f, 0.0f, 0.01f, 12.0f, 12.01f }, { -24.0f, -12.0f, 0.0f, 3.00f, 7.0f, 10.0f }, { -24.0f, -12.0f, 0.0f, 3.00f, 7.0f, 12.0f }, { -24.0f, -12.0f, 0.0f, 3.00f, 7.0f, 14.0f }, { -24.0f, -12.0f, 0.0f, 3.00f, 7.0f, 17.0f }, { -24.0f, -12.0f, 0.0f, 6.99f, 12.0f, 19.0f }, { -24.0f, -12.0f, 0.0f, 4.00f, 7.0f, 17.0f }, { -24.0f, -12.0f, 0.0f, 4.00f, 7.0f, 14.0f }, { -24.0f, -12.0f, 0.0f, 4.00f, 7.0f, 12.0f }, { -24.0f, -12.0f, 0.0f, 4.00f, 7.0f, 11.0f }, { -24.0f, -12.0f, 0.0f, 5.00f, 7.0f, 12.0f }, }, { { -12.0f, 0.0f, 0.01f, 12.0f }, { -12.0f, 3.0f, 7.0f, 10.0f }, { -12.0f, 3.0f, 7.0f, 12.0f }, { -12.0f, 3.0f, 7.0f, 14.0f }, { -12.0f, 3.0f, 7.0f, 17.0f }, { -12.0f, 7.0f, 12.0f, 19.0f }, { -12.0f, 4.0f, 7.0f, 17.0f }, { -12.0f, 4.0f, 7.0f, 14.0f }, { -12.0f, 4.0f, 7.0f, 12.0f }, { -12.0f, 4.0f, 7.0f, 11.0f }, { -12.0f, 5.0f, 7.0f, 12.0f }, }, { { 0.0f, 0.01f, 12.0f }, { 0.0f, 3.0f, 10.0f }, { 0.0f, 3.0f, 7.0f }, { 0.0f, 3.0f, 14.0f }, { 0.0f, 3.0f, 17.0f }, { 0.0f, 7.0f, 19.0f }, { 0.0f, 4.0f, 17.0f }, { 0.0f, 4.0f, 14.0f }, { 0.0f, 4.0f, 7.0f }, { 0.0f, 4.0f, 11.0f }, { 0.0f, 5.0f, 7.0f }, } }; #endif // BRYAN_CHORDS void StringSynthPart::ProcessEnvelopes( float shape, uint8_t* flags, float* values) { float decay = shape; float attack = 0.0f; if (shape < 0.5f) { attack = 0.0f; } else { attack = (shape - 0.5f) * 2.0f; } // Convert the arbitrary values to actual units. float period = kSampleRate / kMaxBlockSize; float attack_time = SemitonesToRatio(attack * 96.0f) * 0.005f * period; // float decay_time = SemitonesToRatio(decay * 96.0f) * 0.125f * period; float decay_time = SemitonesToRatio(decay * 84.0f) * 0.180f * period; float attack_rate = 1.0f / attack_time; float decay_rate = 1.0f / decay_time; for (int32_t i = 0; i < polyphony_; ++i) { float drone = shape < 0.98f ? 0.0f : (shape - 0.98f) * 55.0f; if (drone >= 1.0f) drone = 1.0f; group_[i].envelope.set_ad(attack_rate, decay_rate); float value = group_[i].envelope.Process(flags[i]); values[i] = value + (1.0f - value) * drone; } } const int32_t kFormantTableSize = 5; const float formants[kFormantTableSize][kNumFormants] = { { 700, 1100, 2400 }, { 500, 1300, 1700 }, { 400, 2000, 2500 }, { 600, 800, 2400 }, { 300, 900, 2200 }, }; void StringSynthPart::ProcessFormantFilter( float vowel, float shift, float resonance, float* out, float* aux, size_t size) { for (size_t i = 0; i < size; ++i) { filter_in_buffer_[i] = out[i] + aux[i]; } fill(&out[0], &out[size], 0.0f); fill(&aux[0], &aux[size], 0.0f); vowel *= (kFormantTableSize - 1.001f); MAKE_INTEGRAL_FRACTIONAL(vowel); for (int32_t i = 0; i < kNumFormants; ++i) { float a = formants[vowel_integral][i]; float b = formants[vowel_integral + 1][i]; float f = a + (b - a) * vowel_fractional; f *= shift; formant_filter_[i].set_f_q(f / kSampleRate, resonance); formant_filter_[i].Process( filter_in_buffer_, filter_out_buffer_, size); const float pan = i * 0.3f + 0.2f; for (size_t j = 0; j < size; ++j) { out[j] += filter_out_buffer_[j] * pan * 0.5f; aux[j] += filter_out_buffer_[j] * (1.0f - pan) * 0.5f; } } } struct ChordNote { float note; float amplitude; }; void StringSynthPart::Process( const PerformanceState& performance_state, const Patch& patch, const float* in, float* out, float* aux, size_t size) { // Assign note to a voice. uint8_t envelope_flags[kMaxStringSynthPolyphony]; fill(&envelope_flags[0], &envelope_flags[polyphony_], 0); note_filter_.Process(performance_state.note, performance_state.strum); if (performance_state.strum) { group_[active_group_].tonic = note_filter_.stable_note(); envelope_flags[active_group_] = ENVELOPE_FLAG_FALLING_EDGE; active_group_ = (active_group_ + 1) % polyphony_; envelope_flags[active_group_] = ENVELOPE_FLAG_RISING_EDGE; acquisition_delay_ = 3; } if (acquisition_delay_) { --acquisition_delay_; } else { group_[active_group_].tonic = note_filter_.note(); group_[active_group_].chord = performance_state.chord; group_[active_group_].structure = patch.structure; envelope_flags[active_group_] |= ENVELOPE_FLAG_GATE; } // Process envelopes. float envelope_values[kMaxStringSynthPolyphony]; ProcessEnvelopes(patch.damping, envelope_flags, envelope_values); copy(&in[0], &in[size], &aux[0]); copy(&in[0], &in[size], &out[0]); int32_t chord_size = min(kStringSynthVoices / polyphony_, kMaxChordSize); for (int32_t group = 0; group < polyphony_; ++group) { ChordNote notes[kMaxChordSize]; float harmonics[kNumHarmonics * 2]; ComputeRegistration( envelope_values[group] * 0.25f, patch.brightness, harmonics); // Note enough polyphony for smooth transition between chords. for (int32_t i = 0; i < chord_size; ++i) { float n = chords[polyphony_ - 1][group_[group].chord][i]; notes[i].note = n; notes[i].amplitude = n >= 0.0f && n <= 17.0f ? 1.0f : 0.7f; } for (int32_t chord_note = 0; chord_note < chord_size; ++chord_note) { float note = 0.0f; note += group_[group].tonic; note += performance_state.tonic; note += performance_state.fm; note += notes[chord_note].note; float amplitudes[kNumHarmonics * 2]; for (int32_t i = 0; i < kNumHarmonics * 2; ++i) { amplitudes[i] = notes[chord_note].amplitude * harmonics[i]; } // Fold truncated harmonics. size_t num_harmonics = polyphony_ >= 2 && chord_note < 2 ? kNumHarmonics - 1 : kNumHarmonics; for (int32_t i = num_harmonics; i < kNumHarmonics; ++i) { amplitudes[2 * (num_harmonics - 1)] += amplitudes[2 * i]; amplitudes[2 * (num_harmonics - 1) + 1] += amplitudes[2 * i + 1]; } float frequency = SemitonesToRatio(note - 69.0f) * a3; voice_[group * chord_size + chord_note].Render( frequency, amplitudes, num_harmonics, (group + chord_note) & 1 ? out : aux, size); } } if (clear_fx_) { reverb_.Clear(); clear_fx_ = false; } switch (fx_type_) { case FX_FORMANT: case FX_FORMANT_2: ProcessFormantFilter( patch.position, fx_type_ == FX_FORMANT ? 1.0f : 1.1f, fx_type_ == FX_FORMANT ? 25.0f : 10.0f, out, aux, size); break; case FX_CHORUS: chorus_.set_amount(patch.position); chorus_.set_depth(0.15f + 0.5f * patch.position); chorus_.Process(out, aux, size); break; case FX_ENSEMBLE: ensemble_.set_amount(patch.position * (2.0f - patch.position)); ensemble_.set_depth(0.2f + 0.8f * patch.position * patch.position); ensemble_.Process(out, aux, size); break; case FX_REVERB: case FX_REVERB_2: reverb_.set_amount(patch.position * 0.5f); reverb_.set_diffusion(0.625f); reverb_.set_time(fx_type_ == FX_REVERB ? (0.5f + 0.49f * patch.position) : (0.3f + 0.6f * patch.position)); reverb_.set_input_gain(0.2f); reverb_.set_lp(fx_type_ == FX_REVERB ? 0.3f : 0.6f); reverb_.Process(out, aux, size); break; default: break; } // Prevent main signal cancellation when EVEN gets summed with ODD through // normalization. for (size_t i = 0; i < size; ++i) { aux[i] = -aux[i]; } limiter_.Process(out, aux, size, 1.0f); } } // namespace rings ================================================ FILE: lib/rings/dsp/string_synth_part.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Part for the string synth easter egg. #ifndef RINGS_DSP_STRING_SYNTH_PART_H_ #define RINGS_DSP_STRING_SYNTH_PART_H_ #include "stmlib/stmlib.h" #include "stmlib/dsp/filter.h" #include "rings/dsp/dsp.h" #include "rings/dsp/fx/chorus.h" #include "rings/dsp/fx/ensemble.h" #include "rings/dsp/fx/reverb.h" #include "rings/dsp/limiter.h" #include "rings/dsp/note_filter.h" #include "rings/dsp/patch.h" #include "rings/dsp/performance_state.h" #include "rings/dsp/string_synth_envelope.h" #include "rings/dsp/string_synth_voice.h" namespace rings { const int32_t kMaxStringSynthPolyphony = 4; const int32_t kStringSynthVoices = 12; const int32_t kMaxChordSize = 8; const int32_t kNumHarmonics = 3; const int32_t kNumFormants = 3; enum FxType { FX_FORMANT, FX_CHORUS, FX_REVERB, FX_FORMANT_2, FX_ENSEMBLE, FX_REVERB_2, FX_LAST }; struct VoiceGroup { float tonic; StringSynthEnvelope envelope; int32_t chord; float structure; }; class StringSynthPart { public: StringSynthPart() { } ~StringSynthPart() { } void Init(uint16_t* reverb_buffer); void Process( const PerformanceState& performance_state, const Patch& patch, const float* in, float* out, float* aux, size_t size); inline void set_polyphony(int32_t polyphony) { int32_t old_polyphony = polyphony_; polyphony_ = std::min(polyphony, kMaxStringSynthPolyphony); for (int32_t i = old_polyphony; i < polyphony_; ++i) { group_[i].tonic = group_[0].tonic + i * 0.01f; } if (active_group_ >= polyphony_) { active_group_ = 0; } } inline void set_fx(FxType fx_type) { if ((fx_type % 3) != (fx_type_ % 3)) { clear_fx_ = true; } fx_type_ = fx_type; } private: void ProcessEnvelopes(float shape, uint8_t* flags, float* values); void ComputeRegistration(float gain, float registration, float* amplitudes); void ProcessFormantFilter(float vowel, float shift, float resonance, float* out, float* aux, size_t size); StringSynthVoice voice_[kStringSynthVoices]; VoiceGroup group_[kMaxStringSynthPolyphony]; stmlib::Svf formant_filter_[kNumFormants]; Ensemble ensemble_; Reverb reverb_; Chorus chorus_; Limiter limiter_; int32_t num_voices_; int32_t active_group_; uint32_t step_counter_; int32_t polyphony_; int32_t acquisition_delay_; FxType fx_type_; NoteFilter note_filter_; float filter_in_buffer_[kMaxBlockSize]; float filter_out_buffer_[kMaxBlockSize]; bool clear_fx_; DISALLOW_COPY_AND_ASSIGN(StringSynthPart); }; } // namespace rings #endif // RINGS_DSP_STRING_SYNTH_VOICE_H_ ================================================ FILE: lib/rings/dsp/string_synth_voice.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Voice for the string synth easter egg. #ifndef RINGS_DSP_STRING_SYNTH_VOICE_H_ #define RINGS_DSP_STRING_SYNTH_VOICE_H_ #include "stmlib/stmlib.h" #include "rings/dsp/string_synth_oscillator.h" namespace rings { template class StringSynthVoice { public: StringSynthVoice() { } ~StringSynthVoice() { } void Init() { for (size_t i = 0; i < num_harmonics; ++i) { oscillator_[i].Init(); } } void Render( float frequency, const float* amplitudes, size_t summed_harmonics, float* out, size_t size) { oscillator_[0].template Render( frequency, amplitudes[0], amplitudes[1], out, size); amplitudes += 2; for (size_t i = 1; i < summed_harmonics; ++i) { frequency *= 2.0f; oscillator_[i].template Render( frequency, amplitudes[0], amplitudes[1], out, size); amplitudes += 2; } } private: StringSynthOscillator oscillator_[num_harmonics]; DISALLOW_COPY_AND_ASSIGN(StringSynthVoice); }; } // namespace rings #endif // RINGS_DSP_STRING_SYNTH_VOICE_H_ ================================================ FILE: lib/rings/dsp/strummer.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Strumming logic. #ifndef RINGS_DSP_STRUMMER_H_ #define RINGS_DSP_STRUMMER_H_ #include "stmlib/stmlib.h" #include "rings/dsp/onset_detector.h" #include "rings/dsp/part.h" namespace rings { class Strummer { public: Strummer() { } ~Strummer() { } void Init(float ioi, float sr) { onset_detector_.Init( 8.0f / kSampleRate, 160.0f / kSampleRate, 1600.0f / kSampleRate, sr, ioi); inhibit_timer_ = static_cast(ioi * sr); inhibit_counter_ = 0; previous_note_ = 69.0f; } void Process( const float* in, size_t size, PerformanceState* performance_state) { bool has_onset = in && onset_detector_.Process(in, size); bool note_changed = fabsf(performance_state->note - previous_note_) > 0.4f; int32_t inhibit_timer = inhibit_timer_; if (performance_state->internal_strum) { bool has_external_note_cv = !performance_state->internal_note; bool has_external_exciter = !performance_state->internal_exciter; if (has_external_note_cv) { performance_state->strum = note_changed; } else if (has_external_exciter) { performance_state->strum = has_onset; // Use longer inhibit time for onset detector. inhibit_timer *= 4; } else { // Nothing is connected. Should the module play itself in this case? performance_state->strum = false; } } if (inhibit_counter_) { --inhibit_counter_; performance_state->strum = false; } else { if (performance_state->strum) { inhibit_counter_ = inhibit_timer; } } previous_note_ = performance_state->note; } private: float previous_note_; int32_t inhibit_counter_; int32_t inhibit_timer_; OnsetDetector onset_detector_; DISALLOW_COPY_AND_ASSIGN(Strummer); }; } // namespace rings #endif // RINGS_DSP_STRUMMER_H_ ================================================ FILE: lib/rings/resources.cc ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resources definitions. // // Automatically generated with: // make resources #include "rings/resources.h" #ifndef FLASHMEM #include "pgmspace.h" #endif namespace rings { const float FLASHMEM lut_sine[] = { 0.000000000e+00, 1.533980186e-03, 3.067956763e-03, 4.601926120e-03, 6.135884649e-03, 7.669828740e-03, 9.203754782e-03, 1.073765917e-02, 1.227153829e-02, 1.380538853e-02, 1.533920628e-02, 1.687298795e-02, 1.840672991e-02, 1.994042855e-02, 2.147408028e-02, 2.300768147e-02, 2.454122852e-02, 2.607471783e-02, 2.760814578e-02, 2.914150876e-02, 3.067480318e-02, 3.220802541e-02, 3.374117185e-02, 3.527423890e-02, 3.680722294e-02, 3.834012037e-02, 3.987292759e-02, 4.140564098e-02, 4.293825693e-02, 4.447077185e-02, 4.600318213e-02, 4.753548416e-02, 4.906767433e-02, 5.059974904e-02, 5.213170468e-02, 5.366353765e-02, 5.519524435e-02, 5.672682117e-02, 5.825826450e-02, 5.978957075e-02, 6.132073630e-02, 6.285175756e-02, 6.438263093e-02, 6.591335280e-02, 6.744391956e-02, 6.897432763e-02, 7.050457339e-02, 7.203465325e-02, 7.356456360e-02, 7.509430085e-02, 7.662386139e-02, 7.815324163e-02, 7.968243797e-02, 8.121144681e-02, 8.274026455e-02, 8.426888759e-02, 8.579731234e-02, 8.732553521e-02, 8.885355258e-02, 9.038136088e-02, 9.190895650e-02, 9.343633585e-02, 9.496349533e-02, 9.649043136e-02, 9.801714033e-02, 9.954361866e-02, 1.010698628e-01, 1.025958690e-01, 1.041216339e-01, 1.056471537e-01, 1.071724250e-01, 1.086974440e-01, 1.102222073e-01, 1.117467112e-01, 1.132709522e-01, 1.147949266e-01, 1.163186309e-01, 1.178420615e-01, 1.193652148e-01, 1.208880872e-01, 1.224106752e-01, 1.239329751e-01, 1.254549834e-01, 1.269766965e-01, 1.284981108e-01, 1.300192227e-01, 1.315400287e-01, 1.330605252e-01, 1.345807085e-01, 1.361005752e-01, 1.376201216e-01, 1.391393442e-01, 1.406582393e-01, 1.421768035e-01, 1.436950332e-01, 1.452129247e-01, 1.467304745e-01, 1.482476790e-01, 1.497645347e-01, 1.512810380e-01, 1.527971853e-01, 1.543129730e-01, 1.558283977e-01, 1.573434556e-01, 1.588581433e-01, 1.603724572e-01, 1.618863938e-01, 1.633999494e-01, 1.649131205e-01, 1.664259035e-01, 1.679382950e-01, 1.694502912e-01, 1.709618888e-01, 1.724730840e-01, 1.739838734e-01, 1.754942534e-01, 1.770042204e-01, 1.785137709e-01, 1.800229014e-01, 1.815316083e-01, 1.830398880e-01, 1.845477369e-01, 1.860551517e-01, 1.875621286e-01, 1.890686641e-01, 1.905747548e-01, 1.920803970e-01, 1.935855873e-01, 1.950903220e-01, 1.965945977e-01, 1.980984107e-01, 1.996017576e-01, 2.011046348e-01, 2.026070388e-01, 2.041089661e-01, 2.056104131e-01, 2.071113762e-01, 2.086118520e-01, 2.101118369e-01, 2.116113274e-01, 2.131103199e-01, 2.146088110e-01, 2.161067971e-01, 2.176042746e-01, 2.191012402e-01, 2.205976901e-01, 2.220936210e-01, 2.235890292e-01, 2.250839114e-01, 2.265782638e-01, 2.280720832e-01, 2.295653658e-01, 2.310581083e-01, 2.325503070e-01, 2.340419586e-01, 2.355330594e-01, 2.370236060e-01, 2.385135948e-01, 2.400030224e-01, 2.414918853e-01, 2.429801799e-01, 2.444679027e-01, 2.459550503e-01, 2.474416192e-01, 2.489276057e-01, 2.504130066e-01, 2.518978182e-01, 2.533820370e-01, 2.548656596e-01, 2.563486825e-01, 2.578311022e-01, 2.593129151e-01, 2.607941179e-01, 2.622747070e-01, 2.637546790e-01, 2.652340303e-01, 2.667127575e-01, 2.681908571e-01, 2.696683256e-01, 2.711451595e-01, 2.726213554e-01, 2.740969099e-01, 2.755718193e-01, 2.770460803e-01, 2.785196894e-01, 2.799926431e-01, 2.814649379e-01, 2.829365705e-01, 2.844075372e-01, 2.858778347e-01, 2.873474595e-01, 2.888164082e-01, 2.902846773e-01, 2.917522632e-01, 2.932191627e-01, 2.946853722e-01, 2.961508882e-01, 2.976157074e-01, 2.990798263e-01, 3.005432414e-01, 3.020059493e-01, 3.034679466e-01, 3.049292297e-01, 3.063897954e-01, 3.078496400e-01, 3.093087603e-01, 3.107671527e-01, 3.122248139e-01, 3.136817404e-01, 3.151379288e-01, 3.165933756e-01, 3.180480774e-01, 3.195020308e-01, 3.209552324e-01, 3.224076788e-01, 3.238593665e-01, 3.253102922e-01, 3.267604523e-01, 3.282098436e-01, 3.296584625e-01, 3.311063058e-01, 3.325533699e-01, 3.339996514e-01, 3.354451471e-01, 3.368898534e-01, 3.383337670e-01, 3.397768844e-01, 3.412192023e-01, 3.426607173e-01, 3.441014260e-01, 3.455413250e-01, 3.469804108e-01, 3.484186802e-01, 3.498561298e-01, 3.512927561e-01, 3.527285558e-01, 3.541635254e-01, 3.555976617e-01, 3.570309612e-01, 3.584634206e-01, 3.598950365e-01, 3.613258056e-01, 3.627557244e-01, 3.641847896e-01, 3.656129978e-01, 3.670403457e-01, 3.684668300e-01, 3.698924471e-01, 3.713171940e-01, 3.727410670e-01, 3.741640630e-01, 3.755861785e-01, 3.770074102e-01, 3.784277548e-01, 3.798472089e-01, 3.812657692e-01, 3.826834324e-01, 3.841001950e-01, 3.855160538e-01, 3.869310055e-01, 3.883450467e-01, 3.897581741e-01, 3.911703843e-01, 3.925816741e-01, 3.939920401e-01, 3.954014789e-01, 3.968099874e-01, 3.982175622e-01, 3.996241998e-01, 4.010298972e-01, 4.024346509e-01, 4.038384576e-01, 4.052413140e-01, 4.066432169e-01, 4.080441629e-01, 4.094441487e-01, 4.108431711e-01, 4.122412267e-01, 4.136383122e-01, 4.150344245e-01, 4.164295601e-01, 4.178237158e-01, 4.192168884e-01, 4.206090744e-01, 4.220002708e-01, 4.233904741e-01, 4.247796812e-01, 4.261678887e-01, 4.275550934e-01, 4.289412921e-01, 4.303264813e-01, 4.317106580e-01, 4.330938189e-01, 4.344759606e-01, 4.358570799e-01, 4.372371737e-01, 4.386162385e-01, 4.399942713e-01, 4.413712687e-01, 4.427472276e-01, 4.441221446e-01, 4.454960165e-01, 4.468688402e-01, 4.482406123e-01, 4.496113297e-01, 4.509809890e-01, 4.523495872e-01, 4.537171210e-01, 4.550835871e-01, 4.564489824e-01, 4.578133036e-01, 4.591765475e-01, 4.605387110e-01, 4.618997907e-01, 4.632597836e-01, 4.646186863e-01, 4.659764958e-01, 4.673332087e-01, 4.686888220e-01, 4.700433325e-01, 4.713967368e-01, 4.727490320e-01, 4.741002147e-01, 4.754502817e-01, 4.767992301e-01, 4.781470564e-01, 4.794937577e-01, 4.808393306e-01, 4.821837721e-01, 4.835270789e-01, 4.848692480e-01, 4.862102761e-01, 4.875501601e-01, 4.888888969e-01, 4.902264833e-01, 4.915629161e-01, 4.928981922e-01, 4.942323085e-01, 4.955652618e-01, 4.968970490e-01, 4.982276670e-01, 4.995571125e-01, 5.008853826e-01, 5.022124740e-01, 5.035383837e-01, 5.048631085e-01, 5.061866453e-01, 5.075089911e-01, 5.088301425e-01, 5.101500967e-01, 5.114688504e-01, 5.127864006e-01, 5.141027442e-01, 5.154178780e-01, 5.167317990e-01, 5.180445041e-01, 5.193559902e-01, 5.206662541e-01, 5.219752929e-01, 5.232831035e-01, 5.245896827e-01, 5.258950275e-01, 5.271991348e-01, 5.285020015e-01, 5.298036247e-01, 5.311040012e-01, 5.324031279e-01, 5.337010018e-01, 5.349976199e-01, 5.362929791e-01, 5.375870763e-01, 5.388799085e-01, 5.401714727e-01, 5.414617659e-01, 5.427507849e-01, 5.440385267e-01, 5.453249884e-01, 5.466101669e-01, 5.478940592e-01, 5.491766622e-01, 5.504579729e-01, 5.517379884e-01, 5.530167056e-01, 5.542941215e-01, 5.555702330e-01, 5.568450373e-01, 5.581185312e-01, 5.593907119e-01, 5.606615762e-01, 5.619311212e-01, 5.631993440e-01, 5.644662415e-01, 5.657318108e-01, 5.669960488e-01, 5.682589527e-01, 5.695205193e-01, 5.707807459e-01, 5.720396293e-01, 5.732971667e-01, 5.745533550e-01, 5.758081914e-01, 5.770616729e-01, 5.783137964e-01, 5.795645591e-01, 5.808139581e-01, 5.820619903e-01, 5.833086529e-01, 5.845539430e-01, 5.857978575e-01, 5.870403935e-01, 5.882815482e-01, 5.895213186e-01, 5.907597019e-01, 5.919966950e-01, 5.932322950e-01, 5.944664992e-01, 5.956993045e-01, 5.969307081e-01, 5.981607070e-01, 5.993892984e-01, 6.006164794e-01, 6.018422471e-01, 6.030665985e-01, 6.042895309e-01, 6.055110414e-01, 6.067311270e-01, 6.079497850e-01, 6.091670123e-01, 6.103828063e-01, 6.115971639e-01, 6.128100824e-01, 6.140215589e-01, 6.152315906e-01, 6.164401745e-01, 6.176473079e-01, 6.188529880e-01, 6.200572118e-01, 6.212599765e-01, 6.224612794e-01, 6.236611175e-01, 6.248594881e-01, 6.260563884e-01, 6.272518155e-01, 6.284457666e-01, 6.296382389e-01, 6.308292296e-01, 6.320187359e-01, 6.332067551e-01, 6.343932842e-01, 6.355783205e-01, 6.367618612e-01, 6.379439036e-01, 6.391244449e-01, 6.403034822e-01, 6.414810128e-01, 6.426570340e-01, 6.438315429e-01, 6.450045368e-01, 6.461760130e-01, 6.473459686e-01, 6.485144010e-01, 6.496813074e-01, 6.508466850e-01, 6.520105311e-01, 6.531728430e-01, 6.543336178e-01, 6.554928530e-01, 6.566505457e-01, 6.578066933e-01, 6.589612930e-01, 6.601143421e-01, 6.612658378e-01, 6.624157776e-01, 6.635641586e-01, 6.647109782e-01, 6.658562337e-01, 6.669999223e-01, 6.681420414e-01, 6.692825883e-01, 6.704215604e-01, 6.715589548e-01, 6.726947691e-01, 6.738290004e-01, 6.749616461e-01, 6.760927036e-01, 6.772221701e-01, 6.783500431e-01, 6.794763199e-01, 6.806009978e-01, 6.817240742e-01, 6.828455464e-01, 6.839654118e-01, 6.850836678e-01, 6.862003117e-01, 6.873153409e-01, 6.884287528e-01, 6.895405447e-01, 6.906507141e-01, 6.917592584e-01, 6.928661748e-01, 6.939714609e-01, 6.950751140e-01, 6.961771315e-01, 6.972775108e-01, 6.983762494e-01, 6.994733446e-01, 7.005687939e-01, 7.016625947e-01, 7.027547445e-01, 7.038452405e-01, 7.049340804e-01, 7.060212614e-01, 7.071067812e-01, 7.081906370e-01, 7.092728264e-01, 7.103533469e-01, 7.114321957e-01, 7.125093706e-01, 7.135848688e-01, 7.146586879e-01, 7.157308253e-01, 7.168012785e-01, 7.178700451e-01, 7.189371224e-01, 7.200025080e-01, 7.210661993e-01, 7.221281939e-01, 7.231884893e-01, 7.242470830e-01, 7.253039724e-01, 7.263591551e-01, 7.274126286e-01, 7.284643904e-01, 7.295144381e-01, 7.305627692e-01, 7.316093812e-01, 7.326542717e-01, 7.336974381e-01, 7.347388781e-01, 7.357785892e-01, 7.368165689e-01, 7.378528148e-01, 7.388873245e-01, 7.399200955e-01, 7.409511254e-01, 7.419804117e-01, 7.430079521e-01, 7.440337442e-01, 7.450577854e-01, 7.460800735e-01, 7.471006060e-01, 7.481193805e-01, 7.491363945e-01, 7.501516458e-01, 7.511651319e-01, 7.521768504e-01, 7.531867990e-01, 7.541949753e-01, 7.552013769e-01, 7.562060014e-01, 7.572088465e-01, 7.582099098e-01, 7.592091890e-01, 7.602066817e-01, 7.612023855e-01, 7.621962981e-01, 7.631884173e-01, 7.641787405e-01, 7.651672656e-01, 7.661539902e-01, 7.671389119e-01, 7.681220285e-01, 7.691033376e-01, 7.700828370e-01, 7.710605243e-01, 7.720363972e-01, 7.730104534e-01, 7.739826906e-01, 7.749531066e-01, 7.759216990e-01, 7.768884657e-01, 7.778534042e-01, 7.788165124e-01, 7.797777879e-01, 7.807372286e-01, 7.816948321e-01, 7.826505962e-01, 7.836045186e-01, 7.845565972e-01, 7.855068296e-01, 7.864552136e-01, 7.874017470e-01, 7.883464276e-01, 7.892892532e-01, 7.902302214e-01, 7.911693302e-01, 7.921065773e-01, 7.930419605e-01, 7.939754776e-01, 7.949071263e-01, 7.958369046e-01, 7.967648102e-01, 7.976908409e-01, 7.986149946e-01, 7.995372691e-01, 8.004576622e-01, 8.013761717e-01, 8.022927955e-01, 8.032075315e-01, 8.041203774e-01, 8.050313311e-01, 8.059403906e-01, 8.068475535e-01, 8.077528179e-01, 8.086561816e-01, 8.095576424e-01, 8.104571983e-01, 8.113548470e-01, 8.122505866e-01, 8.131444148e-01, 8.140363297e-01, 8.149263291e-01, 8.158144108e-01, 8.167005729e-01, 8.175848132e-01, 8.184671296e-01, 8.193475201e-01, 8.202259826e-01, 8.211025150e-01, 8.219771153e-01, 8.228497814e-01, 8.237205112e-01, 8.245893028e-01, 8.254561540e-01, 8.263210628e-01, 8.271840273e-01, 8.280450453e-01, 8.289041148e-01, 8.297612338e-01, 8.306164003e-01, 8.314696123e-01, 8.323208678e-01, 8.331701647e-01, 8.340175011e-01, 8.348628750e-01, 8.357062844e-01, 8.365477272e-01, 8.373872016e-01, 8.382247056e-01, 8.390602371e-01, 8.398937942e-01, 8.407253750e-01, 8.415549774e-01, 8.423825996e-01, 8.432082396e-01, 8.440318955e-01, 8.448535652e-01, 8.456732470e-01, 8.464909388e-01, 8.473066387e-01, 8.481203448e-01, 8.489320552e-01, 8.497417680e-01, 8.505494813e-01, 8.513551931e-01, 8.521589016e-01, 8.529606049e-01, 8.537603011e-01, 8.545579884e-01, 8.553536647e-01, 8.561473284e-01, 8.569389774e-01, 8.577286100e-01, 8.585162243e-01, 8.593018184e-01, 8.600853904e-01, 8.608669386e-01, 8.616464611e-01, 8.624239561e-01, 8.631994217e-01, 8.639728561e-01, 8.647442575e-01, 8.655136241e-01, 8.662809540e-01, 8.670462455e-01, 8.678094968e-01, 8.685707060e-01, 8.693298713e-01, 8.700869911e-01, 8.708420635e-01, 8.715950867e-01, 8.723460589e-01, 8.730949784e-01, 8.738418435e-01, 8.745866523e-01, 8.753294031e-01, 8.760700942e-01, 8.768087238e-01, 8.775452902e-01, 8.782797917e-01, 8.790122264e-01, 8.797425928e-01, 8.804708891e-01, 8.811971135e-01, 8.819212643e-01, 8.826433400e-01, 8.833633387e-01, 8.840812587e-01, 8.847970984e-01, 8.855108561e-01, 8.862225301e-01, 8.869321188e-01, 8.876396204e-01, 8.883450333e-01, 8.890483559e-01, 8.897495864e-01, 8.904487232e-01, 8.911457648e-01, 8.918407094e-01, 8.925335554e-01, 8.932243012e-01, 8.939129451e-01, 8.945994856e-01, 8.952839210e-01, 8.959662498e-01, 8.966464702e-01, 8.973245807e-01, 8.980005797e-01, 8.986744657e-01, 8.993462370e-01, 9.000158920e-01, 9.006834292e-01, 9.013488470e-01, 9.020121439e-01, 9.026733182e-01, 9.033323685e-01, 9.039892931e-01, 9.046440906e-01, 9.052967593e-01, 9.059472978e-01, 9.065957045e-01, 9.072419779e-01, 9.078861165e-01, 9.085281187e-01, 9.091679831e-01, 9.098057081e-01, 9.104412923e-01, 9.110747341e-01, 9.117060320e-01, 9.123351846e-01, 9.129621904e-01, 9.135870479e-01, 9.142097557e-01, 9.148303122e-01, 9.154487161e-01, 9.160649658e-01, 9.166790599e-01, 9.172909970e-01, 9.179007756e-01, 9.185083943e-01, 9.191138517e-01, 9.197171463e-01, 9.203182767e-01, 9.209172415e-01, 9.215140393e-01, 9.221086687e-01, 9.227011283e-01, 9.232914167e-01, 9.238795325e-01, 9.244654743e-01, 9.250492408e-01, 9.256308305e-01, 9.262102421e-01, 9.267874743e-01, 9.273625257e-01, 9.279353948e-01, 9.285060805e-01, 9.290745813e-01, 9.296408958e-01, 9.302050229e-01, 9.307669611e-01, 9.313267091e-01, 9.318842656e-01, 9.324396293e-01, 9.329927988e-01, 9.335437730e-01, 9.340925504e-01, 9.346391298e-01, 9.351835099e-01, 9.357256895e-01, 9.362656672e-01, 9.368034417e-01, 9.373390119e-01, 9.378723764e-01, 9.384035341e-01, 9.389324835e-01, 9.394592236e-01, 9.399837530e-01, 9.405060706e-01, 9.410261751e-01, 9.415440652e-01, 9.420597398e-01, 9.425731976e-01, 9.430844375e-01, 9.435934582e-01, 9.441002585e-01, 9.446048373e-01, 9.451071933e-01, 9.456073254e-01, 9.461052324e-01, 9.466009131e-01, 9.470943664e-01, 9.475855910e-01, 9.480745859e-01, 9.485613499e-01, 9.490458819e-01, 9.495281806e-01, 9.500082450e-01, 9.504860739e-01, 9.509616663e-01, 9.514350210e-01, 9.519061368e-01, 9.523750127e-01, 9.528416476e-01, 9.533060404e-01, 9.537681899e-01, 9.542280951e-01, 9.546857549e-01, 9.551411683e-01, 9.555943341e-01, 9.560452513e-01, 9.564939189e-01, 9.569403357e-01, 9.573845008e-01, 9.578264130e-01, 9.582660714e-01, 9.587034749e-01, 9.591386225e-01, 9.595715131e-01, 9.600021457e-01, 9.604305194e-01, 9.608566331e-01, 9.612804858e-01, 9.617020765e-01, 9.621214043e-01, 9.625384680e-01, 9.629532669e-01, 9.633657998e-01, 9.637760658e-01, 9.641840640e-01, 9.645897933e-01, 9.649932529e-01, 9.653944417e-01, 9.657933589e-01, 9.661900034e-01, 9.665843745e-01, 9.669764710e-01, 9.673662922e-01, 9.677538371e-01, 9.681391047e-01, 9.685220943e-01, 9.689028048e-01, 9.692812354e-01, 9.696573851e-01, 9.700312532e-01, 9.704028387e-01, 9.707721407e-01, 9.711391584e-01, 9.715038910e-01, 9.718663375e-01, 9.722264971e-01, 9.725843689e-01, 9.729399522e-01, 9.732932461e-01, 9.736442497e-01, 9.739929622e-01, 9.743393828e-01, 9.746835107e-01, 9.750253451e-01, 9.753648851e-01, 9.757021300e-01, 9.760370790e-01, 9.763697313e-01, 9.767000861e-01, 9.770281427e-01, 9.773539001e-01, 9.776773578e-01, 9.779985149e-01, 9.783173707e-01, 9.786339244e-01, 9.789481753e-01, 9.792601226e-01, 9.795697657e-01, 9.798771037e-01, 9.801821360e-01, 9.804848618e-01, 9.807852804e-01, 9.810833912e-01, 9.813791933e-01, 9.816726862e-01, 9.819638691e-01, 9.822527414e-01, 9.825393023e-01, 9.828235512e-01, 9.831054874e-01, 9.833851103e-01, 9.836624192e-01, 9.839374134e-01, 9.842100924e-01, 9.844804554e-01, 9.847485018e-01, 9.850142310e-01, 9.852776424e-01, 9.855387353e-01, 9.857975092e-01, 9.860539633e-01, 9.863080972e-01, 9.865599103e-01, 9.868094018e-01, 9.870565713e-01, 9.873014182e-01, 9.875439418e-01, 9.877841416e-01, 9.880220171e-01, 9.882575677e-01, 9.884907929e-01, 9.887216920e-01, 9.889502645e-01, 9.891765100e-01, 9.894004278e-01, 9.896220175e-01, 9.898412785e-01, 9.900582103e-01, 9.902728124e-01, 9.904850843e-01, 9.906950254e-01, 9.909026354e-01, 9.911079137e-01, 9.913108598e-01, 9.915114733e-01, 9.917097537e-01, 9.919057004e-01, 9.920993131e-01, 9.922905913e-01, 9.924795346e-01, 9.926661424e-01, 9.928504145e-01, 9.930323502e-01, 9.932119492e-01, 9.933892111e-01, 9.935641355e-01, 9.937367219e-01, 9.939069700e-01, 9.940748793e-01, 9.942404495e-01, 9.944036801e-01, 9.945645707e-01, 9.947231211e-01, 9.948793308e-01, 9.950331994e-01, 9.951847267e-01, 9.953339121e-01, 9.954807555e-01, 9.956252564e-01, 9.957674145e-01, 9.959072294e-01, 9.960447009e-01, 9.961798286e-01, 9.963126122e-01, 9.964430514e-01, 9.965711458e-01, 9.966968952e-01, 9.968202993e-01, 9.969413578e-01, 9.970600703e-01, 9.971764367e-01, 9.972904567e-01, 9.974021299e-01, 9.975114561e-01, 9.976184351e-01, 9.977230666e-01, 9.978253504e-01, 9.979252862e-01, 9.980228738e-01, 9.981181129e-01, 9.982110034e-01, 9.983015449e-01, 9.983897374e-01, 9.984755806e-01, 9.985590742e-01, 9.986402182e-01, 9.987190122e-01, 9.987954562e-01, 9.988695499e-01, 9.989412932e-01, 9.990106859e-01, 9.990777278e-01, 9.991424187e-01, 9.992047586e-01, 9.992647473e-01, 9.993223846e-01, 9.993776704e-01, 9.994306046e-01, 9.994811870e-01, 9.995294175e-01, 9.995752960e-01, 9.996188225e-01, 9.996599967e-01, 9.996988187e-01, 9.997352883e-01, 9.997694054e-01, 9.998011699e-01, 9.998305818e-01, 9.998576410e-01, 9.998823475e-01, 9.999047011e-01, 9.999247018e-01, 9.999423497e-01, 9.999576446e-01, 9.999705864e-01, 9.999811753e-01, 9.999894111e-01, 9.999952938e-01, 9.999988235e-01, 1.000000000e+00, 9.999988235e-01, 9.999952938e-01, 9.999894111e-01, 9.999811753e-01, 9.999705864e-01, 9.999576446e-01, 9.999423497e-01, 9.999247018e-01, 9.999047011e-01, 9.998823475e-01, 9.998576410e-01, 9.998305818e-01, 9.998011699e-01, 9.997694054e-01, 9.997352883e-01, 9.996988187e-01, 9.996599967e-01, 9.996188225e-01, 9.995752960e-01, 9.995294175e-01, 9.994811870e-01, 9.994306046e-01, 9.993776704e-01, 9.993223846e-01, 9.992647473e-01, 9.992047586e-01, 9.991424187e-01, 9.990777278e-01, 9.990106859e-01, 9.989412932e-01, 9.988695499e-01, 9.987954562e-01, 9.987190122e-01, 9.986402182e-01, 9.985590742e-01, 9.984755806e-01, 9.983897374e-01, 9.983015449e-01, 9.982110034e-01, 9.981181129e-01, 9.980228738e-01, 9.979252862e-01, 9.978253504e-01, 9.977230666e-01, 9.976184351e-01, 9.975114561e-01, 9.974021299e-01, 9.972904567e-01, 9.971764367e-01, 9.970600703e-01, 9.969413578e-01, 9.968202993e-01, 9.966968952e-01, 9.965711458e-01, 9.964430514e-01, 9.963126122e-01, 9.961798286e-01, 9.960447009e-01, 9.959072294e-01, 9.957674145e-01, 9.956252564e-01, 9.954807555e-01, 9.953339121e-01, 9.951847267e-01, 9.950331994e-01, 9.948793308e-01, 9.947231211e-01, 9.945645707e-01, 9.944036801e-01, 9.942404495e-01, 9.940748793e-01, 9.939069700e-01, 9.937367219e-01, 9.935641355e-01, 9.933892111e-01, 9.932119492e-01, 9.930323502e-01, 9.928504145e-01, 9.926661424e-01, 9.924795346e-01, 9.922905913e-01, 9.920993131e-01, 9.919057004e-01, 9.917097537e-01, 9.915114733e-01, 9.913108598e-01, 9.911079137e-01, 9.909026354e-01, 9.906950254e-01, 9.904850843e-01, 9.902728124e-01, 9.900582103e-01, 9.898412785e-01, 9.896220175e-01, 9.894004278e-01, 9.891765100e-01, 9.889502645e-01, 9.887216920e-01, 9.884907929e-01, 9.882575677e-01, 9.880220171e-01, 9.877841416e-01, 9.875439418e-01, 9.873014182e-01, 9.870565713e-01, 9.868094018e-01, 9.865599103e-01, 9.863080972e-01, 9.860539633e-01, 9.857975092e-01, 9.855387353e-01, 9.852776424e-01, 9.850142310e-01, 9.847485018e-01, 9.844804554e-01, 9.842100924e-01, 9.839374134e-01, 9.836624192e-01, 9.833851103e-01, 9.831054874e-01, 9.828235512e-01, 9.825393023e-01, 9.822527414e-01, 9.819638691e-01, 9.816726862e-01, 9.813791933e-01, 9.810833912e-01, 9.807852804e-01, 9.804848618e-01, 9.801821360e-01, 9.798771037e-01, 9.795697657e-01, 9.792601226e-01, 9.789481753e-01, 9.786339244e-01, 9.783173707e-01, 9.779985149e-01, 9.776773578e-01, 9.773539001e-01, 9.770281427e-01, 9.767000861e-01, 9.763697313e-01, 9.760370790e-01, 9.757021300e-01, 9.753648851e-01, 9.750253451e-01, 9.746835107e-01, 9.743393828e-01, 9.739929622e-01, 9.736442497e-01, 9.732932461e-01, 9.729399522e-01, 9.725843689e-01, 9.722264971e-01, 9.718663375e-01, 9.715038910e-01, 9.711391584e-01, 9.707721407e-01, 9.704028387e-01, 9.700312532e-01, 9.696573851e-01, 9.692812354e-01, 9.689028048e-01, 9.685220943e-01, 9.681391047e-01, 9.677538371e-01, 9.673662922e-01, 9.669764710e-01, 9.665843745e-01, 9.661900034e-01, 9.657933589e-01, 9.653944417e-01, 9.649932529e-01, 9.645897933e-01, 9.641840640e-01, 9.637760658e-01, 9.633657998e-01, 9.629532669e-01, 9.625384680e-01, 9.621214043e-01, 9.617020765e-01, 9.612804858e-01, 9.608566331e-01, 9.604305194e-01, 9.600021457e-01, 9.595715131e-01, 9.591386225e-01, 9.587034749e-01, 9.582660714e-01, 9.578264130e-01, 9.573845008e-01, 9.569403357e-01, 9.564939189e-01, 9.560452513e-01, 9.555943341e-01, 9.551411683e-01, 9.546857549e-01, 9.542280951e-01, 9.537681899e-01, 9.533060404e-01, 9.528416476e-01, 9.523750127e-01, 9.519061368e-01, 9.514350210e-01, 9.509616663e-01, 9.504860739e-01, 9.500082450e-01, 9.495281806e-01, 9.490458819e-01, 9.485613499e-01, 9.480745859e-01, 9.475855910e-01, 9.470943664e-01, 9.466009131e-01, 9.461052324e-01, 9.456073254e-01, 9.451071933e-01, 9.446048373e-01, 9.441002585e-01, 9.435934582e-01, 9.430844375e-01, 9.425731976e-01, 9.420597398e-01, 9.415440652e-01, 9.410261751e-01, 9.405060706e-01, 9.399837530e-01, 9.394592236e-01, 9.389324835e-01, 9.384035341e-01, 9.378723764e-01, 9.373390119e-01, 9.368034417e-01, 9.362656672e-01, 9.357256895e-01, 9.351835099e-01, 9.346391298e-01, 9.340925504e-01, 9.335437730e-01, 9.329927988e-01, 9.324396293e-01, 9.318842656e-01, 9.313267091e-01, 9.307669611e-01, 9.302050229e-01, 9.296408958e-01, 9.290745813e-01, 9.285060805e-01, 9.279353948e-01, 9.273625257e-01, 9.267874743e-01, 9.262102421e-01, 9.256308305e-01, 9.250492408e-01, 9.244654743e-01, 9.238795325e-01, 9.232914167e-01, 9.227011283e-01, 9.221086687e-01, 9.215140393e-01, 9.209172415e-01, 9.203182767e-01, 9.197171463e-01, 9.191138517e-01, 9.185083943e-01, 9.179007756e-01, 9.172909970e-01, 9.166790599e-01, 9.160649658e-01, 9.154487161e-01, 9.148303122e-01, 9.142097557e-01, 9.135870479e-01, 9.129621904e-01, 9.123351846e-01, 9.117060320e-01, 9.110747341e-01, 9.104412923e-01, 9.098057081e-01, 9.091679831e-01, 9.085281187e-01, 9.078861165e-01, 9.072419779e-01, 9.065957045e-01, 9.059472978e-01, 9.052967593e-01, 9.046440906e-01, 9.039892931e-01, 9.033323685e-01, 9.026733182e-01, 9.020121439e-01, 9.013488470e-01, 9.006834292e-01, 9.000158920e-01, 8.993462370e-01, 8.986744657e-01, 8.980005797e-01, 8.973245807e-01, 8.966464702e-01, 8.959662498e-01, 8.952839210e-01, 8.945994856e-01, 8.939129451e-01, 8.932243012e-01, 8.925335554e-01, 8.918407094e-01, 8.911457648e-01, 8.904487232e-01, 8.897495864e-01, 8.890483559e-01, 8.883450333e-01, 8.876396204e-01, 8.869321188e-01, 8.862225301e-01, 8.855108561e-01, 8.847970984e-01, 8.840812587e-01, 8.833633387e-01, 8.826433400e-01, 8.819212643e-01, 8.811971135e-01, 8.804708891e-01, 8.797425928e-01, 8.790122264e-01, 8.782797917e-01, 8.775452902e-01, 8.768087238e-01, 8.760700942e-01, 8.753294031e-01, 8.745866523e-01, 8.738418435e-01, 8.730949784e-01, 8.723460589e-01, 8.715950867e-01, 8.708420635e-01, 8.700869911e-01, 8.693298713e-01, 8.685707060e-01, 8.678094968e-01, 8.670462455e-01, 8.662809540e-01, 8.655136241e-01, 8.647442575e-01, 8.639728561e-01, 8.631994217e-01, 8.624239561e-01, 8.616464611e-01, 8.608669386e-01, 8.600853904e-01, 8.593018184e-01, 8.585162243e-01, 8.577286100e-01, 8.569389774e-01, 8.561473284e-01, 8.553536647e-01, 8.545579884e-01, 8.537603011e-01, 8.529606049e-01, 8.521589016e-01, 8.513551931e-01, 8.505494813e-01, 8.497417680e-01, 8.489320552e-01, 8.481203448e-01, 8.473066387e-01, 8.464909388e-01, 8.456732470e-01, 8.448535652e-01, 8.440318955e-01, 8.432082396e-01, 8.423825996e-01, 8.415549774e-01, 8.407253750e-01, 8.398937942e-01, 8.390602371e-01, 8.382247056e-01, 8.373872016e-01, 8.365477272e-01, 8.357062844e-01, 8.348628750e-01, 8.340175011e-01, 8.331701647e-01, 8.323208678e-01, 8.314696123e-01, 8.306164003e-01, 8.297612338e-01, 8.289041148e-01, 8.280450453e-01, 8.271840273e-01, 8.263210628e-01, 8.254561540e-01, 8.245893028e-01, 8.237205112e-01, 8.228497814e-01, 8.219771153e-01, 8.211025150e-01, 8.202259826e-01, 8.193475201e-01, 8.184671296e-01, 8.175848132e-01, 8.167005729e-01, 8.158144108e-01, 8.149263291e-01, 8.140363297e-01, 8.131444148e-01, 8.122505866e-01, 8.113548470e-01, 8.104571983e-01, 8.095576424e-01, 8.086561816e-01, 8.077528179e-01, 8.068475535e-01, 8.059403906e-01, 8.050313311e-01, 8.041203774e-01, 8.032075315e-01, 8.022927955e-01, 8.013761717e-01, 8.004576622e-01, 7.995372691e-01, 7.986149946e-01, 7.976908409e-01, 7.967648102e-01, 7.958369046e-01, 7.949071263e-01, 7.939754776e-01, 7.930419605e-01, 7.921065773e-01, 7.911693302e-01, 7.902302214e-01, 7.892892532e-01, 7.883464276e-01, 7.874017470e-01, 7.864552136e-01, 7.855068296e-01, 7.845565972e-01, 7.836045186e-01, 7.826505962e-01, 7.816948321e-01, 7.807372286e-01, 7.797777879e-01, 7.788165124e-01, 7.778534042e-01, 7.768884657e-01, 7.759216990e-01, 7.749531066e-01, 7.739826906e-01, 7.730104534e-01, 7.720363972e-01, 7.710605243e-01, 7.700828370e-01, 7.691033376e-01, 7.681220285e-01, 7.671389119e-01, 7.661539902e-01, 7.651672656e-01, 7.641787405e-01, 7.631884173e-01, 7.621962981e-01, 7.612023855e-01, 7.602066817e-01, 7.592091890e-01, 7.582099098e-01, 7.572088465e-01, 7.562060014e-01, 7.552013769e-01, 7.541949753e-01, 7.531867990e-01, 7.521768504e-01, 7.511651319e-01, 7.501516458e-01, 7.491363945e-01, 7.481193805e-01, 7.471006060e-01, 7.460800735e-01, 7.450577854e-01, 7.440337442e-01, 7.430079521e-01, 7.419804117e-01, 7.409511254e-01, 7.399200955e-01, 7.388873245e-01, 7.378528148e-01, 7.368165689e-01, 7.357785892e-01, 7.347388781e-01, 7.336974381e-01, 7.326542717e-01, 7.316093812e-01, 7.305627692e-01, 7.295144381e-01, 7.284643904e-01, 7.274126286e-01, 7.263591551e-01, 7.253039724e-01, 7.242470830e-01, 7.231884893e-01, 7.221281939e-01, 7.210661993e-01, 7.200025080e-01, 7.189371224e-01, 7.178700451e-01, 7.168012785e-01, 7.157308253e-01, 7.146586879e-01, 7.135848688e-01, 7.125093706e-01, 7.114321957e-01, 7.103533469e-01, 7.092728264e-01, 7.081906370e-01, 7.071067812e-01, 7.060212614e-01, 7.049340804e-01, 7.038452405e-01, 7.027547445e-01, 7.016625947e-01, 7.005687939e-01, 6.994733446e-01, 6.983762494e-01, 6.972775108e-01, 6.961771315e-01, 6.950751140e-01, 6.939714609e-01, 6.928661748e-01, 6.917592584e-01, 6.906507141e-01, 6.895405447e-01, 6.884287528e-01, 6.873153409e-01, 6.862003117e-01, 6.850836678e-01, 6.839654118e-01, 6.828455464e-01, 6.817240742e-01, 6.806009978e-01, 6.794763199e-01, 6.783500431e-01, 6.772221701e-01, 6.760927036e-01, 6.749616461e-01, 6.738290004e-01, 6.726947691e-01, 6.715589548e-01, 6.704215604e-01, 6.692825883e-01, 6.681420414e-01, 6.669999223e-01, 6.658562337e-01, 6.647109782e-01, 6.635641586e-01, 6.624157776e-01, 6.612658378e-01, 6.601143421e-01, 6.589612930e-01, 6.578066933e-01, 6.566505457e-01, 6.554928530e-01, 6.543336178e-01, 6.531728430e-01, 6.520105311e-01, 6.508466850e-01, 6.496813074e-01, 6.485144010e-01, 6.473459686e-01, 6.461760130e-01, 6.450045368e-01, 6.438315429e-01, 6.426570340e-01, 6.414810128e-01, 6.403034822e-01, 6.391244449e-01, 6.379439036e-01, 6.367618612e-01, 6.355783205e-01, 6.343932842e-01, 6.332067551e-01, 6.320187359e-01, 6.308292296e-01, 6.296382389e-01, 6.284457666e-01, 6.272518155e-01, 6.260563884e-01, 6.248594881e-01, 6.236611175e-01, 6.224612794e-01, 6.212599765e-01, 6.200572118e-01, 6.188529880e-01, 6.176473079e-01, 6.164401745e-01, 6.152315906e-01, 6.140215589e-01, 6.128100824e-01, 6.115971639e-01, 6.103828063e-01, 6.091670123e-01, 6.079497850e-01, 6.067311270e-01, 6.055110414e-01, 6.042895309e-01, 6.030665985e-01, 6.018422471e-01, 6.006164794e-01, 5.993892984e-01, 5.981607070e-01, 5.969307081e-01, 5.956993045e-01, 5.944664992e-01, 5.932322950e-01, 5.919966950e-01, 5.907597019e-01, 5.895213186e-01, 5.882815482e-01, 5.870403935e-01, 5.857978575e-01, 5.845539430e-01, 5.833086529e-01, 5.820619903e-01, 5.808139581e-01, 5.795645591e-01, 5.783137964e-01, 5.770616729e-01, 5.758081914e-01, 5.745533550e-01, 5.732971667e-01, 5.720396293e-01, 5.707807459e-01, 5.695205193e-01, 5.682589527e-01, 5.669960488e-01, 5.657318108e-01, 5.644662415e-01, 5.631993440e-01, 5.619311212e-01, 5.606615762e-01, 5.593907119e-01, 5.581185312e-01, 5.568450373e-01, 5.555702330e-01, 5.542941215e-01, 5.530167056e-01, 5.517379884e-01, 5.504579729e-01, 5.491766622e-01, 5.478940592e-01, 5.466101669e-01, 5.453249884e-01, 5.440385267e-01, 5.427507849e-01, 5.414617659e-01, 5.401714727e-01, 5.388799085e-01, 5.375870763e-01, 5.362929791e-01, 5.349976199e-01, 5.337010018e-01, 5.324031279e-01, 5.311040012e-01, 5.298036247e-01, 5.285020015e-01, 5.271991348e-01, 5.258950275e-01, 5.245896827e-01, 5.232831035e-01, 5.219752929e-01, 5.206662541e-01, 5.193559902e-01, 5.180445041e-01, 5.167317990e-01, 5.154178780e-01, 5.141027442e-01, 5.127864006e-01, 5.114688504e-01, 5.101500967e-01, 5.088301425e-01, 5.075089911e-01, 5.061866453e-01, 5.048631085e-01, 5.035383837e-01, 5.022124740e-01, 5.008853826e-01, 4.995571125e-01, 4.982276670e-01, 4.968970490e-01, 4.955652618e-01, 4.942323085e-01, 4.928981922e-01, 4.915629161e-01, 4.902264833e-01, 4.888888969e-01, 4.875501601e-01, 4.862102761e-01, 4.848692480e-01, 4.835270789e-01, 4.821837721e-01, 4.808393306e-01, 4.794937577e-01, 4.781470564e-01, 4.767992301e-01, 4.754502817e-01, 4.741002147e-01, 4.727490320e-01, 4.713967368e-01, 4.700433325e-01, 4.686888220e-01, 4.673332087e-01, 4.659764958e-01, 4.646186863e-01, 4.632597836e-01, 4.618997907e-01, 4.605387110e-01, 4.591765475e-01, 4.578133036e-01, 4.564489824e-01, 4.550835871e-01, 4.537171210e-01, 4.523495872e-01, 4.509809890e-01, 4.496113297e-01, 4.482406123e-01, 4.468688402e-01, 4.454960165e-01, 4.441221446e-01, 4.427472276e-01, 4.413712687e-01, 4.399942713e-01, 4.386162385e-01, 4.372371737e-01, 4.358570799e-01, 4.344759606e-01, 4.330938189e-01, 4.317106580e-01, 4.303264813e-01, 4.289412921e-01, 4.275550934e-01, 4.261678887e-01, 4.247796812e-01, 4.233904741e-01, 4.220002708e-01, 4.206090744e-01, 4.192168884e-01, 4.178237158e-01, 4.164295601e-01, 4.150344245e-01, 4.136383122e-01, 4.122412267e-01, 4.108431711e-01, 4.094441487e-01, 4.080441629e-01, 4.066432169e-01, 4.052413140e-01, 4.038384576e-01, 4.024346509e-01, 4.010298972e-01, 3.996241998e-01, 3.982175622e-01, 3.968099874e-01, 3.954014789e-01, 3.939920401e-01, 3.925816741e-01, 3.911703843e-01, 3.897581741e-01, 3.883450467e-01, 3.869310055e-01, 3.855160538e-01, 3.841001950e-01, 3.826834324e-01, 3.812657692e-01, 3.798472089e-01, 3.784277548e-01, 3.770074102e-01, 3.755861785e-01, 3.741640630e-01, 3.727410670e-01, 3.713171940e-01, 3.698924471e-01, 3.684668300e-01, 3.670403457e-01, 3.656129978e-01, 3.641847896e-01, 3.627557244e-01, 3.613258056e-01, 3.598950365e-01, 3.584634206e-01, 3.570309612e-01, 3.555976617e-01, 3.541635254e-01, 3.527285558e-01, 3.512927561e-01, 3.498561298e-01, 3.484186802e-01, 3.469804108e-01, 3.455413250e-01, 3.441014260e-01, 3.426607173e-01, 3.412192023e-01, 3.397768844e-01, 3.383337670e-01, 3.368898534e-01, 3.354451471e-01, 3.339996514e-01, 3.325533699e-01, 3.311063058e-01, 3.296584625e-01, 3.282098436e-01, 3.267604523e-01, 3.253102922e-01, 3.238593665e-01, 3.224076788e-01, 3.209552324e-01, 3.195020308e-01, 3.180480774e-01, 3.165933756e-01, 3.151379288e-01, 3.136817404e-01, 3.122248139e-01, 3.107671527e-01, 3.093087603e-01, 3.078496400e-01, 3.063897954e-01, 3.049292297e-01, 3.034679466e-01, 3.020059493e-01, 3.005432414e-01, 2.990798263e-01, 2.976157074e-01, 2.961508882e-01, 2.946853722e-01, 2.932191627e-01, 2.917522632e-01, 2.902846773e-01, 2.888164082e-01, 2.873474595e-01, 2.858778347e-01, 2.844075372e-01, 2.829365705e-01, 2.814649379e-01, 2.799926431e-01, 2.785196894e-01, 2.770460803e-01, 2.755718193e-01, 2.740969099e-01, 2.726213554e-01, 2.711451595e-01, 2.696683256e-01, 2.681908571e-01, 2.667127575e-01, 2.652340303e-01, 2.637546790e-01, 2.622747070e-01, 2.607941179e-01, 2.593129151e-01, 2.578311022e-01, 2.563486825e-01, 2.548656596e-01, 2.533820370e-01, 2.518978182e-01, 2.504130066e-01, 2.489276057e-01, 2.474416192e-01, 2.459550503e-01, 2.444679027e-01, 2.429801799e-01, 2.414918853e-01, 2.400030224e-01, 2.385135948e-01, 2.370236060e-01, 2.355330594e-01, 2.340419586e-01, 2.325503070e-01, 2.310581083e-01, 2.295653658e-01, 2.280720832e-01, 2.265782638e-01, 2.250839114e-01, 2.235890292e-01, 2.220936210e-01, 2.205976901e-01, 2.191012402e-01, 2.176042746e-01, 2.161067971e-01, 2.146088110e-01, 2.131103199e-01, 2.116113274e-01, 2.101118369e-01, 2.086118520e-01, 2.071113762e-01, 2.056104131e-01, 2.041089661e-01, 2.026070388e-01, 2.011046348e-01, 1.996017576e-01, 1.980984107e-01, 1.965945977e-01, 1.950903220e-01, 1.935855873e-01, 1.920803970e-01, 1.905747548e-01, 1.890686641e-01, 1.875621286e-01, 1.860551517e-01, 1.845477369e-01, 1.830398880e-01, 1.815316083e-01, 1.800229014e-01, 1.785137709e-01, 1.770042204e-01, 1.754942534e-01, 1.739838734e-01, 1.724730840e-01, 1.709618888e-01, 1.694502912e-01, 1.679382950e-01, 1.664259035e-01, 1.649131205e-01, 1.633999494e-01, 1.618863938e-01, 1.603724572e-01, 1.588581433e-01, 1.573434556e-01, 1.558283977e-01, 1.543129730e-01, 1.527971853e-01, 1.512810380e-01, 1.497645347e-01, 1.482476790e-01, 1.467304745e-01, 1.452129247e-01, 1.436950332e-01, 1.421768035e-01, 1.406582393e-01, 1.391393442e-01, 1.376201216e-01, 1.361005752e-01, 1.345807085e-01, 1.330605252e-01, 1.315400287e-01, 1.300192227e-01, 1.284981108e-01, 1.269766965e-01, 1.254549834e-01, 1.239329751e-01, 1.224106752e-01, 1.208880872e-01, 1.193652148e-01, 1.178420615e-01, 1.163186309e-01, 1.147949266e-01, 1.132709522e-01, 1.117467112e-01, 1.102222073e-01, 1.086974440e-01, 1.071724250e-01, 1.056471537e-01, 1.041216339e-01, 1.025958690e-01, 1.010698628e-01, 9.954361866e-02, 9.801714033e-02, 9.649043136e-02, 9.496349533e-02, 9.343633585e-02, 9.190895650e-02, 9.038136088e-02, 8.885355258e-02, 8.732553521e-02, 8.579731234e-02, 8.426888759e-02, 8.274026455e-02, 8.121144681e-02, 7.968243797e-02, 7.815324163e-02, 7.662386139e-02, 7.509430085e-02, 7.356456360e-02, 7.203465325e-02, 7.050457339e-02, 6.897432763e-02, 6.744391956e-02, 6.591335280e-02, 6.438263093e-02, 6.285175756e-02, 6.132073630e-02, 5.978957075e-02, 5.825826450e-02, 5.672682117e-02, 5.519524435e-02, 5.366353765e-02, 5.213170468e-02, 5.059974904e-02, 4.906767433e-02, 4.753548416e-02, 4.600318213e-02, 4.447077185e-02, 4.293825693e-02, 4.140564098e-02, 3.987292759e-02, 3.834012037e-02, 3.680722294e-02, 3.527423890e-02, 3.374117185e-02, 3.220802541e-02, 3.067480318e-02, 2.914150876e-02, 2.760814578e-02, 2.607471783e-02, 2.454122852e-02, 2.300768147e-02, 2.147408028e-02, 1.994042855e-02, 1.840672991e-02, 1.687298795e-02, 1.533920628e-02, 1.380538853e-02, 1.227153829e-02, 1.073765917e-02, 9.203754782e-03, 7.669828740e-03, 6.135884649e-03, 4.601926120e-03, 3.067956763e-03, 1.533980186e-03, 1.224646799e-16, -1.533980186e-03, -3.067956763e-03, -4.601926120e-03, -6.135884649e-03, -7.669828740e-03, -9.203754782e-03, -1.073765917e-02, -1.227153829e-02, -1.380538853e-02, -1.533920628e-02, -1.687298795e-02, -1.840672991e-02, -1.994042855e-02, -2.147408028e-02, -2.300768147e-02, -2.454122852e-02, -2.607471783e-02, -2.760814578e-02, -2.914150876e-02, -3.067480318e-02, -3.220802541e-02, -3.374117185e-02, -3.527423890e-02, -3.680722294e-02, -3.834012037e-02, -3.987292759e-02, -4.140564098e-02, -4.293825693e-02, -4.447077185e-02, -4.600318213e-02, -4.753548416e-02, -4.906767433e-02, -5.059974904e-02, -5.213170468e-02, -5.366353765e-02, -5.519524435e-02, -5.672682117e-02, -5.825826450e-02, -5.978957075e-02, -6.132073630e-02, -6.285175756e-02, -6.438263093e-02, -6.591335280e-02, -6.744391956e-02, -6.897432763e-02, -7.050457339e-02, -7.203465325e-02, -7.356456360e-02, -7.509430085e-02, -7.662386139e-02, -7.815324163e-02, -7.968243797e-02, -8.121144681e-02, -8.274026455e-02, -8.426888759e-02, -8.579731234e-02, -8.732553521e-02, -8.885355258e-02, -9.038136088e-02, -9.190895650e-02, -9.343633585e-02, -9.496349533e-02, -9.649043136e-02, -9.801714033e-02, -9.954361866e-02, -1.010698628e-01, -1.025958690e-01, -1.041216339e-01, -1.056471537e-01, -1.071724250e-01, -1.086974440e-01, -1.102222073e-01, -1.117467112e-01, -1.132709522e-01, -1.147949266e-01, -1.163186309e-01, -1.178420615e-01, -1.193652148e-01, -1.208880872e-01, -1.224106752e-01, -1.239329751e-01, -1.254549834e-01, -1.269766965e-01, -1.284981108e-01, -1.300192227e-01, -1.315400287e-01, -1.330605252e-01, -1.345807085e-01, -1.361005752e-01, -1.376201216e-01, -1.391393442e-01, -1.406582393e-01, -1.421768035e-01, -1.436950332e-01, -1.452129247e-01, -1.467304745e-01, -1.482476790e-01, -1.497645347e-01, -1.512810380e-01, -1.527971853e-01, -1.543129730e-01, -1.558283977e-01, -1.573434556e-01, -1.588581433e-01, -1.603724572e-01, -1.618863938e-01, -1.633999494e-01, -1.649131205e-01, -1.664259035e-01, -1.679382950e-01, -1.694502912e-01, -1.709618888e-01, -1.724730840e-01, -1.739838734e-01, -1.754942534e-01, -1.770042204e-01, -1.785137709e-01, -1.800229014e-01, -1.815316083e-01, -1.830398880e-01, -1.845477369e-01, -1.860551517e-01, -1.875621286e-01, -1.890686641e-01, -1.905747548e-01, -1.920803970e-01, -1.935855873e-01, -1.950903220e-01, -1.965945977e-01, -1.980984107e-01, -1.996017576e-01, -2.011046348e-01, -2.026070388e-01, -2.041089661e-01, -2.056104131e-01, -2.071113762e-01, -2.086118520e-01, -2.101118369e-01, -2.116113274e-01, -2.131103199e-01, -2.146088110e-01, -2.161067971e-01, -2.176042746e-01, -2.191012402e-01, -2.205976901e-01, -2.220936210e-01, -2.235890292e-01, -2.250839114e-01, -2.265782638e-01, -2.280720832e-01, -2.295653658e-01, -2.310581083e-01, -2.325503070e-01, -2.340419586e-01, -2.355330594e-01, -2.370236060e-01, -2.385135948e-01, -2.400030224e-01, -2.414918853e-01, -2.429801799e-01, -2.444679027e-01, -2.459550503e-01, -2.474416192e-01, -2.489276057e-01, -2.504130066e-01, -2.518978182e-01, -2.533820370e-01, -2.548656596e-01, -2.563486825e-01, -2.578311022e-01, -2.593129151e-01, -2.607941179e-01, -2.622747070e-01, -2.637546790e-01, -2.652340303e-01, -2.667127575e-01, -2.681908571e-01, -2.696683256e-01, -2.711451595e-01, -2.726213554e-01, -2.740969099e-01, -2.755718193e-01, -2.770460803e-01, -2.785196894e-01, -2.799926431e-01, -2.814649379e-01, -2.829365705e-01, -2.844075372e-01, -2.858778347e-01, -2.873474595e-01, -2.888164082e-01, -2.902846773e-01, -2.917522632e-01, -2.932191627e-01, -2.946853722e-01, -2.961508882e-01, -2.976157074e-01, -2.990798263e-01, -3.005432414e-01, -3.020059493e-01, -3.034679466e-01, -3.049292297e-01, -3.063897954e-01, -3.078496400e-01, -3.093087603e-01, -3.107671527e-01, -3.122248139e-01, -3.136817404e-01, -3.151379288e-01, -3.165933756e-01, -3.180480774e-01, -3.195020308e-01, -3.209552324e-01, -3.224076788e-01, -3.238593665e-01, -3.253102922e-01, -3.267604523e-01, -3.282098436e-01, -3.296584625e-01, -3.311063058e-01, -3.325533699e-01, -3.339996514e-01, -3.354451471e-01, -3.368898534e-01, -3.383337670e-01, -3.397768844e-01, -3.412192023e-01, -3.426607173e-01, -3.441014260e-01, -3.455413250e-01, -3.469804108e-01, -3.484186802e-01, -3.498561298e-01, -3.512927561e-01, -3.527285558e-01, -3.541635254e-01, -3.555976617e-01, -3.570309612e-01, -3.584634206e-01, -3.598950365e-01, -3.613258056e-01, -3.627557244e-01, -3.641847896e-01, -3.656129978e-01, -3.670403457e-01, -3.684668300e-01, -3.698924471e-01, -3.713171940e-01, -3.727410670e-01, -3.741640630e-01, -3.755861785e-01, -3.770074102e-01, -3.784277548e-01, -3.798472089e-01, -3.812657692e-01, -3.826834324e-01, -3.841001950e-01, -3.855160538e-01, -3.869310055e-01, -3.883450467e-01, -3.897581741e-01, -3.911703843e-01, -3.925816741e-01, -3.939920401e-01, -3.954014789e-01, -3.968099874e-01, -3.982175622e-01, -3.996241998e-01, -4.010298972e-01, -4.024346509e-01, -4.038384576e-01, -4.052413140e-01, -4.066432169e-01, -4.080441629e-01, -4.094441487e-01, -4.108431711e-01, -4.122412267e-01, -4.136383122e-01, -4.150344245e-01, -4.164295601e-01, -4.178237158e-01, -4.192168884e-01, -4.206090744e-01, -4.220002708e-01, -4.233904741e-01, -4.247796812e-01, -4.261678887e-01, -4.275550934e-01, -4.289412921e-01, -4.303264813e-01, -4.317106580e-01, -4.330938189e-01, -4.344759606e-01, -4.358570799e-01, -4.372371737e-01, -4.386162385e-01, -4.399942713e-01, -4.413712687e-01, -4.427472276e-01, -4.441221446e-01, -4.454960165e-01, -4.468688402e-01, -4.482406123e-01, -4.496113297e-01, -4.509809890e-01, -4.523495872e-01, -4.537171210e-01, -4.550835871e-01, -4.564489824e-01, -4.578133036e-01, -4.591765475e-01, -4.605387110e-01, -4.618997907e-01, -4.632597836e-01, -4.646186863e-01, -4.659764958e-01, -4.673332087e-01, -4.686888220e-01, -4.700433325e-01, -4.713967368e-01, -4.727490320e-01, -4.741002147e-01, -4.754502817e-01, -4.767992301e-01, -4.781470564e-01, -4.794937577e-01, -4.808393306e-01, -4.821837721e-01, -4.835270789e-01, -4.848692480e-01, -4.862102761e-01, -4.875501601e-01, -4.888888969e-01, -4.902264833e-01, -4.915629161e-01, -4.928981922e-01, -4.942323085e-01, -4.955652618e-01, -4.968970490e-01, -4.982276670e-01, -4.995571125e-01, -5.008853826e-01, -5.022124740e-01, -5.035383837e-01, -5.048631085e-01, -5.061866453e-01, -5.075089911e-01, -5.088301425e-01, -5.101500967e-01, -5.114688504e-01, -5.127864006e-01, -5.141027442e-01, -5.154178780e-01, -5.167317990e-01, -5.180445041e-01, -5.193559902e-01, -5.206662541e-01, -5.219752929e-01, -5.232831035e-01, -5.245896827e-01, -5.258950275e-01, -5.271991348e-01, -5.285020015e-01, -5.298036247e-01, -5.311040012e-01, -5.324031279e-01, -5.337010018e-01, -5.349976199e-01, -5.362929791e-01, -5.375870763e-01, -5.388799085e-01, -5.401714727e-01, -5.414617659e-01, -5.427507849e-01, -5.440385267e-01, -5.453249884e-01, -5.466101669e-01, -5.478940592e-01, -5.491766622e-01, -5.504579729e-01, -5.517379884e-01, -5.530167056e-01, -5.542941215e-01, -5.555702330e-01, -5.568450373e-01, -5.581185312e-01, -5.593907119e-01, -5.606615762e-01, -5.619311212e-01, -5.631993440e-01, -5.644662415e-01, -5.657318108e-01, -5.669960488e-01, -5.682589527e-01, -5.695205193e-01, -5.707807459e-01, -5.720396293e-01, -5.732971667e-01, -5.745533550e-01, -5.758081914e-01, -5.770616729e-01, -5.783137964e-01, -5.795645591e-01, -5.808139581e-01, -5.820619903e-01, -5.833086529e-01, -5.845539430e-01, -5.857978575e-01, -5.870403935e-01, -5.882815482e-01, -5.895213186e-01, -5.907597019e-01, -5.919966950e-01, -5.932322950e-01, -5.944664992e-01, -5.956993045e-01, -5.969307081e-01, -5.981607070e-01, -5.993892984e-01, -6.006164794e-01, -6.018422471e-01, -6.030665985e-01, -6.042895309e-01, -6.055110414e-01, -6.067311270e-01, -6.079497850e-01, -6.091670123e-01, -6.103828063e-01, -6.115971639e-01, -6.128100824e-01, -6.140215589e-01, -6.152315906e-01, -6.164401745e-01, -6.176473079e-01, -6.188529880e-01, -6.200572118e-01, -6.212599765e-01, -6.224612794e-01, -6.236611175e-01, -6.248594881e-01, -6.260563884e-01, -6.272518155e-01, -6.284457666e-01, -6.296382389e-01, -6.308292296e-01, -6.320187359e-01, -6.332067551e-01, -6.343932842e-01, -6.355783205e-01, -6.367618612e-01, -6.379439036e-01, -6.391244449e-01, -6.403034822e-01, -6.414810128e-01, -6.426570340e-01, -6.438315429e-01, -6.450045368e-01, -6.461760130e-01, -6.473459686e-01, -6.485144010e-01, -6.496813074e-01, -6.508466850e-01, -6.520105311e-01, -6.531728430e-01, -6.543336178e-01, -6.554928530e-01, -6.566505457e-01, -6.578066933e-01, -6.589612930e-01, -6.601143421e-01, -6.612658378e-01, -6.624157776e-01, -6.635641586e-01, -6.647109782e-01, -6.658562337e-01, -6.669999223e-01, -6.681420414e-01, -6.692825883e-01, -6.704215604e-01, -6.715589548e-01, -6.726947691e-01, -6.738290004e-01, -6.749616461e-01, -6.760927036e-01, -6.772221701e-01, -6.783500431e-01, -6.794763199e-01, -6.806009978e-01, -6.817240742e-01, -6.828455464e-01, -6.839654118e-01, -6.850836678e-01, -6.862003117e-01, -6.873153409e-01, -6.884287528e-01, -6.895405447e-01, -6.906507141e-01, -6.917592584e-01, -6.928661748e-01, -6.939714609e-01, -6.950751140e-01, -6.961771315e-01, -6.972775108e-01, -6.983762494e-01, -6.994733446e-01, -7.005687939e-01, -7.016625947e-01, -7.027547445e-01, -7.038452405e-01, -7.049340804e-01, -7.060212614e-01, -7.071067812e-01, -7.081906370e-01, -7.092728264e-01, -7.103533469e-01, -7.114321957e-01, -7.125093706e-01, -7.135848688e-01, -7.146586879e-01, -7.157308253e-01, -7.168012785e-01, -7.178700451e-01, -7.189371224e-01, -7.200025080e-01, -7.210661993e-01, -7.221281939e-01, -7.231884893e-01, -7.242470830e-01, -7.253039724e-01, -7.263591551e-01, -7.274126286e-01, -7.284643904e-01, -7.295144381e-01, -7.305627692e-01, -7.316093812e-01, -7.326542717e-01, -7.336974381e-01, -7.347388781e-01, -7.357785892e-01, -7.368165689e-01, -7.378528148e-01, -7.388873245e-01, -7.399200955e-01, -7.409511254e-01, -7.419804117e-01, -7.430079521e-01, -7.440337442e-01, -7.450577854e-01, -7.460800735e-01, -7.471006060e-01, -7.481193805e-01, -7.491363945e-01, -7.501516458e-01, -7.511651319e-01, -7.521768504e-01, -7.531867990e-01, -7.541949753e-01, -7.552013769e-01, -7.562060014e-01, -7.572088465e-01, -7.582099098e-01, -7.592091890e-01, -7.602066817e-01, -7.612023855e-01, -7.621962981e-01, -7.631884173e-01, -7.641787405e-01, -7.651672656e-01, -7.661539902e-01, -7.671389119e-01, -7.681220285e-01, -7.691033376e-01, -7.700828370e-01, -7.710605243e-01, -7.720363972e-01, -7.730104534e-01, -7.739826906e-01, -7.749531066e-01, -7.759216990e-01, -7.768884657e-01, -7.778534042e-01, -7.788165124e-01, -7.797777879e-01, -7.807372286e-01, -7.816948321e-01, -7.826505962e-01, -7.836045186e-01, -7.845565972e-01, -7.855068296e-01, -7.864552136e-01, -7.874017470e-01, -7.883464276e-01, -7.892892532e-01, -7.902302214e-01, -7.911693302e-01, -7.921065773e-01, -7.930419605e-01, -7.939754776e-01, -7.949071263e-01, -7.958369046e-01, -7.967648102e-01, -7.976908409e-01, -7.986149946e-01, -7.995372691e-01, -8.004576622e-01, -8.013761717e-01, -8.022927955e-01, -8.032075315e-01, -8.041203774e-01, -8.050313311e-01, -8.059403906e-01, -8.068475535e-01, -8.077528179e-01, -8.086561816e-01, -8.095576424e-01, -8.104571983e-01, -8.113548470e-01, -8.122505866e-01, -8.131444148e-01, -8.140363297e-01, -8.149263291e-01, -8.158144108e-01, -8.167005729e-01, -8.175848132e-01, -8.184671296e-01, -8.193475201e-01, -8.202259826e-01, -8.211025150e-01, -8.219771153e-01, -8.228497814e-01, -8.237205112e-01, -8.245893028e-01, -8.254561540e-01, -8.263210628e-01, -8.271840273e-01, -8.280450453e-01, -8.289041148e-01, -8.297612338e-01, -8.306164003e-01, -8.314696123e-01, -8.323208678e-01, -8.331701647e-01, -8.340175011e-01, -8.348628750e-01, -8.357062844e-01, -8.365477272e-01, -8.373872016e-01, -8.382247056e-01, -8.390602371e-01, -8.398937942e-01, -8.407253750e-01, -8.415549774e-01, -8.423825996e-01, -8.432082396e-01, -8.440318955e-01, -8.448535652e-01, -8.456732470e-01, -8.464909388e-01, -8.473066387e-01, -8.481203448e-01, -8.489320552e-01, -8.497417680e-01, -8.505494813e-01, -8.513551931e-01, -8.521589016e-01, -8.529606049e-01, -8.537603011e-01, -8.545579884e-01, -8.553536647e-01, -8.561473284e-01, -8.569389774e-01, -8.577286100e-01, -8.585162243e-01, -8.593018184e-01, -8.600853904e-01, -8.608669386e-01, -8.616464611e-01, -8.624239561e-01, -8.631994217e-01, -8.639728561e-01, -8.647442575e-01, -8.655136241e-01, -8.662809540e-01, -8.670462455e-01, -8.678094968e-01, -8.685707060e-01, -8.693298713e-01, -8.700869911e-01, -8.708420635e-01, -8.715950867e-01, -8.723460589e-01, -8.730949784e-01, -8.738418435e-01, -8.745866523e-01, -8.753294031e-01, -8.760700942e-01, -8.768087238e-01, -8.775452902e-01, -8.782797917e-01, -8.790122264e-01, -8.797425928e-01, -8.804708891e-01, -8.811971135e-01, -8.819212643e-01, -8.826433400e-01, -8.833633387e-01, -8.840812587e-01, -8.847970984e-01, -8.855108561e-01, -8.862225301e-01, -8.869321188e-01, -8.876396204e-01, -8.883450333e-01, -8.890483559e-01, -8.897495864e-01, -8.904487232e-01, -8.911457648e-01, -8.918407094e-01, -8.925335554e-01, -8.932243012e-01, -8.939129451e-01, -8.945994856e-01, -8.952839210e-01, -8.959662498e-01, -8.966464702e-01, -8.973245807e-01, -8.980005797e-01, -8.986744657e-01, -8.993462370e-01, -9.000158920e-01, -9.006834292e-01, -9.013488470e-01, -9.020121439e-01, -9.026733182e-01, -9.033323685e-01, -9.039892931e-01, -9.046440906e-01, -9.052967593e-01, -9.059472978e-01, -9.065957045e-01, -9.072419779e-01, -9.078861165e-01, -9.085281187e-01, -9.091679831e-01, -9.098057081e-01, -9.104412923e-01, -9.110747341e-01, -9.117060320e-01, -9.123351846e-01, -9.129621904e-01, -9.135870479e-01, -9.142097557e-01, -9.148303122e-01, -9.154487161e-01, -9.160649658e-01, -9.166790599e-01, -9.172909970e-01, -9.179007756e-01, -9.185083943e-01, -9.191138517e-01, -9.197171463e-01, -9.203182767e-01, -9.209172415e-01, -9.215140393e-01, -9.221086687e-01, -9.227011283e-01, -9.232914167e-01, -9.238795325e-01, -9.244654743e-01, -9.250492408e-01, -9.256308305e-01, -9.262102421e-01, -9.267874743e-01, -9.273625257e-01, -9.279353948e-01, -9.285060805e-01, -9.290745813e-01, -9.296408958e-01, -9.302050229e-01, -9.307669611e-01, -9.313267091e-01, -9.318842656e-01, -9.324396293e-01, -9.329927988e-01, -9.335437730e-01, -9.340925504e-01, -9.346391298e-01, -9.351835099e-01, -9.357256895e-01, -9.362656672e-01, -9.368034417e-01, -9.373390119e-01, -9.378723764e-01, -9.384035341e-01, -9.389324835e-01, -9.394592236e-01, -9.399837530e-01, -9.405060706e-01, -9.410261751e-01, -9.415440652e-01, -9.420597398e-01, -9.425731976e-01, -9.430844375e-01, -9.435934582e-01, -9.441002585e-01, -9.446048373e-01, -9.451071933e-01, -9.456073254e-01, -9.461052324e-01, -9.466009131e-01, -9.470943664e-01, -9.475855910e-01, -9.480745859e-01, -9.485613499e-01, -9.490458819e-01, -9.495281806e-01, -9.500082450e-01, -9.504860739e-01, -9.509616663e-01, -9.514350210e-01, -9.519061368e-01, -9.523750127e-01, -9.528416476e-01, -9.533060404e-01, -9.537681899e-01, -9.542280951e-01, -9.546857549e-01, -9.551411683e-01, -9.555943341e-01, -9.560452513e-01, -9.564939189e-01, -9.569403357e-01, -9.573845008e-01, -9.578264130e-01, -9.582660714e-01, -9.587034749e-01, -9.591386225e-01, -9.595715131e-01, -9.600021457e-01, -9.604305194e-01, -9.608566331e-01, -9.612804858e-01, -9.617020765e-01, -9.621214043e-01, -9.625384680e-01, -9.629532669e-01, -9.633657998e-01, -9.637760658e-01, -9.641840640e-01, -9.645897933e-01, -9.649932529e-01, -9.653944417e-01, -9.657933589e-01, -9.661900034e-01, -9.665843745e-01, -9.669764710e-01, -9.673662922e-01, -9.677538371e-01, -9.681391047e-01, -9.685220943e-01, -9.689028048e-01, -9.692812354e-01, -9.696573851e-01, -9.700312532e-01, -9.704028387e-01, -9.707721407e-01, -9.711391584e-01, -9.715038910e-01, -9.718663375e-01, -9.722264971e-01, -9.725843689e-01, -9.729399522e-01, -9.732932461e-01, -9.736442497e-01, -9.739929622e-01, -9.743393828e-01, -9.746835107e-01, -9.750253451e-01, -9.753648851e-01, -9.757021300e-01, -9.760370790e-01, -9.763697313e-01, -9.767000861e-01, -9.770281427e-01, -9.773539001e-01, -9.776773578e-01, -9.779985149e-01, -9.783173707e-01, -9.786339244e-01, -9.789481753e-01, -9.792601226e-01, -9.795697657e-01, -9.798771037e-01, -9.801821360e-01, -9.804848618e-01, -9.807852804e-01, -9.810833912e-01, -9.813791933e-01, -9.816726862e-01, -9.819638691e-01, -9.822527414e-01, -9.825393023e-01, -9.828235512e-01, -9.831054874e-01, -9.833851103e-01, -9.836624192e-01, -9.839374134e-01, -9.842100924e-01, -9.844804554e-01, -9.847485018e-01, -9.850142310e-01, -9.852776424e-01, -9.855387353e-01, -9.857975092e-01, -9.860539633e-01, -9.863080972e-01, -9.865599103e-01, -9.868094018e-01, -9.870565713e-01, -9.873014182e-01, -9.875439418e-01, -9.877841416e-01, -9.880220171e-01, -9.882575677e-01, -9.884907929e-01, -9.887216920e-01, -9.889502645e-01, -9.891765100e-01, -9.894004278e-01, -9.896220175e-01, -9.898412785e-01, -9.900582103e-01, -9.902728124e-01, -9.904850843e-01, -9.906950254e-01, -9.909026354e-01, -9.911079137e-01, -9.913108598e-01, -9.915114733e-01, -9.917097537e-01, -9.919057004e-01, -9.920993131e-01, -9.922905913e-01, -9.924795346e-01, -9.926661424e-01, -9.928504145e-01, -9.930323502e-01, -9.932119492e-01, -9.933892111e-01, -9.935641355e-01, -9.937367219e-01, -9.939069700e-01, -9.940748793e-01, -9.942404495e-01, -9.944036801e-01, -9.945645707e-01, -9.947231211e-01, -9.948793308e-01, -9.950331994e-01, -9.951847267e-01, -9.953339121e-01, -9.954807555e-01, -9.956252564e-01, -9.957674145e-01, -9.959072294e-01, -9.960447009e-01, -9.961798286e-01, -9.963126122e-01, -9.964430514e-01, -9.965711458e-01, -9.966968952e-01, -9.968202993e-01, -9.969413578e-01, -9.970600703e-01, -9.971764367e-01, -9.972904567e-01, -9.974021299e-01, -9.975114561e-01, -9.976184351e-01, -9.977230666e-01, -9.978253504e-01, -9.979252862e-01, -9.980228738e-01, -9.981181129e-01, -9.982110034e-01, -9.983015449e-01, -9.983897374e-01, -9.984755806e-01, -9.985590742e-01, -9.986402182e-01, -9.987190122e-01, -9.987954562e-01, -9.988695499e-01, -9.989412932e-01, -9.990106859e-01, -9.990777278e-01, -9.991424187e-01, -9.992047586e-01, -9.992647473e-01, -9.993223846e-01, -9.993776704e-01, -9.994306046e-01, -9.994811870e-01, -9.995294175e-01, -9.995752960e-01, -9.996188225e-01, -9.996599967e-01, -9.996988187e-01, -9.997352883e-01, -9.997694054e-01, -9.998011699e-01, -9.998305818e-01, -9.998576410e-01, -9.998823475e-01, -9.999047011e-01, -9.999247018e-01, -9.999423497e-01, -9.999576446e-01, -9.999705864e-01, -9.999811753e-01, -9.999894111e-01, -9.999952938e-01, -9.999988235e-01, -1.000000000e+00, -9.999988235e-01, -9.999952938e-01, -9.999894111e-01, -9.999811753e-01, -9.999705864e-01, -9.999576446e-01, -9.999423497e-01, -9.999247018e-01, -9.999047011e-01, -9.998823475e-01, -9.998576410e-01, -9.998305818e-01, -9.998011699e-01, -9.997694054e-01, -9.997352883e-01, -9.996988187e-01, -9.996599967e-01, -9.996188225e-01, -9.995752960e-01, -9.995294175e-01, -9.994811870e-01, -9.994306046e-01, -9.993776704e-01, -9.993223846e-01, -9.992647473e-01, -9.992047586e-01, -9.991424187e-01, -9.990777278e-01, -9.990106859e-01, -9.989412932e-01, -9.988695499e-01, -9.987954562e-01, -9.987190122e-01, -9.986402182e-01, -9.985590742e-01, -9.984755806e-01, -9.983897374e-01, -9.983015449e-01, -9.982110034e-01, -9.981181129e-01, -9.980228738e-01, -9.979252862e-01, -9.978253504e-01, -9.977230666e-01, -9.976184351e-01, -9.975114561e-01, -9.974021299e-01, -9.972904567e-01, -9.971764367e-01, -9.970600703e-01, -9.969413578e-01, -9.968202993e-01, -9.966968952e-01, -9.965711458e-01, -9.964430514e-01, -9.963126122e-01, -9.961798286e-01, -9.960447009e-01, -9.959072294e-01, -9.957674145e-01, -9.956252564e-01, -9.954807555e-01, -9.953339121e-01, -9.951847267e-01, -9.950331994e-01, -9.948793308e-01, -9.947231211e-01, -9.945645707e-01, -9.944036801e-01, -9.942404495e-01, -9.940748793e-01, -9.939069700e-01, -9.937367219e-01, -9.935641355e-01, -9.933892111e-01, -9.932119492e-01, -9.930323502e-01, -9.928504145e-01, -9.926661424e-01, -9.924795346e-01, -9.922905913e-01, -9.920993131e-01, -9.919057004e-01, -9.917097537e-01, -9.915114733e-01, -9.913108598e-01, -9.911079137e-01, -9.909026354e-01, -9.906950254e-01, -9.904850843e-01, -9.902728124e-01, -9.900582103e-01, -9.898412785e-01, -9.896220175e-01, -9.894004278e-01, -9.891765100e-01, -9.889502645e-01, -9.887216920e-01, -9.884907929e-01, -9.882575677e-01, -9.880220171e-01, -9.877841416e-01, -9.875439418e-01, -9.873014182e-01, -9.870565713e-01, -9.868094018e-01, -9.865599103e-01, -9.863080972e-01, -9.860539633e-01, -9.857975092e-01, -9.855387353e-01, -9.852776424e-01, -9.850142310e-01, -9.847485018e-01, -9.844804554e-01, -9.842100924e-01, -9.839374134e-01, -9.836624192e-01, -9.833851103e-01, -9.831054874e-01, -9.828235512e-01, -9.825393023e-01, -9.822527414e-01, -9.819638691e-01, -9.816726862e-01, -9.813791933e-01, -9.810833912e-01, -9.807852804e-01, -9.804848618e-01, -9.801821360e-01, -9.798771037e-01, -9.795697657e-01, -9.792601226e-01, -9.789481753e-01, -9.786339244e-01, -9.783173707e-01, -9.779985149e-01, -9.776773578e-01, -9.773539001e-01, -9.770281427e-01, -9.767000861e-01, -9.763697313e-01, -9.760370790e-01, -9.757021300e-01, -9.753648851e-01, -9.750253451e-01, -9.746835107e-01, -9.743393828e-01, -9.739929622e-01, -9.736442497e-01, -9.732932461e-01, -9.729399522e-01, -9.725843689e-01, -9.722264971e-01, -9.718663375e-01, -9.715038910e-01, -9.711391584e-01, -9.707721407e-01, -9.704028387e-01, -9.700312532e-01, -9.696573851e-01, -9.692812354e-01, -9.689028048e-01, -9.685220943e-01, -9.681391047e-01, -9.677538371e-01, -9.673662922e-01, -9.669764710e-01, -9.665843745e-01, -9.661900034e-01, -9.657933589e-01, -9.653944417e-01, -9.649932529e-01, -9.645897933e-01, -9.641840640e-01, -9.637760658e-01, -9.633657998e-01, -9.629532669e-01, -9.625384680e-01, -9.621214043e-01, -9.617020765e-01, -9.612804858e-01, -9.608566331e-01, -9.604305194e-01, -9.600021457e-01, -9.595715131e-01, -9.591386225e-01, -9.587034749e-01, -9.582660714e-01, -9.578264130e-01, -9.573845008e-01, -9.569403357e-01, -9.564939189e-01, -9.560452513e-01, -9.555943341e-01, -9.551411683e-01, -9.546857549e-01, -9.542280951e-01, -9.537681899e-01, -9.533060404e-01, -9.528416476e-01, -9.523750127e-01, -9.519061368e-01, -9.514350210e-01, -9.509616663e-01, -9.504860739e-01, -9.500082450e-01, -9.495281806e-01, -9.490458819e-01, -9.485613499e-01, -9.480745859e-01, -9.475855910e-01, -9.470943664e-01, -9.466009131e-01, -9.461052324e-01, -9.456073254e-01, -9.451071933e-01, -9.446048373e-01, -9.441002585e-01, -9.435934582e-01, -9.430844375e-01, -9.425731976e-01, -9.420597398e-01, -9.415440652e-01, -9.410261751e-01, -9.405060706e-01, -9.399837530e-01, -9.394592236e-01, -9.389324835e-01, -9.384035341e-01, -9.378723764e-01, -9.373390119e-01, -9.368034417e-01, -9.362656672e-01, -9.357256895e-01, -9.351835099e-01, -9.346391298e-01, -9.340925504e-01, -9.335437730e-01, -9.329927988e-01, -9.324396293e-01, -9.318842656e-01, -9.313267091e-01, -9.307669611e-01, -9.302050229e-01, -9.296408958e-01, -9.290745813e-01, -9.285060805e-01, -9.279353948e-01, -9.273625257e-01, -9.267874743e-01, -9.262102421e-01, -9.256308305e-01, -9.250492408e-01, -9.244654743e-01, -9.238795325e-01, -9.232914167e-01, -9.227011283e-01, -9.221086687e-01, -9.215140393e-01, -9.209172415e-01, -9.203182767e-01, -9.197171463e-01, -9.191138517e-01, -9.185083943e-01, -9.179007756e-01, -9.172909970e-01, -9.166790599e-01, -9.160649658e-01, -9.154487161e-01, -9.148303122e-01, -9.142097557e-01, -9.135870479e-01, -9.129621904e-01, -9.123351846e-01, -9.117060320e-01, -9.110747341e-01, -9.104412923e-01, -9.098057081e-01, -9.091679831e-01, -9.085281187e-01, -9.078861165e-01, -9.072419779e-01, -9.065957045e-01, -9.059472978e-01, -9.052967593e-01, -9.046440906e-01, -9.039892931e-01, -9.033323685e-01, -9.026733182e-01, -9.020121439e-01, -9.013488470e-01, -9.006834292e-01, -9.000158920e-01, -8.993462370e-01, -8.986744657e-01, -8.980005797e-01, -8.973245807e-01, -8.966464702e-01, -8.959662498e-01, -8.952839210e-01, -8.945994856e-01, -8.939129451e-01, -8.932243012e-01, -8.925335554e-01, -8.918407094e-01, -8.911457648e-01, -8.904487232e-01, -8.897495864e-01, -8.890483559e-01, -8.883450333e-01, -8.876396204e-01, -8.869321188e-01, -8.862225301e-01, -8.855108561e-01, -8.847970984e-01, -8.840812587e-01, -8.833633387e-01, -8.826433400e-01, -8.819212643e-01, -8.811971135e-01, -8.804708891e-01, -8.797425928e-01, -8.790122264e-01, -8.782797917e-01, -8.775452902e-01, -8.768087238e-01, -8.760700942e-01, -8.753294031e-01, -8.745866523e-01, -8.738418435e-01, -8.730949784e-01, -8.723460589e-01, -8.715950867e-01, -8.708420635e-01, -8.700869911e-01, -8.693298713e-01, -8.685707060e-01, -8.678094968e-01, -8.670462455e-01, -8.662809540e-01, -8.655136241e-01, -8.647442575e-01, -8.639728561e-01, -8.631994217e-01, -8.624239561e-01, -8.616464611e-01, -8.608669386e-01, -8.600853904e-01, -8.593018184e-01, -8.585162243e-01, -8.577286100e-01, -8.569389774e-01, -8.561473284e-01, -8.553536647e-01, -8.545579884e-01, -8.537603011e-01, -8.529606049e-01, -8.521589016e-01, -8.513551931e-01, -8.505494813e-01, -8.497417680e-01, -8.489320552e-01, -8.481203448e-01, -8.473066387e-01, -8.464909388e-01, -8.456732470e-01, -8.448535652e-01, -8.440318955e-01, -8.432082396e-01, -8.423825996e-01, -8.415549774e-01, -8.407253750e-01, -8.398937942e-01, -8.390602371e-01, -8.382247056e-01, -8.373872016e-01, -8.365477272e-01, -8.357062844e-01, -8.348628750e-01, -8.340175011e-01, -8.331701647e-01, -8.323208678e-01, -8.314696123e-01, -8.306164003e-01, -8.297612338e-01, -8.289041148e-01, -8.280450453e-01, -8.271840273e-01, -8.263210628e-01, -8.254561540e-01, -8.245893028e-01, -8.237205112e-01, -8.228497814e-01, -8.219771153e-01, -8.211025150e-01, -8.202259826e-01, -8.193475201e-01, -8.184671296e-01, -8.175848132e-01, -8.167005729e-01, -8.158144108e-01, -8.149263291e-01, -8.140363297e-01, -8.131444148e-01, -8.122505866e-01, -8.113548470e-01, -8.104571983e-01, -8.095576424e-01, -8.086561816e-01, -8.077528179e-01, -8.068475535e-01, -8.059403906e-01, -8.050313311e-01, -8.041203774e-01, -8.032075315e-01, -8.022927955e-01, -8.013761717e-01, -8.004576622e-01, -7.995372691e-01, -7.986149946e-01, -7.976908409e-01, -7.967648102e-01, -7.958369046e-01, -7.949071263e-01, -7.939754776e-01, -7.930419605e-01, -7.921065773e-01, -7.911693302e-01, -7.902302214e-01, -7.892892532e-01, -7.883464276e-01, -7.874017470e-01, -7.864552136e-01, -7.855068296e-01, -7.845565972e-01, -7.836045186e-01, -7.826505962e-01, -7.816948321e-01, -7.807372286e-01, -7.797777879e-01, -7.788165124e-01, -7.778534042e-01, -7.768884657e-01, -7.759216990e-01, -7.749531066e-01, -7.739826906e-01, -7.730104534e-01, -7.720363972e-01, -7.710605243e-01, -7.700828370e-01, -7.691033376e-01, -7.681220285e-01, -7.671389119e-01, -7.661539902e-01, -7.651672656e-01, -7.641787405e-01, -7.631884173e-01, -7.621962981e-01, -7.612023855e-01, -7.602066817e-01, -7.592091890e-01, -7.582099098e-01, -7.572088465e-01, -7.562060014e-01, -7.552013769e-01, -7.541949753e-01, -7.531867990e-01, -7.521768504e-01, -7.511651319e-01, -7.501516458e-01, -7.491363945e-01, -7.481193805e-01, -7.471006060e-01, -7.460800735e-01, -7.450577854e-01, -7.440337442e-01, -7.430079521e-01, -7.419804117e-01, -7.409511254e-01, -7.399200955e-01, -7.388873245e-01, -7.378528148e-01, -7.368165689e-01, -7.357785892e-01, -7.347388781e-01, -7.336974381e-01, -7.326542717e-01, -7.316093812e-01, -7.305627692e-01, -7.295144381e-01, -7.284643904e-01, -7.274126286e-01, -7.263591551e-01, -7.253039724e-01, -7.242470830e-01, -7.231884893e-01, -7.221281939e-01, -7.210661993e-01, -7.200025080e-01, -7.189371224e-01, -7.178700451e-01, -7.168012785e-01, -7.157308253e-01, -7.146586879e-01, -7.135848688e-01, -7.125093706e-01, -7.114321957e-01, -7.103533469e-01, -7.092728264e-01, -7.081906370e-01, -7.071067812e-01, -7.060212614e-01, -7.049340804e-01, -7.038452405e-01, -7.027547445e-01, -7.016625947e-01, -7.005687939e-01, -6.994733446e-01, -6.983762494e-01, -6.972775108e-01, -6.961771315e-01, -6.950751140e-01, -6.939714609e-01, -6.928661748e-01, -6.917592584e-01, -6.906507141e-01, -6.895405447e-01, -6.884287528e-01, -6.873153409e-01, -6.862003117e-01, -6.850836678e-01, -6.839654118e-01, -6.828455464e-01, -6.817240742e-01, -6.806009978e-01, -6.794763199e-01, -6.783500431e-01, -6.772221701e-01, -6.760927036e-01, -6.749616461e-01, -6.738290004e-01, -6.726947691e-01, -6.715589548e-01, -6.704215604e-01, -6.692825883e-01, -6.681420414e-01, -6.669999223e-01, -6.658562337e-01, -6.647109782e-01, -6.635641586e-01, -6.624157776e-01, -6.612658378e-01, -6.601143421e-01, -6.589612930e-01, -6.578066933e-01, -6.566505457e-01, -6.554928530e-01, -6.543336178e-01, -6.531728430e-01, -6.520105311e-01, -6.508466850e-01, -6.496813074e-01, -6.485144010e-01, -6.473459686e-01, -6.461760130e-01, -6.450045368e-01, -6.438315429e-01, -6.426570340e-01, -6.414810128e-01, -6.403034822e-01, -6.391244449e-01, -6.379439036e-01, -6.367618612e-01, -6.355783205e-01, -6.343932842e-01, -6.332067551e-01, -6.320187359e-01, -6.308292296e-01, -6.296382389e-01, -6.284457666e-01, -6.272518155e-01, -6.260563884e-01, -6.248594881e-01, -6.236611175e-01, -6.224612794e-01, -6.212599765e-01, -6.200572118e-01, -6.188529880e-01, -6.176473079e-01, -6.164401745e-01, -6.152315906e-01, -6.140215589e-01, -6.128100824e-01, -6.115971639e-01, -6.103828063e-01, -6.091670123e-01, -6.079497850e-01, -6.067311270e-01, -6.055110414e-01, -6.042895309e-01, -6.030665985e-01, -6.018422471e-01, -6.006164794e-01, -5.993892984e-01, -5.981607070e-01, -5.969307081e-01, -5.956993045e-01, -5.944664992e-01, -5.932322950e-01, -5.919966950e-01, -5.907597019e-01, -5.895213186e-01, -5.882815482e-01, -5.870403935e-01, -5.857978575e-01, -5.845539430e-01, -5.833086529e-01, -5.820619903e-01, -5.808139581e-01, -5.795645591e-01, -5.783137964e-01, -5.770616729e-01, -5.758081914e-01, -5.745533550e-01, -5.732971667e-01, -5.720396293e-01, -5.707807459e-01, -5.695205193e-01, -5.682589527e-01, -5.669960488e-01, -5.657318108e-01, -5.644662415e-01, -5.631993440e-01, -5.619311212e-01, -5.606615762e-01, -5.593907119e-01, -5.581185312e-01, -5.568450373e-01, -5.555702330e-01, -5.542941215e-01, -5.530167056e-01, -5.517379884e-01, -5.504579729e-01, -5.491766622e-01, -5.478940592e-01, -5.466101669e-01, -5.453249884e-01, -5.440385267e-01, -5.427507849e-01, -5.414617659e-01, -5.401714727e-01, -5.388799085e-01, -5.375870763e-01, -5.362929791e-01, -5.349976199e-01, -5.337010018e-01, -5.324031279e-01, -5.311040012e-01, -5.298036247e-01, -5.285020015e-01, -5.271991348e-01, -5.258950275e-01, -5.245896827e-01, -5.232831035e-01, -5.219752929e-01, -5.206662541e-01, -5.193559902e-01, -5.180445041e-01, -5.167317990e-01, -5.154178780e-01, -5.141027442e-01, -5.127864006e-01, -5.114688504e-01, -5.101500967e-01, -5.088301425e-01, -5.075089911e-01, -5.061866453e-01, -5.048631085e-01, -5.035383837e-01, -5.022124740e-01, -5.008853826e-01, -4.995571125e-01, -4.982276670e-01, -4.968970490e-01, -4.955652618e-01, -4.942323085e-01, -4.928981922e-01, -4.915629161e-01, -4.902264833e-01, -4.888888969e-01, -4.875501601e-01, -4.862102761e-01, -4.848692480e-01, -4.835270789e-01, -4.821837721e-01, -4.808393306e-01, -4.794937577e-01, -4.781470564e-01, -4.767992301e-01, -4.754502817e-01, -4.741002147e-01, -4.727490320e-01, -4.713967368e-01, -4.700433325e-01, -4.686888220e-01, -4.673332087e-01, -4.659764958e-01, -4.646186863e-01, -4.632597836e-01, -4.618997907e-01, -4.605387110e-01, -4.591765475e-01, -4.578133036e-01, -4.564489824e-01, -4.550835871e-01, -4.537171210e-01, -4.523495872e-01, -4.509809890e-01, -4.496113297e-01, -4.482406123e-01, -4.468688402e-01, -4.454960165e-01, -4.441221446e-01, -4.427472276e-01, -4.413712687e-01, -4.399942713e-01, -4.386162385e-01, -4.372371737e-01, -4.358570799e-01, -4.344759606e-01, -4.330938189e-01, -4.317106580e-01, -4.303264813e-01, -4.289412921e-01, -4.275550934e-01, -4.261678887e-01, -4.247796812e-01, -4.233904741e-01, -4.220002708e-01, -4.206090744e-01, -4.192168884e-01, -4.178237158e-01, -4.164295601e-01, -4.150344245e-01, -4.136383122e-01, -4.122412267e-01, -4.108431711e-01, -4.094441487e-01, -4.080441629e-01, -4.066432169e-01, -4.052413140e-01, -4.038384576e-01, -4.024346509e-01, -4.010298972e-01, -3.996241998e-01, -3.982175622e-01, -3.968099874e-01, -3.954014789e-01, -3.939920401e-01, -3.925816741e-01, -3.911703843e-01, -3.897581741e-01, -3.883450467e-01, -3.869310055e-01, -3.855160538e-01, -3.841001950e-01, -3.826834324e-01, -3.812657692e-01, -3.798472089e-01, -3.784277548e-01, -3.770074102e-01, -3.755861785e-01, -3.741640630e-01, -3.727410670e-01, -3.713171940e-01, -3.698924471e-01, -3.684668300e-01, -3.670403457e-01, -3.656129978e-01, -3.641847896e-01, -3.627557244e-01, -3.613258056e-01, -3.598950365e-01, -3.584634206e-01, -3.570309612e-01, -3.555976617e-01, -3.541635254e-01, -3.527285558e-01, -3.512927561e-01, -3.498561298e-01, -3.484186802e-01, -3.469804108e-01, -3.455413250e-01, -3.441014260e-01, -3.426607173e-01, -3.412192023e-01, -3.397768844e-01, -3.383337670e-01, -3.368898534e-01, -3.354451471e-01, -3.339996514e-01, -3.325533699e-01, -3.311063058e-01, -3.296584625e-01, -3.282098436e-01, -3.267604523e-01, -3.253102922e-01, -3.238593665e-01, -3.224076788e-01, -3.209552324e-01, -3.195020308e-01, -3.180480774e-01, -3.165933756e-01, -3.151379288e-01, -3.136817404e-01, -3.122248139e-01, -3.107671527e-01, -3.093087603e-01, -3.078496400e-01, -3.063897954e-01, -3.049292297e-01, -3.034679466e-01, -3.020059493e-01, -3.005432414e-01, -2.990798263e-01, -2.976157074e-01, -2.961508882e-01, -2.946853722e-01, -2.932191627e-01, -2.917522632e-01, -2.902846773e-01, -2.888164082e-01, -2.873474595e-01, -2.858778347e-01, -2.844075372e-01, -2.829365705e-01, -2.814649379e-01, -2.799926431e-01, -2.785196894e-01, -2.770460803e-01, -2.755718193e-01, -2.740969099e-01, -2.726213554e-01, -2.711451595e-01, -2.696683256e-01, -2.681908571e-01, -2.667127575e-01, -2.652340303e-01, -2.637546790e-01, -2.622747070e-01, -2.607941179e-01, -2.593129151e-01, -2.578311022e-01, -2.563486825e-01, -2.548656596e-01, -2.533820370e-01, -2.518978182e-01, -2.504130066e-01, -2.489276057e-01, -2.474416192e-01, -2.459550503e-01, -2.444679027e-01, -2.429801799e-01, -2.414918853e-01, -2.400030224e-01, -2.385135948e-01, -2.370236060e-01, -2.355330594e-01, -2.340419586e-01, -2.325503070e-01, -2.310581083e-01, -2.295653658e-01, -2.280720832e-01, -2.265782638e-01, -2.250839114e-01, -2.235890292e-01, -2.220936210e-01, -2.205976901e-01, -2.191012402e-01, -2.176042746e-01, -2.161067971e-01, -2.146088110e-01, -2.131103199e-01, -2.116113274e-01, -2.101118369e-01, -2.086118520e-01, -2.071113762e-01, -2.056104131e-01, -2.041089661e-01, -2.026070388e-01, -2.011046348e-01, -1.996017576e-01, -1.980984107e-01, -1.965945977e-01, -1.950903220e-01, -1.935855873e-01, -1.920803970e-01, -1.905747548e-01, -1.890686641e-01, -1.875621286e-01, -1.860551517e-01, -1.845477369e-01, -1.830398880e-01, -1.815316083e-01, -1.800229014e-01, -1.785137709e-01, -1.770042204e-01, -1.754942534e-01, -1.739838734e-01, -1.724730840e-01, -1.709618888e-01, -1.694502912e-01, -1.679382950e-01, -1.664259035e-01, -1.649131205e-01, -1.633999494e-01, -1.618863938e-01, -1.603724572e-01, -1.588581433e-01, -1.573434556e-01, -1.558283977e-01, -1.543129730e-01, -1.527971853e-01, -1.512810380e-01, -1.497645347e-01, -1.482476790e-01, -1.467304745e-01, -1.452129247e-01, -1.436950332e-01, -1.421768035e-01, -1.406582393e-01, -1.391393442e-01, -1.376201216e-01, -1.361005752e-01, -1.345807085e-01, -1.330605252e-01, -1.315400287e-01, -1.300192227e-01, -1.284981108e-01, -1.269766965e-01, -1.254549834e-01, -1.239329751e-01, -1.224106752e-01, -1.208880872e-01, -1.193652148e-01, -1.178420615e-01, -1.163186309e-01, -1.147949266e-01, -1.132709522e-01, -1.117467112e-01, -1.102222073e-01, -1.086974440e-01, -1.071724250e-01, -1.056471537e-01, -1.041216339e-01, -1.025958690e-01, -1.010698628e-01, -9.954361866e-02, -9.801714033e-02, -9.649043136e-02, -9.496349533e-02, -9.343633585e-02, -9.190895650e-02, -9.038136088e-02, -8.885355258e-02, -8.732553521e-02, -8.579731234e-02, -8.426888759e-02, -8.274026455e-02, -8.121144681e-02, -7.968243797e-02, -7.815324163e-02, -7.662386139e-02, -7.509430085e-02, -7.356456360e-02, -7.203465325e-02, -7.050457339e-02, -6.897432763e-02, -6.744391956e-02, -6.591335280e-02, -6.438263093e-02, -6.285175756e-02, -6.132073630e-02, -5.978957075e-02, -5.825826450e-02, -5.672682117e-02, -5.519524435e-02, -5.366353765e-02, -5.213170468e-02, -5.059974904e-02, -4.906767433e-02, -4.753548416e-02, -4.600318213e-02, -4.447077185e-02, -4.293825693e-02, -4.140564098e-02, -3.987292759e-02, -3.834012037e-02, -3.680722294e-02, -3.527423890e-02, -3.374117185e-02, -3.220802541e-02, -3.067480318e-02, -2.914150876e-02, -2.760814578e-02, -2.607471783e-02, -2.454122852e-02, -2.300768147e-02, -2.147408028e-02, -1.994042855e-02, -1.840672991e-02, -1.687298795e-02, -1.533920628e-02, -1.380538853e-02, -1.227153829e-02, -1.073765917e-02, -9.203754782e-03, -7.669828740e-03, -6.135884649e-03, -4.601926120e-03, -3.067956763e-03, -1.533980186e-03, -2.449293598e-16, 1.533980186e-03, 3.067956763e-03, 4.601926120e-03, 6.135884649e-03, 7.669828740e-03, 9.203754782e-03, 1.073765917e-02, 1.227153829e-02, 1.380538853e-02, 1.533920628e-02, 1.687298795e-02, 1.840672991e-02, 1.994042855e-02, 2.147408028e-02, 2.300768147e-02, 2.454122852e-02, 2.607471783e-02, 2.760814578e-02, 2.914150876e-02, 3.067480318e-02, 3.220802541e-02, 3.374117185e-02, 3.527423890e-02, 3.680722294e-02, 3.834012037e-02, 3.987292759e-02, 4.140564098e-02, 4.293825693e-02, 4.447077185e-02, 4.600318213e-02, 4.753548416e-02, 4.906767433e-02, 5.059974904e-02, 5.213170468e-02, 5.366353765e-02, 5.519524435e-02, 5.672682117e-02, 5.825826450e-02, 5.978957075e-02, 6.132073630e-02, 6.285175756e-02, 6.438263093e-02, 6.591335280e-02, 6.744391956e-02, 6.897432763e-02, 7.050457339e-02, 7.203465325e-02, 7.356456360e-02, 7.509430085e-02, 7.662386139e-02, 7.815324163e-02, 7.968243797e-02, 8.121144681e-02, 8.274026455e-02, 8.426888759e-02, 8.579731234e-02, 8.732553521e-02, 8.885355258e-02, 9.038136088e-02, 9.190895650e-02, 9.343633585e-02, 9.496349533e-02, 9.649043136e-02, 9.801714033e-02, 9.954361866e-02, 1.010698628e-01, 1.025958690e-01, 1.041216339e-01, 1.056471537e-01, 1.071724250e-01, 1.086974440e-01, 1.102222073e-01, 1.117467112e-01, 1.132709522e-01, 1.147949266e-01, 1.163186309e-01, 1.178420615e-01, 1.193652148e-01, 1.208880872e-01, 1.224106752e-01, 1.239329751e-01, 1.254549834e-01, 1.269766965e-01, 1.284981108e-01, 1.300192227e-01, 1.315400287e-01, 1.330605252e-01, 1.345807085e-01, 1.361005752e-01, 1.376201216e-01, 1.391393442e-01, 1.406582393e-01, 1.421768035e-01, 1.436950332e-01, 1.452129247e-01, 1.467304745e-01, 1.482476790e-01, 1.497645347e-01, 1.512810380e-01, 1.527971853e-01, 1.543129730e-01, 1.558283977e-01, 1.573434556e-01, 1.588581433e-01, 1.603724572e-01, 1.618863938e-01, 1.633999494e-01, 1.649131205e-01, 1.664259035e-01, 1.679382950e-01, 1.694502912e-01, 1.709618888e-01, 1.724730840e-01, 1.739838734e-01, 1.754942534e-01, 1.770042204e-01, 1.785137709e-01, 1.800229014e-01, 1.815316083e-01, 1.830398880e-01, 1.845477369e-01, 1.860551517e-01, 1.875621286e-01, 1.890686641e-01, 1.905747548e-01, 1.920803970e-01, 1.935855873e-01, 1.950903220e-01, 1.965945977e-01, 1.980984107e-01, 1.996017576e-01, 2.011046348e-01, 2.026070388e-01, 2.041089661e-01, 2.056104131e-01, 2.071113762e-01, 2.086118520e-01, 2.101118369e-01, 2.116113274e-01, 2.131103199e-01, 2.146088110e-01, 2.161067971e-01, 2.176042746e-01, 2.191012402e-01, 2.205976901e-01, 2.220936210e-01, 2.235890292e-01, 2.250839114e-01, 2.265782638e-01, 2.280720832e-01, 2.295653658e-01, 2.310581083e-01, 2.325503070e-01, 2.340419586e-01, 2.355330594e-01, 2.370236060e-01, 2.385135948e-01, 2.400030224e-01, 2.414918853e-01, 2.429801799e-01, 2.444679027e-01, 2.459550503e-01, 2.474416192e-01, 2.489276057e-01, 2.504130066e-01, 2.518978182e-01, 2.533820370e-01, 2.548656596e-01, 2.563486825e-01, 2.578311022e-01, 2.593129151e-01, 2.607941179e-01, 2.622747070e-01, 2.637546790e-01, 2.652340303e-01, 2.667127575e-01, 2.681908571e-01, 2.696683256e-01, 2.711451595e-01, 2.726213554e-01, 2.740969099e-01, 2.755718193e-01, 2.770460803e-01, 2.785196894e-01, 2.799926431e-01, 2.814649379e-01, 2.829365705e-01, 2.844075372e-01, 2.858778347e-01, 2.873474595e-01, 2.888164082e-01, 2.902846773e-01, 2.917522632e-01, 2.932191627e-01, 2.946853722e-01, 2.961508882e-01, 2.976157074e-01, 2.990798263e-01, 3.005432414e-01, 3.020059493e-01, 3.034679466e-01, 3.049292297e-01, 3.063897954e-01, 3.078496400e-01, 3.093087603e-01, 3.107671527e-01, 3.122248139e-01, 3.136817404e-01, 3.151379288e-01, 3.165933756e-01, 3.180480774e-01, 3.195020308e-01, 3.209552324e-01, 3.224076788e-01, 3.238593665e-01, 3.253102922e-01, 3.267604523e-01, 3.282098436e-01, 3.296584625e-01, 3.311063058e-01, 3.325533699e-01, 3.339996514e-01, 3.354451471e-01, 3.368898534e-01, 3.383337670e-01, 3.397768844e-01, 3.412192023e-01, 3.426607173e-01, 3.441014260e-01, 3.455413250e-01, 3.469804108e-01, 3.484186802e-01, 3.498561298e-01, 3.512927561e-01, 3.527285558e-01, 3.541635254e-01, 3.555976617e-01, 3.570309612e-01, 3.584634206e-01, 3.598950365e-01, 3.613258056e-01, 3.627557244e-01, 3.641847896e-01, 3.656129978e-01, 3.670403457e-01, 3.684668300e-01, 3.698924471e-01, 3.713171940e-01, 3.727410670e-01, 3.741640630e-01, 3.755861785e-01, 3.770074102e-01, 3.784277548e-01, 3.798472089e-01, 3.812657692e-01, 3.826834324e-01, 3.841001950e-01, 3.855160538e-01, 3.869310055e-01, 3.883450467e-01, 3.897581741e-01, 3.911703843e-01, 3.925816741e-01, 3.939920401e-01, 3.954014789e-01, 3.968099874e-01, 3.982175622e-01, 3.996241998e-01, 4.010298972e-01, 4.024346509e-01, 4.038384576e-01, 4.052413140e-01, 4.066432169e-01, 4.080441629e-01, 4.094441487e-01, 4.108431711e-01, 4.122412267e-01, 4.136383122e-01, 4.150344245e-01, 4.164295601e-01, 4.178237158e-01, 4.192168884e-01, 4.206090744e-01, 4.220002708e-01, 4.233904741e-01, 4.247796812e-01, 4.261678887e-01, 4.275550934e-01, 4.289412921e-01, 4.303264813e-01, 4.317106580e-01, 4.330938189e-01, 4.344759606e-01, 4.358570799e-01, 4.372371737e-01, 4.386162385e-01, 4.399942713e-01, 4.413712687e-01, 4.427472276e-01, 4.441221446e-01, 4.454960165e-01, 4.468688402e-01, 4.482406123e-01, 4.496113297e-01, 4.509809890e-01, 4.523495872e-01, 4.537171210e-01, 4.550835871e-01, 4.564489824e-01, 4.578133036e-01, 4.591765475e-01, 4.605387110e-01, 4.618997907e-01, 4.632597836e-01, 4.646186863e-01, 4.659764958e-01, 4.673332087e-01, 4.686888220e-01, 4.700433325e-01, 4.713967368e-01, 4.727490320e-01, 4.741002147e-01, 4.754502817e-01, 4.767992301e-01, 4.781470564e-01, 4.794937577e-01, 4.808393306e-01, 4.821837721e-01, 4.835270789e-01, 4.848692480e-01, 4.862102761e-01, 4.875501601e-01, 4.888888969e-01, 4.902264833e-01, 4.915629161e-01, 4.928981922e-01, 4.942323085e-01, 4.955652618e-01, 4.968970490e-01, 4.982276670e-01, 4.995571125e-01, 5.008853826e-01, 5.022124740e-01, 5.035383837e-01, 5.048631085e-01, 5.061866453e-01, 5.075089911e-01, 5.088301425e-01, 5.101500967e-01, 5.114688504e-01, 5.127864006e-01, 5.141027442e-01, 5.154178780e-01, 5.167317990e-01, 5.180445041e-01, 5.193559902e-01, 5.206662541e-01, 5.219752929e-01, 5.232831035e-01, 5.245896827e-01, 5.258950275e-01, 5.271991348e-01, 5.285020015e-01, 5.298036247e-01, 5.311040012e-01, 5.324031279e-01, 5.337010018e-01, 5.349976199e-01, 5.362929791e-01, 5.375870763e-01, 5.388799085e-01, 5.401714727e-01, 5.414617659e-01, 5.427507849e-01, 5.440385267e-01, 5.453249884e-01, 5.466101669e-01, 5.478940592e-01, 5.491766622e-01, 5.504579729e-01, 5.517379884e-01, 5.530167056e-01, 5.542941215e-01, 5.555702330e-01, 5.568450373e-01, 5.581185312e-01, 5.593907119e-01, 5.606615762e-01, 5.619311212e-01, 5.631993440e-01, 5.644662415e-01, 5.657318108e-01, 5.669960488e-01, 5.682589527e-01, 5.695205193e-01, 5.707807459e-01, 5.720396293e-01, 5.732971667e-01, 5.745533550e-01, 5.758081914e-01, 5.770616729e-01, 5.783137964e-01, 5.795645591e-01, 5.808139581e-01, 5.820619903e-01, 5.833086529e-01, 5.845539430e-01, 5.857978575e-01, 5.870403935e-01, 5.882815482e-01, 5.895213186e-01, 5.907597019e-01, 5.919966950e-01, 5.932322950e-01, 5.944664992e-01, 5.956993045e-01, 5.969307081e-01, 5.981607070e-01, 5.993892984e-01, 6.006164794e-01, 6.018422471e-01, 6.030665985e-01, 6.042895309e-01, 6.055110414e-01, 6.067311270e-01, 6.079497850e-01, 6.091670123e-01, 6.103828063e-01, 6.115971639e-01, 6.128100824e-01, 6.140215589e-01, 6.152315906e-01, 6.164401745e-01, 6.176473079e-01, 6.188529880e-01, 6.200572118e-01, 6.212599765e-01, 6.224612794e-01, 6.236611175e-01, 6.248594881e-01, 6.260563884e-01, 6.272518155e-01, 6.284457666e-01, 6.296382389e-01, 6.308292296e-01, 6.320187359e-01, 6.332067551e-01, 6.343932842e-01, 6.355783205e-01, 6.367618612e-01, 6.379439036e-01, 6.391244449e-01, 6.403034822e-01, 6.414810128e-01, 6.426570340e-01, 6.438315429e-01, 6.450045368e-01, 6.461760130e-01, 6.473459686e-01, 6.485144010e-01, 6.496813074e-01, 6.508466850e-01, 6.520105311e-01, 6.531728430e-01, 6.543336178e-01, 6.554928530e-01, 6.566505457e-01, 6.578066933e-01, 6.589612930e-01, 6.601143421e-01, 6.612658378e-01, 6.624157776e-01, 6.635641586e-01, 6.647109782e-01, 6.658562337e-01, 6.669999223e-01, 6.681420414e-01, 6.692825883e-01, 6.704215604e-01, 6.715589548e-01, 6.726947691e-01, 6.738290004e-01, 6.749616461e-01, 6.760927036e-01, 6.772221701e-01, 6.783500431e-01, 6.794763199e-01, 6.806009978e-01, 6.817240742e-01, 6.828455464e-01, 6.839654118e-01, 6.850836678e-01, 6.862003117e-01, 6.873153409e-01, 6.884287528e-01, 6.895405447e-01, 6.906507141e-01, 6.917592584e-01, 6.928661748e-01, 6.939714609e-01, 6.950751140e-01, 6.961771315e-01, 6.972775108e-01, 6.983762494e-01, 6.994733446e-01, 7.005687939e-01, 7.016625947e-01, 7.027547445e-01, 7.038452405e-01, 7.049340804e-01, 7.060212614e-01, 7.071067812e-01, 7.081906370e-01, 7.092728264e-01, 7.103533469e-01, 7.114321957e-01, 7.125093706e-01, 7.135848688e-01, 7.146586879e-01, 7.157308253e-01, 7.168012785e-01, 7.178700451e-01, 7.189371224e-01, 7.200025080e-01, 7.210661993e-01, 7.221281939e-01, 7.231884893e-01, 7.242470830e-01, 7.253039724e-01, 7.263591551e-01, 7.274126286e-01, 7.284643904e-01, 7.295144381e-01, 7.305627692e-01, 7.316093812e-01, 7.326542717e-01, 7.336974381e-01, 7.347388781e-01, 7.357785892e-01, 7.368165689e-01, 7.378528148e-01, 7.388873245e-01, 7.399200955e-01, 7.409511254e-01, 7.419804117e-01, 7.430079521e-01, 7.440337442e-01, 7.450577854e-01, 7.460800735e-01, 7.471006060e-01, 7.481193805e-01, 7.491363945e-01, 7.501516458e-01, 7.511651319e-01, 7.521768504e-01, 7.531867990e-01, 7.541949753e-01, 7.552013769e-01, 7.562060014e-01, 7.572088465e-01, 7.582099098e-01, 7.592091890e-01, 7.602066817e-01, 7.612023855e-01, 7.621962981e-01, 7.631884173e-01, 7.641787405e-01, 7.651672656e-01, 7.661539902e-01, 7.671389119e-01, 7.681220285e-01, 7.691033376e-01, 7.700828370e-01, 7.710605243e-01, 7.720363972e-01, 7.730104534e-01, 7.739826906e-01, 7.749531066e-01, 7.759216990e-01, 7.768884657e-01, 7.778534042e-01, 7.788165124e-01, 7.797777879e-01, 7.807372286e-01, 7.816948321e-01, 7.826505962e-01, 7.836045186e-01, 7.845565972e-01, 7.855068296e-01, 7.864552136e-01, 7.874017470e-01, 7.883464276e-01, 7.892892532e-01, 7.902302214e-01, 7.911693302e-01, 7.921065773e-01, 7.930419605e-01, 7.939754776e-01, 7.949071263e-01, 7.958369046e-01, 7.967648102e-01, 7.976908409e-01, 7.986149946e-01, 7.995372691e-01, 8.004576622e-01, 8.013761717e-01, 8.022927955e-01, 8.032075315e-01, 8.041203774e-01, 8.050313311e-01, 8.059403906e-01, 8.068475535e-01, 8.077528179e-01, 8.086561816e-01, 8.095576424e-01, 8.104571983e-01, 8.113548470e-01, 8.122505866e-01, 8.131444148e-01, 8.140363297e-01, 8.149263291e-01, 8.158144108e-01, 8.167005729e-01, 8.175848132e-01, 8.184671296e-01, 8.193475201e-01, 8.202259826e-01, 8.211025150e-01, 8.219771153e-01, 8.228497814e-01, 8.237205112e-01, 8.245893028e-01, 8.254561540e-01, 8.263210628e-01, 8.271840273e-01, 8.280450453e-01, 8.289041148e-01, 8.297612338e-01, 8.306164003e-01, 8.314696123e-01, 8.323208678e-01, 8.331701647e-01, 8.340175011e-01, 8.348628750e-01, 8.357062844e-01, 8.365477272e-01, 8.373872016e-01, 8.382247056e-01, 8.390602371e-01, 8.398937942e-01, 8.407253750e-01, 8.415549774e-01, 8.423825996e-01, 8.432082396e-01, 8.440318955e-01, 8.448535652e-01, 8.456732470e-01, 8.464909388e-01, 8.473066387e-01, 8.481203448e-01, 8.489320552e-01, 8.497417680e-01, 8.505494813e-01, 8.513551931e-01, 8.521589016e-01, 8.529606049e-01, 8.537603011e-01, 8.545579884e-01, 8.553536647e-01, 8.561473284e-01, 8.569389774e-01, 8.577286100e-01, 8.585162243e-01, 8.593018184e-01, 8.600853904e-01, 8.608669386e-01, 8.616464611e-01, 8.624239561e-01, 8.631994217e-01, 8.639728561e-01, 8.647442575e-01, 8.655136241e-01, 8.662809540e-01, 8.670462455e-01, 8.678094968e-01, 8.685707060e-01, 8.693298713e-01, 8.700869911e-01, 8.708420635e-01, 8.715950867e-01, 8.723460589e-01, 8.730949784e-01, 8.738418435e-01, 8.745866523e-01, 8.753294031e-01, 8.760700942e-01, 8.768087238e-01, 8.775452902e-01, 8.782797917e-01, 8.790122264e-01, 8.797425928e-01, 8.804708891e-01, 8.811971135e-01, 8.819212643e-01, 8.826433400e-01, 8.833633387e-01, 8.840812587e-01, 8.847970984e-01, 8.855108561e-01, 8.862225301e-01, 8.869321188e-01, 8.876396204e-01, 8.883450333e-01, 8.890483559e-01, 8.897495864e-01, 8.904487232e-01, 8.911457648e-01, 8.918407094e-01, 8.925335554e-01, 8.932243012e-01, 8.939129451e-01, 8.945994856e-01, 8.952839210e-01, 8.959662498e-01, 8.966464702e-01, 8.973245807e-01, 8.980005797e-01, 8.986744657e-01, 8.993462370e-01, 9.000158920e-01, 9.006834292e-01, 9.013488470e-01, 9.020121439e-01, 9.026733182e-01, 9.033323685e-01, 9.039892931e-01, 9.046440906e-01, 9.052967593e-01, 9.059472978e-01, 9.065957045e-01, 9.072419779e-01, 9.078861165e-01, 9.085281187e-01, 9.091679831e-01, 9.098057081e-01, 9.104412923e-01, 9.110747341e-01, 9.117060320e-01, 9.123351846e-01, 9.129621904e-01, 9.135870479e-01, 9.142097557e-01, 9.148303122e-01, 9.154487161e-01, 9.160649658e-01, 9.166790599e-01, 9.172909970e-01, 9.179007756e-01, 9.185083943e-01, 9.191138517e-01, 9.197171463e-01, 9.203182767e-01, 9.209172415e-01, 9.215140393e-01, 9.221086687e-01, 9.227011283e-01, 9.232914167e-01, 9.238795325e-01, 9.244654743e-01, 9.250492408e-01, 9.256308305e-01, 9.262102421e-01, 9.267874743e-01, 9.273625257e-01, 9.279353948e-01, 9.285060805e-01, 9.290745813e-01, 9.296408958e-01, 9.302050229e-01, 9.307669611e-01, 9.313267091e-01, 9.318842656e-01, 9.324396293e-01, 9.329927988e-01, 9.335437730e-01, 9.340925504e-01, 9.346391298e-01, 9.351835099e-01, 9.357256895e-01, 9.362656672e-01, 9.368034417e-01, 9.373390119e-01, 9.378723764e-01, 9.384035341e-01, 9.389324835e-01, 9.394592236e-01, 9.399837530e-01, 9.405060706e-01, 9.410261751e-01, 9.415440652e-01, 9.420597398e-01, 9.425731976e-01, 9.430844375e-01, 9.435934582e-01, 9.441002585e-01, 9.446048373e-01, 9.451071933e-01, 9.456073254e-01, 9.461052324e-01, 9.466009131e-01, 9.470943664e-01, 9.475855910e-01, 9.480745859e-01, 9.485613499e-01, 9.490458819e-01, 9.495281806e-01, 9.500082450e-01, 9.504860739e-01, 9.509616663e-01, 9.514350210e-01, 9.519061368e-01, 9.523750127e-01, 9.528416476e-01, 9.533060404e-01, 9.537681899e-01, 9.542280951e-01, 9.546857549e-01, 9.551411683e-01, 9.555943341e-01, 9.560452513e-01, 9.564939189e-01, 9.569403357e-01, 9.573845008e-01, 9.578264130e-01, 9.582660714e-01, 9.587034749e-01, 9.591386225e-01, 9.595715131e-01, 9.600021457e-01, 9.604305194e-01, 9.608566331e-01, 9.612804858e-01, 9.617020765e-01, 9.621214043e-01, 9.625384680e-01, 9.629532669e-01, 9.633657998e-01, 9.637760658e-01, 9.641840640e-01, 9.645897933e-01, 9.649932529e-01, 9.653944417e-01, 9.657933589e-01, 9.661900034e-01, 9.665843745e-01, 9.669764710e-01, 9.673662922e-01, 9.677538371e-01, 9.681391047e-01, 9.685220943e-01, 9.689028048e-01, 9.692812354e-01, 9.696573851e-01, 9.700312532e-01, 9.704028387e-01, 9.707721407e-01, 9.711391584e-01, 9.715038910e-01, 9.718663375e-01, 9.722264971e-01, 9.725843689e-01, 9.729399522e-01, 9.732932461e-01, 9.736442497e-01, 9.739929622e-01, 9.743393828e-01, 9.746835107e-01, 9.750253451e-01, 9.753648851e-01, 9.757021300e-01, 9.760370790e-01, 9.763697313e-01, 9.767000861e-01, 9.770281427e-01, 9.773539001e-01, 9.776773578e-01, 9.779985149e-01, 9.783173707e-01, 9.786339244e-01, 9.789481753e-01, 9.792601226e-01, 9.795697657e-01, 9.798771037e-01, 9.801821360e-01, 9.804848618e-01, 9.807852804e-01, 9.810833912e-01, 9.813791933e-01, 9.816726862e-01, 9.819638691e-01, 9.822527414e-01, 9.825393023e-01, 9.828235512e-01, 9.831054874e-01, 9.833851103e-01, 9.836624192e-01, 9.839374134e-01, 9.842100924e-01, 9.844804554e-01, 9.847485018e-01, 9.850142310e-01, 9.852776424e-01, 9.855387353e-01, 9.857975092e-01, 9.860539633e-01, 9.863080972e-01, 9.865599103e-01, 9.868094018e-01, 9.870565713e-01, 9.873014182e-01, 9.875439418e-01, 9.877841416e-01, 9.880220171e-01, 9.882575677e-01, 9.884907929e-01, 9.887216920e-01, 9.889502645e-01, 9.891765100e-01, 9.894004278e-01, 9.896220175e-01, 9.898412785e-01, 9.900582103e-01, 9.902728124e-01, 9.904850843e-01, 9.906950254e-01, 9.909026354e-01, 9.911079137e-01, 9.913108598e-01, 9.915114733e-01, 9.917097537e-01, 9.919057004e-01, 9.920993131e-01, 9.922905913e-01, 9.924795346e-01, 9.926661424e-01, 9.928504145e-01, 9.930323502e-01, 9.932119492e-01, 9.933892111e-01, 9.935641355e-01, 9.937367219e-01, 9.939069700e-01, 9.940748793e-01, 9.942404495e-01, 9.944036801e-01, 9.945645707e-01, 9.947231211e-01, 9.948793308e-01, 9.950331994e-01, 9.951847267e-01, 9.953339121e-01, 9.954807555e-01, 9.956252564e-01, 9.957674145e-01, 9.959072294e-01, 9.960447009e-01, 9.961798286e-01, 9.963126122e-01, 9.964430514e-01, 9.965711458e-01, 9.966968952e-01, 9.968202993e-01, 9.969413578e-01, 9.970600703e-01, 9.971764367e-01, 9.972904567e-01, 9.974021299e-01, 9.975114561e-01, 9.976184351e-01, 9.977230666e-01, 9.978253504e-01, 9.979252862e-01, 9.980228738e-01, 9.981181129e-01, 9.982110034e-01, 9.983015449e-01, 9.983897374e-01, 9.984755806e-01, 9.985590742e-01, 9.986402182e-01, 9.987190122e-01, 9.987954562e-01, 9.988695499e-01, 9.989412932e-01, 9.990106859e-01, 9.990777278e-01, 9.991424187e-01, 9.992047586e-01, 9.992647473e-01, 9.993223846e-01, 9.993776704e-01, 9.994306046e-01, 9.994811870e-01, 9.995294175e-01, 9.995752960e-01, 9.996188225e-01, 9.996599967e-01, 9.996988187e-01, 9.997352883e-01, 9.997694054e-01, 9.998011699e-01, 9.998305818e-01, 9.998576410e-01, 9.998823475e-01, 9.999047011e-01, 9.999247018e-01, 9.999423497e-01, 9.999576446e-01, 9.999705864e-01, 9.999811753e-01, 9.999894111e-01, 9.999952938e-01, 9.999988235e-01, 1.000000000e+00, }; const float FLASHMEM lut_4_decades[] = { 1.000000000e+00, 1.036632928e+00, 1.074607828e+00, 1.113973860e+00, 1.154781985e+00, 1.197085030e+00, 1.240937761e+00, 1.286396945e+00, 1.333521432e+00, 1.382372227e+00, 1.433012570e+00, 1.485508017e+00, 1.539926526e+00, 1.596338544e+00, 1.654817100e+00, 1.715437896e+00, 1.778279410e+00, 1.843422992e+00, 1.910952975e+00, 1.980956779e+00, 2.053525026e+00, 2.128751662e+00, 2.206734069e+00, 2.287573200e+00, 2.371373706e+00, 2.458244069e+00, 2.548296748e+00, 2.641648320e+00, 2.738419634e+00, 2.838735965e+00, 2.942727176e+00, 3.050527890e+00, 3.162277660e+00, 3.278121151e+00, 3.398208329e+00, 3.522694651e+00, 3.651741273e+00, 3.785515249e+00, 3.924189758e+00, 4.067944321e+00, 4.216965034e+00, 4.371444813e+00, 4.531583638e+00, 4.697588817e+00, 4.869675252e+00, 5.048065717e+00, 5.232991147e+00, 5.424690937e+00, 5.623413252e+00, 5.829415347e+00, 6.042963902e+00, 6.264335367e+00, 6.493816316e+00, 6.731703824e+00, 6.978305849e+00, 7.233941627e+00, 7.498942093e+00, 7.773650302e+00, 8.058421878e+00, 8.353625470e+00, 8.659643234e+00, 8.976871324e+00, 9.305720409e+00, 9.646616199e+00, 1.000000000e+01, 1.036632928e+01, 1.074607828e+01, 1.113973860e+01, 1.154781985e+01, 1.197085030e+01, 1.240937761e+01, 1.286396945e+01, 1.333521432e+01, 1.382372227e+01, 1.433012570e+01, 1.485508017e+01, 1.539926526e+01, 1.596338544e+01, 1.654817100e+01, 1.715437896e+01, 1.778279410e+01, 1.843422992e+01, 1.910952975e+01, 1.980956779e+01, 2.053525026e+01, 2.128751662e+01, 2.206734069e+01, 2.287573200e+01, 2.371373706e+01, 2.458244069e+01, 2.548296748e+01, 2.641648320e+01, 2.738419634e+01, 2.838735965e+01, 2.942727176e+01, 3.050527890e+01, 3.162277660e+01, 3.278121151e+01, 3.398208329e+01, 3.522694651e+01, 3.651741273e+01, 3.785515249e+01, 3.924189758e+01, 4.067944321e+01, 4.216965034e+01, 4.371444813e+01, 4.531583638e+01, 4.697588817e+01, 4.869675252e+01, 5.048065717e+01, 5.232991147e+01, 5.424690937e+01, 5.623413252e+01, 5.829415347e+01, 6.042963902e+01, 6.264335367e+01, 6.493816316e+01, 6.731703824e+01, 6.978305849e+01, 7.233941627e+01, 7.498942093e+01, 7.773650302e+01, 8.058421878e+01, 8.353625470e+01, 8.659643234e+01, 8.976871324e+01, 9.305720409e+01, 9.646616199e+01, 1.000000000e+02, 1.036632928e+02, 1.074607828e+02, 1.113973860e+02, 1.154781985e+02, 1.197085030e+02, 1.240937761e+02, 1.286396945e+02, 1.333521432e+02, 1.382372227e+02, 1.433012570e+02, 1.485508017e+02, 1.539926526e+02, 1.596338544e+02, 1.654817100e+02, 1.715437896e+02, 1.778279410e+02, 1.843422992e+02, 1.910952975e+02, 1.980956779e+02, 2.053525026e+02, 2.128751662e+02, 2.206734069e+02, 2.287573200e+02, 2.371373706e+02, 2.458244069e+02, 2.548296748e+02, 2.641648320e+02, 2.738419634e+02, 2.838735965e+02, 2.942727176e+02, 3.050527890e+02, 3.162277660e+02, 3.278121151e+02, 3.398208329e+02, 3.522694651e+02, 3.651741273e+02, 3.785515249e+02, 3.924189758e+02, 4.067944321e+02, 4.216965034e+02, 4.371444813e+02, 4.531583638e+02, 4.697588817e+02, 4.869675252e+02, 5.048065717e+02, 5.232991147e+02, 5.424690937e+02, 5.623413252e+02, 5.829415347e+02, 6.042963902e+02, 6.264335367e+02, 6.493816316e+02, 6.731703824e+02, 6.978305849e+02, 7.233941627e+02, 7.498942093e+02, 7.773650302e+02, 8.058421878e+02, 8.353625470e+02, 8.659643234e+02, 8.976871324e+02, 9.305720409e+02, 9.646616199e+02, 1.000000000e+03, 1.036632928e+03, 1.074607828e+03, 1.113973860e+03, 1.154781985e+03, 1.197085030e+03, 1.240937761e+03, 1.286396945e+03, 1.333521432e+03, 1.382372227e+03, 1.433012570e+03, 1.485508017e+03, 1.539926526e+03, 1.596338544e+03, 1.654817100e+03, 1.715437896e+03, 1.778279410e+03, 1.843422992e+03, 1.910952975e+03, 1.980956779e+03, 2.053525026e+03, 2.128751662e+03, 2.206734069e+03, 2.287573200e+03, 2.371373706e+03, 2.458244069e+03, 2.548296748e+03, 2.641648320e+03, 2.738419634e+03, 2.838735965e+03, 2.942727176e+03, 3.050527890e+03, 3.162277660e+03, 3.278121151e+03, 3.398208329e+03, 3.522694651e+03, 3.651741273e+03, 3.785515249e+03, 3.924189758e+03, 4.067944321e+03, 4.216965034e+03, 4.371444813e+03, 4.531583638e+03, 4.697588817e+03, 4.869675252e+03, 5.048065717e+03, 5.232991147e+03, 5.424690937e+03, 5.623413252e+03, 5.829415347e+03, 6.042963902e+03, 6.264335367e+03, 6.493816316e+03, 6.731703824e+03, 6.978305849e+03, 7.233941627e+03, 7.498942093e+03, 7.773650302e+03, 8.058421878e+03, 8.353625470e+03, 8.659643234e+03, 8.976871324e+03, 9.305720409e+03, 9.646616199e+03, 1.000000000e+04, }; const float FLASHMEM lut_svf_shift[] = { 2.500000000e-01, 2.408119579e-01, 2.316544611e-01, 2.225575501e-01, 2.135502761e-01, 2.046602549e-01, 1.959132760e-01, 1.873329789e-01, 1.789406032e-01, 1.707548172e-01, 1.627916233e-01, 1.550643347e-01, 1.475836177e-01, 1.403575876e-01, 1.333919506e-01, 1.266901772e-01, 1.202537001e-01, 1.140821254e-01, 1.081734480e-01, 1.025242668e-01, 9.712999179e-02, 9.198504051e-02, 8.708302003e-02, 8.241689360e-02, 7.797913038e-02, 7.376183852e-02, 6.975688172e-02, 6.595598018e-02, 6.235079694e-02, 5.893301078e-02, 5.569437701e-02, 5.262677742e-02, 4.972226058e-02, 4.697307381e-02, 4.437168789e-02, 4.191081545e-02, 3.958342416e-02, 3.738274529e-02, 3.530227864e-02, 3.333579426e-02, 3.147733169e-02, 2.972119704e-02, 2.806195849e-02, 2.649444041e-02, 2.501371653e-02, 2.361510230e-02, 2.229414676e-02, 2.104662398e-02, 1.986852431e-02, 1.875604550e-02, 1.770558386e-02, 1.671372543e-02, 1.577723728e-02, 1.489305906e-02, 1.405829467e-02, 1.327020425e-02, 1.252619642e-02, 1.182382076e-02, 1.116076060e-02, 1.053482614e-02, 9.943947824e-03, 9.386169992e-03, 8.859644866e-03, 8.362626781e-03, 7.893466717e-03, 7.450607078e-03, 7.032576744e-03, 6.637986365e-03, 6.265523903e-03, 5.913950392e-03, 5.582095932e-03, 5.268855886e-03, 4.973187279e-03, 4.694105394e-03, 4.430680542e-03, 4.182035018e-03, 3.947340207e-03, 3.725813861e-03, 3.516717519e-03, 3.319354065e-03, 3.133065427e-03, 2.957230396e-03, 2.791262569e-03, 2.634608406e-03, 2.486745394e-03, 2.347180309e-03, 2.215447582e-03, 2.091107747e-03, 1.973745986e-03, 1.862970740e-03, 1.758412418e-03, 1.659722154e-03, 1.566570656e-03, 1.478647104e-03, 1.395658114e-03, 1.317326764e-03, 1.243391669e-03, 1.173606108e-03, 1.107737206e-03, 1.045565155e-03, 9.868824789e-04, 9.314933471e-04, 8.792129165e-04, 8.298667176e-04, 7.832900713e-04, 7.393275405e-04, 6.978324110e-04, 6.586662024e-04, 6.216982059e-04, 5.868050482e-04, 5.538702800e-04, 5.227839874e-04, 4.934424252e-04, 4.657476707e-04, 4.396072968e-04, 4.149340639e-04, 3.916456285e-04, 3.696642688e-04, 3.489166247e-04, 3.293334538e-04, 3.108493994e-04, 2.934027734e-04, 2.769353496e-04, 2.613921700e-04, 2.467213608e-04, 2.328739600e-04, 2.198037532e-04, 2.074671201e-04, 1.958228884e-04, 1.848321967e-04, 1.744583648e-04, 1.646667709e-04, 1.554247368e-04, 1.467014179e-04, 1.384677010e-04, 1.306961070e-04, 1.233606989e-04, 1.164369956e-04, 1.099018897e-04, 1.037335710e-04, 9.791145345e-05, 9.241610615e-05, 8.722918894e-05, 8.233339098e-05, 7.771237301e-05, 7.335071282e-05, 6.923385378e-05, 6.534805627e-05, 6.168035179e-05, 5.821849973e-05, 5.495094649e-05, 5.186678690e-05, 4.895572788e-05, 4.620805405e-05, 4.361459529e-05, 4.116669618e-05, 3.885618709e-05, 3.667535690e-05, 3.461692730e-05, 3.267402848e-05, 3.084017618e-05, 2.910925011e-05, 2.747547345e-05, 2.593339362e-05, 2.447786409e-05, 2.310402715e-05, 2.180729775e-05, 2.058334818e-05, 1.942809362e-05, 1.833767851e-05, 1.730846370e-05, 1.633701428e-05, 1.542008813e-05, 1.455462508e-05, 1.373773675e-05, 1.296669683e-05, 1.223893206e-05, 1.155201359e-05, 1.090364889e-05, 1.029167410e-05, 9.714046817e-06, 9.168839263e-06, 8.654231857e-06, 8.168507146e-06, 7.710044069e-06, 7.277312546e-06, 6.868868378e-06, 6.483348419e-06, 6.119466033e-06, 5.776006796e-06, 5.451824445e-06, 5.145837051e-06, 4.857023409e-06, 4.584419632e-06, 4.327115929e-06, 4.084253574e-06, 3.855022035e-06, 3.638656274e-06, 3.434434189e-06, 3.241674210e-06, 3.059733017e-06, 2.888003398e-06, 2.725912223e-06, 2.572918525e-06, 2.428511705e-06, 2.292209816e-06, 2.163557965e-06, 2.042126787e-06, 1.927511018e-06, 1.819328137e-06, 1.717217095e-06, 1.620837105e-06, 1.529866508e-06, 1.444001699e-06, 1.362956111e-06, 1.286459263e-06, 1.214255852e-06, 1.146104908e-06, 1.081778982e-06, 1.021063394e-06, 9.637555088e-07, 9.096640684e-07, 8.586085474e-07, 8.104185525e-07, 7.649332542e-07, 7.220008496e-07, 6.814780557e-07, 6.432296314e-07, 6.071279262e-07, 5.730524541e-07, 5.408894912e-07, 5.105316968e-07, 4.818777544e-07, 4.548320342e-07, 4.293042737e-07, 4.052092763e-07, 3.824666271e-07, 3.610004248e-07, 3.407390278e-07, 3.216148157e-07, 3.035639631e-07, 2.865262270e-07, 2.704447456e-07, 2.552658484e-07, 2.409388772e-07, 2.274160171e-07, 2.146521368e-07, 2.026046381e-07, 1.912333136e-07, 1.805002124e-07, 1.703695139e-07, 1.608074078e-07, 1.517819816e-07, 1.432631135e-07, 1.352223728e-07, 1.276329242e-07, 1.204694386e-07, }; const float FLASHMEM lut_stiffness[] = { -6.250000000e-02, -6.152343750e-02, -6.054687500e-02, -5.957031250e-02, -5.859375000e-02, -5.761718750e-02, -5.664062500e-02, -5.566406250e-02, -5.468750000e-02, -5.371093750e-02, -5.273437500e-02, -5.175781250e-02, -5.078125000e-02, -4.980468750e-02, -4.882812500e-02, -4.785156250e-02, -4.687500000e-02, -4.589843750e-02, -4.492187500e-02, -4.394531250e-02, -4.296875000e-02, -4.199218750e-02, -4.101562500e-02, -4.003906250e-02, -3.906250000e-02, -3.808593750e-02, -3.710937500e-02, -3.613281250e-02, -3.515625000e-02, -3.417968750e-02, -3.320312500e-02, -3.222656250e-02, -3.125000000e-02, -3.027343750e-02, -2.929687500e-02, -2.832031250e-02, -2.734375000e-02, -2.636718750e-02, -2.539062500e-02, -2.441406250e-02, -2.343750000e-02, -2.246093750e-02, -2.148437500e-02, -2.050781250e-02, -1.953125000e-02, -1.855468750e-02, -1.757812500e-02, -1.660156250e-02, -1.562500000e-02, -1.464843750e-02, -1.367187500e-02, -1.269531250e-02, -1.171875000e-02, -1.074218750e-02, -9.765625000e-03, -8.789062500e-03, -7.812500000e-03, -6.835937500e-03, -5.859375000e-03, -4.882812500e-03, -3.906250000e-03, -2.929687500e-03, -1.953125000e-03, -9.765625000e-04, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 6.029410294e-05, 3.672617230e-04, 6.835957809e-04, 1.009582073e-03, 1.345515115e-03, 1.691698412e-03, 2.048444725e-03, 2.416076364e-03, 2.794925468e-03, 3.185334315e-03, 3.587655624e-03, 4.002252878e-03, 4.429500650e-03, 4.869784943e-03, 5.323503537e-03, 5.791066350e-03, 6.272895808e-03, 6.769427226e-03, 7.281109202e-03, 7.808404022e-03, 8.351788076e-03, 8.911752293e-03, 9.488802580e-03, 1.008346028e-02, 1.069626264e-02, 1.132776331e-02, 1.197853283e-02, 1.264915914e-02, 1.334024813e-02, 1.405242417e-02, 1.478633069e-02, 1.554263074e-02, 1.632200761e-02, 1.712516545e-02, 1.795282987e-02, 1.880574864e-02, 1.968469234e-02, 2.059045506e-02, 2.152385512e-02, 2.248573583e-02, 2.347696619e-02, 2.449844176e-02, 2.555108540e-02, 2.663584813e-02, 2.775370999e-02, 2.890568094e-02, 3.009280173e-02, 3.131614488e-02, 3.257681565e-02, 3.387595299e-02, 3.521473064e-02, 3.659435812e-02, 3.801608189e-02, 3.948118641e-02, 4.099099536e-02, 4.254687278e-02, 4.415022437e-02, 4.580249868e-02, 4.750518848e-02, 4.925983210e-02, 5.106801479e-02, 5.293137017e-02, 5.485158172e-02, 5.683038428e-02, 5.886956562e-02, 6.097096806e-02, 6.313649016e-02, 6.536808837e-02, 6.766777886e-02, 7.003763933e-02, 7.247981084e-02, 7.499649981e-02, 7.758997998e-02, 8.026259446e-02, 8.301675786e-02, 8.585495846e-02, 8.877976048e-02, 9.179380636e-02, 9.489981918e-02, 9.810060511e-02, 1.013990559e-01, 1.047981517e-01, 1.083009634e-01, 1.119106556e-01, 1.156304895e-01, 1.194638260e-01, 1.234141283e-01, 1.274849653e-01, 1.316800149e-01, 1.360030671e-01, 1.404580277e-01, 1.450489216e-01, 1.497798965e-01, 1.546552266e-01, 1.596793166e-01, 1.648567056e-01, 1.701920711e-01, 1.756902336e-01, 1.813561603e-01, 1.871949702e-01, 1.932119385e-01, 1.994125013e-01, 2.058022605e-01, 2.123869891e-01, 2.191726361e-01, 2.261653322e-01, 2.333713949e-01, 2.407973346e-01, 2.484498605e-01, 2.563358863e-01, 2.644625367e-01, 2.728371538e-01, 2.814673039e-01, 2.903607839e-01, 2.995256288e-01, 3.089701187e-01, 3.187027863e-01, 3.287324247e-01, 3.390680953e-01, 3.497191360e-01, 3.606951697e-01, 3.720061128e-01, 3.836621843e-01, 3.956739150e-01, 4.080521572e-01, 4.208080940e-01, 4.339532500e-01, 4.474995013e-01, 4.614590865e-01, 4.758446177e-01, 4.906690914e-01, 5.059459012e-01, 5.216888491e-01, 5.379121581e-01, 5.546304856e-01, 5.718589358e-01, 5.896130741e-01, 6.079089407e-01, 6.267630651e-01, 6.461924814e-01, 6.662147434e-01, 6.868479405e-01, 7.081107139e-01, 7.300222738e-01, 7.526024164e-01, 7.758715422e-01, 7.998506739e-01, 8.245614757e-01, 8.500262730e-01, 8.762680723e-01, 9.033105820e-01, 9.311782340e-01, 9.598962059e-01, 9.894904431e-01, 1.000000745e+00, 1.000037649e+00, 1.000262504e+00, 1.000964607e+00, 1.002570034e+00, 1.005639154e+00, 1.010861180e+00, 1.019043988e+00, 1.031097087e+00, 1.048005353e+00, 1.070791059e+00, 1.100461817e+00, 1.137942574e+00, 1.183990632e+00, 1.239094135e+00, 1.303356514e+00, 1.376372085e+00, 1.457101344e+00, 1.543758274e+00, 1.633725943e+00, 1.723520185e+00, 1.808823654e+00, 1.884612937e+00, 1.945398753e+00, 2.000000000e+00, 2.000000000e+00, }; const float FLASHMEM lut_fm_frequency_quantizer[] = { -1.200000000e+01, -1.200000000e+01, -1.200000000e+01, -1.184000000e+01, -1.184000000e+01, -1.184000000e+01, -1.111000000e+01, -1.038000000e+01, -9.650000000e+00, -8.920000000e+00, -8.190000000e+00, -7.460000000e+00, -6.730000000e+00, -6.000000000e+00, -6.000000000e+00, -6.000000000e+00, -5.545511612e+00, -5.091023223e+00, -4.636534835e+00, -4.182046446e+00, -4.182046446e+00, -4.182046446e+00, -3.659290641e+00, -3.136534835e+00, -2.613779029e+00, -2.091023223e+00, -1.568267417e+00, -1.045511612e+00, -5.227558058e-01, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 1.600000000e-01, 1.600000000e-01, 1.600000000e-01, 8.900000000e-01, 1.620000000e+00, 2.350000000e+00, 3.080000000e+00, 3.810000000e+00, 4.540000000e+00, 5.270000000e+00, 6.000000000e+00, 6.000000000e+00, 6.000000000e+00, 6.454488388e+00, 6.908976777e+00, 7.363465165e+00, 7.817953554e+00, 7.817953554e+00, 7.817953554e+00, 8.285529931e+00, 8.753106309e+00, 9.220682687e+00, 9.688259065e+00, 9.688259065e+00, 9.688259065e+00, 1.026619430e+01, 1.084412953e+01, 1.142206477e+01, 1.200000000e+01, 1.200000000e+01, 1.200000000e+01, 1.216000000e+01, 1.216000000e+01, 1.216000000e+01, 1.262977500e+01, 1.309955001e+01, 1.356932501e+01, 1.403910002e+01, 1.403910002e+01, 1.403910002e+01, 1.490761987e+01, 1.577613972e+01, 1.664465957e+01, 1.751317942e+01, 1.751317942e+01, 1.751317942e+01, 1.800000000e+01, 1.800000000e+01, 1.800000000e+01, 1.850977500e+01, 1.901955001e+01, 1.901955001e+01, 1.901955001e+01, 1.981795355e+01, 1.981795355e+01, 1.981795355e+01, 2.066386428e+01, 2.150977500e+01, 2.150977500e+01, 2.150977500e+01, 2.213233125e+01, 2.275488750e+01, 2.337744375e+01, 2.400000000e+01, 2.400000000e+01, 2.400000000e+01, 2.450977500e+01, 2.501955001e+01, 2.501955001e+01, 2.501955001e+01, 2.547403840e+01, 2.592852679e+01, 2.638301517e+01, 2.683750356e+01, 2.683750356e+01, 2.683750356e+01, 2.735032035e+01, 2.786313714e+01, 2.786313714e+01, 2.786313714e+01, 2.839735285e+01, 2.893156857e+01, 2.946578428e+01, 3.000000000e+01, 3.000000000e+01, 3.000000000e+01, 3.075000000e+01, 3.150000000e+01, 3.225000000e+01, 3.300000000e+01, 3.375000000e+01, 3.450000000e+01, 3.525000000e+01, 3.600000000e+01, 3.600000000e+01, 3.600000000e+01, 3.600000000e+01, }; const float* lookup_table_table[] = { lut_sine, lut_4_decades, lut_svf_shift, lut_stiffness, lut_fm_frequency_quantizer, }; } // namespace rings ================================================ FILE: lib/rings/resources.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resources definitions. // // Automatically generated with: // make resources #ifndef RINGS_RESOURCES_H_ #define RINGS_RESOURCES_H_ #include "stmlib/stmlib.h" namespace rings { typedef uint8_t ResourceId; extern const int16_t* lookup_table_int16_table[]; extern const uint32_t* lookup_table_uint32_table[]; extern const float* lookup_table_table[]; extern const float lut_sine[]; extern const float lut_4_decades[]; extern const float lut_svf_shift[]; extern const float lut_stiffness[]; extern const float lut_fm_frequency_quantizer[]; const int LUT_SINE = 0; const int LUT_SINE_SIZE = 5121; const int LUT_4_DECADES = 1; const int LUT_4_DECADES_SIZE = 257; const int LUT_SVF_SHIFT = 2; const int LUT_SVF_SHIFT_SIZE = 257; const int LUT_STIFFNESS = 3; const int LUT_STIFFNESS_SIZE = 257; const int LUT_FM_FREQUENCY_QUANTIZER = 4; const int LUT_FM_FREQUENCY_QUANTIZER_SIZE = 129; } // namespace rings #endif // RINGS_RESOURCES_H_ ================================================ FILE: lib/soundpipe/revsc.c ================================================ /* * RevSC * * This code has been extracted from the Csound opcode "reverbsc". * It has been modified to work as a Soundpipe module. * * Original Author(s): Sean Costello, Istvan Varga * Year: 1999, 2005 * Location: Opcodes/reverbsc.c * */ #include #include #include #include #include "revsc.h" #define DEFAULT_SRATE 44100.0 #define MIN_SRATE 5000.0 #define MAX_SRATE 1000000.0 #define MAX_PITCHMOD 20.0 #define DELAYPOS_SHIFT 28 #define DELAYPOS_SCALE 0x10000000 #define DELAYPOS_MASK 0x0FFFFFFF #ifndef M_PI #define M_PI 3.14159265358979323846 /* pi */ #endif /* reverbParams[n][0] = delay time (in seconds) */ /* reverbParams[n][1] = random variation in delay time (in seconds) */ /* reverbParams[n][2] = random variation frequency (in 1/sec) */ /* reverbParams[n][3] = random seed (0 - 32767) */ static const SPFLOAT reverbParams[8][4] = { { (2473.0 / DEFAULT_SRATE), 0.0010, 3.100, 1966.0 }, { (2767.0 / DEFAULT_SRATE), 0.0011, 3.500, 29491.0 }, { (3217.0 / DEFAULT_SRATE), 0.0017, 1.110, 22937.0 }, { (3557.0 / DEFAULT_SRATE), 0.0006, 3.973, 9830.0 }, { (3907.0 / DEFAULT_SRATE), 0.0010, 2.341, 20643.0 }, { (4127.0 / DEFAULT_SRATE), 0.0011, 1.897, 22937.0 }, { (2143.0 / DEFAULT_SRATE), 0.0017, 0.891, 29491.0 }, { (1933.0 / DEFAULT_SRATE), 0.0006, 3.221, 14417.0 } }; static int delay_line_max_samples(SPFLOAT sr, SPFLOAT iPitchMod, int n); static int init_delay_line(sp_revsc *p, sp_revsc_dl *lp, int n); static int delay_line_bytes_alloc(SPFLOAT sr, SPFLOAT iPitchMod, int n); static const SPFLOAT outputGain = 0.35; static const SPFLOAT jpScale = 0.25; int sp_revsc_init(sp_data *sp, sp_revsc *p) { p->iSampleRate = sp->sr; p->sampleRate = sp->sr; p->feedback = 0.97; p->lpfreq = 10000; p->iPitchMod = 1; p->iSkipInit = 0; p->dampFact = 1.0; p->prv_LPFreq = 0.0; p->initDone = 1; int i, nBytes = 0; for(i = 0; i < 8; i++){ nBytes += delay_line_bytes_alloc(sp->sr, 1, i); } if(sp->aux.size >= nBytes) { p->aux.ptr = sp->aux.ptr; p->aux.size = nBytes; } else { return SP_NOT_OK; } nBytes = 0; for (i = 0; i < 8; i++) { p->delayLines[i].buf = (SPFLOAT*)((p->aux.ptr) + nBytes); init_delay_line(p, &p->delayLines[i], i); nBytes += delay_line_bytes_alloc(sp->sr, 1, i); } return SP_OK; } static int delay_line_max_samples(SPFLOAT sr, SPFLOAT iPitchMod, int n) { SPFLOAT maxDel; maxDel = reverbParams[n][0]; maxDel += (reverbParams[n][1] * (SPFLOAT) iPitchMod * 1.125); return (int) (maxDel * sr + 16.5); } static int delay_line_bytes_alloc(SPFLOAT sr, SPFLOAT iPitchMod, int n) { int nBytes = 0; nBytes += (delay_line_max_samples(sr, iPitchMod, n) * (int) sizeof(SPFLOAT)); return nBytes; } static void next_random_lineseg(sp_revsc *p, sp_revsc_dl *lp, int n) { SPFLOAT prvDel, nxtDel, phs_incVal; /* update random seed */ if (lp->seedVal < 0) lp->seedVal += 0x10000; lp->seedVal = (lp->seedVal * 15625 + 1) & 0xFFFF; if (lp->seedVal >= 0x8000) lp->seedVal -= 0x10000; /* length of next segment in samples */ lp->randLine_cnt = (int) ((p->sampleRate / reverbParams[n][2]) + 0.5); prvDel = (SPFLOAT) lp->writePos; prvDel -= ((SPFLOAT) lp->readPos + ((SPFLOAT) lp->readPosFrac / (SPFLOAT) DELAYPOS_SCALE)); while (prvDel < 0.0) prvDel += lp->bufferSize; prvDel = prvDel / p->sampleRate; /* previous delay time in seconds */ nxtDel = (SPFLOAT) lp->seedVal * reverbParams[n][1] / 32768.0; /* next delay time in seconds */ nxtDel = reverbParams[n][0] + (nxtDel * (SPFLOAT) p->iPitchMod); /* calculate phase increment per sample */ phs_incVal = (prvDel - nxtDel) / (SPFLOAT) lp->randLine_cnt; phs_incVal = phs_incVal * p->sampleRate + 1.0; lp->readPosFrac_inc = (int) (phs_incVal * DELAYPOS_SCALE + 0.5); } static int init_delay_line(sp_revsc *p, sp_revsc_dl *lp, int n) { SPFLOAT readPos; /* int i; */ /* calculate length of delay line */ lp->bufferSize = delay_line_max_samples(p->sampleRate, 1, n); lp->dummy = 0; lp->writePos = 0; /* set random seed */ lp->seedVal = (int) (reverbParams[n][3] + 0.5); /* set initial delay time */ readPos = (SPFLOAT) lp->seedVal * reverbParams[n][1] / 32768; readPos = reverbParams[n][0] + (readPos * (SPFLOAT) p->iPitchMod); readPos = (SPFLOAT) lp->bufferSize - (readPos * p->sampleRate); lp->readPos = (int) readPos; readPos = (readPos - (SPFLOAT) lp->readPos) * (SPFLOAT) DELAYPOS_SCALE; lp->readPosFrac = (int) (readPos + 0.5); /* initialise first random line segment */ next_random_lineseg(p, lp, n); /* clear delay line to zero */ lp->filterState = 0.0; memset(lp->buf, 0, sizeof(SPFLOAT) * lp->bufferSize); return SP_OK; } int sp_revsc_compute(sp_data *sp, sp_revsc *p, SPFLOAT *in1, SPFLOAT *in2, SPFLOAT *out1, SPFLOAT *out2) { SPFLOAT ainL, ainR, aoutL, aoutR; SPFLOAT vm1, v0, v1, v2, am1, a0, a1, a2, frac; sp_revsc_dl *lp; int readPos; uint32_t n; int bufferSize; /* Local copy */ SPFLOAT dampFact = p->dampFact; if (p->initDone <= 0) return SP_NOT_OK; /* calculate tone filter coefficient if frequency changed */ if (p->lpfreq != p->prv_LPFreq) { p->prv_LPFreq = p->lpfreq; dampFact = 2.0f - cosf(p->prv_LPFreq * (2 * M_PI) / p->sampleRate); dampFact = p->dampFact = dampFact - sqrtf(dampFact * dampFact - 1.0f); } /* calculate "resultant junction pressure" and mix to input signals */ ainL = aoutL = aoutR = 0.0; for (n = 0; n < 8; n++) { ainL += p->delayLines[n].filterState; } ainL *= jpScale; ainR = ainL + *in2; ainL = ainL + *in1; /* loop through all delay lines */ for (n = 0; n < 8; n++) { lp = &p->delayLines[n]; bufferSize = lp->bufferSize; /* send input signal and feedback to delay line */ lp->buf[lp->writePos] = (SPFLOAT) ((n & 1 ? ainR : ainL) - lp->filterState); if (++lp->writePos >= bufferSize) { lp->writePos -= bufferSize; } /* read from delay line with cubic interpolation */ if (lp->readPosFrac >= DELAYPOS_SCALE) { lp->readPos += (lp->readPosFrac >> DELAYPOS_SHIFT); lp->readPosFrac &= DELAYPOS_MASK; } if (lp->readPos >= bufferSize) lp->readPos -= bufferSize; readPos = lp->readPos; frac = (SPFLOAT) lp->readPosFrac * (1.0 / (SPFLOAT) DELAYPOS_SCALE); /* calculate interpolation coefficients */ a2 = frac * frac; a2 -= 1.0; a2 *= (1.0 / 6.0); a1 = frac; a1 += 1.0; a1 *= 0.5; am1 = a1 - 1.0; a0 = 3.0 * a2; a1 -= a0; am1 -= a2; a0 -= frac; /* read four samples for interpolation */ if (readPos > 0 && readPos < (bufferSize - 2)) { vm1 = (SPFLOAT) (lp->buf[readPos - 1]); v0 = (SPFLOAT) (lp->buf[readPos]); v1 = (SPFLOAT) (lp->buf[readPos + 1]); v2 = (SPFLOAT) (lp->buf[readPos + 2]); } else { /* at buffer wrap-around, need to check index */ if (--readPos < 0) readPos += bufferSize; vm1 = (SPFLOAT) lp->buf[readPos]; if (++readPos >= bufferSize) readPos -= bufferSize; v0 = (SPFLOAT) lp->buf[readPos]; if (++readPos >= bufferSize) readPos -= bufferSize; v1 = (SPFLOAT) lp->buf[readPos]; if (++readPos >= bufferSize) readPos -= bufferSize; v2 = (SPFLOAT) lp->buf[readPos]; } v0 = (am1 * vm1 + a0 * v0 + a1 * v1 + a2 * v2) * frac + v0; /* update buffer read position */ lp->readPosFrac += lp->readPosFrac_inc; /* apply feedback gain and lowpass filter */ v0 *= (SPFLOAT) p->feedback; v0 = (lp->filterState - v0) * dampFact + v0; lp->filterState = v0; /* mix to output */ if (n & 1) { aoutR += v0; }else{ aoutL += v0; } /* start next random line segment if current one has reached endpoint */ if (--(lp->randLine_cnt) <= 0) { next_random_lineseg(p, lp, n); } } /* someday, use aoutR for multimono out */ *out1 = aoutL * outputGain; *out2 = aoutR * outputGain; return SP_OK; } ================================================ FILE: lib/soundpipe/revsc.h ================================================ #pragma once #include "soundpipe.h" typedef struct { int writePos; int bufferSize; int readPos; int readPosFrac; int readPosFrac_inc; int dummy; int seedVal; int randLine_cnt; SPFLOAT filterState; SPFLOAT *buf; } sp_revsc_dl; typedef struct { SPFLOAT feedback, lpfreq; SPFLOAT iSampleRate, iPitchMod, iSkipInit; SPFLOAT sampleRate; SPFLOAT dampFact; SPFLOAT prv_LPFreq; int initDone; sp_revsc_dl delayLines[8]; sp_auxdata aux; } sp_revsc; int sp_revsc_init(sp_data *sp, sp_revsc *p); int sp_revsc_compute(sp_data *sp, sp_revsc *p, SPFLOAT *in1, SPFLOAT *in2, SPFLOAT *out1, SPFLOAT *out2); ================================================ FILE: lib/soundpipe/soundpipe.c ================================================ #include "soundpipe.h" #include uint32_t sp_rand(sp_data *sp) { uint32_t val = (1103515245 * sp->rand + 12345) % SP_RANDMAX; sp->rand = val; return val; } ================================================ FILE: lib/soundpipe/soundpipe.h ================================================ #pragma once #include #include typedef float SPFLOAT; #define SP_OK 1 #define SP_NOT_OK 0 #define SP_RANDMAX 2147483648 typedef struct sp_auxdata { size_t size; void *ptr; } sp_auxdata; typedef struct { SPFLOAT *out; uint32_t sr; uint32_t rand; sp_auxdata aux; } sp_data; ================================================ FILE: lib/stmlib/.gitignore ================================================ # Precompiled python modules *.pyc # LaTeX compiled file *.pdf *.log *.aux # OS X crap .DS_Stor? ================================================ FILE: lib/stmlib/LICENSE ================================================ Except when noted otherwise, all code is copyright Emilie Gillet and is released under the MIT License with the following notice: Copyright 2012 Emilie Gillet. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- The code in third_party/STM is from STMicroelectronics, and released with the following notice: THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. ------------------------------------------------------------------------------- The code in programming/serial is from Ivan A-R, and released under the GPL with the following notice: Author: Ivan A-R Project page: http://tuxotronic.org/wiki/projects/stm32loader This file is part of stm32loader. stm32loader 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, or (at your option) any later version. stm32loader 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 stm32loader; see the file COPYING3. If not see . ================================================ FILE: lib/stmlib/README.md ================================================ Mutable Instruments' project template, makefile, and libraries for STM32F projects. See LICENSE for licensing information. More to come! ================================================ FILE: lib/stmlib/algorithms/note_stack.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Stack of currently pressed keys. // // Currently pressed keys are stored as a linked list. The linked list is used // as a LIFO stack to allow monosynth-like behaviour. An example of such // behaviour is: // player presses and holds C4-> C4 is played. // player presses and holds C5 (while holding C4) -> C5 is played. // player presses and holds G4 (while holding C4&C5)-> G4 is played. // player releases C5 -> G4 is played. // player releases G4 -> C4 is played. // // The nodes used in the linked list are pre-allocated from a pool of N // nodes, so the "pointers" (to the root element for example) are not actual // pointers, but indices of an element in the pool. // // Additionally, an array of pointers is stored to allow random access to the // n-th note, sorted by ascending order of pitch (for arpeggiation). #ifndef STMLIB_ALGORITHMS_NOTE_STACK_H_ #define STMLIB_ALGORITHMS_NOTE_STACK_H_ #include "stmlib/stmlib.h" #include namespace stmlib { enum NoteStackFlags { NOTE_STACK_PRIORITY_LAST, NOTE_STACK_PRIORITY_LOW, NOTE_STACK_PRIORITY_HIGH, NOTE_STACK_PRIORITY_FIRST, NOTE_STACK_FREE_SLOT = 0xff }; struct NoteEntry { uint8_t note; uint8_t velocity; uint8_t next_ptr; // Base 1. }; template class NoteStack { public: NoteStack() { } ~NoteStack() { } void Init() { Clear(); } void NoteOn(uint8_t note, uint8_t velocity) { // Remove the note from the list first (in case it is already here). NoteOff(note); // In case of saturation, remove the least recently played note from the // stack. if (size_ == capacity) { uint8_t least_recent_note = 1; for (uint8_t i = 1; i <= capacity; ++i) { if (pool_[i].next_ptr == 0) { least_recent_note = pool_[i].note; } } NoteOff(least_recent_note); } // Now we are ready to insert the new note. Find a free slot to insert it. uint8_t free_slot = 1; for (uint8_t i = 1; i <= capacity; ++i) { if (pool_[i].note == NOTE_STACK_FREE_SLOT) { free_slot = i; break; } } pool_[free_slot].next_ptr = root_ptr_; pool_[free_slot].note = note; pool_[free_slot].velocity = velocity; root_ptr_ = free_slot; // The last step consists in inserting the note in the sorted list. for (uint8_t i = 0; i < size_; ++i) { if (pool_[sorted_ptr_[i]].note > note) { for (uint8_t j = size_; j > i; --j) { sorted_ptr_[j] = sorted_ptr_[j - 1]; } sorted_ptr_[i] = free_slot; free_slot = 0; break; } } if (free_slot) { sorted_ptr_[size_] = free_slot; } ++size_; } void NoteOff(uint8_t note) { uint8_t current = root_ptr_; uint8_t previous = 0; while (current) { if (pool_[current].note == note) { break; } previous = current; current = pool_[current].next_ptr; } if (current) { if (previous) { pool_[previous].next_ptr = pool_[current].next_ptr; } else { root_ptr_ = pool_[current].next_ptr; } for (uint8_t i = 0; i < size_; ++i) { if (sorted_ptr_[i] == current) { for (uint8_t j = i; j < size_ - 1; ++j) { sorted_ptr_[j] = sorted_ptr_[j + 1]; } break; } } pool_[current].next_ptr = 0; pool_[current].note = NOTE_STACK_FREE_SLOT; pool_[current].velocity = 0; --size_; } } void Clear() { size_ = 0; memset(pool_ + 1, 0, sizeof(NoteEntry) * capacity); memset(sorted_ptr_ + 1, 0, capacity); root_ptr_ = 0; for (uint8_t i = 0; i <= capacity; ++i) { pool_[i].note = NOTE_STACK_FREE_SLOT; } } uint8_t size() const { return size_; } uint8_t max_size() const { return capacity; } const NoteEntry& most_recent_note() const { return pool_[root_ptr_]; } const NoteEntry& least_recent_note() const { uint8_t current = root_ptr_; while (current && pool_[current].next_ptr) { current = pool_[current].next_ptr; } return pool_[current]; } const NoteEntry& played_note(uint8_t index) const { uint8_t current = root_ptr_; index = size_ - index - 1; for (uint8_t i = 0; i < index; ++i) { current = pool_[current].next_ptr; } return pool_[current]; } const NoteEntry& sorted_note(uint8_t index) const { return pool_[sorted_ptr_[index]]; } const NoteEntry& note(uint8_t index) const { return pool_[index]; } NoteEntry* mutable_note(uint8_t index) { return &pool_[index]; } const NoteEntry& dummy() const { return pool_[0]; } const NoteEntry& note_by_priority(NoteStackFlags priority, uint8_t index=0) { if (size() <= index) { return dummy(); } switch (priority) { case NOTE_STACK_PRIORITY_LAST: return played_note(size() - 1 - index); case NOTE_STACK_PRIORITY_LOW: return sorted_note(index); case NOTE_STACK_PRIORITY_HIGH: return sorted_note(size() - 1 - index); case NOTE_STACK_PRIORITY_FIRST: return played_note(index); default: return dummy(); } } private: uint8_t size_; NoteEntry pool_[capacity + 1]; // First element is a dummy node! uint8_t root_ptr_; // Base 1. uint8_t sorted_ptr_[capacity + 1]; // Base 1. DISALLOW_COPY_AND_ASSIGN(NoteStack); }; } // namespace stmlib #endif // STMLIB_ALGORITHMS_NOTE_STACK_H_ ================================================ FILE: lib/stmlib/algorithms/pattern_predictor.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Pattern predictor for synchronization to drum patterns or clocks with swing. #ifndef STMLIB_ALGORITHMS_PATTERN_PREDICTOR_H_ #define STMLIB_ALGORITHMS_PATTERN_PREDICTOR_H_ #include "stmlib/stmlib.h" #include #include namespace stmlib { template class PatternPredictor { public: PatternPredictor() { } void Init() { history_pointer_ = 0; std::fill(&history_[0], &history_[history_size], 0); std::fill( &prediction_error_[0], &prediction_error_[max_candidate_period + 1], 0); std::fill( &predicted_period_[0], &predicted_period_[max_candidate_period + 1], 0); } uint32_t Predict(int32_t value) { history_[history_pointer_] = value; int best_period = 0; for (int i = 0; i <= max_candidate_period; ++i) { int32_t error = abs(predicted_period_[i] - value); int32_t delta = error - prediction_error_[i]; // Compute LP-ed prediction error. if (delta > 0) { prediction_error_[i] += delta >> 1; } else { prediction_error_[i] += delta >> 3; } if (i == 0) { predicted_period_[i] = (value + predicted_period_[i]) >> 1; } else { uint32_t t = history_pointer_ + 1 + history_size - i; predicted_period_[i] = history_[t % history_size]; } if (prediction_error_[i] < prediction_error_[best_period]) { best_period = i; } } history_pointer_ = (history_pointer_ + 1) % history_size; return static_cast(predicted_period_[best_period]); } private: uint32_t history_[history_size]; int32_t prediction_error_[max_candidate_period + 1]; int32_t predicted_period_[max_candidate_period + 1]; uint32_t history_pointer_; DISALLOW_COPY_AND_ASSIGN(PatternPredictor); }; } // namespace stmlib #endif // STMLIB_ALGORITHMS_PATTERN_PREDICTOR_H_ ================================================ FILE: lib/stmlib/algorithms/tiny_map.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // A rather inefficient (lookup and insertion in O(n)) map. Useful for storing // very small mappings (say about 16 values). #ifndef STMLIB_ALGORITHMS_TINY_MAP_H_ #define STMLIB_ALGORITHMS_TINY_MAP_H_ #include "stmlib/stmlib.h" #include namespace stmlib { template< typename Key, typename Value, uint8_t capacity, uint8_t EMPTY = 0xff> class TinyMap { public: struct Entry { Key key; Value value; }; TinyMap() { } ~TinyMap() { } void Init() { Clear(); } void Put(Key key, Value value) { Entry* entry = Search(key); if (entry == NULL) { entry = SearchFreeSlot(); } if (entry == NULL) { entry = &map_[0]; } entry->key = key; entry->value = value; // Speed up retrieval for next query, in the very common case that when // element is inserted, the next query is for this same element. if (value != EMPTY) { recent_search_ = entry; } else { recent_delete_ = entry; } } const Entry* Find(uint8_t key) { return Search(key); } void Clear() { memset(map_, EMPTY, capacity * sizeof(Entry)); recent_search_ = recent_delete_ = &map_[0]; } private: Entry* Search(Key key) { if (recent_search_->key == key) { return recent_search_; } for (uint8_t i = 0; i < capacity; ++i) { if (map_[i].key == key) { recent_search_ = &map_[i]; return recent_search_; } } return NULL; } Entry* SearchFreeSlot() { if (recent_delete_->value == EMPTY) { return recent_delete_; } for (uint8_t i = 0; i < capacity; ++i) { if (map_[i].value == EMPTY) { recent_delete_ = &map_[i]; return recent_delete_; } } return NULL; } Entry map_[capacity]; Entry* recent_search_; Entry* recent_delete_; DISALLOW_COPY_AND_ASSIGN(TinyMap); }; } // namespace stmlib #endif // STMLIB_ALGORITHMS_TINY_MAP_H_ ================================================ FILE: lib/stmlib/algorithms/voice_allocator.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Polyphonic voice allocator. #ifndef STMLIB_ALGORITHMS_VOICE_ALLOCATOR_H_ #define STMLIB_ALGORITHMS_VOICE_ALLOCATOR_H_ #include "stmlib/stmlib.h" #include namespace stmlib { enum VoiceAllocatorFlags { NOT_ALLOCATED = 0xff, ACTIVE_NOTE = 0x80 }; enum VoiceStealingMode { VOICE_STEALING_MODE_LRU, VOICE_STEALING_MODE_MRU }; template class VoiceAllocator { public: VoiceAllocator() { } void Init() { size_ = 0; Clear(); } uint8_t NoteOn(uint8_t note) { return NoteOn(note, VOICE_STEALING_MODE_LRU); } uint8_t NoteOn(uint8_t note, VoiceStealingMode voice_stealing_mode) { if (size_ == 0) { return NOT_ALLOCATED; } // First, check if there is a voice currently playing this note. In this // case, this voice will be responsible for retriggering this note. // Hint: if you're more into string instruments than keyboard instruments, // you can safely comment those lines. uint8_t voice = Find(note); // Then, try to find the least recently touched, currently inactive voice. if (voice == NOT_ALLOCATED) { for (uint8_t i = 0; i < capacity; ++i) { if (lru_[i] < size_ && !(pool_[lru_[i]] & ACTIVE_NOTE)) { voice = lru_[i]; } } } // If all voices are active, use the least or most recently played note // (voice-stealing). if (voice == NOT_ALLOCATED) { for (uint8_t i = 0; i < capacity; ++i) { uint8_t candidate = voice_stealing_mode == VOICE_STEALING_MODE_LRU ? i : capacity - 1 - i; if (lru_[candidate] < size_) { voice = lru_[candidate]; } } } pool_[voice] = note | ACTIVE_NOTE; Touch(voice); return voice; } uint8_t NoteOff(uint8_t note) { uint8_t voice = Find(note); if (voice != NOT_ALLOCATED) { pool_[voice] &= 0x7f; Touch(voice); } return voice; } uint8_t Find(uint8_t note) const { for (uint8_t i = 0; i < size_; ++i) { if ((pool_[i] & 0x7f) == note) { return i; } } return NOT_ALLOCATED; } void Clear() { memset(&pool_, 0, sizeof(pool_)); for (uint8_t i = 0; i < capacity; ++i) { lru_[i] = capacity - i - 1; } } inline void ClearNotes() { for (uint8_t i = 0; i < capacity; ++i) { pool_[i] &= 0x7f; } } inline void set_size(uint8_t size) { size_ = size; } inline uint8_t size() const { return size_; } private: void Touch(uint8_t voice) { int8_t source = capacity - 1; int8_t destination = capacity - 1; while (source >= 0) { if (lru_[source] != voice) { lru_[destination--] = lru_[source]; } --source; } lru_[0] = voice; } uint8_t pool_[capacity]; // Holds the indices of the voices sorted by most recent usage. uint8_t lru_[capacity]; uint8_t size_; DISALLOW_COPY_AND_ASSIGN(VoiceAllocator); }; } // namespace stmlib #endif // STMLIB_ALGORITHMS_VOICE_ALLOCATOR_H_ ================================================ FILE: lib/stmlib/dsp/atan.cc ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Fast arc-tangent routines. #include "stmlib/dsp/atan.h" namespace stmlib { /* extern */ const uint16_t atan_lut[513] = { 0, 20, 40, 61, 81, 101, 122, 142, 162, 183, 203, 224, 244, 264, 285, 305, 326, 346, 366, 387, 407, 427, 448, 468, 489, 509, 529, 550, 570, 591, 611, 631, 652, 672, 693, 713, 733, 754, 774, 795, 815, 836, 856, 877, 897, 917, 938, 958, 979, 999, 1020, 1040, 1061, 1081, 1102, 1122, 1143, 1163, 1184, 1204, 1225, 1245, 1266, 1286, 1307, 1327, 1348, 1368, 1389, 1409, 1430, 1451, 1471, 1492, 1512, 1533, 1554, 1574, 1595, 1615, 1636, 1657, 1677, 1698, 1719, 1739, 1760, 1780, 1801, 1822, 1843, 1863, 1884, 1905, 1925, 1946, 1967, 1988, 2008, 2029, 2050, 2071, 2091, 2112, 2133, 2154, 2175, 2195, 2216, 2237, 2258, 2279, 2300, 2321, 2342, 2362, 2383, 2404, 2425, 2446, 2467, 2488, 2509, 2530, 2551, 2572, 2593, 2614, 2635, 2656, 2677, 2698, 2719, 2740, 2761, 2783, 2804, 2825, 2846, 2867, 2888, 2910, 2931, 2952, 2973, 2994, 3016, 3037, 3058, 3079, 3101, 3122, 3143, 3165, 3186, 3207, 3229, 3250, 3272, 3293, 3315, 3336, 3357, 3379, 3400, 3422, 3443, 3465, 3487, 3508, 3530, 3551, 3573, 3595, 3616, 3638, 3660, 3681, 3703, 3725, 3747, 3768, 3790, 3812, 3834, 3856, 3877, 3899, 3921, 3943, 3965, 3987, 4009, 4031, 4053, 4075, 4097, 4119, 4141, 4163, 4185, 4207, 4230, 4252, 4274, 4296, 4318, 4341, 4363, 4385, 4408, 4430, 4452, 4475, 4497, 4520, 4542, 4565, 4587, 4610, 4632, 4655, 4677, 4700, 4723, 4745, 4768, 4791, 4813, 4836, 4859, 4882, 4905, 4927, 4950, 4973, 4996, 5019, 5042, 5065, 5088, 5111, 5134, 5158, 5181, 5204, 5227, 5250, 5274, 5297, 5320, 5344, 5367, 5390, 5414, 5437, 5461, 5484, 5508, 5532, 5555, 5579, 5603, 5626, 5650, 5674, 5698, 5721, 5745, 5769, 5793, 5817, 5841, 5865, 5889, 5914, 5938, 5962, 5986, 6010, 6035, 6059, 6084, 6108, 6132, 6157, 6181, 6206, 6231, 6255, 6280, 6305, 6330, 6354, 6379, 6404, 6429, 6454, 6479, 6504, 6529, 6554, 6580, 6605, 6630, 6656, 6681, 6706, 6732, 6757, 6783, 6809, 6834, 6860, 6886, 6912, 6937, 6963, 6989, 7015, 7041, 7068, 7094, 7120, 7146, 7173, 7199, 7225, 7252, 7278, 7305, 7332, 7358, 7385, 7412, 7439, 7466, 7493, 7520, 7547, 7574, 7602, 7629, 7656, 7684, 7711, 7739, 7767, 7795, 7822, 7850, 7878, 7906, 7934, 7962, 7991, 8019, 8047, 8076, 8104, 8133, 8162, 8190, 8219, 8248, 8277, 8306, 8335, 8365, 8394, 8423, 8453, 8483, 8512, 8542, 8572, 8602, 8632, 8662, 8692, 8723, 8753, 8784, 8814, 8845, 8876, 8907, 8938, 8969, 9000, 9032, 9063, 9095, 9127, 9158, 9190, 9223, 9255, 9287, 9319, 9352, 9385, 9418, 9451, 9484, 9517, 9550, 9584, 9617, 9651, 9685, 9719, 9753, 9788, 9822, 9857, 9892, 9927, 9962, 9998, 10033, 10069, 10105, 10141, 10177, 10213, 10250, 10287, 10324, 10361, 10399, 10436, 10474, 10512, 10550, 10589, 10628, 10667, 10706, 10745, 10785, 10825, 10865, 10906, 10946, 10988, 11029, 11070, 11112, 11155, 11197, 11240, 11283, 11327, 11371, 11415, 11460, 11505, 11550, 11596, 11642, 11688, 11736, 11783, 11831, 11879, 11928, 11978, 12028, 12078, 12129, 12181, 12233, 12286, 12340, 12394, 12449, 12505, 12561, 12618, 12676, 12735, 12795, 12856, 12918, 12981, 13045, 13111, 13177, 13245, 13315, 13386, 13459, 13533, 13610, 13688, 13769, 13853, 13939, 14028, 14121, 14218, 14319, 14425, 14537, 14657, 14785, 14925, 15079, 15254, 15461, 15731, 16383, }; // Generated with: // static void init_atan_lut() { // for (size_t i = 0; i < 513; ++i) { // atan_lut[i] = 65536.0 / (2 * M_PI) * asinf(i / 512.0f); // printf("%5d, ", atan_lut[i]); // if (i % 8 == 7) { // printf("\n"); // } // } // printf("\n"); // } } // namespace stmlib ================================================ FILE: lib/stmlib/dsp/atan.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Fast arc-tangent routines. #ifndef STMLIB_DSP_ATAN_H_ #define STMLIB_DSP_ATAN_H_ #include "stmlib/stmlib.h" #include "stmlib/dsp/rsqrt.h" #include namespace stmlib { static inline uint16_t fast_atan2(float y, float x) { static const uint32_t sign_mask = 0x80000000; static const float b = 0.596227f; uint32_t ux_s = sign_mask & unsafe_bit_cast(x); uint32_t uy_s = sign_mask & unsafe_bit_cast(y); uint32_t offset = ((~ux_s & uy_s) >> 29 | ux_s >> 30) << 14; float bxy_a = fabsf(b * x * y); float num = bxy_a + y * y; float atan_1q = num / (x * x + bxy_a + num); uint32_t uatan_2q = (ux_s ^ uy_s) | unsafe_bit_cast(atan_1q); return unsafe_bit_cast(uatan_2q) * 16384 + offset; } extern const uint16_t atan_lut[513]; static inline uint16_t fast_atan2r(float y, float x, float* r) { float squared_magnitude = x * x + y * y; if (squared_magnitude == 0.0f) { *r = 0.0f; return 0.0f; } float rinv = fast_rsqrt_carmack(squared_magnitude); *r = rinv * squared_magnitude; static const uint32_t sign_mask = 0x80000000; uint32_t ux_s = sign_mask & unsafe_bit_cast(x); uint32_t uy_s = sign_mask & unsafe_bit_cast(y); uint32_t quadrant = ((~ux_s & uy_s) >> 29 | ux_s >> 30); uint16_t angle = 0; x = fabsf(x); y = fabsf(y); if (y > x) { angle = 16384 - atan_lut[static_cast(x * rinv * 512.0f + 0.5f)]; } else { angle = atan_lut[static_cast(y * rinv * 512.0f + 0.5f)]; } if (ux_s ^ uy_s) { angle = -angle; } return angle + (quadrant << 14); } } // namespace stmlib #endif // STMLIB_DSP_ATAN_H_ ================================================ FILE: lib/stmlib/dsp/atan_approximations.py ================================================ import numpy import pylab def dumb(f): return f * numpy.pi def pade(f): return f * -0.90585 / (-0.28833 + f * f) def poly3taylor(f): fsq = f * f r = 0.3333333 * numpy.pi ** 3 r *= fsq r += numpy.pi r *= f return r def poly3gradient(f, a=3.736e-01): fsq = f * f r = a * numpy.pi ** 3 r *= fsq r += numpy.pi r *= f return r def poly5mdsp(f, a=3.1755e-01, b=2.033e-01): fsq = f * f r = b * numpy.pi ** 5 r *= fsq r += a * numpy.pi ** 3 r *= fsq r += numpy.pi r *= f return r def poly5gradient(f, a=3.260e-01, b=1.823e-01): f = f * numpy.pi fsq = f * f r = b r *= fsq r += a r *= fsq r += 1.0 r *= f return r def poly11mdsp(f): fsq = f * f r = 9.5168091e-03 * numpy.pi ** 11 r *= fsq r += 2.900525e-03 * numpy.pi ** 9 r *= fsq r += 5.33740603e-02 * numpy.pi **7 r *= fsq r += 1.333923995e-01 * numpy.pi **5 r *= fsq r += 3.333314036e-01 * numpy.pi **3 r *= fsq r += numpy.pi r *= f return r def compute_filter_settings(cutoff, resonance): g = numpy.tan(numpy.pi * cutoff) + resonance * 0 r = 1.0 / resonance + cutoff * 0 h = 1 / (1 + r * g + g * g) return g, r, h def evaluate(groundtruth_f, approximate_g): approximate_f = numpy.arctan(approximate_g) / numpy.pi return numpy.log2(approximate_f / groundtruth_f) * 1200.0 f = numpy.exp(numpy.linspace(numpy.log(16), numpy.log(10000), 1000.0)) f /= 48000.0 g, _, _ = compute_filter_settings(f, 0.5) approximations = [pade, poly3gradient, poly5mdsp, poly5gradient, poly11mdsp] # # a_ = numpy.linspace(3.259e-01, 3.261e-01, 100) # b_ = numpy.linspace(1.822e-01, 1.823e-01, 100) # error = numpy.zeros((100, 100)) # best = 1e8 # arg_best = None # for i, a in enumerate(a_): # for j, b in enumerate(b_): # error[i, j] = (evaluate(f, fast0(f, a, b)) ** 2).sum() # if error[i, j] < best: # best = error[i, j] # arg_best = (a, b) # # print arg_best # pylab.plot(coefficient, error) # pylab.show() pylab.figure(figsize=(15,10)) for i, a in enumerate(approximations): n = len(approximations) # pylab.subplot(n * 100 + 10 + i + 1) pylab.plot(f * 48000, evaluate(f, a(f))) pylab.xlabel('Hz') pylab.ylabel('$\delta$ cents') pylab.legend(map(lambda x: x.__name__, approximations)) pylab.tight_layout() #pylab.savefig('plot.pdf') pylab.show() ================================================ FILE: lib/stmlib/dsp/cosine_oscillator.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Cosine oscillator. Generates a cosine between 0.0 and 1.0 with minimal // CPU use. #ifndef STMLIB_DSP_COSINE_OSCILLATOR_H_ #define STMLIB_DSP_COSINE_OSCILLATOR_H_ #include "stmlib/stmlib.h" #include namespace stmlib { enum CosineOscillatorMode { COSINE_OSCILLATOR_APPROXIMATE, COSINE_OSCILLATOR_EXACT }; class CosineOscillator { public: CosineOscillator() { } ~CosineOscillator() { } template inline void Init(float frequency) { if (mode == COSINE_OSCILLATOR_APPROXIMATE) { InitApproximate(frequency); } else { iir_coefficient_ = 2.0f * cosf(2.0f * float(M_PI) * frequency); initial_amplitude_ = iir_coefficient_ * 0.25f; } Start(); } inline void InitApproximate(float frequency) { float sign = 16.0f; frequency -= 0.25f; if (frequency < 0.0f) { frequency = -frequency; } else { if (frequency > 0.5f) { frequency -= 0.5f; } else { sign = -16.0f; } } iir_coefficient_ = sign * frequency * (1.0f - 2.0f * frequency); initial_amplitude_ = iir_coefficient_ * 0.25f; } inline void Start() { y1_ = initial_amplitude_; y0_ = 0.5f; } inline float value() const { return y1_ + 0.5f; } inline float Next() { float temp = y0_; y0_ = iir_coefficient_ * y0_ - y1_; y1_ = temp; return temp + 0.5f; } private: float y1_; float y0_; float iir_coefficient_; float initial_amplitude_; DISALLOW_COPY_AND_ASSIGN(CosineOscillator); }; } // namespace stmlib #endif // STMLIB_DSP_COSINE_OSCILLATOR_H_ ================================================ FILE: lib/stmlib/dsp/delay_line.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Delay line. #ifndef STMLIB_DSP_DELAY_LINE_H_ #define STMLIB_DSP_DELAY_LINE_H_ #include "stmlib/stmlib.h" #include "stmlib/dsp/dsp.h" #include namespace stmlib { template class DelayLine { public: DelayLine() { } ~DelayLine() { } void Init() { Reset(); } void Reset() { std::fill(&line_[0], &line_[max_delay], T(0)); delay_ = 1; write_ptr_ = 0; } inline void set_delay(size_t delay) { delay_ = delay; } inline void Write(const T sample) { line_[write_ptr_] = sample; write_ptr_ = (write_ptr_ - 1 + max_delay) % max_delay; } inline const T Allpass(const T sample, size_t delay, const T coefficient) { T read = line_[(write_ptr_ + delay) % max_delay]; T write = sample + coefficient * read; Write(write); return -write * coefficient + read; } inline const T WriteRead(const T sample, float delay) { Write(sample); return Read(delay); } inline const T Read() const { return line_[(write_ptr_ + delay_) % max_delay]; } inline const T Read(size_t delay) const { return line_[(write_ptr_ + delay) % max_delay]; } inline const T Read(float delay) const { MAKE_INTEGRAL_FRACTIONAL(delay) const T a = line_[(write_ptr_ + delay_integral) % max_delay]; const T b = line_[(write_ptr_ + delay_integral + 1) % max_delay]; return a + (b - a) * delay_fractional; } inline const T ReadHermite(float delay) const { MAKE_INTEGRAL_FRACTIONAL(delay) int32_t t = (write_ptr_ + delay_integral + max_delay); const T xm1 = line_[(t - 1) % max_delay]; const T x0 = line_[(t) % max_delay]; const T x1 = line_[(t + 1) % max_delay]; const T x2 = line_[(t + 2) % max_delay]; const float c = (x1 - xm1) * 0.5f; const float v = x0 - x1; const float w = c + v; const float a = w + v + (x2 - x0) * 0.5f; const float b_neg = w + a; const float f = delay_fractional; return (((a * f) - b_neg) * f + c) * f + x0; } private: size_t write_ptr_; size_t delay_; T line_[max_delay]; DISALLOW_COPY_AND_ASSIGN(DelayLine); }; } // namespace stmlib #endif // STMLIB_DSP_DELAY_LINE_H_ ================================================ FILE: lib/stmlib/dsp/dsp.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // DSP utility routines. #ifndef STMLIB_UTILS_DSP_DSP_H_ #define STMLIB_UTILS_DSP_DSP_H_ #include "stmlib/stmlib.h" #include #include namespace stmlib { #define MAKE_INTEGRAL_FRACTIONAL(x) \ int32_t x ## _integral = static_cast(x); \ float x ## _fractional = x - static_cast(x ## _integral); inline float Interpolate(const float* table, float index, float size) { index *= size; MAKE_INTEGRAL_FRACTIONAL(index) float a = table[index_integral]; float b = table[index_integral + 1]; return a + (b - a) * index_fractional; } inline float InterpolateHermite(const float* table, float index, float size) { index *= size; MAKE_INTEGRAL_FRACTIONAL(index) const float xm1 = table[index_integral - 1]; const float x0 = table[index_integral + 0]; const float x1 = table[index_integral + 1]; const float x2 = table[index_integral + 2]; const float c = (x1 - xm1) * 0.5f; const float v = x0 - x1; const float w = c + v; const float a = w + v + (x2 - x0) * 0.5f; const float b_neg = w + a; const float f = index_fractional; return (((a * f) - b_neg) * f + c) * f + x0; } inline float InterpolateWrap(const float* table, float index, float size) { index -= static_cast(static_cast(index)); index *= size; MAKE_INTEGRAL_FRACTIONAL(index) float a = table[index_integral]; float b = table[index_integral + 1]; return a + (b - a) * index_fractional; } inline float SmoothStep(float value) { return value * value * (3.0f - 2.0f * value); } #define ONE_POLE(out, in, coefficient) out += (coefficient) * ((in) - out); #define SLOPE(out, in, positive, negative) { \ float error = (in) - out; \ out += (error > 0 ? positive : negative) * error; \ } #define SLEW(out, in, delta) { \ float error = (in) - out; \ float d = (delta); \ if (error > d) { \ error = d; \ } else if (error < -d) { \ error = -d; \ } \ out += error; \ } inline float Crossfade(float a, float b, float fade) { return a + (b - a) * fade; } inline float SoftLimit(float x) { return x * (27.0f + x * x) / (27.0f + 9.0f * x * x); } inline float SoftClip(float x) { if (x < -3.0f) { return -1.0f; } else if (x > 3.0f) { return 1.0f; } else { return SoftLimit(x); } } #ifdef TEST inline int32_t Clip16(int32_t x) { if (x < -32768) { return -32768; } else if (x > 32767) { return 32767; } else { return x; } } inline uint16_t ClipU16(int32_t x) { if (x < 0) { return 0; } else if (x > 65535) { return 65535; } else { return x; } } #else inline int32_t Clip16(int32_t x) { int32_t result; __asm ("ssat %0, %1, %2" : "=r" (result) : "I" (16), "r" (x) ); return result; } inline uint32_t ClipU16(int32_t x) { uint32_t result; __asm ("usat %0, %1, %2" : "=r" (result) : "I" (16), "r" (x) ); return result; } #endif #ifdef TEST inline float Sqrt(float x) { return sqrtf(x); } #else inline float Sqrt(float x) { float result; __asm ("vsqrt.f32 %0, %1" : "=w" (result) : "w" (x) ); return result; } #endif inline int16_t SoftConvert(float x) { return Clip16(static_cast(SoftLimit(x * 0.5f) * 32768.0f)); } } // namespace stmlib #endif // STMLIB_UTILS_DSP_DSP_H_ ================================================ FILE: lib/stmlib/dsp/filter.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Zero-delay-feedback filters (one pole and SVF). // Naive SVF. #ifndef STMLIB_DSP_FILTER_H_ #define STMLIB_DSP_FILTER_H_ #include "stmlib/stmlib.h" #include #include namespace stmlib { enum FilterMode { FILTER_MODE_LOW_PASS, FILTER_MODE_BAND_PASS, FILTER_MODE_BAND_PASS_NORMALIZED, FILTER_MODE_HIGH_PASS }; enum FrequencyApproximation { FREQUENCY_EXACT, FREQUENCY_ACCURATE, FREQUENCY_FAST, FREQUENCY_DIRTY }; #define M_PI_F float(M_PI) #define M_PI_POW_2 M_PI * M_PI #define M_PI_POW_3 M_PI_POW_2 * M_PI #define M_PI_POW_5 M_PI_POW_3 * M_PI_POW_2 #define M_PI_POW_7 M_PI_POW_5 * M_PI_POW_2 #define M_PI_POW_9 M_PI_POW_7 * M_PI_POW_2 #define M_PI_POW_11 M_PI_POW_9 * M_PI_POW_2 class DCBlocker { public: DCBlocker() { } ~DCBlocker() { } void Init(float pole) { x_ = 0.0f; y_ = 0.0f; pole_ = pole; } inline void Process(float* in_out, size_t size) { float x = x_; float y = y_; const float pole = pole_; while (size--) { float old_x = x; x = *in_out; *in_out++ = y = y * pole + x - old_x; } x_ = x; y_ = y; } private: float pole_; float x_; float y_; }; class OnePole { public: OnePole() { } ~OnePole() { } void Init() { set_f(0.01f); Reset(); } void Reset() { state_ = 0.0f; } template static inline float tan(float f) { if (approximation == FREQUENCY_EXACT) { // Clip coefficient to about 100. f = f < 0.497f ? f : 0.497f; return tanf(M_PI_F * f); } else if (approximation == FREQUENCY_DIRTY) { // Optimized for frequencies below 8kHz. const float a = 3.736e-01f * M_PI_POW_3; return f * (M_PI_F + a * f * f); } else if (approximation == FREQUENCY_FAST) { // The usual tangent approximation uses 3.1755e-01 and 2.033e-01, but // the coefficients used here are optimized to minimize error for the // 16Hz to 16kHz range, with a sample rate of 48kHz. const float a = 3.260e-01f * M_PI_POW_3; const float b = 1.823e-01f * M_PI_POW_5; float f2 = f * f; return f * (M_PI_F + f2 * (a + b * f2)); } else if (approximation == FREQUENCY_ACCURATE) { // These coefficients don't need to be tweaked for the audio range. const float a = 3.333314036e-01f * M_PI_POW_3; const float b = 1.333923995e-01f * M_PI_POW_5; const float c = 5.33740603e-02f * M_PI_POW_7; const float d = 2.900525e-03f * M_PI_POW_9; const float e = 9.5168091e-03f * M_PI_POW_11; float f2 = f * f; return f * (M_PI_F + f2 * (a + f2 * (b + f2 * (c + f2 * (d + f2 * e))))); } } // Set frequency and resonance from true units. Various approximations // are available to avoid the cost of tanf. template inline void set_f(float f) { g_ = tan(f); gi_ = 1.0f / (1.0f + g_); } template inline float Process(float in) { float lp; lp = (g_ * in + state_) * gi_; state_ = g_ * (in - lp) + lp; if (mode == FILTER_MODE_LOW_PASS) { return lp; } else if (mode == FILTER_MODE_HIGH_PASS) { return in - lp; } else { return 0.0f; } } template inline void Process(float* in_out, size_t size) { while (size--) { *in_out = Process(*in_out); ++in_out; } } private: float g_; float gi_; float state_; DISALLOW_COPY_AND_ASSIGN(OnePole); }; class Svf { public: Svf() { } ~Svf() { } void Init() { set_f_q(0.01f, 100.0f); Reset(); } void Reset() { state_1_ = state_2_ = 0.0f; } // Copy settings from another filter. inline void set(const Svf& f) { g_ = f.g(); r_ = f.r(); h_ = f.h(); } // Set all parameters from LUT. inline void set_g_r_h(float g, float r, float h) { g_ = g; r_ = r; h_ = h; } // Set frequency and resonance coefficients from LUT, adjust remaining // parameter. inline void set_g_r(float g, float r) { g_ = g; r_ = r; h_ = 1.0f / (1.0f + r_ * g_ + g_ * g_); } // Set frequency from LUT, resonance in true units, adjust the rest. inline void set_g_q(float g, float resonance) { g_ = g; r_ = 1.0f / resonance; h_ = 1.0f / (1.0f + r_ * g_ + g_ * g_); } // Set frequency and resonance from true units. Various approximations // are available to avoid the cost of tanf. template inline void set_f_q(float f, float resonance) { g_ = OnePole::tan(f); r_ = 1.0f / resonance; h_ = 1.0f / (1.0f + r_ * g_ + g_ * g_); } template inline float Process(float in) { float hp, bp, lp; hp = (in - r_ * state_1_ - g_ * state_1_ - state_2_) * h_; bp = g_ * hp + state_1_; state_1_ = g_ * hp + bp; lp = g_ * bp + state_2_; state_2_ = g_ * bp + lp; if (mode == FILTER_MODE_LOW_PASS) { return lp; } else if (mode == FILTER_MODE_BAND_PASS) { return bp; } else if (mode == FILTER_MODE_BAND_PASS_NORMALIZED) { return bp * r_; } else if (mode == FILTER_MODE_HIGH_PASS) { return hp; } } template inline void Process(float in, float* out_1, float* out_2) { float hp, bp, lp; hp = (in - r_ * state_1_ - g_ * state_1_ - state_2_) * h_; bp = g_ * hp + state_1_; state_1_ = g_ * hp + bp; lp = g_ * bp + state_2_; state_2_ = g_ * bp + lp; if (mode_1 == FILTER_MODE_LOW_PASS) { *out_1 = lp; } else if (mode_1 == FILTER_MODE_BAND_PASS) { *out_1 = bp; } else if (mode_1 == FILTER_MODE_BAND_PASS_NORMALIZED) { *out_1 = bp * r_; } else if (mode_1 == FILTER_MODE_HIGH_PASS) { *out_1 = hp; } if (mode_2 == FILTER_MODE_LOW_PASS) { *out_2 = lp; } else if (mode_2 == FILTER_MODE_BAND_PASS) { *out_2 = bp; } else if (mode_2 == FILTER_MODE_BAND_PASS_NORMALIZED) { *out_2 = bp * r_; } else if (mode_2 == FILTER_MODE_HIGH_PASS) { *out_2 = hp; } } template inline void Process(const float* in, float* out, size_t size) { float hp, bp, lp; float state_1 = state_1_; float state_2 = state_2_; while (size--) { hp = (*in - r_ * state_1 - g_ * state_1 - state_2) * h_; bp = g_ * hp + state_1; state_1 = g_ * hp + bp; lp = g_ * bp + state_2; state_2 = g_ * bp + lp; float value; if (mode == FILTER_MODE_LOW_PASS) { value = lp; } else if (mode == FILTER_MODE_BAND_PASS) { value = bp; } else if (mode == FILTER_MODE_BAND_PASS_NORMALIZED) { value = bp * r_; } else if (mode == FILTER_MODE_HIGH_PASS) { value = hp; } *out = value; ++out; ++in; } state_1_ = state_1; state_2_ = state_2; } template inline void ProcessAdd(const float* in, float* out, size_t size, float gain) { float hp, bp, lp; float state_1 = state_1_; float state_2 = state_2_; while (size--) { hp = (*in - r_ * state_1 - g_ * state_1 - state_2) * h_; bp = g_ * hp + state_1; state_1 = g_ * hp + bp; lp = g_ * bp + state_2; state_2 = g_ * bp + lp; float value; if (mode == FILTER_MODE_LOW_PASS) { value = lp; } else if (mode == FILTER_MODE_BAND_PASS) { value = bp; } else if (mode == FILTER_MODE_BAND_PASS_NORMALIZED) { value = bp * r_; } else if (mode == FILTER_MODE_HIGH_PASS) { value = hp; } *out += gain * value; ++out; ++in; } state_1_ = state_1; state_2_ = state_2; } template inline void Process(const float* in, float* out, size_t size, size_t stride) { float hp, bp, lp; float state_1 = state_1_; float state_2 = state_2_; while (size--) { hp = (*in - r_ * state_1 - g_ * state_1 - state_2) * h_; bp = g_ * hp + state_1; state_1 = g_ * hp + bp; lp = g_ * bp + state_2; state_2 = g_ * bp + lp; float value; if (mode == FILTER_MODE_LOW_PASS) { value = lp; } else if (mode == FILTER_MODE_BAND_PASS) { value = bp; } else if (mode == FILTER_MODE_BAND_PASS_NORMALIZED) { value = bp * r_; } else if (mode == FILTER_MODE_HIGH_PASS) { value = hp; } *out = value; out += stride; in += stride; } state_1_ = state_1; state_2_ = state_2; } inline void ProcessMultimode( const float* in, float* out, size_t size, float mode) { float hp, bp, lp; float state_1 = state_1_; float state_2 = state_2_; float hp_gain = mode < 0.5f ? -mode * 2.0f : -2.0f + mode * 2.0f; float lp_gain = mode < 0.5f ? 1.0f - mode * 2.0f : 0.0f; float bp_gain = mode < 0.5f ? 0.0f : mode * 2.0f - 1.0f; while (size--) { hp = (*in - r_ * state_1 - g_ * state_1 - state_2) * h_; bp = g_ * hp + state_1; state_1 = g_ * hp + bp; lp = g_ * bp + state_2; state_2 = g_ * bp + lp; *out = hp_gain * hp + bp_gain * bp + lp_gain * lp; ++in; ++out; } state_1_ = state_1; state_2_ = state_2; } inline void ProcessMultimodeLPtoHP( const float* in, float* out, size_t size, float mode) { float hp, bp, lp; float state_1 = state_1_; float state_2 = state_2_; float hp_gain = std::min(-mode * 2.0f + 1.0f, 0.0f); float bp_gain = 1.0f - 2.0f * fabsf(mode - 0.5f); float lp_gain = std::max(1.0f - mode * 2.0f, 0.0f); while (size--) { hp = (*in - r_ * state_1 - g_ * state_1 - state_2) * h_; bp = g_ * hp + state_1; state_1 = g_ * hp + bp; lp = g_ * bp + state_2; state_2 = g_ * bp + lp; *out = hp_gain * hp + bp_gain * bp + lp_gain * lp; ++in; ++out; } state_1_ = state_1; state_2_ = state_2; } template inline void Process( const float* in, float* out_1, float* out_2, size_t size, float gain_1, float gain_2) { float hp, bp, lp; float state_1 = state_1_; float state_2 = state_2_; while (size--) { hp = (*in - r_ * state_1 - g_ * state_1 - state_2) * h_; bp = g_ * hp + state_1; state_1 = g_ * hp + bp; lp = g_ * bp + state_2; state_2 = g_ * bp + lp; float value; if (mode == FILTER_MODE_LOW_PASS) { value = lp; } else if (mode == FILTER_MODE_BAND_PASS) { value = bp; } else if (mode == FILTER_MODE_BAND_PASS_NORMALIZED) { value = bp * r_; } else if (mode == FILTER_MODE_HIGH_PASS) { value = hp; } *out_1 += value * gain_1; *out_2 += value * gain_2; ++out_1; ++out_2; ++in; } state_1_ = state_1; state_2_ = state_2; } inline float g() const { return g_; } inline float r() const { return r_; } inline float h() const { return h_; } private: float g_; float r_; float h_; float state_1_; float state_2_; DISALLOW_COPY_AND_ASSIGN(Svf); }; // Naive Chamberlin SVF. class NaiveSvf { public: NaiveSvf() { } ~NaiveSvf() { } void Init() { set_f_q(0.01f, 100.0f); Reset(); } void Reset() { lp_ = bp_ = 0.0f; } // Set frequency and resonance from true units. Various approximations // are available to avoid the cost of sinf. template inline void set_f_q(float f, float resonance) { if (approximation == FREQUENCY_EXACT) { f = f < 0.497f ? f : 0.497f; f_ = 2.0f * sinf(M_PI_F * f); } else { f = f < 0.158f ? f : 0.158f; f_ = 2.0f * M_PI_F * f; } damp_ = 1.0f / resonance; } template inline float Process(float in) { float hp, notch, bp_normalized; bp_normalized = bp_ * damp_; notch = in - bp_normalized; lp_ += f_ * bp_; hp = notch - lp_; bp_ += f_ * hp; if (mode == FILTER_MODE_LOW_PASS) { return lp_; } else if (mode == FILTER_MODE_BAND_PASS) { return bp_; } else if (mode == FILTER_MODE_BAND_PASS_NORMALIZED) { return bp_normalized; } else if (mode == FILTER_MODE_HIGH_PASS) { return hp; } } inline float lp() const { return lp_; } inline float bp() const { return bp_; } template inline void Process(const float* in, float* out, size_t size) { float hp, notch, bp_normalized; float lp = lp_; float bp = bp_; while (size--) { bp_normalized = bp * damp_; notch = *in++ - bp_normalized; lp += f_ * bp; hp = notch - lp; bp += f_ * hp; if (mode == FILTER_MODE_LOW_PASS) { *out++ = lp; } else if (mode == FILTER_MODE_BAND_PASS) { *out++ = bp; } else if (mode == FILTER_MODE_BAND_PASS_NORMALIZED) { *out++ = bp_normalized; } else if (mode == FILTER_MODE_HIGH_PASS) { *out++ = hp; } } lp_ = lp; bp_ = bp; } inline void Split(const float* in, float* low, float* high, size_t size) { float hp, notch, bp_normalized; float lp = lp_; float bp = bp_; while (size--) { bp_normalized = bp * damp_; notch = *in++ - bp_normalized; lp += f_ * bp; hp = notch - lp; bp += f_ * hp; *low++ = lp; *high++ = hp; } lp_ = lp; bp_ = bp; } template inline void Process(const float* in, float* out, size_t size, size_t decimate) { float hp, notch, bp_normalized; float lp = lp_; float bp = bp_; size_t n = decimate - 1; while (size--) { bp_normalized = bp * damp_; notch = *in++ - bp_normalized; lp += f_ * bp; hp = notch - lp; bp += f_ * hp; ++n; if (n == decimate) { if (mode == FILTER_MODE_LOW_PASS) { *out++ = lp; } else if (mode == FILTER_MODE_BAND_PASS) { *out++ = bp; } else if (mode == FILTER_MODE_BAND_PASS_NORMALIZED) { *out++ = bp_normalized; } else if (mode == FILTER_MODE_HIGH_PASS) { *out++ = hp; } n = 0; } } lp_ = lp; bp_ = bp; } private: float f_; float damp_; float lp_; float bp_; DISALLOW_COPY_AND_ASSIGN(NaiveSvf); }; // Modified Chamberlin SVF (Duane K. Wise) // http://www.dafx.ca/proceedings/papers/p_053.pdf class ModifiedSvf { public: ModifiedSvf() { } ~ModifiedSvf() { } void Init() { Reset(); } void Reset() { lp_ = bp_ = 0.0f; } inline void set_f_fq(float f, float fq) { f_ = f; fq_ = fq; x_ = 0.0f; } template inline void Process(const float* in, float* out, size_t size) { float lp = lp_; float bp = bp_; float x = x_; const float fq = fq_; const float f = f_; while (size--) { lp += f * bp; bp += -fq * bp -f * lp + *in; if (mode == FILTER_MODE_BAND_PASS || mode == FILTER_MODE_BAND_PASS_NORMALIZED) { bp += x; } x = *in++; if (mode == FILTER_MODE_LOW_PASS) { *out++ = lp * f; } else if (mode == FILTER_MODE_BAND_PASS) { *out++ = bp * f; } else if (mode == FILTER_MODE_BAND_PASS_NORMALIZED) { *out++ = bp * fq; } else if (mode == FILTER_MODE_HIGH_PASS) { *out++ = x - lp * f - bp * fq; } } lp_ = lp; bp_ = bp; x_ = x; } private: float f_; float fq_; float x_; float lp_; float bp_; DISALLOW_COPY_AND_ASSIGN(ModifiedSvf); }; // Two passes of modified Chamberlin SVF with the same coefficients - // to implement Linkwitz–Riley (Butterworth squared) crossover filters. class CrossoverSvf { public: CrossoverSvf() { } ~CrossoverSvf() { } void Init() { Reset(); } void Reset() { lp_[0] = bp_[0] = lp_[1] = bp_[1] = 0.0f; x_[0] = 0.0f; x_[1] = 0.0f; } inline void set_f_fq(float f, float fq) { f_ = f; fq_ = fq; } template inline void Process(const float* in, float* out, size_t size) { float lp_1 = lp_[0]; float bp_1 = bp_[0]; float lp_2 = lp_[1]; float bp_2 = bp_[1]; float x_1 = x_[0]; float x_2 = x_[1]; const float fq = fq_; const float f = f_; while (size--) { lp_1 += f * bp_1; bp_1 += -fq * bp_1 -f * lp_1 + *in; if (mode == FILTER_MODE_BAND_PASS || mode == FILTER_MODE_BAND_PASS_NORMALIZED) { bp_1 += x_1; } x_1 = *in++; float y; if (mode == FILTER_MODE_LOW_PASS) { y = lp_1 * f; } else if (mode == FILTER_MODE_BAND_PASS) { y = bp_1 * f; } else if (mode == FILTER_MODE_BAND_PASS_NORMALIZED) { y = bp_1 * fq; } else if (mode == FILTER_MODE_HIGH_PASS) { y = x_1 - lp_1 * f - bp_1 * fq; } lp_2 += f * bp_2; bp_2 += -fq * bp_2 -f * lp_2 + y; if (mode == FILTER_MODE_BAND_PASS || mode == FILTER_MODE_BAND_PASS_NORMALIZED) { bp_2 += x_2; } x_2 = y; if (mode == FILTER_MODE_LOW_PASS) { *out++ = lp_2 * f; } else if (mode == FILTER_MODE_BAND_PASS) { *out++ = bp_2 * f; } else if (mode == FILTER_MODE_BAND_PASS_NORMALIZED) { *out++ = bp_2 * fq; } else if (mode == FILTER_MODE_HIGH_PASS) { *out++ = x_2 - lp_2 * f - bp_2 * fq; } } lp_[0] = lp_1; bp_[0] = bp_1; lp_[1] = lp_2; bp_[1] = bp_2; x_[0] = x_1; x_[1] = x_2; } private: float f_; float fq_; float x_[2]; float lp_[2]; float bp_[2]; DISALLOW_COPY_AND_ASSIGN(CrossoverSvf); }; } // namespace stmlib #endif // STMLIB_DSP_FILTER_H_ ================================================ FILE: lib/stmlib/dsp/hysteresis_filter.h ================================================ // Copyright 2019 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Threshold type filter that filters out slow jumps of a value. #ifndef STMLIB_DSP_HYSTERESIS_FILTER_H_ #define STMLIB_DSP_HYSTERESIS_FILTER_H_ #include "stmlib/stmlib.h" namespace stmlib { class HysteresisFilter { public: HysteresisFilter() { } ~HysteresisFilter() { } void Init(float threshold) { value_ = 0.0f; threshold_ = threshold; } inline float Process(float value) { return Process(value, threshold_); } inline float Process(float value, float threshold) { if (threshold == 0.0f) { value_ = value; } else { float error = value - value_; if (error > threshold) { value_ = value - threshold; } else if (error < -threshold) { value_ = value + threshold; } } return value_; } inline float value() const { return value_; } private: float value_; float threshold_; DISALLOW_COPY_AND_ASSIGN(HysteresisFilter); }; } // namespace stmlib #endif // STMLIB_DSP_HYSTERESIS_FILTER_H_ ================================================ FILE: lib/stmlib/dsp/hysteresis_quantizer.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Quantize a float in [0, 1] to an integer in [0, num_steps[. Apply hysteresis // to prevent jumps near the decision boundary. #ifndef STMLIB_DSP_HYSTERESIS_QUANTIZER_H_ #define STMLIB_DSP_HYSTERESIS_QUANTIZER_H_ #include "stmlib/stmlib.h" namespace stmlib { class HysteresisQuantizer { public: HysteresisQuantizer() { } ~HysteresisQuantizer() { } void Init() { quantized_value_ = 0; } inline int Process(float value, int num_steps) { return Process(value, num_steps, 0.25f); } inline int Process(float value, int num_steps, float hysteresis) { return Process(0, value, num_steps, hysteresis); } inline int Process(int base, float value, int num_steps, float hysteresis) { value *= static_cast(num_steps - 1); value += static_cast(base); float hysteresis_feedback = value > static_cast(quantized_value_) ? -hysteresis : hysteresis; int q = static_cast(value + hysteresis_feedback + 0.5f); CONSTRAIN(q, 0, num_steps - 1); quantized_value_ = q; return q; } template const T& Lookup(const T* array, float value, int num_steps) { return array[Process(value, num_steps)]; } private: int quantized_value_; DISALLOW_COPY_AND_ASSIGN(HysteresisQuantizer); }; // Note: currently refactoring this aspect of all Mutable Instruments modules. // The codebase will progressively use only this class, at which point the other // version will be deprecated class HysteresisQuantizer2 { public: HysteresisQuantizer2() { } ~HysteresisQuantizer2() { } void Init(int num_steps, float hysteresis, bool symmetric) { num_steps_ = num_steps; hysteresis_ = hysteresis; scale_ = static_cast(symmetric ? num_steps - 1 : num_steps); offset_ = symmetric ? 0.0f : -0.5f; quantized_value_ = 0; } inline int Process(float value) { return Process(0, value); } inline int Process(int base, float value) { value *= scale_; value += offset_; value += static_cast(base); float hysteresis_sign = value > static_cast(quantized_value_) ? -1.0f : +1.0f; int q = static_cast(value + hysteresis_sign * hysteresis_ + 0.5f); CONSTRAIN(q, 0, num_steps_ - 1); quantized_value_ = q; return q; } template const T& Lookup(const T* array, float value) { return array[Process(value)]; } inline int num_steps() const { return num_steps_; } inline int quantized_value() const { return quantized_value_; } private: int num_steps_; float hysteresis_; float scale_; float offset_; int quantized_value_; DISALLOW_COPY_AND_ASSIGN(HysteresisQuantizer2); }; } // namespace stmlib #endif // STMLIB_DSP_HYSTERESIS_QUANTIZER_H_ ================================================ FILE: lib/stmlib/dsp/limiter.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Limiter. #ifndef STMLIB_DSP_LIMITER_H_ #define STMLIB_DSP_LIMITER_H_ #include "stmlib/stmlib.h" #include #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/filter.h" namespace stmlib { class Limiter { public: Limiter() { } ~Limiter() { } void Init() { peak_ = 0.5f; } void Process(float pre_gain, float* in_out, size_t size) { while (size--) { float s = *in_out * pre_gain; SLOPE(peak_, fabsf(s), 0.05f, 0.00002f); float gain = (peak_ <= 1.0f ? 1.0f : 1.0f / peak_); *in_out++ = s * gain * 0.8f; } } private: float peak_; DISALLOW_COPY_AND_ASSIGN(Limiter); }; } // namespace stmlib #endif // STMLIB_DSP_LIMITER_H_ ================================================ FILE: lib/stmlib/dsp/parameter_interpolator.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Linear interpolation of parameters in rendering loops. #ifndef STMLIB_DSP_PARAMETER_INTERPOLATOR_H_ #define STMLIB_DSP_PARAMETER_INTERPOLATOR_H_ #include "stmlib/stmlib.h" namespace stmlib { class ParameterInterpolator { public: ParameterInterpolator() { } ParameterInterpolator(float* state, float new_value, size_t size) { Init(state, new_value, size); } ParameterInterpolator(float* state, float new_value, float step) { state_ = state; value_ = *state; increment_ = (new_value - *state) * step; } ~ParameterInterpolator() { *state_ = value_; } inline void Init(float* state, float new_value, size_t size) { state_ = state; value_ = *state; increment_ = (new_value - *state) / static_cast(size); } inline float Next() { value_ += increment_; return value_; } inline float subsample(float t) { return value_ + increment_ * t; } private: float* state_; float value_; float increment_; }; } // namespace stmlib #endif // STMLIB_DSP_PARAMETER_INTERPOLATOR_H_ ================================================ FILE: lib/stmlib/dsp/polyblep.h ================================================ // Copyright 2017 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Polynomial approximation of band-limited step for band-limited waveform // synthesis. #ifndef STMLIB_DSP_POLYBLEP_H_ #define STMLIB_DSP_POLYBLEP_H_ #include "stmlib/stmlib.h" namespace stmlib { inline float ThisBlepSample(float t) { return 0.5f * t * t; } inline float NextBlepSample(float t) { t = 1.0f - t; return -0.5f * t * t; } inline float NextIntegratedBlepSample(float t) { const float t1 = 0.5f * t; const float t2 = t1 * t1; const float t4 = t2 * t2; return 0.1875f - t1 + 1.5f * t2 - t4; } inline float ThisIntegratedBlepSample(float t) { return NextIntegratedBlepSample(1.0f - t); } } // namespace stmlib #endif // STMLIB_DSP_POLYBLEP_H_ ================================================ FILE: lib/stmlib/dsp/rsqrt.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Fast reciprocal of square-root routines. #ifndef STMLIB_DSP_RSQRT_H_ #define STMLIB_DSP_RSQRT_H_ #include "stmlib/stmlib.h" namespace stmlib { template struct unsafe_bit_cast_t { union { From from; To to; }; }; template To unsafe_bit_cast(From from) { unsafe_bit_cast_t u; u.from = from; return u.to; } static inline float fast_rsqrt_carmack(float x) { uint32_t i; float x2, y; const float threehalfs = 1.5f; y = x; i = unsafe_bit_cast(y); i = 0x5f3759df - (i >> 1); y = unsafe_bit_cast(i); x2 = x * 0.5f; y = y * (threehalfs - (x2 * y * y)); return y; } static inline float fast_rsqrt_accurate(float fp0) { float _min = 1.0e-38; float _1p5 = 1.5; float fp1, fp2, fp3; uint32_t q = unsafe_bit_cast(fp0); fp2 = unsafe_bit_cast(0x5F3997BB - ((q >> 1) & 0x3FFFFFFF)); fp1 = _1p5 * fp0 - fp0; fp3 = fp2 * fp2; if (fp0 < _min) { return fp0 > 0 ? fp2 : 1000.0f; } fp3 = _1p5 - fp1 * fp3; fp2 = fp2 * fp3; fp3 = fp2 * fp2; fp3 = _1p5 - fp1 * fp3; fp2 = fp2 * fp3; fp3 = fp2 * fp2; fp3 = _1p5 - fp1 * fp3; return fp2 * fp3; } } // namespace stmlib #endif // STMLIB_DSP_RSQRT_H_ ================================================ FILE: lib/stmlib/dsp/sample_rate_converter.h ================================================ // Copyright 2015 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Sample rate converter. #ifndef STMLIB_DSP_SAMPLE_RATE_CONVERTER_H_ #define STMLIB_DSP_SAMPLE_RATE_CONVERTER_H_ #include "stmlib/stmlib.h" #include namespace stmlib { enum SampleRateConversionDirection { SRC_UP, SRC_DOWN }; template struct SRC_FIR { }; template struct FilterState { public: enum { n = N }; inline void Push(float value) { tail.Push(head); head = value; } template inline float Read() const { return i == 0 ? head : tail.template Read(); } inline void Load(const float* x_state) { head = x_state[0]; tail.Load(x_state + 1); } inline void Save(float* x_state) { x_state[0] = head; tail.Save(x_state + 1); } private: float head; FilterState tail; }; template<> class FilterState<1> { public: enum { n = 1 }; inline void Push(float value) { head = value; } template inline float Read() const { return head; } inline void Load(const float* x_state) { head = x_state[0]; } inline void Save(float* x_state) { x_state[0] = head; } private: float head; }; template struct Accumulator { enum { h_index = mirror != 0 && h_offset + i * h_stride >= mirror / 2 ? mirror - 1 - i * h_stride - h_offset : h_offset + i * h_stride }; template inline float operator()(const float* x, const IR& h) const { Accumulator a; return x[i * x_stride] * h.template Read() + a(x, h); } template inline float operator()(const FilterState& x, const IR& h) const { Accumulator a; return x.template Read() * h.template Read() + a(x, h); } }; template struct Accumulator<0, x_stride, h_stride, mirror, i, h_offset> { template inline float operator()(const float* x, const IR& h) const { return 0.0f; } template inline float operator()(const FilterState& x, const IR& h) const { return 0.0f; } }; template struct PolyphaseStage { template inline void operator()(float* &y, const T& x, const IR& h) const { Accumulator a; *y++ = a(x, h); PolyphaseStage p; p(y, x, h); } }; template struct PolyphaseStage { template inline void operator()(float* &y, const T& x, const IR& h) const { } }; template< SampleRateConversionDirection direction, int32_t ratio, int32_t filter_size> class SampleRateConverter { }; template class SampleRateConverter { public: SampleRateConverter() { } ~SampleRateConverter() { } inline void Init() { } inline int32_t delay() const { return 0; } inline void Process(const float* in, float* out, size_t input_size) { std::copy(&in[0], &in[input_size], &out[0]); } private: DISALLOW_COPY_AND_ASSIGN(SampleRateConverter); }; template class SampleRateConverter { public: SampleRateConverter() { } ~SampleRateConverter() { } inline void Init() { } inline int32_t delay() const { return 0; } inline void Process(const float* in, float* out, size_t input_size) { std::copy(&in[0], &in[input_size], &out[0]); } private: DISALLOW_COPY_AND_ASSIGN(SampleRateConverter); }; template class SampleRateConverter { private: enum { N = filter_size / ratio, K = ratio }; public: SampleRateConverter() { } ~SampleRateConverter() { } inline void Init() { std::fill(&x_[0], &x_[N], 0); }; inline int32_t delay() const { return filter_size / ratio / 2; } inline void Process(const float* in, float* out, size_t input_size) { SRC_FIR ir; FilterState x; x.Load(x_); while (input_size--) { x.Push(*in++); PolyphaseStage polyphase_stage; polyphase_stage(out, x, ir); } x.Save(x_); } private: float x_[N]; DISALLOW_COPY_AND_ASSIGN(SampleRateConverter); }; template class SampleRateConverter { private: enum { N = filter_size, K = ratio }; public: SampleRateConverter() { } ~SampleRateConverter() { } inline void Init() { std::fill(&x_[0], &x_[2 * N], 0); x_ptr_ = &x_[N - 1]; }; inline int32_t delay() const { return filter_size / 2; } inline void Process(const float* in, float* out, size_t input_size) { // When downsampling, the number of input samples must be a multiple // of the downsampling ratio. if ((input_size % ratio) != 0) { return; } SRC_FIR ir; if (input_size >= 8 * filter_size) { std::copy(&in[0], &in[N], &x_[N - 1]); // Generate the samples which require access to the history buffer. for (int32_t i = 0; i < N; i += ratio) { Accumulator accumulator; *out++ = accumulator(&x_[N - 1 + i], ir); in += ratio; input_size -= ratio; } // From now on, all the samples we need to access are located inside // the input buffer passed as an argument, and since the filter // is small, we can unroll the summation loop. if ((input_size / ratio) & 1) { while (input_size) { Accumulator accumulator; *out++ = accumulator(in, ir); input_size -= ratio; in += ratio; } } else { while (input_size) { Accumulator accumulator; *out++ = accumulator(in, ir); *out++ = accumulator(in + ratio, ir); input_size -= 2 * ratio; in += 2 * ratio; } } // Copy last input samples to history buffer. std::copy(&in[-N + 1], &in[0], &x_[0]); } else { // Variant which uses a circular buffer to store history. while (input_size) { for (int32_t i = 0; i < ratio; ++i) { x_ptr_[0] = x_ptr_[N] = *in++; --x_ptr_; if (x_ptr_ < x_) { x_ptr_ += N; } } input_size -= ratio; Accumulator accumulator; *out++ = accumulator(&x_ptr_[1], ir); } } } private: float x_[2 * N]; float* x_ptr_; DISALLOW_COPY_AND_ASSIGN(SampleRateConverter); }; } // namespace stmlib #endif // STMLIB_DSP_SAMPLE_RATE_CONVERTER_H_ ================================================ FILE: lib/stmlib/dsp/units.cc ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Conversion from semitones to frequency ratio. #include "stmlib/dsp/units.h" namespace stmlib { /* extern */ const float lut_pitch_ratio_high[] = { 6.151958251e-04, 6.517772725e-04, 6.905339660e-04, 7.315952524e-04, 7.750981699e-04, 8.211879055e-04, 8.700182794e-04, 9.217522585e-04, 9.765625000e-04, 1.034631928e-03, 1.096154344e-03, 1.161335073e-03, 1.230391650e-03, 1.303554545e-03, 1.381067932e-03, 1.463190505e-03, 1.550196340e-03, 1.642375811e-03, 1.740036559e-03, 1.843504517e-03, 1.953125000e-03, 2.069263856e-03, 2.192308688e-03, 2.322670146e-03, 2.460783301e-03, 2.607109090e-03, 2.762135864e-03, 2.926381010e-03, 3.100392680e-03, 3.284751622e-03, 3.480073118e-03, 3.687009034e-03, 3.906250000e-03, 4.138527712e-03, 4.384617376e-03, 4.645340293e-03, 4.921566601e-03, 5.214218180e-03, 5.524271728e-03, 5.852762019e-03, 6.200785359e-03, 6.569503244e-03, 6.960146235e-03, 7.374018068e-03, 7.812500000e-03, 8.277055425e-03, 8.769234752e-03, 9.290680586e-03, 9.843133202e-03, 1.042843636e-02, 1.104854346e-02, 1.170552404e-02, 1.240157072e-02, 1.313900649e-02, 1.392029247e-02, 1.474803614e-02, 1.562500000e-02, 1.655411085e-02, 1.753846950e-02, 1.858136117e-02, 1.968626640e-02, 2.085687272e-02, 2.209708691e-02, 2.341104808e-02, 2.480314144e-02, 2.627801298e-02, 2.784058494e-02, 2.949607227e-02, 3.125000000e-02, 3.310822170e-02, 3.507693901e-02, 3.716272234e-02, 3.937253281e-02, 4.171374544e-02, 4.419417382e-02, 4.682209615e-02, 4.960628287e-02, 5.255602595e-02, 5.568116988e-02, 5.899214454e-02, 6.250000000e-02, 6.621644340e-02, 7.015387802e-02, 7.432544469e-02, 7.874506562e-02, 8.342749089e-02, 8.838834765e-02, 9.364419230e-02, 9.921256575e-02, 1.051120519e-01, 1.113623398e-01, 1.179842891e-01, 1.250000000e-01, 1.324328868e-01, 1.403077560e-01, 1.486508894e-01, 1.574901312e-01, 1.668549818e-01, 1.767766953e-01, 1.872883846e-01, 1.984251315e-01, 2.102241038e-01, 2.227246795e-01, 2.359685782e-01, 2.500000000e-01, 2.648657736e-01, 2.806155121e-01, 2.973017788e-01, 3.149802625e-01, 3.337099635e-01, 3.535533906e-01, 3.745767692e-01, 3.968502630e-01, 4.204482076e-01, 4.454493591e-01, 4.719371563e-01, 5.000000000e-01, 5.297315472e-01, 5.612310242e-01, 5.946035575e-01, 6.299605249e-01, 6.674199271e-01, 7.071067812e-01, 7.491535384e-01, 7.937005260e-01, 8.408964153e-01, 8.908987181e-01, 9.438743127e-01, 1.000000000e+00, 1.059463094e+00, 1.122462048e+00, 1.189207115e+00, 1.259921050e+00, 1.334839854e+00, 1.414213562e+00, 1.498307077e+00, 1.587401052e+00, 1.681792831e+00, 1.781797436e+00, 1.887748625e+00, 2.000000000e+00, 2.118926189e+00, 2.244924097e+00, 2.378414230e+00, 2.519842100e+00, 2.669679708e+00, 2.828427125e+00, 2.996614154e+00, 3.174802104e+00, 3.363585661e+00, 3.563594873e+00, 3.775497251e+00, 4.000000000e+00, 4.237852377e+00, 4.489848193e+00, 4.756828460e+00, 5.039684200e+00, 5.339359417e+00, 5.656854249e+00, 5.993228308e+00, 6.349604208e+00, 6.727171322e+00, 7.127189745e+00, 7.550994501e+00, 8.000000000e+00, 8.475704755e+00, 8.979696386e+00, 9.513656920e+00, 1.007936840e+01, 1.067871883e+01, 1.131370850e+01, 1.198645662e+01, 1.269920842e+01, 1.345434264e+01, 1.425437949e+01, 1.510198900e+01, 1.600000000e+01, 1.695140951e+01, 1.795939277e+01, 1.902731384e+01, 2.015873680e+01, 2.135743767e+01, 2.262741700e+01, 2.397291323e+01, 2.539841683e+01, 2.690868529e+01, 2.850875898e+01, 3.020397801e+01, 3.200000000e+01, 3.390281902e+01, 3.591878555e+01, 3.805462768e+01, 4.031747360e+01, 4.271487533e+01, 4.525483400e+01, 4.794582646e+01, 5.079683366e+01, 5.381737058e+01, 5.701751796e+01, 6.040795601e+01, 6.400000000e+01, 6.780563804e+01, 7.183757109e+01, 7.610925536e+01, 8.063494719e+01, 8.542975067e+01, 9.050966799e+01, 9.589165292e+01, 1.015936673e+02, 1.076347412e+02, 1.140350359e+02, 1.208159120e+02, 1.280000000e+02, 1.356112761e+02, 1.436751422e+02, 1.522185107e+02, 1.612698944e+02, 1.708595013e+02, 1.810193360e+02, 1.917833058e+02, 2.031873347e+02, 2.152694823e+02, 2.280700718e+02, 2.416318240e+02, 2.560000000e+02, 2.712225522e+02, 2.873502844e+02, 3.044370214e+02, 3.225397888e+02, 3.417190027e+02, 3.620386720e+02, 3.835666117e+02, 4.063746693e+02, 4.305389646e+02, 4.561401437e+02, 4.832636481e+02, 5.120000000e+02, 5.424451043e+02, 5.747005687e+02, 6.088740429e+02, 6.450795775e+02, 6.834380053e+02, 7.240773439e+02, 7.671332234e+02, 8.127493386e+02, 8.610779292e+02, 9.122802874e+02, 9.665272962e+02, 1.024000000e+03, 1.084890209e+03, 1.149401137e+03, 1.217748086e+03, 1.290159155e+03, 1.366876011e+03, 1.448154688e+03, 1.534266447e+03, }; /* extern */ const float lut_pitch_ratio_low[] = { 1.000000000e+00, 1.000225659e+00, 1.000451370e+00, 1.000677131e+00, 1.000902943e+00, 1.001128806e+00, 1.001354720e+00, 1.001580685e+00, 1.001806701e+00, 1.002032768e+00, 1.002258886e+00, 1.002485055e+00, 1.002711275e+00, 1.002937546e+00, 1.003163868e+00, 1.003390242e+00, 1.003616666e+00, 1.003843141e+00, 1.004069668e+00, 1.004296246e+00, 1.004522874e+00, 1.004749554e+00, 1.004976285e+00, 1.005203068e+00, 1.005429901e+00, 1.005656786e+00, 1.005883722e+00, 1.006110709e+00, 1.006337747e+00, 1.006564836e+00, 1.006791977e+00, 1.007019169e+00, 1.007246412e+00, 1.007473707e+00, 1.007701053e+00, 1.007928450e+00, 1.008155898e+00, 1.008383398e+00, 1.008610949e+00, 1.008838551e+00, 1.009066205e+00, 1.009293910e+00, 1.009521667e+00, 1.009749475e+00, 1.009977334e+00, 1.010205245e+00, 1.010433207e+00, 1.010661221e+00, 1.010889286e+00, 1.011117403e+00, 1.011345571e+00, 1.011573790e+00, 1.011802061e+00, 1.012030384e+00, 1.012258758e+00, 1.012487183e+00, 1.012715661e+00, 1.012944189e+00, 1.013172770e+00, 1.013401401e+00, 1.013630085e+00, 1.013858820e+00, 1.014087607e+00, 1.014316445e+00, 1.014545335e+00, 1.014774277e+00, 1.015003270e+00, 1.015232315e+00, 1.015461411e+00, 1.015690560e+00, 1.015919760e+00, 1.016149011e+00, 1.016378315e+00, 1.016607670e+00, 1.016837077e+00, 1.017066536e+00, 1.017296046e+00, 1.017525609e+00, 1.017755223e+00, 1.017984889e+00, 1.018214607e+00, 1.018444376e+00, 1.018674198e+00, 1.018904071e+00, 1.019133996e+00, 1.019363973e+00, 1.019594002e+00, 1.019824083e+00, 1.020054216e+00, 1.020284401e+00, 1.020514637e+00, 1.020744926e+00, 1.020975266e+00, 1.021205659e+00, 1.021436104e+00, 1.021666600e+00, 1.021897149e+00, 1.022127749e+00, 1.022358402e+00, 1.022589107e+00, 1.022819863e+00, 1.023050672e+00, 1.023281533e+00, 1.023512446e+00, 1.023743411e+00, 1.023974428e+00, 1.024205498e+00, 1.024436619e+00, 1.024667793e+00, 1.024899019e+00, 1.025130297e+00, 1.025361627e+00, 1.025593009e+00, 1.025824444e+00, 1.026055931e+00, 1.026287470e+00, 1.026519061e+00, 1.026750705e+00, 1.026982401e+00, 1.027214149e+00, 1.027445949e+00, 1.027677802e+00, 1.027909707e+00, 1.028141664e+00, 1.028373674e+00, 1.028605736e+00, 1.028837851e+00, 1.029070017e+00, 1.029302237e+00, 1.029534508e+00, 1.029766832e+00, 1.029999209e+00, 1.030231638e+00, 1.030464119e+00, 1.030696653e+00, 1.030929239e+00, 1.031161878e+00, 1.031394569e+00, 1.031627313e+00, 1.031860109e+00, 1.032092958e+00, 1.032325859e+00, 1.032558813e+00, 1.032791820e+00, 1.033024879e+00, 1.033257991e+00, 1.033491155e+00, 1.033724372e+00, 1.033957641e+00, 1.034190964e+00, 1.034424338e+00, 1.034657766e+00, 1.034891246e+00, 1.035124779e+00, 1.035358364e+00, 1.035592003e+00, 1.035825694e+00, 1.036059437e+00, 1.036293234e+00, 1.036527083e+00, 1.036760985e+00, 1.036994940e+00, 1.037228947e+00, 1.037463008e+00, 1.037697121e+00, 1.037931287e+00, 1.038165506e+00, 1.038399777e+00, 1.038634102e+00, 1.038868479e+00, 1.039102910e+00, 1.039337393e+00, 1.039571929e+00, 1.039806518e+00, 1.040041160e+00, 1.040275855e+00, 1.040510603e+00, 1.040745404e+00, 1.040980258e+00, 1.041215165e+00, 1.041450125e+00, 1.041685138e+00, 1.041920204e+00, 1.042155323e+00, 1.042390495e+00, 1.042625720e+00, 1.042860998e+00, 1.043096329e+00, 1.043331714e+00, 1.043567151e+00, 1.043802642e+00, 1.044038185e+00, 1.044273782e+00, 1.044509433e+00, 1.044745136e+00, 1.044980892e+00, 1.045216702e+00, 1.045452565e+00, 1.045688481e+00, 1.045924450e+00, 1.046160473e+00, 1.046396549e+00, 1.046632678e+00, 1.046868860e+00, 1.047105096e+00, 1.047341385e+00, 1.047577727e+00, 1.047814123e+00, 1.048050572e+00, 1.048287074e+00, 1.048523630e+00, 1.048760239e+00, 1.048996902e+00, 1.049233618e+00, 1.049470387e+00, 1.049707210e+00, 1.049944086e+00, 1.050181015e+00, 1.050417999e+00, 1.050655035e+00, 1.050892125e+00, 1.051129269e+00, 1.051366466e+00, 1.051603717e+00, 1.051841021e+00, 1.052078378e+00, 1.052315790e+00, 1.052553255e+00, 1.052790773e+00, 1.053028345e+00, 1.053265971e+00, 1.053503650e+00, 1.053741383e+00, 1.053979169e+00, 1.054217010e+00, 1.054454903e+00, 1.054692851e+00, 1.054930852e+00, 1.055168907e+00, 1.055407016e+00, 1.055645178e+00, 1.055883395e+00, 1.056121664e+00, 1.056359988e+00, 1.056598366e+00, 1.056836797e+00, 1.057075282e+00, 1.057313821e+00, 1.057552413e+00, 1.057791060e+00, 1.058029760e+00, 1.058268515e+00, 1.058507323e+00, 1.058746185e+00, 1.058985101e+00, 1.059224071e+00, }; // Original python code // // TABLE_SIZE = 256 // // ratio = numpy.arange(0, TABLE_SIZE) - 128 // ratio = 2 ** (ratio / 12.0) // semitone = 2 ** (numpy.arange(0, TABLE_SIZE) / 256.0 / 12.0) // // lookup_tables.append(('pitch_ratio_high', ratio)) // lookup_tables.append(('pitch_ratio_low', semitone)) } // namespace stmlib ================================================ FILE: lib/stmlib/dsp/units.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Conversion from semitones to frequency ratio. #ifndef STMLIB_DSP_UNITS_H_ #define STMLIB_DSP_UNITS_H_ #include "stmlib/stmlib.h" #include "stmlib/dsp/dsp.h" namespace stmlib { // https://pichenettes.github.io/mutable-instruments-documentation/tech_notes/exponential_conversion_in_digital_oscillators/ // Computes 2^x by using a polynomial approximation of 2^frac(x) and directly // incrementing the exponent of the IEEE 754 representation of the result // by int(x). Depending on the use case, the order of the polynomial // approximation can be chosen. template inline float Pow2Fast(float x) { union { float f; int32_t w; } r; if (order == 1) { r.w = float(1 << 23) * (127.0f + x); return r.f; } int32_t x_integral = static_cast(x); if (x < 0.0f) { --x_integral; } x -= static_cast(x_integral); if (order == 1) { r.f = 1.0f + x; } else if (order == 2) { r.f = 1.0f + x * (0.6565f + x * 0.3435f); } else if (order == 3) { r.f = 1.0f + x * (0.6958f + x * (0.2251f + x * 0.0791f)); } r.w += x_integral << 23; return r.f; } #ifdef SemitonesToRatioFast inline float SemitonesToRatio(float semitones){ return Pow2Fast<1>(semitones / 12.f); } #else extern const float lut_pitch_ratio_high[257]; extern const float lut_pitch_ratio_low[257]; inline float SemitonesToRatio(float semitones) { float pitch = semitones + 128.0f; MAKE_INTEGRAL_FRACTIONAL(pitch) return lut_pitch_ratio_high[pitch_integral] * \ lut_pitch_ratio_low[static_cast(pitch_fractional * 256.0f)]; } #endif inline float SemitonesToRatioSafe(float semitones) { float scale = 1.0f; while (semitones > 120.0f) { semitones -= 120.0f; scale *= 1024.0f; } while (semitones < -120.0f) { semitones += 120.0f; scale *= 1.0f / 1024.0f; } return scale * SemitonesToRatio(semitones); } inline float Exp2Safe(float value) { return SemitonesToRatioSafe(value * 12.0f); } } // namespace stmlib #endif // STMLIB_DSP_UNITS_H_ ================================================ FILE: lib/stmlib/makefile.inc ================================================ # Copyright 2012 Emilie Gillet. # # Author: Emilie Gillet (emilie.o.gillet@gmail.com) # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # # See http://creativecommons.org/licenses/MIT/ for more information. # ------------------------------------------------------------------------------ # Files and directories # ------------------------------------------------------------------------------ TOOLCHAIN_PATH ?= /usr/local/arm/ PGM_INTERFACE ?= stlink-v2 # PGM_INTERFACE ?= ftdi/olimex-arm-jtag-swd # PGM_INTERFACE ?= ftdi/olimex-arm-usb-ocd-h ifeq ($(PGM_INTERFACE),ftdi/olimex-arm-jtag-swd) OPENOCD_INTERFACE_SCRIPT ?= interface/ftdi/olimex-arm-usb-ocd-h.cfg -f interface/ftdi/olimex-arm-jtag-swd.cfg else OPENOCD_INTERFACE_SCRIPT ?= interface/$(PGM_INTERFACE).cfg endif OPENOCD_SCRIPT_PATH ?= /opt/local/share/openocd/scripts/ PGM_SERIAL_PORT ?= /dev/ftdi-usbserial PGM_SERIAL_BAUD_RATE ?= 115200 PGM_SERIAL_VERIFY ?= -v # --- You should not have to modify these -------------------------------------- TOOLCHAIN_BIN = $(TOOLCHAIN_PATH)bin/ STM32_PATH = stmlib/third_party/STM # --- Do not modify anything below this point ---------------------------------- BUILD_ROOT = build/ BUILD_DIR = $(BUILD_ROOT)$(TARGET)/ CC = $(TOOLCHAIN_BIN)arm-none-eabi-gcc CXX = $(TOOLCHAIN_BIN)arm-none-eabi-g++ AS = $(TOOLCHAIN_BIN)arm-none-eabi-as OBJCOPY = $(TOOLCHAIN_BIN)arm-none-eabi-objcopy DB = $(TOOLCHAIN_BIN)arm-none-eabi-gdb OBJDUMP = $(TOOLCHAIN_BIN)arm-none-eabi-objdump AR = $(TOOLCHAIN_BIN)arm-none-eabi-ar SIZE = $(TOOLCHAIN_BIN)arm-none-eabi-size NM = $(TOOLCHAIN_BIN)arm-none-eabi-nm REMOVE = rm -f CAT = cat FORMAT_SIZE = | figlet | cowsay -n -f moose FORMAT_RAMSIZE = | figlet | cowsay -n -f small STM32LOADER_PATH = stmlib/programming/serial/ OPENOCD_SCRIPTS_PATH = stmlib/programming/jtag/ # ------------------------------------------------------------------------------ # Files and directories for the user code # ------------------------------------------------------------------------------ VPATH = $(PACKAGES) CC_FILES = $(notdir $(wildcard $(patsubst %,%/*.cc,$(PACKAGES)))) C_FILES = $(notdir $(wildcard $(patsubst %,%/*.c,$(PACKAGES)))) AS_FILES = $(notdir $(wildcard $(patsubst %,%/*.s,$(PACKAGES)))) TARGET_BIN = $(BUILD_DIR)$(TARGET).bin TARGET_ELF = $(BUILD_DIR)$(TARGET).elf TARGET_HEX = $(BUILD_DIR)$(TARGET).hex COMBO_HEX = $(BUILD_DIR)$(TARGET)_bootloader_combo.hex COMBO_BIN = $(BUILD_DIR)$(TARGET)_bootloader_combo.bin BOOTLOADER_HEX = $(BUILD_ROOT)$(BOOTLOADER)/$(BOOTLOADER).hex TARGET_SIZE = $(BUILD_DIR)$(TARGET).size TARGETS = $(BUILD_DIR)$(TARGET).* DEP_FILE = $(BUILD_DIR)depends.mk # ------------------------------------------------------------------------------ # Platform specific flags # ------------------------------------------------------------------------------ ifeq ($(FAMILY),f4xx) MODEL_DEFINE = STM32F40_41xxx -DSTM32F4XX -DARM_MATH_CM4 -D__FPU_PRESENT STARTUP_OBJ = $(BUILD_DIR)startup_stm32f4xx.o LINKER_SCRIPT = stmlib/linker_scripts/stm32f4xx_flash$(LD_SUFFIX).ld FW_STDDRIVER_DIR = $(STM32_PATH)/STM32F4xx_StdPeriph_Driver ARCHFLAGS = -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb-interwork -funroll-loops ARCH_DEFINE = GCC_ARMCM4 OPENOCD_TARGET = f4x else ifeq ($(FAMILY),f37x) MODEL_DEFINE = STM32F37X -DARM_MATH_CM4 -D__FPU_PRESENT STARTUP_OBJ = $(BUILD_DIR)startup_stm32f37x.o LINKER_SCRIPT = stmlib/linker_scripts/stm32f373x_flash$(LD_SUFFIX).ld FW_STDDRIVER_DIR = $(STM32_PATH)/STM32F37x_StdPeriph_Driver ARCHFLAGS = -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb-interwork -funroll-loops --specs=nano.specs ARCH_DEFINE = GCC_ARMCM4 OPENOCD_TARGET = f3x else ifeq ($(FAMILY),f0xx) MODEL_DEFINE = STM32F0XX STARTUP_OBJ = $(BUILD_DIR)startup_stm32f0xx.o LINKER_SCRIPT = stmlib/linker_scripts/stm32f0xx_flash$(LD_SUFFIX).ld FW_STDDRIVER_DIR = $(STM32_PATH)/STM32F0xx_StdPeriph_Driver ARCHFLAGS = -mcpu=cortex-m0 -mthumb -mthumb-interwork -funroll-loops ARCH_DEFINE = GCC_ARMCM0 OPENOCD_TARGET = f0x else ifeq ($(FAMILY),f7xx) MODEL_DEFINE = STM32F7XX -DSTM32F765xx -DARM_MATH_CM7 -D__FPU_PRESENT STARTUP_OBJ = $(BUILD_DIR)startup_stm32f765xx.o LINKER_SCRIPT = stmlib/linker_scripts/stm32f7xx_flash$(LD_SUFFIX).ld FW_STDDRIVER_DIR = $(STM32_PATH)/STM32F7xx_HAL_Driver ARCHFLAGS = -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-d16 -mthumb-interwork -funroll-loops ARCH_DEFINE = GCC_ARMCM7 OPENOCD_TARGET = f7x else ifeq ($(FAMILY),h7xx) MODEL_DEFINE = STM32H7XX -DSTM32H743xx -DARM_MATH_CM7 -D__FPU_PRESENT STARTUP_OBJ = $(BUILD_DIR)startup_stm32h743xx.o LINKER_SCRIPT = stmlib/linker_scripts/stm32h7xx_flash$(LD_SUFFIX).ld FW_STDDRIVER_DIR = $(STM32_PATH)/STM32H7xx_HAL_Driver ARCHFLAGS = -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-d16 -mthumb-interwork -funroll-loops ARCH_DEFINE = GCC_ARMCM7 OPENOCD_TARGET = h7x_dual_bank else ifeq ($(FAMILY),g4xx) MODEL_DEFINE = STM32G4XX -DSTM32G473xx -DARM_MATH_CM7 -D__FPU_PRESENT STARTUP_OBJ = $(BUILD_DIR)startup_stm32g473xx.o LINKER_SCRIPT = stmlib/linker_scripts/stm32g4xx_flash$(LD_SUFFIX).ld FW_STDDRIVER_DIR = $(STM32_PATH)/STM32G4xx_HAL_Driver ARCHFLAGS = -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-d16 -mthumb-interwork -funroll-loops ARCH_DEFINE = GCC_ARMCM7 OPENOCD_TARGET = g4x else ifeq ($(DENSITY),hd) MODEL_DEFINE = STM32F10X_HD -DSTM32F10X else ifeq ($(DENSITY),md) MODEL_DEFINE = STM32F10X_MD -DSTM32F10X else MODEL_DEFINE = STM32F10X_CL -DSTM32F10X endif STARTUP_OBJ = $(BUILD_DIR)startup_stm32f10x_$(DENSITY).o LINKER_SCRIPT = stmlib/linker_scripts/stm32f10x_flash_$(DENSITY)$(LD_SUFFIX).ld FW_STDDRIVER_DIR = $(STM32_PATH)/STM32F10x_StdPeriph_Driver ARCHFLAGS = -mcpu=cortex-m3 -mthumb -fno-unroll-loops ARCH_DEFINE = GCC_ARMCM3 OPENOCD_TARGET = f1x endif ifeq ($(APPLICATION),TRUE) APPLICATION_DEFINE = -DAPPLICATION LD_SUFFIX = _application BASE_ADDRESS = 0x08004000 else ifeq ($(APPLICATION_SMALL),TRUE) APPLICATION_DEFINE = -DAPPLICATION LD_SUFFIX = _application_small BASE_ADDRESS = 0x08001000 else ifeq ($(APPLICATION_LARGE),TRUE) APPLICATION_DEFINE = -DAPPLICATION LD_SUFFIX = _application_large BASE_ADDRESS = 0x08008000 else APPLICATION_DEFINE = -DNO_APPLICATION LD_SUFFIX = BASE_ADDRESS = 0x08000000 endif OPENOCD_TARGET_SCRIPT ?= target/stm32$(OPENOCD_TARGET).cfg # ------------------------------------------------------------------------------ # Flags for gcc/binutils # ------------------------------------------------------------------------------ INCFLAGS = \ -I. \ -D$(ARCH_DEFINE) \ -D$(MODEL_DEFINE) \ $(APPLICATION_DEFINE) \ $(PROJECT_CONFIGURATION) \ -DF_CPU=$(F_CPU) \ -DF_CRYSTAL=$(F_CRYSTAL) \ -DHSE_VALUE=$(F_CRYSTAL) \ -DUSE_STDPERIPH_DRIVER \ -D$(SYSCLOCK)=$(F_CPU) CCFLAGS = \ -g -O2 -Wall -Werror -Wno-unused-local-typedefs -Wno-strict-aliasing \ -fasm \ -finline \ -finline-functions-called-once \ -fdata-sections \ -ffunction-sections \ -fshort-enums \ -fno-move-loop-invariants \ -fno-unwind-tables \ $(INCFLAGS) \ $(ARCHFLAGS) CPPFLAGS = -fno-exceptions -fno-rtti ASFLAGS = $(ARCHFLAGS) LDFLAGS = \ -Wl,-Map=$(BUILD_DIR)$(TARGET).map \ -Wl,--gc-sections \ -T $(LINKER_SCRIPT) \ $(ARCHFLAGS) \ $(INCFLAGS) \ -L$(STM32_PATH) # ------------------------------------------------------------------------------ # Files and directories for the system firmware # ------------------------------------------------------------------------------ FW_BUILD_DIR = $(BUILD_ROOT)stm_firmware/ FW_CORE_DIR = $(STM32_PATH)/CMSIS/CM3_$(FAMILY) FW_STARTUP_DIR = $(FW_CORE_DIR)/startup/gcc FW_STDDRIVER_SRCDIR = $(FW_STDDRIVER_DIR)/src FW_STDDRIVER_INCDIR = $(FW_STDDRIVER_DIR)/inc FW_USB_DIR = $(STM32_PATH)/STM32_USB-FS-Device_Driver FW_USB_SRCDIR = $(FW_USB_DIR)/src FW_USB_INCDIR = $(FW_USB_DIR)/inc INCFLAGS += -I$(STM32_PATH) -I$(FW_CORE_DIR) -I$(FW_STARTUP_DIR) -I$(FW_STDDRIVER_INCDIR) VPATH += $(FW_CORE_DIR) $(FW_STARTUP_DIR) $(FW_STDDRIVER_SRCDIR) $(STM32_PATH) $(FW_BUILD_DIR) CORE_C_FILES = $(notdir $(wildcard $(patsubst %,%/*.c,$(FW_CORE_DIR)))) DRIVERS_C_FILES = $(notdir $(wildcard $(patsubst %,%/*.c,$(FW_STDDRIVER_SRCDIR)))) USB_C_FILES = $(notdir $(wildcard $(patsubst %,%/*.c,$(FW_USB_SRCDIR)))) C_FILES += $(CORE_C_FILES) C_FILES += $(DRIVERS_C_FILES) ifeq ($(USB),enabled) INCFLAGS += -I$(FW_USB_INCDIR) VPATH += $(FW_USB_SRCDIR) C_FILES += $(USB_C_FILES) endif # ------------------------------------------------------------------------------ # Source compiling and dependency analysis # ------------------------------------------------------------------------------ $(BUILD_DIR)%.o: %.s $(CC) -c -x assembler-with-cpp $(ASFLAGS) $< -o $@ $(BUILD_DIR)%.o: %.c $(CC) -c $(CCFLAGS) -std=c99 $< -o $@ $(BUILD_DIR)%.o: %.cc $(CXX) -c $(CCFLAGS) $(CPPFLAGS) $< -o $@ $(BUILD_DIR)%.d: %.s $(CC) -c -x assembler-with-cpp -MM $(ASFLAGS) $< -MF $@ -MT $(@:.d=.o) $(BUILD_DIR)%.d: %.c $(CC) -MM $(CCFLAGS) $< -MF $@ -MT $(@:.d=.o) $(BUILD_DIR)%.d: %.cc $(CXX) -MM $(CCFLAGS) $(CPPFLAGS) $< -MF $@ -MT $(@:.d=.o) # ------------------------------------------------------------------------------ # Object file conversion # ------------------------------------------------------------------------------ $(BUILD_DIR)%.hex: $(BUILD_DIR)%.elf $(OBJCOPY) -O ihex $< $@ $(BUILD_DIR)%.bin: $(BUILD_DIR)%.elf $(OBJCOPY) -O binary $< $@ $(BUILD_DIR)%.lss: $(BUILD_DIR)%.elf $(OBJDUMP) -d -h -S $< > $@ $(BUILD_DIR)%.sym: $(BUILD_DIR)%.elf $(NM) -n $< > $@ # ------------------------------------------------------------------------------ # What to build # ------------------------------------------------------------------------------ OBJ_FILES = $(CC_FILES:.cc=.o) $(C_FILES:.c=.o) $(AS_FILES:.s=.o) OBJS = $(patsubst %,$(BUILD_DIR)%,$(OBJ_FILES)) $(STARTUP_OBJ) DEPS = $(OBJS:.o=.d) all: $(BUILD_DIR) $(TARGET_HEX) # ------------------------------------------------------------------------------ # Resources # ------------------------------------------------------------------------------ RESOURCE_COMPILER = stmlib/tools/resources_compiler.py resources: $(TARGET)/resources.cc $(TARGET)/resources.cc: $(wildcard $(RESOURCES)/*.py) python $(RESOURCE_COMPILER) $(RESOURCES)/resources.py # ------------------------------------------------------------------------------ # Main rules # ------------------------------------------------------------------------------ $(BUILD_DIR): mkdir -p $(BUILD_DIR) $(TARGET_ELF): $(OBJS) $(CC) $(LDFLAGS) -o $(TARGET_ELF) $(OBJS) $(DEP_FILE): $(BUILD_DIR) $(DEPS) cat $(DEPS) > $(DEP_FILE) bin: $(TARGET_BIN) hex: $(TARGET_HEX) clean: $(REMOVE) $(OBJS) $(TARGETS) $(DEP_FILE) $(DEPS) depends: $(DEPS) cat $(DEPS) > $(DEP_FILE) $(TARGET_SIZE): $(TARGET_ELF) $(SIZE) $(TARGET_ELF) > $(TARGET_SIZE) $(BUILD_DIR)$(TARGET).top_symbols: $(TARGET_ELF) $(NM) $(TARGET_ELF) --size-sort -C -f bsd -r > $@ size: $(TARGET_SIZE) cat $(TARGET_SIZE) | awk '{ print $$1+$$2 }' | tail -n1 $(FORMAT_SIZE) ramsize: $(TARGET_SIZE) cat $(TARGET_SIZE) | awk '{ print $$2+$$3 }' | tail -n1 $(FORMAT_RAMSIZE) disassemble: build/$(TARGET)/$(TARGET).lss build/$(TARGET)/$(TARGET).top_symbols .PHONY: all bin clean depends resources include $(DEP_FILE) # ------------------------------------------------------------------------------ # Bootloader merging # ------------------------------------------------------------------------------ $(COMBO_BIN): $(TARGET_HEX) $(BOOTLOADER_HEX) cat $(TARGET_HEX) $(BOOTLOADER_HEX) | \ awk -f stmlib/programming/merge_hex.awk > $(COMBO_HEX) $(OBJCOPY) -I ihex -O binary $(COMBO_HEX) $(COMBO_BIN) # ------------------------------------------------------------------------------ # Firmware flashing # ------------------------------------------------------------------------------ BASE_JTAG_CMD = $(OPENOCD_BIN_PATH)openocd \ -s $(OPENOCD_SCRIPT_PATH) \ -f $(OPENOCD_INTERFACE_SCRIPT) \ -f $(OPENOCD_TARGET_SCRIPT) \ -c "init" -c "halt" -c "sleep 200" POSTLUDE = -c "sleep 200" -c "reset run" -c "shutdown" upload: $(UPLOAD_COMMAND) image_serial: python $(STM32LOADER_PATH)stm32loader.py \ -p $(PGM_SERIAL_PORT) \ -b $(PGM_SERIAL_BAUD_RATE) \ -r -l 131072 image.bin upload_serial: $(TARGET_BIN) python $(STM32LOADER_PATH)stm32loader.py \ -p $(PGM_SERIAL_PORT) \ -b $(PGM_SERIAL_BAUD_RATE) \ -e $(PGM_SERIAL_VERIFY) \ -a $(BASE_ADDRESS) \ -w $(TARGET_BIN) upload_serial_no_erase: $(TARGET_BIN) python $(STM32LOADER_PATH)stm32loader.py \ -p $(PGM_SERIAL_PORT) \ -b $(PGM_SERIAL_BAUD_RATE) $(PGM_SERIAL_VERIFY)\ -a $(BASE_ADDRESS) \ -w $(TARGET_BIN) upload_combo_serial: $(COMBO_BIN) python $(STM32LOADER_PATH)stm32loader.py \ -p $(PGM_SERIAL_PORT) \ -b $(PGM_SERIAL_BAUD_RATE) \ -e $(PGM_SERIAL_VERIFY) \ -w $(COMBO_BIN) upload_combo_serial_no_erase: $(COMBO_BIN) python $(STM32LOADER_PATH)stm32loader.py \ -p $(PGM_SERIAL_PORT) \ -b $(PGM_SERIAL_BAUD_RATE) $(PGM_SERIAL_VERIFY)\ -w $(COMBO_BIN) image_jtag: $(BASE_JTAG_CMD) \ -c "dump_image image.bin 0x08000000 131072" \ $(POSTLUDE) image_jtag_256k: $(BASE_JTAG_CMD) \ -c "dump_image image.bin 0x08000000 262144" \ $(POSTLUDE) image_jtag_1M: $(BASE_JTAG_CMD) \ -c "dump_image image.bin 0x08000000 1048576" \ $(POSTLUDE) debug_server: $(TARGET_BIN) $(OPENOCD_BIN_PATH)openocd \ -s $(OPENOCD_SCRIPT_PATH) \ -f $(OPENOCD_INTERFACE_SCRIPT) \ -f $(OPENOCD_TARGET_SCRIPT) \ -c "init;reset;halt" \ debug_client: $(DB) --eval-command="target remote localhost:3333" $(TARGET_ELF) erase_jtag: $(BASE_JTAG_CMD) \ -f $(OPENOCD_SCRIPTS_PATH)erase_$(FAMILY).cfg \ $(POSTLUDE) upload_jtag: $(TARGET_BIN) $(BASE_JTAG_CMD) \ -f $(OPENOCD_SCRIPTS_PATH)erase_$(FAMILY).cfg \ -c "flash write_image erase $(TARGET_BIN) 0x08000000" \ -c "verify_image $(TARGET_BIN) 0x08000000" \ $(POSTLUDE) upload_combo_jtag: $(COMBO_BIN) $(BASE_JTAG_CMD) \ -f $(OPENOCD_SCRIPTS_PATH)erase_$(FAMILY).cfg \ -c "flash write_image erase $(COMBO_BIN) 0x08000000" \ -c "verify_image $(COMBO_BIN) 0x08000000" \ $(POSTLUDE) upload_jtag_no_erase: $(TARGET_BIN) $(BASE_JTAG_CMD) \ -c "flash write_image erase $(TARGET_BIN) 0x08000000" \ -c "verify_image $(TARGET_BIN) 0x08000000" \ $(POSTLUDE) upload_combo_jtag_no_erase: $(COMBO_BIN) $(BASE_JTAG_CMD) \ -c "flash write_image erase $(COMBO_BIN) 0x08000000" \ -c "verify_image $(COMBO_BIN) 0x08000000" \ $(POSTLUDE) upload_jtag_erase_first: $(TARGET_BIN) $(BASE_JTAG_CMD) \ -c "flash erase_address 0x08000000 32768" \ -c "reset halt" \ -c "flash write_image erase $(TARGET_BIN) 0x08000000" \ -c "verify_image $(TARGET_BIN) 0x08000000" \ $(POSTLUDE) upload_combo_jtag_erase_first: $(COMBO_BIN) $(BASE_JTAG_CMD) \ -c "flash erase_address 0x08000000 32768" \ -c "reset halt" \ -c "flash write_image erase $(COMBO_BIN) 0x08000000" \ -c "verify_image $(COMBO_BIN) 0x08000000" \ $(POSTLUDE) upload_jtag_erase_first_sector: $(TARGET_BIN) $(BASE_JTAG_CMD) \ -c "flash erase_address 0x08000000 0x20000" \ -c "reset halt" \ -c "flash write_image erase $(TARGET_BIN) 0x08000000" \ -c "verify_image $(TARGET_BIN) 0x08000000" \ $(POSTLUDE) upload_combo_jtag_erase_first_sector: $(COMBO_BIN) $(BASE_JTAG_CMD) \ -c "flash erase_address 0x08000000 0x20000" \ -c "reset halt" \ -c "flash write_image erase $(COMBO_BIN) 0x08000000" \ -c "verify_image $(COMBO_BIN) 0x08000000" \ $(POSTLUDE) # Phony target for killing the system FTDI driver on OS X. kill_ftdi: sudo kextunload -b com.FTDI.driver.FTDIUSBSerialDriver reload_ftdi: sudo kextload -b com.FTDI.driver.FTDIUSBSerialDriver .PHONY: upload .PHONY: image_serial .PHONY: upload_serial upload_serial_no_erase .PHONY: upload_combo_serial upload_combo_serial_no_erase .PHONY: image_jtag image_jtag_1M .PHONY: erase_jtag .PHONY: upload_jtag upload_jtag_no_erase upload_jtag_erase_first .PHONY: upload_combo_jtag upload_combo_jtag_no_erase upload_combo_jtag_erase_first .PHONY: kill_ftdi reload_ftdi .PHONY: debug_client debug_server ================================================ FILE: lib/stmlib/midi/midi.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Decoding of MIDI messages. #ifndef STMLIB_MIDI_H_ #define STMLIB_MIDI_H_ namespace stmlib_midi { const uint8_t kCCModulationWheelMsb = 0x01; const uint8_t kCCBreathController = 0x02; const uint8_t kCCFootPedalMsb = 0x04; const uint8_t kCCPortamentoTimeMsb = 0x05; const uint8_t kCCDataEntryMsb = 0x06; const uint8_t kCCVolume = 0x07; const uint8_t kCCBankLsb = 0x20; const uint8_t kCCDataEntryLsb = 0x26; const uint8_t kCCHoldPedal = 0x40; const uint8_t kCCHarmonicIntensity = 0x47; const uint8_t kCCRelease = 0x48; const uint8_t kCCAttack = 0x49; const uint8_t kCCBrightness = 0x4a; const uint8_t kCCDataIncrement = 0x60; const uint8_t kCCDataDecrement = 0x61; const uint8_t kCCNrpnLsb = 0x62; const uint8_t kCCNrpnMsb = 0x63; const uint8_t kCCOmniModeOff = 0x7c; const uint8_t kCCOmniModeOn = 0x7d; const uint8_t kCCMonoModeOn = 0x7e; const uint8_t kCCPolyModeOn = 0x7f; template class MidiStreamParser { public: MidiStreamParser() { running_status_ = 0; data_size_ = 0; expected_data_size_ = 0; } void PushByte(uint8_t byte) { // Active sensing messages are filtered at the source, the hard way... if (byte == 0xfe) { return; } Handler::RawByte(byte); // Realtime messages are immediately passed-through, and do not modify the // state of the parser. if (byte >= 0xf8) { MessageReceived(byte); } else { if (byte >= 0x80) { uint8_t hi = byte & 0xf0; uint8_t lo = byte & 0x0f; data_size_ = 0; expected_data_size_ = 1; switch (hi) { case 0x80: case 0x90: case 0xa0: case 0xb0: expected_data_size_ = 2; break; case 0xc0: case 0xd0: break; // default data size of 1. case 0xe0: expected_data_size_ = 2; break; case 0xf0: if (lo > 0 && lo < 3) { expected_data_size_ = 2; } else if (lo >= 4) { expected_data_size_ = 0; } break; } if (byte == 0xf7) { if (running_status_ == 0xf0) { Handler::SysExEnd(); } running_status_ = 0; } else if (byte == 0xf0) { running_status_ = 0xf0; Handler::SysExStart(); } else { running_status_ = byte; } } else { data_[data_size_++] = byte; } if (data_size_ >= expected_data_size_) { MessageReceived(running_status_); data_size_ = 0; if (running_status_ > 0xf0) { expected_data_size_ = 0; running_status_ = 0; } } } } private: void MessageReceived(uint8_t status) { if (!status) { Handler::BozoByte(data_[0]); } uint8_t hi = status & 0xf0; uint8_t lo = status & 0x0f; // If this is a channel-specific message, check first that the receiver is // tuned to this channel. if (hi != 0xf0 && !Handler::CheckChannel(lo)) { Handler::RawMidiData(status, data_, data_size_, 0); return; } if (status != 0xf0 && status != 0xf7) { Handler::RawMidiData(status, data_, data_size_, 1); } switch (hi) { case 0x80: Handler::NoteOff(lo, data_[0], data_[1]); break; case 0x90: if (data_[1]) { Handler::NoteOn(lo, data_[0], data_[1]); } else { Handler::NoteOff(lo, data_[0], 0); } break; case 0xa0: Handler::Aftertouch(lo, data_[0], data_[1]); break; case 0xb0: Handler::ControlChange(lo, data_[0], data_[1]); break; case 0xc0: Handler::ProgramChange(lo, data_[0]); break; case 0xd0: Handler::Aftertouch(lo, data_[0]); break; case 0xe0: Handler::PitchBend(lo, (static_cast(data_[1]) << 7) + data_[0]); break; case 0xf0: switch(lo) { case 0x0: Handler::SysExByte(data_[0]); break; case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: // TODO(pichenettes): implement this if it makes sense. break; case 0x8: Handler::Clock(); break; case 0x9: break; case 0xa: Handler::Start(); break; case 0xb: Handler::Continue(); break; case 0xc: Handler::Stop(); break; case 0xf: Handler::Reset(); break; } break; } } uint8_t running_status_; uint8_t data_[3]; uint8_t data_size_; // Number of non-status byte received. uint8_t expected_data_size_; // Expected number of non-status bytes. DISALLOW_COPY_AND_ASSIGN(MidiStreamParser); }; } // namespace stmlib_midi #endif // STMLIB_MIDI_H_ ================================================ FILE: lib/stmlib/stmlib.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. #ifndef STMLIB_STMLIB_H_ #define STMLIB_STMLIB_H_ #include #include #include #ifndef NULL #define NULL 0 #endif #ifndef M_PI #define M_PI (3.14159265358979323846) #endif #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ void operator=(const TypeName&) #define CLIP(x) if (x < -32767) x = -32767; if (x > 32767) x = 32767; #define CONSTRAIN(var, min, max) \ if (var < (min)) { \ var = (min); \ } else if (var > (max)) { \ var = (max); \ } #define JOIN(lhs, rhs) JOIN_1(lhs, rhs) #define JOIN_1(lhs, rhs) JOIN_2(lhs, rhs) #define JOIN_2(lhs, rhs) lhs##rhs #define STATIC_ASSERT(expression, message)\ static_assert(expression, #message) #ifndef TEST #define IN_RAM __attribute__ ((section (".ramtext"))) #else #define IN_RAM #endif // TEST #define UNROLL2(x) x; x; #define UNROLL4(x) x; x; x; x; #define UNROLL8(x) x; x; x; x; x; x; x; x; template inline void StaticAssertImplementation() { char static_assert_size_mismatch[b] = { 0 }; } namespace stmlib { typedef union { uint16_t value; uint8_t bytes[2]; } Word; typedef union { uint32_t value; uint16_t words[2]; uint8_t bytes[4]; } LongWord; template struct FourCC { static const uint32_t value = (((((d << 8) | c) << 8) | b) << 8) | a; }; } // namespace stmlib #endif // STMLIB_STMLIB_H_ ================================================ FILE: lib/stmlib/utils/buffer_allocator.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Stream buffer for serialization. #ifndef STMLIB_UTILS_BUFFER_ALLOCATOR_H_ #define STMLIB_UTILS_BUFFER_ALLOCATOR_H_ #include "stmlib/stmlib.h" namespace stmlib { class BufferAllocator { public: BufferAllocator() { } ~BufferAllocator() { } BufferAllocator(void* buffer, size_t size) { Init(buffer, size); } inline void Init(void* buffer, size_t size) { buffer_ = static_cast(buffer); size_ = size; Free(); } template inline T* Allocate(size_t size) { size_t size_bytes = sizeof(T) * size; if (size_bytes <= free_) { T* start = static_cast(static_cast(next_)); next_ += size_bytes; free_ -= size_bytes; return start; } else { return NULL; } } inline void Free() { next_ = buffer_; free_ = size_; } inline size_t free() const { return free_; } private: uint8_t* next_; uint8_t* buffer_; size_t free_; size_t size_; DISALLOW_COPY_AND_ASSIGN(BufferAllocator); }; } // namespace stmlib #endif // STMLIB_UTILS_STREAM_BUFFER_H_ ================================================ FILE: lib/stmlib/utils/crc32.h ================================================ /*- * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or * code or tables extracted from it, as desired without restriction. * * First, the polynomial itself and its table of feedback terms. The * polynomial is * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 * * Note that we take it "backwards" and put the highest-order term in * the lowest-order bit. The X^32 term is "implied"; the LSB is the * X^31 term, etc. The X^0 term (usually shown as "+1") results in * the MSB being 1 * * Note that the usual hardware shift register implementation, which * is what we're using (we're merely optimizing it by doing eight-bit * chunks at a time) shifts bits into the lowest-order term. In our * implementation, that means shifting towards the right. Why do we * do it this way? Because the calculated CRC must be transmitted in * order from highest-order term to lowest-order term. UARTs transmit * characters in order from LSB to MSB. By storing the CRC this way * we hand it to the UART in the order low-byte to high-byte; the UART * sends each low-bit to hight-bit; and the result is transmission bit * by bit from highest- to lowest-order term without requiring any bit * shuffling on our part. Reception works similarly * * The feedback terms table consists of 256, 32-bit entries. Notes * * The table can be generated at runtime if desired; code to do so * is shown later. It might not be obvious, but the feedback * terms simply represent the results of eight shift/xor opera * tions for all combinations of data and CRC register values * * The values must be right-shifted by eight bits by the "updcrc * logic; the shift must be unsigned (bring in zeroes). On some * hardware you could probably optimize the shift in assembler by * using byte-swap instructions * polynomial $edb88320 * * * CRC32 code derived from work by Gary S. Brown. */ #include #include static uint32_t crc32_tab[] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; uint32_t crc32(uint32_t crc, const void *buf, size_t size) { const uint8_t *p; p = static_cast(buf); crc = crc ^ ~0U; while (size--) crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); return crc ^ ~0U; } ================================================ FILE: lib/stmlib/utils/dsp.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // A set of basic operands, especially useful for fixed-point arithmetic, with // fast ASM implementations. #ifndef STMLIB_UTILS_DSP_H_ #define STMLIB_UTILS_DSP_H_ #include "stmlib/stmlib.h" namespace stmlib { inline int16_t Interpolate824(const int16_t* table, uint32_t phase) __attribute__((always_inline)); inline uint16_t Interpolate824(const uint16_t* table, uint32_t phase) __attribute__((always_inline)); inline int16_t Interpolate824(const uint8_t* table, uint32_t phase) __attribute__((always_inline)); inline uint16_t Interpolate88(const uint16_t* table, uint16_t index) __attribute__((always_inline)); inline int16_t Interpolate88(const int16_t* table, uint16_t index) __attribute__((always_inline)); inline int16_t Interpolate1022(const int16_t* table, uint32_t phase) __attribute__((always_inline)); inline int16_t Interpolate115(const int16_t* table, uint32_t phase) __attribute__((always_inline)); inline int16_t Crossfade( const int16_t* table_a, const int16_t* table_b, uint32_t phase, uint16_t balance) __attribute__((always_inline)); inline int16_t Crossfade( const uint8_t* table_a, const uint8_t* table_b, uint32_t phase, uint16_t balance) __attribute__((always_inline)); inline int16_t Crossfade1022( const uint8_t* table_a, const uint8_t* table_b, uint32_t phase, uint16_t balance) __attribute__((always_inline)); inline int16_t Crossfade115( const uint8_t* table_a, const uint8_t* table_b, uint16_t phase, uint16_t balance) __attribute__((always_inline)); inline int16_t Mix(int16_t a, int16_t b, uint16_t balance) { return (a * (65535 - balance) + b * balance) >> 16; } inline uint16_t Mix(uint16_t a, uint16_t b, uint16_t balance) { return (a * (65535 - balance) + b * balance) >> 16; } inline int16_t Interpolate824(const int16_t* table, uint32_t phase) { int32_t a = table[phase >> 24]; int32_t b = table[(phase >> 24) + 1]; return a + ((b - a) * static_cast((phase >> 8) & 0xffff) >> 16); } inline uint16_t Interpolate824(const uint16_t* table, uint32_t phase) { uint32_t a = table[phase >> 24]; uint32_t b = table[(phase >> 24) + 1]; return a + ((b - a) * static_cast((phase >> 8) & 0xffff) >> 16); } inline int16_t Interpolate824(const uint8_t* table, uint32_t phase) { int32_t a = table[phase >> 24]; int32_t b = table[(phase >> 24) + 1]; return (a << 8) + \ ((b - a) * static_cast(phase & 0xffffff) >> 16) - 32768; } inline uint16_t Interpolate88(const uint16_t* table, uint16_t index) { int32_t a = table[index >> 8]; int32_t b = table[(index >> 8) + 1]; return a + ((b - a) * static_cast(index & 0xff) >> 8); } inline int16_t Interpolate88(const int16_t* table, uint16_t index) { int32_t a = table[index >> 8]; int32_t b = table[(index >> 8) + 1]; return a + ((b - a) * static_cast(index & 0xff) >> 8); } inline int16_t Interpolate1022(const int16_t* table, uint32_t phase) { int32_t a = table[phase >> 22]; int32_t b = table[(phase >> 22) + 1]; return a + ((b - a) * static_cast((phase >> 6) & 0xffff) >> 16); } inline int16_t Interpolate115(const int16_t* table, uint16_t phase) { int32_t a = table[phase >> 5]; int32_t b = table[(phase >> 5) + 1]; return a + ((b - a) * static_cast(phase & 0x1f) >> 5); } inline int16_t Crossfade( const int16_t* table_a, const int16_t* table_b, uint32_t phase, uint16_t balance) { int32_t a = Interpolate824(table_a, phase); int32_t b = Interpolate824(table_b, phase); return a + ((b - a) * static_cast(balance) >> 16); } inline int16_t Crossfade( const uint8_t* table_a, const uint8_t* table_b, uint32_t phase, uint16_t balance) { int32_t a = Interpolate824(table_a, phase); int32_t b = Interpolate824(table_b, phase); return a + ((b - a) * static_cast(balance) >> 16); } inline int16_t Crossfade1022( const int16_t* table_a, const int16_t* table_b, uint32_t phase, uint16_t balance) { int32_t a = Interpolate1022(table_a, phase); int32_t b = Interpolate1022(table_b, phase); return a + ((b - a) * static_cast(balance) >> 16); } inline int16_t Crossfade115( const int16_t* table_a, const int16_t* table_b, uint16_t phase, uint16_t balance) { int32_t a = Interpolate115(table_a, phase); int32_t b = Interpolate115(table_b, phase); return a + ((b - a) * static_cast(balance) >> 16); } } // namespace stmlib #endif // STMLIB_UTILS_DSP_H_ ================================================ FILE: lib/stmlib/utils/gate_flags.h ================================================ // Copyright 2017 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Gate bits are pre-processed to tag edges. A typical gate sequence is: // // ------------ // // ---------- ---------- // // 00000000003111111111114000000000 // ^ ^ ^ ^ // | | | | // | | | GATE_FLAG_FALLING // | | | // | | GATE_FLAG_HIGH // | | // | GATE_FLAG_HIGH | GATE_FLAG_RISING // | // GATE_FLAG_LOW #ifndef STMLIB_UTILS_GATE_FLAGS_H_ #define STMLIB_UTILS_GATE_FLAGS_H_ #include "stmlib/stmlib.h" namespace stmlib { enum GateFlagsBits { GATE_FLAG_LOW = 0, GATE_FLAG_HIGH = 1, GATE_FLAG_RISING = 2, GATE_FLAG_FALLING = 4, }; typedef uint8_t GateFlags; inline GateFlags ExtractGateFlags(GateFlags previous, bool current) { previous &= GATE_FLAG_HIGH; if (current) { return previous ? GATE_FLAG_HIGH : (GATE_FLAG_RISING | GATE_FLAG_HIGH); } else { return previous ? GATE_FLAG_FALLING : GATE_FLAG_LOW; } } } // namespace stmlib #endif // STMLIB_UTILS_GATE_FLAGS_H_ ================================================ FILE: lib/stmlib/utils/murmurhash3.h ================================================ //----------------------------------------------------------------------------- // MurmurHash3 was written by Austin Appleby, and is placed in the public // domain. The author hereby disclaims copyright to this source code. //----------------------------------------------------------------------------- uint32_t rotl32 ( uint32_t x, int8_t r ) { return (x << r) | (x >> (32 - r)); } uint32_t fmix32 ( uint32_t h ) { h ^= h >> 16; h *= 0x85ebca6b; h ^= h >> 13; h *= 0xc2b2ae35; h ^= h >> 16; return h; } void MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed, void * out ) { const uint8_t * data = (const uint8_t*)key; const int nblocks = len / 4; uint32_t h1 = seed; const uint32_t c1 = 0xcc9e2d51; const uint32_t c2 = 0x1b873593; //---------- // body const uint32_t * blocks = (const uint32_t *)(data + nblocks*4); for(int i = -nblocks; i; i++) { uint32_t k1 = blocks[i]; k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1; h1 = rotl32(h1,13); h1 = h1*5+0xe6546b64; } //---------- // tail const uint8_t * tail = (const uint8_t*)(data + nblocks*4); uint32_t k1 = 0; switch(len & 3) { case 3: k1 ^= tail[2] << 16; case 2: k1 ^= tail[1] << 8; case 1: k1 ^= tail[0]; k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1; }; //---------- // finalization h1 ^= len; h1 = fmix32(h1); *(uint32_t*)out = h1; } ================================================ FILE: lib/stmlib/utils/random.cc ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Random number generator. #include "stmlib/utils/random.h" namespace stmlib { /* static */ uint32_t Random::rng_state_ = 0x21; } // namespace stmlib ================================================ FILE: lib/stmlib/utils/random.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Fast 16-bit pseudo random number generator. #ifndef STMLIB_UTILS_RANDOM_H_ #define STMLIB_UTILS_RANDOM_H_ #include "stmlib/stmlib.h" namespace stmlib { class Random { public: static inline uint32_t state() { return rng_state_; } static inline void Seed(uint32_t seed) { rng_state_ = seed; } static inline uint32_t GetWord() { rng_state_ = rng_state_ * 1664525L + 1013904223L; return state(); } static inline int16_t GetSample() { return static_cast(GetWord() >> 16); } static inline float GetFloat() { return static_cast(GetWord()) / 4294967296.0f; } private: static uint32_t rng_state_; DISALLOW_COPY_AND_ASSIGN(Random); }; } // namespace stmlib #endif // STMLIB_UTILS_RANDOM_H_ ================================================ FILE: lib/stmlib/utils/ring_buffer.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Basic ringbuffer template #ifndef STMLIB_UTILS_RING_BUFFER_H_ #define STMLIB_UTILS_RING_BUFFER_H_ #include "stmlib/stmlib.h" #include namespace stmlib { template class RingBuffer { public: RingBuffer() { } inline void Init() { read_ptr_ = write_ptr_ = 0; } inline size_t capacity() const { return size; } inline size_t writable() const { return (read_ptr_ - write_ptr_ - 1) % size; } inline size_t readable() const { return (write_ptr_ - read_ptr_) % size; } inline void Write(T v) { while (!writable()); Overwrite(v); } inline void Overwrite(T v) { size_t w = write_ptr_; buffer_[w] = v; write_ptr_ = (w + 1) % size; } inline T* OverwritePtr(size_t n) { size_t w = write_ptr_; T* v = &buffer_[w]; if((w + n) <= size) { write_ptr_ = (w + n) % size; return v; } return nullptr; } inline T Read() { while (!readable()); return ImmediateRead(); } inline T ImmediateRead() { size_t r = read_ptr_; T result = buffer_[r]; read_ptr_ = (r + 1) % size; return result; } inline const T* ImmediateReadPtr(size_t n) { size_t r = read_ptr_; const T* result = &buffer_[r]; if((r + n) <= size) { read_ptr_ = (r + n) % size; return result; } return nullptr; } inline void Flush() { write_ptr_ = read_ptr_; } inline void Swallow(size_t n) { // Read enough samples to make it possible to read 1 sample. if (writable() >= n) { return; } read_ptr_ = (write_ptr_ + 1 + n) % size; } inline void ImmediateRead(T* destination, size_t num_elements) { size_t r = read_ptr_; size_t read = num_elements; if (r + read > size) { read = size - r; } std::copy(&buffer_[r], &buffer_[r + read], destination); if (read != num_elements) { std::copy(&buffer_[0], &buffer_[num_elements - read], destination + read); } read_ptr_ = (r + num_elements) % size; } inline void Overwrite(const T* source, size_t num_elements) { size_t w = write_ptr_; size_t written = num_elements; if (w + written > size) { written = size - w; } std::copy(source, source + written, &buffer_[w]); if (written != num_elements) { std::copy(source + written, source + num_elements, &buffer_[0]); } write_ptr_ = (w + num_elements) % size; } private: T buffer_[size]; volatile size_t read_ptr_; volatile size_t write_ptr_; DISALLOW_COPY_AND_ASSIGN(RingBuffer); }; template class RingBuffer { public: RingBuffer() { } inline void Init() { } inline size_t capacity() const { return 0; } inline size_t writable() const { return 0; } inline size_t readable() const { return 0; } inline void Write(T v) { } inline void Overwrite(T v) { } inline T Read() { return T(0); } inline T ImmediateRead() { return T(0); } inline void Flush() { } inline void ImmediateRead(T* destination, size_t num_elements) { } inline void Overwrite(const T* source, size_t num_elements) { } private: DISALLOW_COPY_AND_ASSIGN(RingBuffer); }; } // namespace stmlib #endif // STMLIB_UTILS_RING_BUFFER_H_ ================================================ FILE: lib/stmlib/utils/stream_buffer.h ================================================ // Copyright 2012 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Stream buffer for serialization. #ifndef STMLIB_UTILS_STREAM_BUFFER_H_ #define STMLIB_UTILS_STREAM_BUFFER_H_ #include "stmlib/stmlib.h" #include #include namespace stmlib { template class StreamBuffer { public: StreamBuffer() { Clear(); } void Clear() { ptr_ = 0; std::fill(&buffer_[0], &buffer_[buffer_size], 0); } inline size_t position() const { return ptr_; } inline const uint8_t* bytes() const { return buffer_; } inline uint8_t* mutable_bytes() { return buffer_; } void Write(const void* data, size_t size) { if (ptr_ + size > buffer_size) { return; } memcpy(&buffer_[ptr_], data, size); ptr_ += size; } template void Write(const T& value) { Write(&value, sizeof(T)); } template void Read(T* value) { if (ptr_ + sizeof(T) > buffer_size) { return; } memcpy((void*)value, &buffer_[ptr_], sizeof(T)); ptr_ += sizeof(T); } inline void Seek(size_t position) { ptr_ = position; } inline void Rewind() { Seek(0); } private: uint8_t buffer_[buffer_size]; size_t ptr_; DISALLOW_COPY_AND_ASSIGN(StreamBuffer); }; } // namespace stmlib #endif // STMLIB_UTILS_STREAM_BUFFER_H_ ================================================ FILE: lib/streams/audio_cv_meter.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Discriminate an ADC signal into audio or CV ; and provide RMS stats. #ifndef STREAMS_AUDIO_CV_METER_H_ #define STREAMS_AUDIO_CV_METER_H_ #include "stmlib/stmlib.h" namespace streams { class AudioCvMeter { public: AudioCvMeter() { } ~AudioCvMeter() { } void Init() { peak_ = 0; zero_crossing_interval_ = 0; average_zero_crossing_interval_ = 0; previous_sample_ = 0; cv_ = false; } void Process(int32_t sample) { if ((sample >> 1) * previous_sample_ < 0 || zero_crossing_interval_ >= 4096) { int32_t error = zero_crossing_interval_ - average_zero_crossing_interval_; average_zero_crossing_interval_ += error >> 3; zero_crossing_interval_ = 0; } else { ++zero_crossing_interval_; } if (cv_ && average_zero_crossing_interval_ < 200) { cv_ = false; } else if (!cv_ && average_zero_crossing_interval_ > 400) { cv_ = true; } previous_sample_ = sample; if (sample < 0) { sample = -sample; } int32_t error = sample - peak_; int32_t coefficient = 33; // 250ms at 1kHz if (error > 0) { coefficient = 809; // 10ms at 1kHz } peak_ += error * coefficient >> 15; } inline bool cv() const { return cv_; } inline int32_t peak() const { return peak_; } private: bool cv_; int32_t peak_; int32_t zero_crossing_interval_; int32_t average_zero_crossing_interval_; int32_t previous_sample_; DISALLOW_COPY_AND_ASSIGN(AudioCvMeter); }; } // namespace streams #endif // STREAMS_AUDIO_CV_METER_H_ ================================================ FILE: lib/streams/compressor.cc ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Compressor. #include "streams/compressor.h" // #include #include "stmlib/utils/dsp.h" namespace streams { using namespace stmlib; // 256 LSB <=> 1.55dB const int32_t kGainConstant = 1 / (1.55 / 6.0 * 65536.0 / 256.0) * 65536; void Compressor::Init() { detector_ = 0; } /* static */ int32_t Compressor::Log2(int32_t value) { if (value <= 0) { value = 1; } int32_t log_value = 0; while (value >= 512) { value >>= 1; log_value += 65536; } while (value < 256) { value <<= 1; log_value -= 65536; } // Value is between 256 and 512, we can use the LUT. return log_value + lut_log2[value - 256]; } /* static */ int32_t Compressor::Exp2(int32_t value) { int32_t num_shifts = 0; while (value >= 65536) { ++num_shifts; value -= 65536; } while (value < 0) { --num_shifts; value += 65536; } // Value is between 0 and 65535, we can use the LUT. int32_t a = lut_exp2[value >> 8]; int32_t b = lut_exp2[(value >> 8) + 1]; int32_t mantissa = a + ((b - a) * (value & 0xff) >> 8); return num_shifts >= 0 ? mantissa << num_shifts : mantissa >> -num_shifts; } /* static */ int32_t Compressor::Compress( int32_t squared_level, int32_t threshold, int32_t ratio, bool soft_knee) { int32_t level = (Log2(squared_level) >> 1) - 15 * 65536; // 15-bit peak int32_t position = level - threshold; if (position < 0) { return 0; } int32_t attenuation = position - (position * ratio >> 8); if (attenuation < 65535 && soft_knee) { int32_t a = lut_soft_knee[attenuation >> 8]; int32_t b = lut_soft_knee[(attenuation >> 8) + 1]; int32_t soft_knee = a + ((b - a) * (attenuation & 0xff) >> 8); attenuation += \ (soft_knee - attenuation) * ((65535 - attenuation) >> 1) >> 15; } return -attenuation; } void Compressor::Process( int16_t audio, int16_t excite, uint16_t* gain, uint16_t* frequency) { int32_t energy; int64_t error; // Detect the RMS level on the EXCITE input. energy = excite; energy *= energy; error = energy - sidechain_signal_detector_; if (error > 0) { sidechain_signal_detector_ += error; } else { // Decay time: 5s. sidechain_signal_detector_ += error * 14174 >> 31; } // If there is no signal on the "excite" input, disable sidechain and // compress by metering input. if (sidechain_signal_detector_ < (1024 * 1024)) { energy = audio; energy *= energy; } // Detect the RMS level on the EXCITE or AUDIO input - whichever active. error = energy - detector_; if (error > 0) { if (attack_coefficient_ == -1) { detector_ += error; } else { detector_ += error * attack_coefficient_ >> 31; } } else { detector_ += error * decay_coefficient_ >> 31; } int32_t g = Compress(detector_, threshold_, ratio_, soft_knee_); gain_reduction_ = g >> 3; g = kUnityGain + ((g + makeup_gain_) * kGainConstant >> 16); if (g > 65535) { g = 65535; } *gain = g; // float ogain = powf(10.0f, 1.55f / 20.0f * (g - kUnityGain) / 256.0f); // printf("%f %f\n", gain_reduction_ / 32768.0 * 24, 20 * logf(ogain) / logf(10.0f)); *frequency = 65535; } } // namespace streams ================================================ FILE: lib/streams/compressor.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Compressor. #ifndef STREAMS_COMPRESSOR_H_ #define STREAMS_COMPRESSOR_H_ #include "stmlib/stmlib.h" #include #include "streams/gain.h" #include "streams/resources.h" namespace streams { class Compressor { public: Compressor() { } ~Compressor() { } void Init(); void Process( int16_t audio, int16_t excite, uint16_t* gain, uint16_t* frequency); void Configure(bool alternate, int32_t* parameters, int32_t* globals) { uint16_t attack_time; uint16_t decay_time; uint16_t amount; uint16_t threshold; if (globals) { attack_time = globals[0] * (128 + 128 + 99) >> 16; // 1ms to 500ms decay_time = 128 + 99 + (globals[2] >> 8); // 50ms to 5000ms threshold = globals[1]; amount = globals[3]; } else { attack_time = !alternate ? 1 : 40; // 0.2ms or 2ms; decay_time = !alternate ? 279 : 236; // 150ms or 70ms; threshold = parameters[0]; amount = parameters[1]; } attack_coefficient_ = lut_lp_coefficients[attack_time]; decay_coefficient_ = lut_lp_coefficients[decay_time]; soft_knee_ = alternate; threshold_ = (-1280 + 5 * (threshold >> 8)) << 8; if (amount < 32768) { // Compression with no makeup gain. ratio_ = lut_compressor_ratio[(32767 - amount) >> 7]; makeup_gain_ = 0; } else { // Adaptive compression with makeup gain. amount -= 32768; int32_t max_gain, knee_gain; max_gain = kMaxExponentialGain; makeup_gain_ = amount * (max_gain >> 8) >> 7; knee_gain = threshold_+ makeup_gain_; if (knee_gain >= 0) { makeup_gain_ = -threshold_; knee_gain = 0; } if (knee_gain > -4096) { // So intense! Brickwall limiter mode. In this case, we use an // instant attack to tame transients as soon as they appear. ratio_ = 0; attack_coefficient_ = -1; } else { ratio_ = knee_gain / (threshold_ >> 8); } } } inline int32_t gain_reduction() const { return gain_reduction_; } private: static int32_t Log2(int32_t value); static int32_t Exp2(int32_t value); static int32_t Compress( int32_t squared_level, int32_t threshold, int32_t ratio, bool soft_knee); int32_t ratio_; // Reciprocal of the ratio, 8:8 int32_t threshold_; int32_t makeup_gain_; bool soft_knee_; int64_t attack_coefficient_; int64_t decay_coefficient_; int64_t detector_; int64_t sidechain_signal_detector_; int32_t gain_reduction_; DISALLOW_COPY_AND_ASSIGN(Compressor); }; } // namespace streams #endif // STREAMS_COMPRESSOR_H_ ================================================ FILE: lib/streams/envelope.cc ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Simple AD envelope - adapted from Peaks' multistage envelope. #include "streams/envelope.h" #include "stmlib/utils/dsp.h" #include "streams/resources.h" #include "streams/gain.h" #include namespace streams { using namespace std; using namespace stmlib; void Envelope::Init() { fill(&shape_[0], &shape_[kMaxNumSegments], ENV_SHAPE_LINEAR); set_ad(0, 8192); segment_ = num_segments_; phase_ = 0; phase_increment_ = 0; start_value_ = 0; value_ = 0; rate_modulation_ = 0; gate_level_ = 0; gate_ = false; hard_reset_ = false; attack_ = 0; decay_ = 0; } void Envelope::Process( int16_t audio, int16_t excite, uint16_t* gain, uint16_t* frequency) { // Smooth frequency amount parameters. frequency_amount_ += (target_frequency_amount_ - frequency_amount_) >> 8; frequency_offset_ += (target_frequency_offset_ - frequency_offset_) >> 8; bool trigger = false; bool release = false; if (gate_ == false) { if (excite > kSchmittTriggerThreshold) { trigger = true; gate_ = true; set_hard_reset(false); } } else { if (excite < (kSchmittTriggerThreshold >> 1)) { gate_ = false; release = false; } else { // Track the level of the signal while the GATE is held. gate_level_ += (excite - gate_level_) >> 8; } } if (trigger) { start_value_ = (segment_ == num_segments_ || hard_reset_) ? level_[0] : value_; segment_ = 0; phase_ = 0; } else if (release && sustain_point_) { start_value_ = value_; segment_ = sustain_point_; phase_ = 0; } else if (phase_ < phase_increment_) { start_value_ = level_[segment_ + 1]; ++segment_; phase_ = 0; } bool done = segment_ == num_segments_; bool sustained = sustain_point_ && segment_ == sustain_point_ && gate_; uint32_t increment = sustained || done ? 0 : lut_env_increments[time_[segment_] >> 8]; // Modulates the envelope rate by the actual excitation pulse. rate_modulation_ += (static_cast(excite > kSchmittTriggerThreshold ? excite : 0) - rate_modulation_) >> 12; increment += static_cast(increment >> 7) * (rate_modulation_ >> 7); phase_increment_ = increment; int32_t a = start_value_; int32_t b = level_[segment_ + 1]; uint16_t t = Interpolate824( lookup_table_table[LUT_ENV_LINEAR + shape_[segment_]], phase_); value_ = a + ((b - a) * (t >> 1) >> 15); phase_ += phase_increment_; // Applies a variable amount of distortion, depending on the level. int32_t compressed = 32767 - ((32767 - value_) * (32767 - value_) >> 15); compressed = 32767 - ((32767 - compressed) * (32767 - compressed) >> 15); int32_t scaled = value_ + ((compressed - value_) * gate_level_ >> 15); scaled = scaled * (28672 + (gate_level_ >> 3)) >> 15; *gain = scaled * kAboveUnityGain >> 15; *frequency = frequency_offset_ + (scaled * frequency_amount_ >> 15); } } // namespace streams ================================================ FILE: lib/streams/envelope.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Simple AD envelope - adapted from Peaks' multistage envelope. #ifndef STREAMS_ENVELOPE_H_ #define STREAMS_ENVELOPE_H_ #include "stmlib/stmlib.h" #include "streams/meta_parameters.h" namespace streams { enum EnvelopeShape { ENV_SHAPE_LINEAR, ENV_SHAPE_EXPONENTIAL, ENV_SHAPE_QUARTIC }; const uint16_t kMaxNumSegments = 8; class Envelope { public: Envelope() { } ~Envelope() { } void Init(); void Process( int16_t audio, int16_t excite, uint16_t* gain, uint16_t* frequency); void Configure(bool alternate, int32_t* parameters, int32_t* globals) { uint16_t a, d; if (globals) { a = globals[0]; d = globals[2]; ComputeAmountOffset( parameters[1], &target_frequency_amount_, &target_frequency_offset_); } else { ComputeAttackDecay(parameters[0], &a, &d); ComputeAmountOffset( parameters[1], &target_frequency_amount_, &target_frequency_offset_); } if (a != attack_ || d != decay_ || alternate != alternate_) { attack_ = a; decay_ = d; alternate_ = alternate; if (alternate_) { set_ar(a, d); } else { set_ad(a, d); } set_hard_reset(true); } } inline void set_time(uint16_t segment, uint16_t time) { time_[segment] = time; } inline void set_level(uint16_t segment, int16_t level) { level_[segment] = level; } inline void set_num_segments(uint16_t num_segments) { num_segments_ = num_segments; } inline void set_sustain_point(uint16_t sustain_point) { sustain_point_ = sustain_point; } inline void set_ad(uint16_t attack, uint16_t decay) { num_segments_ = 2; sustain_point_ = 0; level_[0] = 0; level_[1] = 32767; level_[2] = 0; time_[0] = attack; time_[1] = decay; shape_[0] = ENV_SHAPE_LINEAR; shape_[1] = ENV_SHAPE_EXPONENTIAL; } inline void set_adr( uint16_t attack, uint16_t decay, uint16_t sustain, uint16_t release) { num_segments_ = 3; sustain_point_ = 0; level_[0] = 0; level_[1] = 32767; level_[2] = sustain; level_[3] = 0; time_[0] = attack; time_[1] = decay; time_[2] = release; shape_[0] = ENV_SHAPE_LINEAR; shape_[1] = ENV_SHAPE_LINEAR; shape_[2] = ENV_SHAPE_LINEAR; } inline void set_ar(uint16_t attack, uint16_t decay) { num_segments_ = 2; sustain_point_ = 1; level_[0] = 0; level_[1] = 32767; level_[2] = 0; time_[0] = attack; time_[1] = decay; shape_[0] = ENV_SHAPE_LINEAR; shape_[1] = ENV_SHAPE_LINEAR; } inline void set_adsar( uint16_t attack, uint16_t decay, uint16_t sustain, uint16_t release) { num_segments_ = 4; sustain_point_ = 2; level_[0] = 0; level_[1] = 32767; level_[2] = sustain; level_[3] = 32767; level_[4] = 0; time_[0] = attack; time_[1] = decay; time_[2] = attack; time_[3] = release; shape_[0] = ENV_SHAPE_LINEAR; shape_[1] = ENV_SHAPE_LINEAR; shape_[2] = ENV_SHAPE_LINEAR; shape_[3] = ENV_SHAPE_LINEAR; } inline void set_adar( uint16_t attack, uint16_t decay, uint16_t sustain, uint16_t release) { num_segments_ = 4; sustain_point_ = 0; level_[0] = 0; level_[1] = 32767; level_[2] = sustain; level_[3] = 32767; level_[4] = 0; time_[0] = attack; time_[1] = decay; time_[2] = attack; time_[3] = release; shape_[0] = ENV_SHAPE_LINEAR; shape_[1] = ENV_SHAPE_LINEAR; shape_[2] = ENV_SHAPE_LINEAR; shape_[3] = ENV_SHAPE_LINEAR; } inline void set_hard_reset(bool hard_reset) { hard_reset_ = hard_reset; } private: bool gate_; int16_t level_[kMaxNumSegments]; uint16_t time_[kMaxNumSegments]; EnvelopeShape shape_[kMaxNumSegments]; int16_t segment_; int16_t start_value_; int16_t value_; uint32_t phase_; uint32_t phase_increment_; uint16_t num_segments_; uint16_t sustain_point_; int32_t target_frequency_amount_; int32_t target_frequency_offset_; int32_t frequency_amount_; int32_t frequency_offset_; uint16_t attack_; uint16_t decay_; bool alternate_; bool hard_reset_; int32_t rate_modulation_; int32_t gate_level_; DISALLOW_COPY_AND_ASSIGN(Envelope); }; } // namespace streams #endif // STREAMS_ENVELOPE_H_ ================================================ FILE: lib/streams/filter_controller.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Plain filter. #ifndef STREAMS_FILTER_CONTROLLER_H_ #define STREAMS_FILTER_CONTROLLER_H_ #include "stmlib/stmlib.h" namespace streams { class FilterController { public: FilterController() { } ~FilterController() { } void Init() { frequency_offset_ = 0; frequency_amount_ = 0; } void Process( int16_t audio, int16_t excite, uint16_t* gain, uint16_t* frequency) { // Smooth frequency amount parameters. frequency_amount_ += (target_frequency_amount_ - frequency_amount_) >> 8; frequency_offset_ += (target_frequency_offset_ - frequency_offset_) >> 8; int32_t f; f = frequency_offset_ + (excite * frequency_amount_ >> 14); if (f < 0) { f = 0; } else if (f > 65535) { f = 65535; } *gain = 0; *frequency = f; } void Configure(bool alternate, int32_t* parameters, int32_t* globals) { int32_t amount = parameters[1]; amount -= 32768; amount = amount * amount >> 15; target_frequency_amount_ = parameters[1] < 32768 ? -amount : amount; target_frequency_offset_ = parameters[0]; } private: int32_t target_frequency_amount_; int32_t target_frequency_offset_; int32_t frequency_amount_; int32_t frequency_offset_; DISALLOW_COPY_AND_ASSIGN(FilterController); }; } // namespace streams #endif // STREAMS_ENVELOPE_H_ ================================================ FILE: lib/streams/follower.cc ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Follower. #include "streams/follower.h" #include "stmlib/utils/dsp.h" #include "streams/gain.h" #include "streams/resources.h" namespace streams { using namespace stmlib; void Follower::Init() { analysis_low_.Init(); analysis_low_.set_frequency(45 << 7); analysis_low_.set_resonance(0); analysis_medium_.Init(); analysis_medium_.set_frequency(86 << 7); analysis_medium_.set_resonance(0); for (uint8_t i = 0; i < 3; ++i) { energy_[i][0] = energy_[i][1] = 0; follower_[i] = 0; follower_lp_[i] = 0; spectrum_[i] = 0; } centroid_ = 0; } void Follower::Process( int16_t audio, int16_t excite, uint16_t* gain, uint16_t* frequency) { // Smooth frequency amount parameters. frequency_amount_ += (target_frequency_amount_ - frequency_amount_) >> 8; frequency_offset_ += (target_frequency_offset_ - frequency_offset_) >> 8; analysis_low_.Process(excite); analysis_medium_.Process(analysis_low_.hp()); int32_t channel[3]; channel[0] = analysis_low_.lp(); channel[1] = analysis_medium_.lp(); channel[2] = analysis_medium_.hp(); int32_t envelope = 0; int32_t centroid_numerator = 0; int32_t centroid_denominator = 0; for (int32_t i = 0; i < 3; ++i) { int32_t energy = channel[i]; energy *= energy; // Ride an ascending peak. if (energy_[i][0] < energy_[i][1] && energy_[i][1] < energy && energy > follower_[i]) { follower_[i] = energy; } // Otherwise, hold and snap on local maxima. if (energy_[i][0] <= energy_[i][1] && energy_[i][1] >= energy) { follower_[i] = energy_[i][1]; } energy_[i][0] = energy_[i][1]; energy_[i][1] = energy; // Then let a low-pass filter smooth things out. int64_t error = follower_[i] - follower_lp_[i]; if (error > 0) { follower_lp_[i] += error * attack_coefficient_[i] >> 31; } else { follower_lp_[i] += error * decay_coefficient_[i] >> 31; } envelope += follower_lp_[i] >> 13; // Integrate more slowly for spectrum estimation. if (only_filter_) { error = follower_lp_[i] - spectrum_[i]; spectrum_[i] += error >> 6; } else { error = follower_[i] - spectrum_[i]; spectrum_[i] += error >> 10; } centroid_numerator += i * (spectrum_[i] >> 1) >> 16; centroid_denominator += spectrum_[i] >> 16; } if (envelope > 65535) { envelope = 65535; } else if (envelope < 0) { envelope = 0; } uint16_t gain_mod = Interpolate824(lut_square_root, envelope << 16) >> 1; int32_t centroid = (centroid_numerator << 15) / (centroid_denominator + 1); if (gain_mod > 4096) { centroid_ = centroid; } else if (gain_mod > 2048) { centroid_ += (centroid - centroid_) >> 8; } *gain = gain_mod * kUnityGain >> 15; *frequency = frequency_offset_ + (centroid_ * frequency_amount_ >> 15); if (only_filter_) { *gain = *frequency; *frequency = 65535; } } } // namespace streams ================================================ FILE: lib/streams/follower.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Follower. #ifndef STREAMS_FOLLOWER_H_ #define STREAMS_FOLLOWER_H_ #include "stmlib/stmlib.h" #include "streams/meta_parameters.h" #include "streams/resources.h" #include "streams/svf.h" namespace streams { const uint16_t kNumBands = 3; class Follower { public: Follower() { } ~Follower() { } void Init(); void Process( int16_t audio, int16_t excite, uint16_t* gain, uint16_t* frequency); void Configure(bool alternate, int32_t* parameters, int32_t* globals) { uint16_t attack_time; uint16_t decay_time; if (globals) { // Attack: 1ms to 100ms attack_time = globals[0] >> 8; // Decay: 10ms to 1000ms decay_time = 128 + (globals[2] >> 8); ComputeAmountOffset( parameters[1], &target_frequency_amount_, &target_frequency_offset_); } else { uint16_t shape = parameters[0]; if (shape < 32768) { // attack: 1ms to 2ms. attack_time = (shape * 39 >> 15); // decay: 10ms to 100ms. decay_time = 128 + (shape * 128 >> 15); } else { shape -= 32768; // attack: 2ms to 20ms. attack_time = 39 + (shape * 128 >> 15); // decay: 100ms to 200ms. decay_time = 128 + 128 + (shape * 39 >> 15); } ComputeAmountOffset( parameters[1], &target_frequency_amount_, &target_frequency_offset_); } // Slow down the attack detection on low frequencies. attack_coefficient_[0] = lut_lp_coefficients[attack_time + 39]; attack_coefficient_[1] = lut_lp_coefficients[attack_time + 19]; attack_coefficient_[2] = lut_lp_coefficients[attack_time + 0]; // Slow down the decay detection on high frequencies as there is more noise. decay_coefficient_[0] = lut_lp_coefficients[decay_time + 39]; decay_coefficient_[1] = lut_lp_coefficients[decay_time + 19]; decay_coefficient_[2] = lut_lp_coefficients[decay_time + 99]; only_filter_ = alternate; } private: Svf analysis_low_; Svf analysis_medium_; int32_t energy_[kNumBands][2]; int64_t follower_[kNumBands]; int64_t attack_coefficient_[kNumBands]; int64_t decay_coefficient_[kNumBands]; int64_t follower_lp_[kNumBands]; int32_t spectrum_[kNumBands]; int32_t centroid_; int32_t frequency_offset_; int32_t frequency_amount_; int32_t target_frequency_offset_; int32_t target_frequency_amount_; int32_t naive_; bool only_filter_; DISALLOW_COPY_AND_ASSIGN(Follower); }; } // namespace streams #endif // STREAMS_FOLLOWER_H_ ================================================ FILE: lib/streams/gain.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Value to output on the DAC to get unitary gain. #ifndef STREAMS_GAIN_H_ #define STREAMS_GAIN_H_ namespace streams { // The DAC sends up to 2.5V through 25k = 0.1mA over the range of the DAC. // The offness compensation resistor sends -10V through 10M = 0.001mA. // Assuming the op-amp offset is negligible, the two balance for a DAC code of // 65536 / 100.0 const int32_t kDefaultOffset = 655; // DAC code giving a unitary gain. const int32_t kUnityGain = 32767; // Slightly above unitary gain. const int32_t kAboveUnityGain = 32896; // Maximum gain in dB in lin mode with a DAC code of 65535 (6 dB). const int32_t kMaxLinearGain = 65536; // Maximum gain in dB in lin mode with a DAC code of 65535 (18 dB). const int32_t kMaxExponentialGain = 218453; const uint16_t kSchmittTriggerThreshold = 32768 * 5 * 2 / 3 / 8; } // namespace streams #endif // STREAMS_GAIN_H_ ================================================ FILE: lib/streams/lorenz_generator.cc ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Lorenz system. #include "streams/lorenz_generator.h" #include "streams/resources.h" namespace streams { using namespace stmlib; const int64_t sigma = 10.0 * (1 << 24); const int64_t rho = 28.0 * (1 << 24); const int64_t beta = 8.0 / 3.0 * (1 << 24); void LorenzGenerator::Init() { x_ = 0.1 * (1 << 24); y_ = 0; z_ = 0; vcf_amount_ = 0; vca_amount_ = 0; } void LorenzGenerator::Process( int16_t audio, int16_t excite, uint16_t* gain, uint16_t* frequency) { vcf_amount_ += (target_vcf_amount_ - vcf_amount_) >> 8; vca_amount_ += (target_vca_amount_ - vca_amount_) >> 8; int32_t rate = rate_ + (excite >> 8); CONSTRAIN(rate, 0, 256); int64_t dt = static_cast(lut_lorenz_rate[rate]); int32_t x = x_ + (dt * ((sigma * (y_ - x_)) >> 24) >> 24); int32_t y = y_ + (dt * ((x_ * (rho - z_) >> 24) - y_) >> 24); int32_t z = z_ + (dt * ((x_ * int64_t(y_) >> 24) - (beta * z_ >> 24)) >> 24); x_ = x; y_ = y; z_ = z; int32_t z_scaled = z >> 14; int32_t x_scaled = (x >> 14) + 32768; if (index_) { // On channel 2, z and y are inverted to get more variety! z = z_scaled; z_scaled = x_scaled; x_scaled = z; } *gain = z_scaled * vca_amount_ >> 15; *frequency = 65535 + ((x_scaled - 65535) * vcf_amount_ >> 15); } } // namespace streams ================================================ FILE: lib/streams/lorenz_generator.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Lorenz system. #ifndef STREAMS_LORENZ_GENERATOR_H_ #define STREAMS_LORENZ_GENERATOR_H_ #include "stmlib/stmlib.h" #include "streams/meta_parameters.h" namespace streams { class LorenzGenerator { public: LorenzGenerator() { } ~LorenzGenerator() { } void Init(); void Process( int16_t audio, int16_t excite, uint16_t* gain, uint16_t* frequency); void set_index(uint8_t index) { index_ = index; } void Configure(bool alternate, int32_t* parameters, int32_t* globals) { rate_ = parameters[0] >> 8; int32_t vcf_amount = 65535 - parameters[1]; int32_t vca_amount = parameters[1]; if (vcf_amount >= 32767) vcf_amount = 32767; if (vca_amount >= 32767) vca_amount = 32767; target_vcf_amount_ = vcf_amount; target_vca_amount_ = vca_amount; } private: int32_t x_, y_, z_; int32_t rate_; int32_t vcf_amount_; int32_t vca_amount_; int32_t target_vcf_amount_; int32_t target_vca_amount_; uint8_t index_; DISALLOW_COPY_AND_ASSIGN(LorenzGenerator); }; } // namespace streams #endif // STREAMS_LORENZ_GENERATOR_H_ ================================================ FILE: lib/streams/meta_parameters.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Control of several parameters from one single knob. #ifndef STREAMS_META_PARAMETERS_H_ #define STREAMS_META_PARAMETERS_H_ #include "stmlib/stmlib.h" namespace streams { inline void ComputeAmountOffset( int32_t value, int32_t* amount, int32_t* offset) { if (value < 32768) { value = 32767 - value; value = value * value >> 15; *amount = (32767 - value) << 1; *offset = 0; } else { *amount = 65535 - ((value - 32768) << 1); *offset = (value - 32768) << 1; } } inline void ComputeAttackDecay(int32_t shape, uint16_t* a, uint16_t* d) { if (shape < 32768) { *a = 0; *d = 13 * (shape >> 3) + 12288; } else if (shape < 49152) { *a = (shape - 32768) << 1; *d = 65535 - ((shape - 32768) >> 1) * 3; } else { *a = 32768 - ((shape - 49152) >> 2) * 5; *d = 65535 - ((shape - 32768) >> 1) * 3; } } } // namespace streams #endif // STREAMS_META_PARAMETERS_H_ ================================================ FILE: lib/streams/resources.cc ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resources definitions. // // Automatically generated with: // make resources #include "streams/resources.h" namespace streams { static const char str_dummy[] = "dummy"; const char* string_table[] = { str_dummy, }; const int16_t wav_gompertz[] = { 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156, 168, 179, 191, 203, 215, 227, 238, 250, 262, 274, 286, 298, 310, 323, 335, 348, 360, 373, 386, 399, 412, 426, 439, 453, 467, 481, 496, 511, 526, 542, 558, 574, 591, 608, 625, 643, 662, 681, 700, 720, 741, 762, 784, 807, 830, 854, 878, 903, 930, 956, 984, 1013, 1042, 1072, 1104, 1136, 1169, 1203, 1238, 1275, 1312, 1350, 1390, 1430, 1472, 1515, 1559, 1605, 1651, 1699, 1749, 1799, 1851, 1904, 1959, 2015, 2072, 2131, 2191, 2252, 2315, 2380, 2446, 2513, 2582, 2652, 2724, 2798, 2873, 2949, 3027, 3106, 3187, 3270, 3354, 3439, 3526, 3615, 3705, 3796, 3889, 3984, 4080, 4177, 4276, 4377, 4479, 4582, 4686, 4793, 4900, 5009, 5119, 5231, 5344, 5458, 5574, 5690, 5808, 5928, 6048, 6170, 6293, 6417, 6542, 6668, 6796, 6924, 7053, 7184, 7315, 7448, 7581, 7715, 7850, 7986, 8123, 8261, 8399, 8538, 8678, 8819, 8960, 9102, 9244, 9387, 9531, 9675, 9820, 9965, 10110, 10256, 10403, 10550, 10697, 10844, 10992, 11140, 11288, 11436, 11585, 11734, 11882, 12031, 12181, 12330, 12479, 12628, 12777, 12926, 13075, 13224, 13373, 13522, 13670, 13819, 13967, 14115, 14263, 14410, 14558, 14705, 14851, 14997, 15143, 15289, 15434, 15579, 15723, 15867, 16011, 16154, 16296, 16438, 16580, 16721, 16861, 17001, 17141, 17280, 17418, 17555, 17692, 17829, 17964, 18099, 18234, 18367, 18500, 18633, 18764, 18895, 19026, 19155, 19284, 19412, 19539, 19666, 19792, 19917, 20041, 20165, 20287, 20409, 20530, 20651, 20770, 20889, 21007, 21124, 21241, 21356, 21471, 21585, 21698, 21810, 21922, 22032, 22142, 22251, 22359, 22466, 22573, 22679, 22783, 22887, 22991, 23093, 23195, 23295, 23395, 23494, 23592, 23690, 23786, 23882, 23977, 24071, 24165, 24257, 24349, 24440, 24530, 24619, 24708, 24795, 24882, 24969, 25054, 25139, 25222, 25305, 25388, 25469, 25550, 25630, 25709, 25788, 25865, 25942, 26019, 26094, 26169, 26243, 26316, 26389, 26461, 26532, 26603, 26672, 26741, 26810, 26878, 26945, 27011, 27077, 27142, 27206, 27270, 27333, 27395, 27457, 27518, 27579, 27639, 27698, 27756, 27814, 27872, 27929, 27985, 28041, 28096, 28150, 28204, 28257, 28310, 28362, 28414, 28465, 28515, 28565, 28614, 28663, 28712, 28759, 28807, 28853, 28900, 28945, 28991, 29035, 29080, 29123, 29167, 29209, 29252, 29294, 29335, 29376, 29416, 29456, 29496, 29535, 29574, 29612, 29650, 29687, 29724, 29760, 29796, 29832, 29867, 29902, 29937, 29971, 30005, 30038, 30071, 30103, 30136, 30167, 30199, 30230, 30261, 30291, 30321, 30351, 30380, 30409, 30438, 30466, 30494, 30521, 30549, 30576, 30602, 30629, 30655, 30681, 30706, 30731, 30756, 30781, 30805, 30829, 30853, 30876, 30899, 30922, 30945, 30967, 30989, 31011, 31032, 31054, 31075, 31096, 31116, 31136, 31156, 31176, 31196, 31215, 31234, 31253, 31272, 31290, 31308, 31326, 31344, 31362, 31379, 31396, 31413, 31430, 31446, 31463, 31479, 31495, 31510, 31526, 31541, 31556, 31571, 31586, 31601, 31615, 31630, 31644, 31658, 31671, 31685, 31698, 31712, 31725, 31738, 31750, 31763, 31775, 31788, 31800, 31812, 31824, 31836, 31847, 31859, 31870, 31881, 31892, 31903, 31914, 31924, 31935, 31945, 31955, 31966, 31976, 31985, 31995, 32005, 32014, 32024, 32033, 32042, 32051, 32060, 32069, 32078, 32086, 32095, 32103, 32111, 32120, 32128, 32136, 32144, 32151, 32159, 32167, 32174, 32182, 32189, 32196, 32203, 32210, 32217, 32224, 32231, 32238, 32244, 32251, 32257, 32264, 32270, 32276, 32282, 32288, 32294, 32300, 32306, 32312, 32318, 32323, 32329, 32334, 32340, 32345, 32350, 32356, 32361, 32366, 32371, 32376, 32381, 32386, 32390, 32395, 32400, 32404, 32409, 32413, 32418, 32422, 32427, 32431, 32435, 32439, 32443, 32447, 32451, 32455, 32459, 32463, 32467, 32471, 32475, 32478, 32482, 32485, 32489, 32492, 32496, 32499, 32503, 32506, 32509, 32513, 32516, 32519, 32522, 32525, 32528, 32531, 32534, 32537, 32540, 32543, 32546, 32548, 32551, 32554, 32557, 32559, 32562, 32564, 32567, 32569, 32572, 32574, 32577, 32579, 32582, 32584, 32586, 32588, 32591, 32593, 32595, 32597, 32599, 32602, 32604, 32606, 32608, 32610, 32612, 32614, 32616, 32618, 32619, 32621, 32623, 32625, 32627, 32628, 32630, 32632, 32634, 32635, 32637, 32639, 32640, 32642, 32643, 32645, 32647, 32648, 32650, 32651, 32652, 32654, 32655, 32657, 32658, 32660, 32661, 32662, 32664, 32665, 32666, 32667, 32669, 32670, 32671, 32672, 32674, 32675, 32676, 32677, 32678, 32679, 32680, 32682, 32683, 32684, 32685, 32686, 32687, 32688, 32689, 32690, 32691, 32692, 32693, 32694, 32695, 32695, 32696, 32697, 32698, 32699, 32700, 32701, 32702, 32702, 32703, 32704, 32705, 32706, 32706, 32707, 32708, 32709, 32709, 32710, 32711, 32712, 32712, 32713, 32714, 32714, 32715, 32716, 32716, 32717, 32718, 32718, 32719, 32719, 32720, 32721, 32721, 32722, 32722, 32723, 32723, 32724, 32725, 32725, 32726, 32726, 32727, 32727, 32728, 32728, 32729, 32729, 32730, 32730, 32731, 32731, 32731, 32732, 32732, 32733, 32733, 32734, 32734, 32735, 32735, 32735, 32736, 32736, 32737, 32737, 32737, 32738, 32738, 32738, 32739, 32739, 32739, 32740, 32740, 32741, 32741, 32741, 32742, 32742, 32742, 32742, 32743, 32743, 32743, 32744, 32744, 32744, 32745, 32745, 32745, 32745, 32746, 32746, 32746, 32747, 32747, 32747, 32747, 32748, 32748, 32748, 32748, 32749, 32749, 32749, 32749, 32749, 32750, 32750, 32750, 32750, 32751, 32751, 32751, 32751, 32751, 32752, 32752, 32752, 32752, 32752, 32753, 32753, 32753, 32753, 32753, 32753, 32754, 32754, 32754, 32754, 32754, 32754, 32755, 32755, 32755, 32755, 32755, 32755, 32756, 32756, 32756, 32756, 32756, 32756, 32756, 32757, 32757, 32757, 32757, 32757, 32757, 32757, 32757, 32758, 32758, 32758, 32758, 32758, 32758, 32758, 32758, 32758, 32759, 32759, 32759, 32759, 32759, 32759, 32759, 32759, 32759, 32760, 32760, 32760, 32760, 32760, 32760, 32760, 32760, 32760, 32760, 32760, 32761, 32761, 32761, 32761, 32761, 32761, 32761, 32761, 32761, 32761, 32761, 32761, 32761, 32762, 32762, 32762, 32762, 32762, 32762, 32762, 32762, 32762, 32762, 32762, 32762, 32762, 32762, 32762, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32763, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32764, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32765, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32766, 32767, }; const int16_t wav_db[] = { -32768, -32768, -24576, -19783, -16384, -13746, -11591, -9770, -8192, -6799, -5554, -4428, -3399, -2453, -1578, -762, 0, 716, 1392, 2031, 2637, 3213, 3763, 4289, 4792, 5274, 5738, 6184, 6613, 7028, 7429, 7816, 8192, 8555, 8908, 9251, 9584, 9907, 10223, 10530, 10829, 11121, 11405, 11683, 11955, 12221, 12481, 12735, 12984, 13227, 13466, 13700, 13930, 14155, 14376, 14592, 14805, 15015, 15220, 15422, 15621, 15816, 16008, 16197, 16384, 16567, 16747, 16925, 17100, 17273, 17443, 17610, 17776, 17939, 18099, 18258, 18415, 18569, 18722, 18872, 19021, 19168, 19313, 19456, 19597, 19737, 19875, 20012, 20147, 20281, 20413, 20543, 20673, 20800, 20927, 21052, 21176, 21298, 21419, 21539, 21658, 21776, 21892, 22007, 22122, 22235, 22347, 22458, 22568, 22676, 22784, 22891, 22997, 23102, 23207, 23310, 23412, 23514, 23614, 23714, 23813, 23911, 24008, 24105, 24200, 24295, 24389, 24483, 24576, 24667, 24759, 24849, 24939, 25028, 25117, 25205, 25292, 25379, 25465, 25550, 25635, 25719, 25802, 25885, 25968, 26049, 26131, 26211, 26291, 26371, 26450, 26529, 26607, 26684, 26761, 26838, 26914, 26989, 27064, 27139, 27213, 27286, 27360, 27432, 27505, 27576, 27648, 27719, 27789, 27860, 27929, 27999, 28067, 28136, 28204, 28272, 28339, 28406, 28473, 28539, 28605, 28670, 28735, 28800, 28865, 28929, 28992, 29056, 29119, 29181, 29244, 29306, 29368, 29429, 29490, 29551, 29611, 29671, 29731, 29791, 29850, 29909, 29968, 30026, 30084, 30142, 30199, 30257, 30314, 30370, 30427, 30483, 30539, 30594, 30650, 30705, 30760, 30814, 30868, 30923, 30976, 31030, 31083, 31136, 31189, 31242, 31294, 31347, 31399, 31450, 31502, 31553, 31604, 31655, 31706, 31756, 31806, 31856, 31906, 31955, 32005, 32054, 32103, 32152, 32200, 32248, 32297, 32345, 32392, 32440, 32487, 32534, 32581, 32628, 32675, 32721, 32721, }; const int16_t* waveforms_table[] = { wav_gompertz, wav_db, }; const uint16_t lut_env_linear[] = { 0, 257, 514, 771, 1028, 1285, 1542, 1799, 2056, 2313, 2570, 2827, 3084, 3341, 3598, 3855, 4112, 4369, 4626, 4883, 5140, 5397, 5654, 5911, 6168, 6425, 6682, 6939, 7196, 7453, 7710, 7967, 8224, 8481, 8738, 8995, 9252, 9509, 9766, 10023, 10280, 10537, 10794, 11051, 11308, 11565, 11822, 12079, 12336, 12593, 12850, 13107, 13364, 13621, 13878, 14135, 14392, 14649, 14906, 15163, 15420, 15677, 15934, 16191, 16448, 16705, 16962, 17219, 17476, 17733, 17990, 18247, 18504, 18761, 19018, 19275, 19532, 19789, 20046, 20303, 20560, 20817, 21074, 21331, 21588, 21845, 22102, 22359, 22616, 22873, 23130, 23387, 23644, 23901, 24158, 24415, 24672, 24929, 25186, 25443, 25700, 25957, 26214, 26471, 26728, 26985, 27242, 27499, 27756, 28013, 28270, 28527, 28784, 29041, 29298, 29555, 29812, 30069, 30326, 30583, 30840, 31097, 31354, 31611, 31868, 32125, 32382, 32639, 32896, 33153, 33410, 33667, 33924, 34181, 34438, 34695, 34952, 35209, 35466, 35723, 35980, 36237, 36494, 36751, 37008, 37265, 37522, 37779, 38036, 38293, 38550, 38807, 39064, 39321, 39578, 39835, 40092, 40349, 40606, 40863, 41120, 41377, 41634, 41891, 42148, 42405, 42662, 42919, 43176, 43433, 43690, 43947, 44204, 44461, 44718, 44975, 45232, 45489, 45746, 46003, 46260, 46517, 46774, 47031, 47288, 47545, 47802, 48059, 48316, 48573, 48830, 49087, 49344, 49601, 49858, 50115, 50372, 50629, 50886, 51143, 51400, 51657, 51914, 52171, 52428, 52685, 52942, 53199, 53456, 53713, 53970, 54227, 54484, 54741, 54998, 55255, 55512, 55769, 56026, 56283, 56540, 56797, 57054, 57311, 57568, 57825, 58082, 58339, 58596, 58853, 59110, 59367, 59624, 59881, 60138, 60395, 60652, 60909, 61166, 61423, 61680, 61937, 62194, 62451, 62708, 62965, 63222, 63479, 63736, 63993, 64250, 64507, 64764, 65021, 65278, 65535, 65535, }; const uint16_t lut_env_expo[] = { 0, 1035, 2054, 3057, 4045, 5018, 5975, 6918, 7846, 8760, 9659, 10545, 11416, 12275, 13120, 13952, 14771, 15577, 16371, 17152, 17921, 18679, 19425, 20159, 20881, 21593, 22294, 22983, 23662, 24331, 24989, 25637, 26274, 26902, 27520, 28129, 28728, 29318, 29899, 30471, 31034, 31588, 32133, 32670, 33199, 33720, 34232, 34737, 35233, 35722, 36204, 36678, 37145, 37604, 38056, 38502, 38940, 39371, 39796, 40215, 40626, 41032, 41431, 41824, 42211, 42592, 42967, 43336, 43699, 44057, 44409, 44756, 45097, 45434, 45764, 46090, 46411, 46727, 47037, 47344, 47645, 47941, 48233, 48521, 48804, 49083, 49357, 49627, 49893, 50155, 50412, 50666, 50916, 51162, 51404, 51642, 51877, 52108, 52335, 52559, 52780, 52997, 53210, 53421, 53628, 53831, 54032, 54230, 54424, 54616, 54804, 54990, 55173, 55353, 55530, 55704, 55876, 56045, 56211, 56375, 56536, 56695, 56851, 57005, 57157, 57306, 57453, 57597, 57740, 57880, 58018, 58153, 58287, 58419, 58548, 58676, 58801, 58925, 59047, 59167, 59285, 59401, 59515, 59628, 59739, 59848, 59955, 60061, 60165, 60267, 60368, 60468, 60566, 60662, 60757, 60850, 60942, 61032, 61121, 61209, 61295, 61380, 61464, 61546, 61628, 61707, 61786, 61863, 61939, 62014, 62088, 62161, 62233, 62303, 62372, 62441, 62508, 62574, 62639, 62703, 62767, 62829, 62890, 62950, 63010, 63068, 63125, 63182, 63238, 63293, 63347, 63400, 63452, 63504, 63554, 63604, 63654, 63702, 63750, 63797, 63843, 63888, 63933, 63977, 64021, 64063, 64105, 64147, 64188, 64228, 64267, 64306, 64344, 64382, 64419, 64456, 64492, 64527, 64562, 64596, 64630, 64664, 64696, 64729, 64760, 64792, 64822, 64853, 64883, 64912, 64941, 64969, 64997, 65025, 65052, 65079, 65105, 65131, 65157, 65182, 65206, 65231, 65255, 65278, 65302, 65324, 65347, 65369, 65391, 65412, 65434, 65454, 65475, 65495, 65515, 65535, 65535, }; const uint16_t lut_env_quartic[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 9, 11, 14, 16, 19, 22, 25, 29, 33, 37, 42, 48, 53, 59, 66, 73, 81, 89, 98, 107, 117, 128, 139, 151, 164, 177, 191, 206, 222, 238, 256, 274, 293, 313, 334, 355, 378, 402, 427, 453, 480, 508, 537, 567, 599, 631, 665, 700, 737, 775, 814, 854, 896, 939, 984, 1030, 1077, 1127, 1177, 1230, 1283, 1339, 1396, 1455, 1515, 1577, 1641, 1707, 1775, 1844, 1916, 1989, 2064, 2141, 2220, 2302, 2385, 2470, 2557, 2647, 2739, 2833, 2929, 3027, 3128, 3231, 3336, 3444, 3554, 3667, 3782, 3899, 4019, 4142, 4267, 4395, 4525, 4658, 4794, 4933, 5074, 5218, 5365, 5515, 5668, 5824, 5983, 6144, 6309, 6477, 6648, 6822, 6999, 7179, 7363, 7550, 7740, 7933, 8130, 8330, 8534, 8741, 8951, 9165, 9383, 9604, 9829, 10057, 10289, 10525, 10765, 11008, 11255, 11507, 11761, 12020, 12283, 12550, 12821, 13096, 13375, 13658, 13945, 14237, 14532, 14832, 15137, 15445, 15758, 16076, 16397, 16724, 17054, 17390, 17730, 18074, 18423, 18777, 19136, 19499, 19868, 20241, 20618, 21001, 21389, 21781, 22179, 22582, 22990, 23403, 23821, 24244, 24672, 25106, 25545, 25990, 26440, 26895, 27355, 27821, 28293, 28770, 29253, 29742, 30236, 30735, 31241, 31752, 32270, 32793, 33321, 33856, 34397, 34944, 35497, 36056, 36621, 37192, 37769, 38353, 38943, 39539, 40142, 40751, 41366, 41988, 42617, 43251, 43893, 44541, 45196, 45857, 46526, 47201, 47882, 48571, 49267, 49969, 50678, 51395, 52118, 52849, 53587, 54332, 55084, 55843, 56610, 57384, 58165, 58954, 59750, 60553, 61364, 62183, 63010, 63843, 64685, 65535, 65535, }; const uint16_t lut_square_root[] = { 0, 4095, 5792, 7094, 8191, 9158, 10032, 10836, 11585, 12287, 12952, 13584, 14188, 14768, 15325, 15863, 16383, 16887, 17377, 17853, 18317, 18769, 19211, 19643, 20065, 20479, 20885, 21283, 21673, 22057, 22434, 22805, 23170, 23529, 23883, 24231, 24575, 24914, 25249, 25579, 25904, 26226, 26544, 26858, 27169, 27476, 27779, 28080, 28377, 28671, 28962, 29250, 29536, 29818, 30098, 30376, 30651, 30923, 31193, 31461, 31726, 31990, 32251, 32510, 32767, 33022, 33275, 33526, 33775, 34023, 34269, 34512, 34755, 34995, 35234, 35471, 35707, 35941, 36174, 36405, 36635, 36863, 37090, 37315, 37539, 37762, 37984, 38204, 38423, 38640, 38857, 39072, 39286, 39499, 39711, 39922, 40131, 40340, 40547, 40754, 40959, 41163, 41366, 41569, 41770, 41970, 42170, 42368, 42566, 42762, 42958, 43153, 43347, 43540, 43732, 43924, 44114, 44304, 44493, 44681, 44868, 45055, 45241, 45426, 45610, 45793, 45976, 46158, 46340, 46520, 46700, 46880, 47058, 47236, 47413, 47590, 47766, 47941, 48116, 48290, 48463, 48636, 48808, 48980, 49151, 49321, 49491, 49660, 49829, 49997, 50164, 50331, 50498, 50663, 50829, 50994, 51158, 51321, 51485, 51647, 51809, 51971, 52132, 52293, 52453, 52613, 52772, 52931, 53089, 53247, 53404, 53561, 53717, 53873, 54029, 54184, 54338, 54492, 54646, 54799, 54952, 55105, 55257, 55408, 55559, 55710, 55861, 56011, 56160, 56309, 56458, 56606, 56754, 56902, 57049, 57196, 57343, 57489, 57634, 57780, 57925, 58069, 58214, 58358, 58501, 58644, 58787, 58930, 59072, 59214, 59355, 59496, 59637, 59778, 59918, 60058, 60197, 60336, 60475, 60614, 60752, 60890, 61028, 61165, 61302, 61439, 61575, 61711, 61847, 61982, 62117, 62252, 62387, 62521, 62655, 62789, 62922, 63056, 63189, 63321, 63453, 63586, 63717, 63849, 63980, 64111, 64242, 64372, 64502, 64632, 64762, 64891, 65020, 65149, 65278, 65406, 65406, }; const uint16_t lut_svf_cutoff[] = { 54, 57, 60, 64, 68, 72, 76, 81, 85, 91, 96, 102, 108, 114, 121, 128, 136, 144, 153, 162, 171, 182, 192, 204, 216, 229, 243, 257, 272, 289, 306, 324, 343, 364, 385, 408, 433, 458, 486, 515, 545, 578, 612, 648, 687, 728, 771, 817, 866, 917, 972, 1030, 1091, 1156, 1225, 1297, 1375, 1456, 1543, 1635, 1732, 1835, 1944, 2060, 2182, 2312, 2449, 2595, 2749, 2912, 3085, 3269, 3463, 3669, 3887, 4118, 4362, 4621, 4895, 5186, 5494, 5819, 6165, 6530, 6917, 7327, 7760, 8219, 8705, 9220, 9764, 10340, 10949, 11593, 12275, 12995, 13757, 14562, 15412, 16309, 17257, 18256, 19310, 20421, 21591, 22822, 24116, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, 25078, }; const uint16_t lut_svf_damp[] = { 65534, 49166, 46069, 43993, 42386, 41058, 39917, 38910, 38007, 37184, 36427, 35726, 35070, 34454, 33873, 33322, 32798, 32299, 31820, 31361, 30920, 30496, 30086, 29690, 29306, 28935, 28574, 28224, 27883, 27551, 27228, 26912, 26605, 26304, 26010, 25723, 25441, 25166, 24896, 24631, 24371, 24116, 23866, 23620, 23379, 23141, 22908, 22678, 22452, 22229, 22010, 21794, 21581, 21371, 21164, 20960, 20759, 20560, 20365, 20171, 19980, 19791, 19605, 19421, 19239, 19059, 18882, 18706, 18532, 18360, 18190, 18022, 17856, 17691, 17528, 17367, 17207, 17049, 16892, 16737, 16583, 16431, 16280, 16131, 15982, 15836, 15690, 15546, 15403, 15261, 15120, 14981, 14843, 14705, 14569, 14434, 14300, 14167, 14036, 13905, 13775, 13646, 13518, 13391, 13265, 13140, 13015, 12892, 12769, 12648, 12527, 12407, 12287, 12169, 12051, 11934, 11818, 11703, 11588, 11474, 11361, 11249, 11137, 11026, 10915, 10805, 10696, 10588, 10480, 10373, 10266, 10160, 10055, 9950, 9846, 9742, 9639, 9537, 9435, 9333, 9233, 9132, 9033, 8933, 8835, 8737, 8639, 8542, 8445, 8349, 8253, 8158, 8063, 7969, 7875, 7782, 7689, 7596, 7504, 7413, 7321, 7231, 7140, 7050, 6961, 6872, 6783, 6695, 6607, 6519, 6432, 6346, 6259, 6173, 6088, 6003, 5918, 5833, 5749, 5665, 5582, 5499, 5416, 5334, 5251, 5170, 5088, 5007, 4926, 4846, 4766, 4686, 4607, 4527, 4449, 4370, 4292, 4214, 4136, 4059, 3982, 3905, 3828, 3752, 3676, 3601, 3525, 3450, 3375, 3301, 3226, 3152, 3078, 3005, 2932, 2859, 2786, 2713, 2641, 2569, 2497, 2426, 2355, 2284, 2213, 2142, 2072, 2002, 1932, 1862, 1793, 1724, 1655, 1586, 1518, 1449, 1381, 1313, 1246, 1178, 1111, 1044, 977, 911, 844, 778, 712, 647, 581, 516, 450, 385, 321, 256, 192, 127, 63, }; const uint16_t lut_2164_gain[] = { 32767, 31340, 29975, 28670, 27421, 26227, 25085, 23993, 22948, 21948, 20993, 20078, 19204, 18368, 17568, 16803, 16071, 15371, 14702, 14062, 13449, 12864, 12303, 11768, 11255, 10765, 10296, 9848, 9419, 9009, 8617, 8241, 7882, 7539, 7211, 6897, 6596, 6309, 6034, 5772, 5520, 5280, 5050, 4830, 4620, 4418, 4226, 4042, 3866, 3698, 3537, 3383, 3235, 3094, 2960, 2831, 2707, 2589, 2477, 2369, 2266, 2167, 2073, 1982, 1896, 1813, 1734, 1659, 1587, 1517, 1451, 1388, 1328, 1270, 1215, 1162, 1111, 1063, 1016, 972, 930, 889, 850, 813, 778, 744, 712, 681, 651, 623, 595, 569, 545, 521, 498, 477, 456, 436, 417, 399, 381, 365, 349, 334, 319, 305, 292, 279, 267, 255, 244, 233, 223, 214, 204, 195, 187, 179, 171, 163, 156, 149, 143, 137, 131, 125, 119, 114, 109, 104, 100, 96, 91, 87, 84, 80, 76, 73, 70, 67, 64, 61, 58, 56, 53, 51, 49, 47, 45, 43, 41, 39, 37, 36, 34, 32, 31, 30, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 16, 15, 14, 14, 13, 12, 12, 11, 11, 10, 10, 9, 9, 9, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; const uint16_t lut_compressor_ratio[] = { 256, 255, 255, 255, 254, 253, 252, 251, 250, 248, 246, 245, 243, 241, 238, 236, 234, 231, 228, 226, 223, 220, 217, 214, 211, 208, 205, 202, 198, 195, 192, 189, 186, 183, 179, 176, 173, 170, 167, 164, 161, 158, 155, 152, 149, 146, 144, 141, 138, 136, 133, 131, 128, 126, 123, 121, 119, 116, 114, 112, 110, 108, 106, 104, 102, 100, 98, 96, 95, 93, 91, 89, 88, 86, 85, 83, 82, 80, 79, 77, 76, 75, 73, 72, 71, 70, 69, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 54, 53, 52, 51, 50, 50, 49, 48, 47, 47, 46, 45, 45, 44, 43, 43, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 32, 31, 31, 30, 30, 30, 29, 29, 29, 28, 28, 28, 27, 27, 27, 26, 26, 26, 25, 25, 25, 24, 24, 24, 24, 23, 23, 23, 23, 22, 22, 22, 22, 21, 21, 21, 21, 20, 20, 20, 20, 20, 19, 19, 19, 19, 19, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, }; const uint16_t lut_soft_knee[] = { 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 5, 6, 8, 10, 13, 15, 19, 22, 26, 31, 36, 41, 47, 53, 61, 68, 76, 85, 95, 105, 116, 127, 140, 153, 167, 182, 197, 214, 231, 249, 269, 289, 310, 332, 355, 380, 405, 431, 459, 488, 518, 549, 581, 615, 649, 685, 723, 762, 802, 843, 886, 930, 976, 1023, 1072, 1123, 1174, 1228, 1283, 1339, 1398, 1457, 1519, 1582, 1647, 1714, 1783, 1853, 1925, 1999, 2075, 2153, 2233, 2315, 2398, 2484, 2572, 2661, 2753, 2847, 2943, 3041, 3141, 3244, 3349, 3455, 3565, 3676, 3790, 3906, 4024, 4145, 4268, 4393, 4521, 4652, 4785, 4920, 5058, 5199, 5342, 5487, 5636, 5787, 5940, 6097, 6256, 6417, 6582, 6749, 6920, 7093, 7268, 7447, 7629, 7813, 8001, 8191, 8385, 8581, 8781, 8984, 9189, 9398, 9610, 9825, 10044, 10265, 10490, 10718, 10949, 11184, 11422, 11663, 11908, 12156, 12408, 12663, 12921, 13183, 13448, 13717, 13990, 14266, 14546, 14829, 15116, 15407, 15701, 15999, 16301, 16607, 16916, 17229, 17547, 17868, 18192, 18521, 18854, 19191, 19531, 19876, 20225, 20577, 20934, 21295, 21660, 22029, 22403, 22780, 23162, 23548, 23939, 24333, 24732, 25135, 25543, 25955, 26371, 26792, 27217, 27647, 28081, 28520, 28963, 29411, 29864, 30321, 30783, 31249, 31720, 32196, 32676, 33162, 33652, 34147, 34646, 35151, 35660, 36175, 36694, 37218, 37747, 38282, 38821, 39365, 39914, 40469, 41028, 41593, 42162, 42737, 43317, 43903, 44493, 45089, 45691, 46297, 46909, 47526, 48149, 48777, 49410, 50049, 50694, 51343, 51999, 52660, 53326, 53999, 54676, 55360, 56049, 56744, 57444, 58151, 58863, 59581, 60304, 61034, 61769, 62510, 63257, 64010, 64770, 65535, }; const uint16_t* lookup_table_table[] = { lut_env_linear, lut_env_expo, lut_env_quartic, lut_square_root, lut_svf_cutoff, lut_svf_damp, lut_2164_gain, lut_compressor_ratio, lut_soft_knee, }; const uint32_t lut_env_increments[] = { 276301411, 231949934, 196150997, 166999666, 143068141, 123273939, 106787653, 92967541, 81312526, 71428035, 63000899, 55780710, 49565850, 44192924, 39528695, 35463892, 31908401, 28787528, 26039050, 23610894, 21459288, 19547282, 17843559, 16321476, 14958281, 13734481, 12633316, 11640330, 10743016, 9930523, 9193410, 8523437, 7913397, 7356972, 6848604, 6383397, 5957029, 5565672, 5205932, 4874792, 4569569, 4287864, 4027536, 3786669, 3563542, 3356609, 3164482, 2985906, 2819752, 2664995, 2520711, 2386061, 2260283, 2142684, 2032635, 1929561, 1832939, 1742290, 1657176, 1577196, 1501984, 1431202, 1364541, 1301717, 1242466, 1186549, 1133742, 1083841, 1036655, 992009, 949741, 909701, 871748, 835755, 801600, 769172, 738367, 709089, 681248, 654760, 629547, 605536, 582659, 560852, 540056, 520215, 501277, 483193, 465917, 449406, 433620, 418521, 404074, 390245, 377002, 364316, 352160, 340506, 329331, 318610, 308322, 298445, 288962, 279851, 271097, 262683, 254593, 246811, 239325, 232121, 225185, 218507, 212074, 205876, 199903, 194146, 188594, 183239, 178072, 173087, 168275, 163628, 159142, 154807, 150620, 146573, 142661, 138879, 135221, 131683, 128260, 124947, 121741, 118636, 115630, 112719, 109899, 107166, 104518, 101951, 99463, 97050, 94709, 92439, 90236, 88099, 86025, 84011, 82056, 80157, 78313, 76521, 74781, 73090, 71446, 69848, 68295, 66785, 65316, 63887, 62497, 61145, 59829, 58549, 57302, 56089, 54907, 53756, 52636, 51544, 50480, 49444, 48434, 47450, 46491, 45556, 44644, 43755, 42888, 42043, 41218, 40413, 39628, 38862, 38114, 37384, 36671, 35976, 35296, 34633, 33985, 33353, 32735, 32131, 31541, 30965, 30401, 29851, 29313, 28786, 28272, 27769, 27277, 26796, 26326, 25866, 25416, 24975, 24545, 24123, 23710, 23307, 22911, 22524, 22146, 21775, 21412, 21056, 20708, 20367, 20033, 19705, 19385, 19071, 18763, 18461, 18166, 17876, 17592, 17314, 17041, 16774, 16512, 16254, 16002, 15755, 15513, 15275, 15041, 14812, 14588, 14368, 14151, 13939, 13731, 13527, 13326, 13130, 12936, 12747, 12561, 12378, 12198, 12022, 11849, 11679, 11512, }; const uint32_t lut_lp_coefficients[] = { 590672516, 319034455, 133800766, 67976239, 63327094, 62214607, 61121376, 60047077, 58991393, 57954009, 56934619, 55932918, 54948609, 53981397, 53030993, 52097114, 51179478, 50277811, 49391841, 48521302, 47665932, 46825472, 45999668, 45188271, 44391035, 43607717, 42838081, 42081892, 41338919, 40608937, 39891723, 39187058, 38494727, 37814517, 37146221, 36489633, 35844551, 35210779, 34588120, 33976383, 33375380, 32784926, 32204838, 31634936, 31075046, 30524993, 29984607, 29453721, 28932170, 28419793, 27916429, 27421923, 26936121, 26458872, 25990026, 25529439, 25076965, 24632464, 24195797, 23766828, 23345422, 22931447, 22524774, 22125276, 21732827, 21347304, 20968586, 20596554, 20231092, 19872084, 19519417, 19172981, 18832666, 18498365, 18169974, 17847387, 17530504, 17219225, 16913451, 16613085, 16318033, 16028202, 15743500, 15463836, 15189122, 14919272, 14654199, 14393820, 14138052, 13886814, 13640026, 13397610, 13159489, 12925588, 12695832, 12470147, 12248464, 12030709, 11816816, 11606715, 11400339, 11197623, 10998503, 10802914, 10610795, 10422085, 10236722, 10054649, 9875806, 9700137, 9527587, 9358098, 9191619, 9028094, 8867473, 8709704, 8554736, 8402520, 8253007, 8106150, 7961901, 7820214, 7681044, 7544346, 7410077, 7278193, 7148653, 7021415, 6896437, 6773681, 6653106, 6534675, 6418348, 6304089, 6191861, 6081629, 5973356, 5867008, 5762550, 5659950, 5559175, 5460191, 5362968, 5267474, 5173678, 5081550, 4991061, 4902182, 4814883, 4729137, 4644917, 4562195, 4480945, 4401140, 4322755, 4245764, 4170144, 4095869, 4022916, 3951261, 3880881, 3811754, 3743857, 3677168, 3611666, 3547330, 3484139, 3422073, 3361112, 3301236, 3242425, 3184662, 3127927, 3072202, 3017468, 2963710, 2910908, 2859047, 2808109, 2758078, 2708937, 2660672, 2613266, 2566704, 2520972, 2476054, 2431935, 2388602, 2346041, 2304238, 2263180, 2222853, 2183243, 2144340, 2106129, 2068599, 2031737, 1995532, 1959971, 1925044, 1890740, 1857046, 1823952, 1791448, 1759523, 1728167, 1697369, 1667120, 1637410, 1608229, 1579568, 1551417, 1523768, 1496612, 1469939, 1443741, 1418011, 1392739, 1367917, 1343537, 1319591, 1296073, 1272973, 1250285, 1228001, 1206114, 1184617, 1163504, 1142766, 1122398, 1102393, 1082744, 1063446, 1044491, 1025874, 1007589, 989630, 971991, 954666, 937650, 920937, 904521, 888399, 872564, 857011, 841735, 826731, 811995, 797521, 783305, 769343, 755630, 742160, 728931, 715938, 703176, 690642, 678331, 666240, 654364, 642699, 631243, 619991, 608939, 598084, 587423, 576952, 566667, 556566, 546644, 536900, 527329, 517929, 508696, 499628, 490722, 481974, 473383, 464944, 456656, 448515, 440520, 432667, 424954, 417379, 409938, 402631, 395453, 388404, 381480, 374679, 368000, 361440, 354997, 348668, 342453, 336348, 330352, 324463, 318678, 312997, 307418, 301937, 296555, 291268, 286076, 280976, 275967, 271047, 266215, 261469, 256808, 252230, 247733, 243317, 238979, 234719, 230535, 226425, 222388, 218424, 214530, 210705, 206949, 203260, 199636, 196077, 192582, 189148, 185776, 182465, 179212, 176017, 172879, 169797, 166770, 163797, 160877, 158009, 155192, 152425, 149708, 147039, 144417, 141843, 139314, 136830, 134391, 131995, 129642, 127331, 125061, 122831, 120641, 118491, 116378, 114304, 112266, 110264, 108299, 106368, 104472, 102609, 100780, 98983, 97218, 95485, 93783, 92111, 90469, 88856, 87272, 85716, 84188, 82687, 81213, 79765, 78343, 76946, 75574, 74227, 72904, 71604, 70328, 69074, 67842, 66633, 65445, 64278, 63132, 62007, 60901, 59815, 58749, 57702, 56673, 55663, 54670, 53696, 52738, 51798, 50875, 49968, 49077, 48202, 47343, 46498, 45669, 44855, 44056, 43270, 42499, 41741, 40997, 40266, 39548, 38843, 38151, 37470, 36802, 36146, 35502, 34869, 34247, 33637, 33037, 32448, 31870, 31301, 30743, 30195, 29657, 29128, 28609, 28099, 27598, 27106, 26623, 26148, 25682, 25224, 24774, 24332, 23899, 23473, 23054, 22643, 22239, 21843, 21454, 21071, 20695, 20326, 19964, 19608, 19258, 18915, 18578, 18247, 17921, 17602, 17288, 16980, 16677, 16380, 16088, 15801, 15519, 15243, 14971, 14704, 14442, 14184, 13931, 13683, 13439, 13199, 12964, 12733, 12506, 12283, 12064, 11849, 11638, 11430, 11226, 11026, 10830, 10637, 10447, 10261, 10078, 9898, 9722, 9548, 9378, 9211, 9047, 8885, 8727, 8571, 8418, 8268, 8121, 7976, 7834, 7694, 7557, 7422, 7290, 7160, 7032, 6907, 6784, 6663, 6544, 6427, 6313, 6200, 6090, 5981, 5875, 5770, 5667, 5566, 5467, 5369, 5273, 5179, 5087, 4996, 4907, 4820, 4734, 4649, 4567, 4485, 4405, 4327, 4249, 4174, 4099, 4026, 3954, 3884, 3815, 3747, 3680, 3614, 3550, 3486, 3424, 3363, 3303, 3244, 3187, 3130, 3074, 3019, 2965, 2912, 2860, 2809, 2759, 2710, 2662, 2614, 2568, 2522, 2477, 2433, 2389, 2347, 2305, 2264, 2224, 2184, 2145, 2107, 2069, 2032, 1996, 1960, 1925, 1891, 1857, 1824, 1792, 1760, 1728, 1698, 1667, 1638, 1608, 1580, 1551, 1524, 1497, 1470, 1444, 1418, 1393, 1368, 1343, 1319, 1296, 1273, 1250, 1228, 1206, 1184, 1163, 1143, 1122, 1102, 1083, 1063, 1044, 1026, 1007, 989, 972, 954, 937, 921, 904, 888, 872, 857, 841, 826, 812, 797, 783, 769, 755, 742, 729, 716, 703, }; const uint32_t lut_exp2[] = { 65536, 65713, 65891, 66070, 66249, 66429, 66609, 66789, 66971, 67152, 67334, 67517, 67700, 67883, 68067, 68252, 68437, 68623, 68809, 68995, 69182, 69370, 69558, 69747, 69936, 70125, 70315, 70506, 70697, 70889, 71081, 71274, 71467, 71661, 71855, 72050, 72245, 72441, 72638, 72834, 73032, 73230, 73429, 73628, 73827, 74027, 74228, 74429, 74631, 74833, 75036, 75240, 75444, 75648, 75853, 76059, 76265, 76472, 76679, 76887, 77096, 77305, 77514, 77725, 77935, 78147, 78359, 78571, 78784, 78998, 79212, 79427, 79642, 79858, 80074, 80292, 80509, 80727, 80946, 81166, 81386, 81607, 81828, 82050, 82272, 82495, 82719, 82943, 83168, 83394, 83620, 83846, 84074, 84302, 84530, 84759, 84989, 85220, 85451, 85682, 85915, 86148, 86381, 86615, 86850, 87086, 87322, 87559, 87796, 88034, 88273, 88512, 88752, 88993, 89234, 89476, 89718, 89962, 90206, 90450, 90695, 90941, 91188, 91435, 91683, 91932, 92181, 92431, 92681, 92933, 93185, 93437, 93691, 93945, 94199, 94455, 94711, 94968, 95225, 95483, 95742, 96002, 96262, 96523, 96785, 97047, 97310, 97574, 97839, 98104, 98370, 98637, 98904, 99172, 99441, 99711, 99981, 100252, 100524, 100797, 101070, 101344, 101619, 101894, 102170, 102447, 102725, 103004, 103283, 103563, 103844, 104125, 104408, 104691, 104975, 105259, 105545, 105831, 106118, 106405, 106694, 106983, 107273, 107564, 107856, 108148, 108441, 108735, 109030, 109326, 109622, 109919, 110217, 110516, 110816, 111116, 111418, 111720, 112023, 112326, 112631, 112936, 113243, 113550, 113857, 114166, 114476, 114786, 115097, 115409, 115722, 116036, 116351, 116666, 116982, 117300, 117618, 117936, 118256, 118577, 118898, 119221, 119544, 119868, 120193, 120519, 120846, 121173, 121502, 121831, 122162, 122493, 122825, 123158, 123492, 123827, 124162, 124499, 124837, 125175, 125514, 125855, 126196, 126538, 126881, 127225, 127570, 127916, 128263, 128611, 128959, 129309, 129660, 130011, 130364, 130717, 131072, }; const uint32_t lut_log2[] = { 524288, 524656, 525023, 525389, 525753, 526116, 526478, 526838, 527197, 527554, 527910, 528265, 528619, 528971, 529322, 529671, 530019, 530366, 530712, 531057, 531400, 531742, 532082, 532422, 532760, 533097, 533433, 533768, 534101, 534434, 534765, 535095, 535424, 535751, 536078, 536403, 536728, 537051, 537373, 537694, 538014, 538333, 538651, 538968, 539283, 539598, 539912, 540224, 540536, 540846, 541156, 541464, 541772, 542078, 542384, 542688, 542992, 543294, 543596, 543896, 544196, 544495, 544793, 545089, 545385, 545680, 545974, 546268, 546560, 546851, 547142, 547431, 547720, 548008, 548295, 548581, 548866, 549150, 549434, 549717, 549998, 550279, 550560, 550839, 551117, 551395, 551672, 551948, 552223, 552498, 552771, 553044, 553316, 553588, 553858, 554128, 554397, 554665, 554932, 555199, 555465, 555730, 555995, 556259, 556522, 556784, 557045, 557306, 557566, 557826, 558084, 558342, 558600, 558856, 559112, 559367, 559622, 559876, 560129, 560381, 560633, 560884, 561135, 561384, 561634, 561882, 562130, 562377, 562624, 562870, 563115, 563359, 563603, 563847, 564089, 564332, 564573, 564814, 565054, 565294, 565533, 565771, 566009, 566247, 566483, 566719, 566955, 567190, 567424, 567658, 567891, 568124, 568356, 568587, 568818, 569048, 569278, 569507, 569736, 569964, 570192, 570419, 570645, 570871, 571096, 571321, 571545, 571769, 571992, 572215, 572437, 572659, 572880, 573101, 573321, 573541, 573760, 573978, 574197, 574414, 574631, 574848, 575064, 575280, 575495, 575709, 575923, 576137, 576350, 576563, 576775, 576987, 577198, 577409, 577619, 577829, 578039, 578248, 578456, 578664, 578872, 579079, 579286, 579492, 579698, 579903, 580108, 580312, 580516, 580720, 580923, 581125, 581328, 581530, 581731, 581932, 582132, 582332, 582532, 582731, 582930, 583129, 583327, 583524, 583721, 583918, 584115, 584311, 584506, 584701, 584896, 585090, 585284, 585478, 585671, 585864, 586056, 586248, 586440, 586631, 586822, 587012, 587202, 587392, 587581, 587770, 587959, 588147, 588335, 588522, 588709, 588896, 589082, 589268, 589453, 589639, 589824, }; const uint32_t lut_lorenz_rate[] = { 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 32, 33, 35, 36, 38, 40, 42, 44, 46, 48, 50, 52, 55, 57, 60, 63, 66, 69, 72, 75, 78, 82, 86, 90, 94, 98, 103, 107, 112, 118, 123, 129, 135, 141, 147, 154, 161, 168, 176, 184, 193, 201, 211, 220, 230, 241, 252, 263, 275, 288, 301, 315, 329, 344, 360, 377, 394, 412, 431, 451, 471, 493, 515, 539, 563, 589, 616, 644, 674, 705, 737, 770, 806, 843, 881, 921, 963, 1007, 1054, 1102, 1152, 1205, 1260, 1317, 1378, 1441, 1506, 1575, 1647, 1722, 1801, 1883, 1970, 2060, 2154, 2252, 2355, 2463, 2575, 2693, 2816, 2945, 3079, 3220, 3367, 3521, 3682, 3850, 4026, 4210, 4402, 4603, 4814, 5034, 5264, 5504, 5756, 6019, 6294, 6581, 6882, 7196, 7525, 7869, 8229, 8605, 8998, 9409, 9839, 10288, 10758, 11250, 11764, 12302, 12864, 13451, 14066, 14709, 15381, 16083, 16818, 17587, 18390, 19230, 20109, 21028, 21989, 22993, 24044, 25142, 26291, 27492, 28748, 30062, 31435, 32872, 34374, 35944, 37586, 39304, 41099, 42977, 44941, 46994, 49141, 51386, 53734, 56189, 58756, 61441, 64248, 67184, 70253, 73463, 76819, 80329, 83999, 87837, 91850, 96047, 100435, 105024, 109822, 114840, 120087, 125573, 131310, 137310, 143583, 150144, 157003, 164177, 171678, 179521, 187723, 196300, 205269, 214647, 224454, 234709, 245433, 256646, 268372, 280634, 293455, 306863, 320883, 335544, }; const uint32_t* lookup_table_32_table[] = { lut_env_increments, lut_lp_coefficients, lut_exp2, lut_log2, lut_lorenz_rate, }; } // namespace streams ================================================ FILE: lib/streams/resources.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Resources definitions. // // Automatically generated with: // make resources #ifndef STREAMS_RESOURCES_H_ #define STREAMS_RESOURCES_H_ #include "stmlib/stmlib.h" namespace streams { typedef uint8_t ResourceId; extern const char* string_table[]; extern const int16_t* waveforms_table[]; extern const uint16_t* lookup_table_table[]; extern const uint32_t* lookup_table_32_table[]; extern const int16_t wav_gompertz[]; extern const int16_t wav_db[]; extern const uint16_t lut_env_linear[]; extern const uint16_t lut_env_expo[]; extern const uint16_t lut_env_quartic[]; extern const uint16_t lut_square_root[]; extern const uint16_t lut_svf_cutoff[]; extern const uint16_t lut_svf_damp[]; extern const uint16_t lut_2164_gain[]; extern const uint16_t lut_compressor_ratio[]; extern const uint16_t lut_soft_knee[]; extern const uint32_t lut_env_increments[]; extern const uint32_t lut_lp_coefficients[]; extern const uint32_t lut_exp2[]; extern const uint32_t lut_log2[]; extern const uint32_t lut_lorenz_rate[]; #define STR_DUMMY 0 // dummy #define WAV_GOMPERTZ 0 #define WAV_GOMPERTZ_SIZE 1025 #define WAV_DB 1 #define WAV_DB_SIZE 257 #define LUT_ENV_LINEAR 0 #define LUT_ENV_LINEAR_SIZE 257 #define LUT_ENV_EXPO 1 #define LUT_ENV_EXPO_SIZE 257 #define LUT_ENV_QUARTIC 2 #define LUT_ENV_QUARTIC_SIZE 257 #define LUT_SQUARE_ROOT 3 #define LUT_SQUARE_ROOT_SIZE 257 #define LUT_SVF_CUTOFF 4 #define LUT_SVF_CUTOFF_SIZE 257 #define LUT_SVF_DAMP 5 #define LUT_SVF_DAMP_SIZE 257 #define LUT_2164_GAIN 6 #define LUT_2164_GAIN_SIZE 257 #define LUT_COMPRESSOR_RATIO 7 #define LUT_COMPRESSOR_RATIO_SIZE 257 #define LUT_SOFT_KNEE 8 #define LUT_SOFT_KNEE_SIZE 257 #define LUT_ENV_INCREMENTS 0 #define LUT_ENV_INCREMENTS_SIZE 257 #define LUT_LP_COEFFICIENTS 1 #define LUT_LP_COEFFICIENTS_SIZE 640 #define LUT_EXP2 2 #define LUT_EXP2_SIZE 257 #define LUT_LOG2 3 #define LUT_LOG2_SIZE 257 #define LUT_LORENZ_RATE 4 #define LUT_LORENZ_RATE_SIZE 257 } // namespace streams #endif // STREAMS_RESOURCES_H_ ================================================ FILE: lib/streams/svf.cc ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // SVF used for modeling the bridged T-networks. #include "streams/svf.h" #include "stmlib/utils/dsp.h" #include "streams/resources.h" namespace streams { using namespace stmlib; void Svf::Init() { lp_ = 0; bp_ = 0; frequency_ = 33 << 7; resonance_ = 16384; dirty_ = true; } void Svf::Process(int32_t in) { if (dirty_) { f_ = Interpolate824(lut_svf_cutoff, frequency_ << 17); damp_ = Interpolate824(lut_svf_damp, resonance_ << 17); dirty_ = false; } int32_t f = f_; int32_t damp = damp_; int32_t notch = in - (bp_ * damp >> 15); lp_ += f * bp_ >> 15; CLIP(lp_) hp_ = notch - lp_; bp_ += f * hp_ >> 15; CLIP(bp_) CLIP(hp_) } } // namespace streams ================================================ FILE: lib/streams/svf.h ================================================ // Copyright 2013 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // SVF used for the envelope follower filter bank. #ifndef STREAMS_SVF_H_ #define STREAMS_SVF_H_ #include "stmlib/stmlib.h" namespace streams { class Svf { public: Svf() { } ~Svf() { } void Init(); void set_frequency(int16_t frequency) { dirty_ = dirty_ || (frequency_ != frequency); frequency_ = frequency; } void set_resonance(int16_t resonance) { resonance_ = resonance; dirty_ = true; } void Process(int32_t sample); inline int32_t lp() const { return lp_; } inline int32_t bp() const { return bp_; } inline int32_t hp() const { return hp_; } private: bool dirty_; int16_t frequency_; int16_t resonance_; int32_t f_; int32_t damp_; int32_t lp_; int32_t bp_; int32_t hp_; DISALLOW_COPY_AND_ASSIGN(Svf); }; } // namespace streams #endif // STREAMS_SVF_H_ ================================================ FILE: lib/streams/vactrol.cc ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Vactrol. #include "streams/vactrol.h" #include "stmlib/utils/dsp.h" #include "streams/gain.h" #include "streams/resources.h" namespace streams { using namespace stmlib; void Vactrol::Init() { state_[0] = 0; state_[1] = 0; state_[2] = 0; state_[3] = 0; excite_ = 0; } void Vactrol::Process( int16_t audio, int16_t excite, uint16_t* gain, uint16_t* frequency) { // Smooth frequency amount parameters. frequency_amount_ += (target_frequency_amount_ - frequency_amount_) >> 8; frequency_offset_ += (target_frequency_offset_ - frequency_offset_) >> 8; int32_t input; int32_t error; int64_t coefficient = 0; if (excite < 0) { excite = 0; } // Simple plucked mode. if (plucked_) { if (gate_ == false) { if (excite > kSchmittTriggerThreshold) { gate_ = true; state_[0] = 32767 << 16; state_[1] = 32767 << 16; } } else { if (excite < (kSchmittTriggerThreshold >> 1)) { gate_ = false; } } // Filter the excitation pulses. state_[0] -= static_cast( state_[0]) * fast_decay_coefficient_ >> 31; state_[1] -= static_cast( state_[1]) * decay_coefficient_ >> 31; // VCF envelope. error = state_[0] - state_[2]; coefficient = error > 0 ? fast_attack_coefficient_ : fast_decay_coefficient_; state_[2] += static_cast(error) * coefficient >> 31; // VCA envelope. error = state_[1] - state_[3]; coefficient = error > 0 ? fast_attack_coefficient_ : decay_coefficient_; // Increase the duration of the tail int64_t strength = error > 0 ? error : -error; coefficient = (coefficient >> 1) + (coefficient * strength >> 31); state_[3] += static_cast(error) * coefficient >> 31; uint16_t vcf_amount = state_[2] >> 16; uint16_t vca_mount = Interpolate1022(wav_gompertz, (state_[3] >> 2) * 3); *gain = kAboveUnityGain * vca_mount >> 15; *frequency = frequency_offset_ + \ (frequency_amount_ * vcf_amount >> 15); return; } // Low-pass filter the negative edges to prevent fast pulse to immediately // decay before the vactrol has started reacting. This allows the EXCITE // input to be used for both controlling the vactrol or just plucking it // from a trigger. error = excite - excite_; coefficient = error > 0 ? (1 << 30) : (decay_coefficient_ << 1); excite_ += static_cast(error) * coefficient >> 31; excite = excite_; input = frequency_offset_; input += frequency_amount_ >> 1; input = (65535 + input) >> 1; input *= excite; state_[3] += static_cast(input - state_[3]) * 67976239 >> 31; error = input - state_[0]; coefficient = 0; if (error > 0) { if (state_[1] > 0) { coefficient = attack_coefficient_; // Increase attack time when the photocell has been desensitized. coefficient += coefficient * (255 - (state_[2] >> 23)) >> 6; } else { coefficient = fast_attack_coefficient_; } } else { if (state_[1] < 0) { coefficient = decay_coefficient_; } else { coefficient = fast_decay_coefficient_; } } // First order. state_[0] += static_cast(error) * coefficient >> 31; // Second order. state_[1] += static_cast(error - state_[1]) * coefficient >> 31; // Memory effect. int32_t sensitivity = state_[0]; if (sensitivity > (1 << 28)) { sensitivity = 1 << 31; } else { sensitivity <<= 3; } error = sensitivity - state_[2]; if (error > 0) { // Get into the "sensitized" state in 1s. state_[2] += static_cast(error) * 138132 >> 31; } else { // Get out of the "sensitized" state in 60s. state_[2] += static_cast(error) * 1151 >> 31; } // Apply non-linearity. int32_t index = state_[0] >> 1; // A little hack to add overshoot... index += (state_[3] >> 15) * (state_[1] >> 15) >> 1; if (index < 0) { index = 0; } else if (index >= (1 << 30)) { index = (1 << 30) - 1; } uint16_t amplitude = index < 536870912 ? Interpolate1022(wav_gompertz, static_cast(index) << 3) : 32767; uint16_t cutoff = index >> 14; if (cutoff >= 32767) cutoff = 32767; cutoff = cutoff * cutoff >> 15; *gain = kAboveUnityGain * amplitude >> 15; *frequency = frequency_offset_ + \ (frequency_amount_ * cutoff >> 15); } } // namespace streams ================================================ FILE: lib/streams/vactrol.h ================================================ // Copyright 2014 Emilie Gillet. // // Author: Emilie Gillet (emilie.o.gillet@gmail.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ----------------------------------------------------------------------------- // // Vactrol. #ifndef STREAMS_VACTROL_H_ #define STREAMS_VACTROL_H_ #include "stmlib/stmlib.h" #include "streams/meta_parameters.h" #include "streams/resources.h" namespace streams { class Vactrol { public: Vactrol() { } ~Vactrol() { } void Init(); void Process( int16_t audio, int16_t excite, uint16_t* gain, uint16_t* frequency); void Configure(bool alternate, int32_t* parameters, int32_t* globals) { uint16_t attack_time; uint16_t decay_time; if (globals) { // Attack: 10ms to 1000ms attack_time = 128 + (globals[0] >> 8); // Decay: 10ms to 5000ms decay_time = 128 + (globals[2] * 355 >> 16); ComputeAmountOffset( parameters[1], &target_frequency_amount_, &target_frequency_offset_); } else { uint16_t shape = parameters[0]; ComputeAmountOffset( parameters[1], &target_frequency_amount_, &target_frequency_offset_); if (shape < 32768) { // attack: 10ms attack_time = 128; // decay: 50ms to 2000ms decay_time = 227 + (shape * 196 >> 15); } else if (shape < 49512) { shape -= 32768; // attack: 10ms to 500ms. attack_time = 128 + (shape * 227 >> 15); // decay: 2000ms to 1000ms. decay_time = 423 - (89 * shape >> 15); } else { shape -= 49512; // attack: 500ms to 50ms. attack_time = 355 - (shape >> 7); // decay: 1000ms to 100ms. decay_time = 384 - (128 * shape >> 15); } } attack_coefficient_ = lut_lp_coefficients[attack_time]; fast_attack_coefficient_ = lut_lp_coefficients[attack_time - 128]; decay_coefficient_ = lut_lp_coefficients[decay_time]; fast_decay_coefficient_ = lut_lp_coefficients[decay_time - 128]; plucked_ = alternate; if (alternate) { fast_attack_coefficient_ <<= 4; } else { decay_coefficient_ >>= 1; } int32_t ringing_tail = 8192; int32_t headroom = 65535 - target_frequency_offset_; if (ringing_tail > headroom) { ringing_tail = headroom; } if (ringing_tail > target_frequency_amount_) { ringing_tail = target_frequency_amount_; } target_frequency_offset_ += ringing_tail; target_frequency_amount_ -= ringing_tail; } private: int32_t target_frequency_amount_; int32_t target_frequency_offset_; int32_t frequency_amount_; int32_t frequency_offset_; int32_t attack_coefficient_; int32_t decay_coefficient_; int32_t fast_attack_coefficient_; int32_t fast_decay_coefficient_; int32_t state_[4]; int32_t excite_; bool gate_; bool plucked_; DISALLOW_COPY_AND_ASSIGN(Vactrol); }; } // namespace streams #endif // STREAMS_VACTROL_H_ ================================================ FILE: lib/xz_lzma2/xz.h ================================================ /* * XZ decompressor * * Authors: Lasse Collin * Igor Pavlov * * This file has been put into the public domain. * You can do whatever you want with this file. */ #ifndef XZ_H #define XZ_H #ifdef __KERNEL__ # include # include #else # include # include #endif #ifdef __cplusplus extern "C" { #endif /** * enum xz_mode - Operation mode * * @XZ_SINGLE: Single-call mode. This uses less RAM than * multi-call modes, because the LZMA2 * dictionary doesn't need to be allocated as * part of the decoder state. All required data * structures are allocated at initialization, * so xz_dec_run() cannot return XZ_MEM_ERROR. * @XZ_PREALLOC: Multi-call mode with preallocated LZMA2 * dictionary buffer. All data structures are * allocated at initialization, so xz_dec_run() * cannot return XZ_MEM_ERROR. * @XZ_DYNALLOC: Multi-call mode. The LZMA2 dictionary is * allocated once the required size has been * parsed from the stream headers. If the * allocation fails, xz_dec_run() will return * XZ_MEM_ERROR. * * It is possible to enable support only for a subset of the above * modes at compile time by defining XZ_DEC_SINGLE, XZ_DEC_PREALLOC, * or XZ_DEC_DYNALLOC. The xz_dec kernel module is always compiled * with support for all operation modes, but the preboot code may * be built with fewer features to minimize code size. */ enum xz_mode { XZ_SINGLE, XZ_PREALLOC, XZ_DYNALLOC }; /** * enum xz_ret - Return codes * @XZ_OK: Everything is OK so far. More input or more * output space is required to continue. This * return code is possible only in multi-call mode * (XZ_PREALLOC or XZ_DYNALLOC). * @XZ_STREAM_END: Operation finished successfully. * @XZ_UNSUPPORTED_CHECK: Integrity check type is not supported. Decoding * is still possible in multi-call mode by simply * calling xz_dec_run() again. * Note that this return value is used only if * XZ_DEC_ANY_CHECK was defined at build time, * which is not used in the kernel. Unsupported * check types return XZ_OPTIONS_ERROR if * XZ_DEC_ANY_CHECK was not defined at build time. * @XZ_MEM_ERROR: Allocating memory failed. This return code is * possible only if the decoder was initialized * with XZ_DYNALLOC. The amount of memory that was * tried to be allocated was no more than the * dict_max argument given to xz_dec_init(). * @XZ_MEMLIMIT_ERROR: A bigger LZMA2 dictionary would be needed than * allowed by the dict_max argument given to * xz_dec_init(). This return value is possible * only in multi-call mode (XZ_PREALLOC or * XZ_DYNALLOC); the single-call mode (XZ_SINGLE) * ignores the dict_max argument. * @XZ_FORMAT_ERROR: File format was not recognized (wrong magic * bytes). * @XZ_OPTIONS_ERROR: This implementation doesn't support the requested * compression options. In the decoder this means * that the header CRC32 matches, but the header * itself specifies something that we don't support. * @XZ_DATA_ERROR: Compressed data is corrupt. * @XZ_BUF_ERROR: Cannot make any progress. Details are slightly * different between multi-call and single-call * mode; more information below. * * In multi-call mode, XZ_BUF_ERROR is returned when two consecutive calls * to XZ code cannot consume any input and cannot produce any new output. * This happens when there is no new input available, or the output buffer * is full while at least one output byte is still pending. Assuming your * code is not buggy, you can get this error only when decoding a compressed * stream that is truncated or otherwise corrupt. * * In single-call mode, XZ_BUF_ERROR is returned only when the output buffer * is too small or the compressed input is corrupt in a way that makes the * decoder produce more output than the caller expected. When it is * (relatively) clear that the compressed input is truncated, XZ_DATA_ERROR * is used instead of XZ_BUF_ERROR. */ enum xz_ret { XZ_OK, XZ_STREAM_END, XZ_UNSUPPORTED_CHECK, XZ_MEM_ERROR, XZ_MEMLIMIT_ERROR, XZ_FORMAT_ERROR, XZ_OPTIONS_ERROR, XZ_DATA_ERROR, XZ_BUF_ERROR }; /** * struct xz_buf - Passing input and output buffers to XZ code * @in: Beginning of the input buffer. This may be NULL if and only * if in_pos is equal to in_size. * @in_pos: Current position in the input buffer. This must not exceed * in_size. * @in_size: Size of the input buffer * @out: Beginning of the output buffer. This may be NULL if and only * if out_pos is equal to out_size. * @out_pos: Current position in the output buffer. This must not exceed * out_size. * @out_size: Size of the output buffer * * Only the contents of the output buffer from out[out_pos] onward, and * the variables in_pos and out_pos are modified by the XZ code. */ struct xz_buf { const uint8_t *in; size_t in_pos; size_t in_size; uint8_t *out; size_t out_pos; size_t out_size; }; /** * struct xz_dec - Opaque type to hold the XZ decoder state */ struct xz_dec; /* * Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used * before calling xz_dec_lzma2_run(). */ struct xz_dec_lzma2 *xz_dec_lzma2_create(enum xz_mode mode, uint32_t dict_max); /* * Decode the LZMA2 properties (one byte) and reset the decoder. Return * XZ_OK on success, XZ_MEMLIMIT_ERROR if the preallocated dictionary is not * big enough, and XZ_OPTIONS_ERROR if props indicates something that this * decoder doesn't support. */ enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, uint8_t props); /* Decode raw LZMA2 stream from b->in to b->out. */ enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, struct xz_buf *b); /* Free the memory allocated for the LZMA2 decoder. */ void xz_dec_lzma2_end(struct xz_dec_lzma2 *s); #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/xz_lzma2/xz_config.h ================================================ /* * Private includes and definitions for userspace use of XZ Embedded * * Author: Lasse Collin * * This file has been put into the public domain. * You can do whatever you want with this file. */ #ifndef XZ_CONFIG_H #define XZ_CONFIG_H /* Uncomment to enable CRC64 support. */ /* #define XZ_USE_CRC64 */ /* Uncomment as needed to enable BCJ filter decoders. */ /* #define XZ_DEC_X86 */ /* #define XZ_DEC_POWERPC */ /* #define XZ_DEC_IA64 */ /* #define XZ_DEC_ARM */ /* #define XZ_DEC_ARMTHUMB */ /* #define XZ_DEC_SPARC */ /* * MSVC doesn't support modern C but XZ Embedded is mostly C89 * so these are enough. */ #ifdef _MSC_VER typedef unsigned char bool; # define true 1 # define false 0 # define inline __inline #else # include #endif #include #include #include "xz.h" void* xz_malloc(size_t s); void xz_free(void* p); #define kmalloc(size, flags) xz_malloc(size) #define kfree(ptr) xz_free(ptr) #define vmalloc(size) xz_malloc(size) #define vfree(ptr) xz_free(ptr) #define memeq(a, b, size) (memcmp(a, b, size) == 0) #define memzero(buf, size) memset(buf, 0, size) #ifndef min # define min(x, y) ((x) < (y) ? (x) : (y)) #endif #define min_t(type, x, y) min(x, y) /* * Some functions have been marked with __always_inline to keep the * performance reasonable even when the compiler is optimizing for * small code size. You may be able to save a few bytes by #defining * __always_inline to plain inline, but don't complain if the code * becomes slow. * * NOTE: System headers on GNU/Linux may #define this macro already, * so if you want to change it, you need to #undef it first. */ #ifndef __always_inline # ifdef __GNUC__ # define __always_inline \ inline __attribute__((__always_inline__)) # else # define __always_inline inline # endif #endif /* Inline functions to access unaligned unsigned 32-bit integers */ #ifndef get_unaligned_le32 static inline uint32_t get_unaligned_le32(const uint8_t *buf) { return (uint32_t)buf[0] | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[2] << 16) | ((uint32_t)buf[3] << 24); } #endif #ifndef get_unaligned_be32 static inline uint32_t get_unaligned_be32(const uint8_t *buf) { return (uint32_t)(buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | (uint32_t)buf[3]; } #endif #ifndef put_unaligned_le32 static inline void put_unaligned_le32(uint32_t val, uint8_t *buf) { buf[0] = (uint8_t)val; buf[1] = (uint8_t)(val >> 8); buf[2] = (uint8_t)(val >> 16); buf[3] = (uint8_t)(val >> 24); } #endif #ifndef put_unaligned_be32 static inline void put_unaligned_be32(uint32_t val, uint8_t *buf) { buf[0] = (uint8_t)(val >> 24); buf[1] = (uint8_t)(val >> 16); buf[2] = (uint8_t)(val >> 8); buf[3] = (uint8_t)val; } #endif /* * Use get_unaligned_le32() also for aligned access for simplicity. On * little endian systems, #define get_le32(ptr) (*(const uint32_t *)(ptr)) * could save a few bytes in code size. */ #ifndef get_le32 # define get_le32 get_unaligned_le32 #endif #endif ================================================ FILE: lib/xz_lzma2/xz_dec_lzma2.c ================================================ /* * LZMA2 decoder * * Authors: Lasse Collin * Igor Pavlov * * This file has been put into the public domain. * You can do whatever you want with this file. */ #include "xz_private.h" #include "xz_lzma2.h" /* * Range decoder initialization eats the first five bytes of each LZMA chunk. */ #define RC_INIT_BYTES 5 /* * Minimum number of usable input buffer to safely decode one LZMA symbol. * The worst case is that we decode 22 bits using probabilities and 26 * direct bits. This may decode at maximum of 20 bytes of input. However, * lzma_main() does an extra normalization before returning, thus we * need to put 21 here. */ #define LZMA_IN_REQUIRED 21 /* * Dictionary (history buffer) * * These are always true: * start <= pos <= full <= end * pos <= limit <= end * * In multi-call mode, also these are true: * end == size * size <= size_max * allocated <= size * * Most of these variables are size_t to support single-call mode, * in which the dictionary variables address the actual output * buffer directly. */ struct dictionary { /* Beginning of the history buffer */ uint8_t *buf; /* Old position in buf (before decoding more data) */ size_t start; /* Position in buf */ size_t pos; /* * How full dictionary is. This is used to detect corrupt input that * would read beyond the beginning of the uncompressed stream. */ size_t full; /* Write limit; we don't write to buf[limit] or later bytes. */ size_t limit; /* * End of the dictionary buffer. In multi-call mode, this is * the same as the dictionary size. In single-call mode, this * indicates the size of the output buffer. */ size_t end; /* * Size of the dictionary as specified in Block Header. This is used * together with "full" to detect corrupt input that would make us * read beyond the beginning of the uncompressed stream. */ uint32_t size; /* * Maximum allowed dictionary size in multi-call mode. * This is ignored in single-call mode. */ uint32_t size_max; /* * Amount of memory currently allocated for the dictionary. * This is used only with XZ_DYNALLOC. (With XZ_PREALLOC, * size_max is always the same as the allocated size.) */ uint32_t allocated; /* Operation mode */ enum xz_mode mode; }; /* Range decoder */ struct rc_dec { uint32_t range; uint32_t code; /* * Number of initializing bytes remaining to be read * by rc_read_init(). */ uint32_t init_bytes_left; /* * Buffer from which we read our input. It can be either * temp.buf or the caller-provided input buffer. */ const uint8_t *in; size_t in_pos; size_t in_limit; }; /* Probabilities for a length decoder. */ struct lzma_len_dec { /* Probability of match length being at least 10 */ uint16_t choice; /* Probability of match length being at least 18 */ uint16_t choice2; /* Probabilities for match lengths 2-9 */ uint16_t low[POS_STATES_MAX][LEN_LOW_SYMBOLS]; /* Probabilities for match lengths 10-17 */ uint16_t mid[POS_STATES_MAX][LEN_MID_SYMBOLS]; /* Probabilities for match lengths 18-273 */ uint16_t high[LEN_HIGH_SYMBOLS]; }; struct lzma_dec { /* Distances of latest four matches */ uint32_t rep0; uint32_t rep1; uint32_t rep2; uint32_t rep3; /* Types of the most recently seen LZMA symbols */ enum lzma_state state; /* * Length of a match. This is updated so that dict_repeat can * be called again to finish repeating the whole match. */ uint32_t len; /* * LZMA properties or related bit masks (number of literal * context bits, a mask dervied from the number of literal * position bits, and a mask dervied from the number * position bits) */ uint32_t lc; uint32_t literal_pos_mask; /* (1 << lp) - 1 */ uint32_t pos_mask; /* (1 << pb) - 1 */ /* If 1, it's a match. Otherwise it's a single 8-bit literal. */ uint16_t is_match[STATES][POS_STATES_MAX]; /* If 1, it's a repeated match. The distance is one of rep0 .. rep3. */ uint16_t is_rep[STATES]; /* * If 0, distance of a repeated match is rep0. * Otherwise check is_rep1. */ uint16_t is_rep0[STATES]; /* * If 0, distance of a repeated match is rep1. * Otherwise check is_rep2. */ uint16_t is_rep1[STATES]; /* If 0, distance of a repeated match is rep2. Otherwise it is rep3. */ uint16_t is_rep2[STATES]; /* * If 1, the repeated match has length of one byte. Otherwise * the length is decoded from rep_len_decoder. */ uint16_t is_rep0_long[STATES][POS_STATES_MAX]; /* * Probability tree for the highest two bits of the match * distance. There is a separate probability tree for match * lengths of 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273]. */ uint16_t dist_slot[DIST_STATES][DIST_SLOTS]; /* * Probility trees for additional bits for match distance * when the distance is in the range [4, 127]. */ uint16_t dist_special[FULL_DISTANCES - DIST_MODEL_END]; /* * Probability tree for the lowest four bits of a match * distance that is equal to or greater than 128. */ uint16_t dist_align[ALIGN_SIZE]; /* Length of a normal match */ struct lzma_len_dec match_len_dec; /* Length of a repeated match */ struct lzma_len_dec rep_len_dec; /* Probabilities of literals */ uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE]; }; struct lzma2_dec { /* Position in xz_dec_lzma2_run(). */ enum lzma2_seq { SEQ_CONTROL, SEQ_UNCOMPRESSED_1, SEQ_UNCOMPRESSED_2, SEQ_COMPRESSED_0, SEQ_COMPRESSED_1, SEQ_PROPERTIES, SEQ_LZMA_PREPARE, SEQ_LZMA_RUN, SEQ_COPY } sequence; /* Next position after decoding the compressed size of the chunk. */ enum lzma2_seq next_sequence; /* Uncompressed size of LZMA chunk (2 MiB at maximum) */ uint32_t uncompressed; /* * Compressed size of LZMA chunk or compressed/uncompressed * size of uncompressed chunk (64 KiB at maximum) */ uint32_t compressed; /* * True if dictionary reset is needed. This is false before * the first chunk (LZMA or uncompressed). */ bool need_dict_reset; /* * True if new LZMA properties are needed. This is false * before the first LZMA chunk. */ bool need_props; }; struct xz_dec_lzma2 { /* * The order below is important on x86 to reduce code size and * it shouldn't hurt on other platforms. Everything up to and * including lzma.pos_mask are in the first 128 bytes on x86-32, * which allows using smaller instructions to access those * variables. On x86-64, fewer variables fit into the first 128 * bytes, but this is still the best order without sacrificing * the readability by splitting the structures. */ struct rc_dec rc; struct dictionary dict; struct lzma2_dec lzma2; struct lzma_dec lzma; /* * Temporary buffer which holds small number of input bytes between * decoder calls. See lzma2_lzma() for details. */ struct { uint32_t size; uint8_t buf[3 * LZMA_IN_REQUIRED]; } temp; }; /************** * Dictionary * **************/ /* * Reset the dictionary state. When in single-call mode, set up the beginning * of the dictionary to point to the actual output buffer. */ static void dict_reset(struct dictionary *dict, struct xz_buf *b) { if (DEC_IS_SINGLE(dict->mode)) { dict->buf = b->out + b->out_pos; dict->end = b->out_size - b->out_pos; } dict->start = 0; dict->pos = 0; dict->limit = 0; dict->full = 0; } /* Set dictionary write limit */ static void dict_limit(struct dictionary *dict, size_t out_max) { if (dict->end - dict->pos <= out_max) dict->limit = dict->end; else dict->limit = dict->pos + out_max; } /* Return true if at least one byte can be written into the dictionary. */ static inline bool dict_has_space(const struct dictionary *dict) { return dict->pos < dict->limit; } /* * Get a byte from the dictionary at the given distance. The distance is * assumed to valid, or as a special case, zero when the dictionary is * still empty. This special case is needed for single-call decoding to * avoid writing a '\0' to the end of the destination buffer. */ static inline uint32_t dict_get(const struct dictionary *dict, uint32_t dist) { size_t offset = dict->pos - dist - 1; if (dist >= dict->pos) offset += dict->end; return dict->full > 0 ? dict->buf[offset] : 0; } /* * Put one byte into the dictionary. It is assumed that there is space for it. */ static inline void dict_put(struct dictionary *dict, uint8_t byte) { dict->buf[dict->pos++] = byte; if (dict->full < dict->pos) dict->full = dict->pos; } /* * Repeat given number of bytes from the given distance. If the distance is * invalid, false is returned. On success, true is returned and *len is * updated to indicate how many bytes were left to be repeated. */ static bool dict_repeat(struct dictionary *dict, uint32_t *len, uint32_t dist) { size_t back; uint32_t left; if (dist >= dict->full || dist >= dict->size) return false; left = min_t(size_t, dict->limit - dict->pos, *len); *len -= left; back = dict->pos - dist - 1; if (dist >= dict->pos) back += dict->end; do { dict->buf[dict->pos++] = dict->buf[back++]; if (back == dict->end) back = 0; } while (--left > 0); if (dict->full < dict->pos) dict->full = dict->pos; return true; } /* Copy uncompressed data as is from input to dictionary and output buffers. */ static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, uint32_t *left) { size_t copy_size; while (*left > 0 && b->in_pos < b->in_size && b->out_pos < b->out_size) { copy_size = min(b->in_size - b->in_pos, b->out_size - b->out_pos); if (copy_size > dict->end - dict->pos) copy_size = dict->end - dict->pos; if (copy_size > *left) copy_size = *left; *left -= copy_size; /* * If doing in-place decompression in single-call mode and the * uncompressed size of the file is larger than the caller * thought (i.e. it is invalid input!), the buffers below may * overlap and cause undefined behavior with memcpy(). * With valid inputs memcpy() would be fine here. */ memmove(dict->buf + dict->pos, b->in + b->in_pos, copy_size); dict->pos += copy_size; if (dict->full < dict->pos) dict->full = dict->pos; if (DEC_IS_MULTI(dict->mode)) { if (dict->pos == dict->end) dict->pos = 0; /* * Like above but for multi-call mode: use memmove() * to avoid undefined behavior with invalid input. */ memmove(b->out + b->out_pos, b->in + b->in_pos, copy_size); } dict->start = dict->pos; b->out_pos += copy_size; b->in_pos += copy_size; } } /* * Flush pending data from dictionary to b->out. It is assumed that there is * enough space in b->out. This is guaranteed because caller uses dict_limit() * before decoding data into the dictionary. */ static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b) { size_t copy_size = dict->pos - dict->start; if (DEC_IS_MULTI(dict->mode)) { if (dict->pos == dict->end) dict->pos = 0; /* * These buffers cannot overlap even if doing in-place * decompression because in multi-call mode dict->buf * has been allocated by us in this file; it's not * provided by the caller like in single-call mode. */ memcpy(b->out + b->out_pos, dict->buf + dict->start, copy_size); } dict->start = dict->pos; b->out_pos += copy_size; return copy_size; } /***************** * Range decoder * *****************/ /* Reset the range decoder. */ static void rc_reset(struct rc_dec *rc) { rc->range = (uint32_t)-1; rc->code = 0; rc->init_bytes_left = RC_INIT_BYTES; } /* * Read the first five initial bytes into rc->code if they haven't been * read already. (Yes, the first byte gets completely ignored.) */ static bool rc_read_init(struct rc_dec *rc, struct xz_buf *b) { while (rc->init_bytes_left > 0) { if (b->in_pos == b->in_size) return false; rc->code = (rc->code << 8) + b->in[b->in_pos++]; --rc->init_bytes_left; } return true; } /* Return true if there may not be enough input for the next decoding loop. */ static inline bool rc_limit_exceeded(const struct rc_dec *rc) { return rc->in_pos > rc->in_limit; } /* * Return true if it is possible (from point of view of range decoder) that * we have reached the end of the LZMA chunk. */ static inline bool rc_is_finished(const struct rc_dec *rc) { return rc->code == 0; } /* Read the next input byte if needed. */ static __always_inline void rc_normalize(struct rc_dec *rc) { if (rc->range < RC_TOP_VALUE) { rc->range <<= RC_SHIFT_BITS; rc->code = (rc->code << RC_SHIFT_BITS) + rc->in[rc->in_pos++]; } } /* * Decode one bit. In some versions, this function has been splitted in three * functions so that the compiler is supposed to be able to more easily avoid * an extra branch. In this particular version of the LZMA decoder, this * doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3 * on x86). Using a non-splitted version results in nicer looking code too. * * NOTE: This must return an int. Do not make it return a bool or the speed * of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care, * and it generates 10-20 % faster code than GCC 3.x from this file anyway.) */ static __always_inline int rc_bit(struct rc_dec *rc, uint16_t *prob) { uint32_t bound; int bit; rc_normalize(rc); bound = (rc->range >> RC_BIT_MODEL_TOTAL_BITS) * *prob; if (rc->code < bound) { rc->range = bound; *prob += (RC_BIT_MODEL_TOTAL - *prob) >> RC_MOVE_BITS; bit = 0; } else { rc->range -= bound; rc->code -= bound; *prob -= *prob >> RC_MOVE_BITS; bit = 1; } return bit; } /* Decode a bittree starting from the most significant bit. */ static __always_inline uint32_t rc_bittree(struct rc_dec *rc, uint16_t *probs, uint32_t limit) { uint32_t symbol = 1; do { if (rc_bit(rc, &probs[symbol])) symbol = (symbol << 1) + 1; else symbol <<= 1; } while (symbol < limit); return symbol; } /* Decode a bittree starting from the least significant bit. */ static __always_inline void rc_bittree_reverse(struct rc_dec *rc, uint16_t *probs, uint32_t *dest, uint32_t limit) { uint32_t symbol = 1; uint32_t i = 0; do { if (rc_bit(rc, &probs[symbol])) { symbol = (symbol << 1) + 1; *dest += 1 << i; } else { symbol <<= 1; } } while (++i < limit); } /* Decode direct bits (fixed fifty-fifty probability) */ static inline void rc_direct(struct rc_dec *rc, uint32_t *dest, uint32_t limit) { uint32_t mask; do { rc_normalize(rc); rc->range >>= 1; rc->code -= rc->range; mask = (uint32_t)0 - (rc->code >> 31); rc->code += rc->range & mask; *dest = (*dest << 1) + (mask + 1); } while (--limit > 0); } /******** * LZMA * ********/ /* Get pointer to literal coder probability array. */ static uint16_t *lzma_literal_probs(struct xz_dec_lzma2 *s) { uint32_t prev_byte = dict_get(&s->dict, 0); uint32_t low = prev_byte >> (8 - s->lzma.lc); uint32_t high = (s->dict.pos & s->lzma.literal_pos_mask) << s->lzma.lc; return s->lzma.literal[low + high]; } /* Decode a literal (one 8-bit byte) */ static void lzma_literal(struct xz_dec_lzma2 *s) { uint16_t *probs; uint32_t symbol; uint32_t match_byte; uint32_t match_bit; uint32_t offset; uint32_t i; probs = lzma_literal_probs(s); if (lzma_state_is_literal(s->lzma.state)) { symbol = rc_bittree(&s->rc, probs, 0x100); } else { symbol = 1; match_byte = dict_get(&s->dict, s->lzma.rep0) << 1; offset = 0x100; do { match_bit = match_byte & offset; match_byte <<= 1; i = offset + match_bit + symbol; if (rc_bit(&s->rc, &probs[i])) { symbol = (symbol << 1) + 1; offset &= match_bit; } else { symbol <<= 1; offset &= ~match_bit; } } while (symbol < 0x100); } dict_put(&s->dict, (uint8_t)symbol); lzma_state_literal(&s->lzma.state); } /* Decode the length of the match into s->lzma.len. */ static void lzma_len(struct xz_dec_lzma2 *s, struct lzma_len_dec *l, uint32_t pos_state) { uint16_t *probs; uint32_t limit; if (!rc_bit(&s->rc, &l->choice)) { probs = l->low[pos_state]; limit = LEN_LOW_SYMBOLS; s->lzma.len = MATCH_LEN_MIN; } else { if (!rc_bit(&s->rc, &l->choice2)) { probs = l->mid[pos_state]; limit = LEN_MID_SYMBOLS; s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS; } else { probs = l->high; limit = LEN_HIGH_SYMBOLS; s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; } } s->lzma.len += rc_bittree(&s->rc, probs, limit) - limit; } /* Decode a match. The distance will be stored in s->lzma.rep0. */ static void lzma_match(struct xz_dec_lzma2 *s, uint32_t pos_state) { uint16_t *probs; uint32_t dist_slot; uint32_t limit; lzma_state_match(&s->lzma.state); s->lzma.rep3 = s->lzma.rep2; s->lzma.rep2 = s->lzma.rep1; s->lzma.rep1 = s->lzma.rep0; lzma_len(s, &s->lzma.match_len_dec, pos_state); probs = s->lzma.dist_slot[lzma_get_dist_state(s->lzma.len)]; dist_slot = rc_bittree(&s->rc, probs, DIST_SLOTS) - DIST_SLOTS; if (dist_slot < DIST_MODEL_START) { s->lzma.rep0 = dist_slot; } else { limit = (dist_slot >> 1) - 1; s->lzma.rep0 = 2 + (dist_slot & 1); if (dist_slot < DIST_MODEL_END) { s->lzma.rep0 <<= limit; probs = s->lzma.dist_special + s->lzma.rep0 - dist_slot - 1; rc_bittree_reverse(&s->rc, probs, &s->lzma.rep0, limit); } else { rc_direct(&s->rc, &s->lzma.rep0, limit - ALIGN_BITS); s->lzma.rep0 <<= ALIGN_BITS; rc_bittree_reverse(&s->rc, s->lzma.dist_align, &s->lzma.rep0, ALIGN_BITS); } } } /* * Decode a repeated match. The distance is one of the four most recently * seen matches. The distance will be stored in s->lzma.rep0. */ static void lzma_rep_match(struct xz_dec_lzma2 *s, uint32_t pos_state) { uint32_t tmp; if (!rc_bit(&s->rc, &s->lzma.is_rep0[s->lzma.state])) { if (!rc_bit(&s->rc, &s->lzma.is_rep0_long[ s->lzma.state][pos_state])) { lzma_state_short_rep(&s->lzma.state); s->lzma.len = 1; return; } } else { if (!rc_bit(&s->rc, &s->lzma.is_rep1[s->lzma.state])) { tmp = s->lzma.rep1; } else { if (!rc_bit(&s->rc, &s->lzma.is_rep2[s->lzma.state])) { tmp = s->lzma.rep2; } else { tmp = s->lzma.rep3; s->lzma.rep3 = s->lzma.rep2; } s->lzma.rep2 = s->lzma.rep1; } s->lzma.rep1 = s->lzma.rep0; s->lzma.rep0 = tmp; } lzma_state_long_rep(&s->lzma.state); lzma_len(s, &s->lzma.rep_len_dec, pos_state); } /* LZMA decoder core */ static bool lzma_main(struct xz_dec_lzma2 *s) { uint32_t pos_state; /* * If the dictionary was reached during the previous call, try to * finish the possibly pending repeat in the dictionary. */ if (dict_has_space(&s->dict) && s->lzma.len > 0) dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0); /* * Decode more LZMA symbols. One iteration may consume up to * LZMA_IN_REQUIRED - 1 bytes. */ while (dict_has_space(&s->dict) && !rc_limit_exceeded(&s->rc)) { pos_state = s->dict.pos & s->lzma.pos_mask; if (!rc_bit(&s->rc, &s->lzma.is_match[ s->lzma.state][pos_state])) { lzma_literal(s); } else { if (rc_bit(&s->rc, &s->lzma.is_rep[s->lzma.state])) lzma_rep_match(s, pos_state); else lzma_match(s, pos_state); if (!dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0)) return false; } } /* * Having the range decoder always normalized when we are outside * this function makes it easier to correctly handle end of the chunk. */ rc_normalize(&s->rc); return true; } /* * Reset the LZMA decoder and range decoder state. Dictionary is nore reset * here, because LZMA state may be reset without resetting the dictionary. */ static void lzma_reset(struct xz_dec_lzma2 *s) { uint16_t *probs; size_t i; s->lzma.state = STATE_LIT_LIT; s->lzma.rep0 = 0; s->lzma.rep1 = 0; s->lzma.rep2 = 0; s->lzma.rep3 = 0; /* * All probabilities are initialized to the same value. This hack * makes the code smaller by avoiding a separate loop for each * probability array. * * This could be optimized so that only that part of literal * probabilities that are actually required. In the common case * we would write 12 KiB less. */ probs = s->lzma.is_match[0]; for (i = 0; i < PROBS_TOTAL; ++i) probs[i] = RC_BIT_MODEL_TOTAL / 2; rc_reset(&s->rc); } /* * Decode and validate LZMA properties (lc/lp/pb) and calculate the bit masks * from the decoded lp and pb values. On success, the LZMA decoder state is * reset and true is returned. */ static bool lzma_props(struct xz_dec_lzma2 *s, uint8_t props) { if (props > (4 * 5 + 4) * 9 + 8) return false; s->lzma.pos_mask = 0; while (props >= 9 * 5) { props -= 9 * 5; ++s->lzma.pos_mask; } s->lzma.pos_mask = (1 << s->lzma.pos_mask) - 1; s->lzma.literal_pos_mask = 0; while (props >= 9) { props -= 9; ++s->lzma.literal_pos_mask; } s->lzma.lc = props; if (s->lzma.lc + s->lzma.literal_pos_mask > 4) return false; s->lzma.literal_pos_mask = (1 << s->lzma.literal_pos_mask) - 1; lzma_reset(s); return true; } /********* * LZMA2 * *********/ /* * The LZMA decoder assumes that if the input limit (s->rc.in_limit) hasn't * been exceeded, it is safe to read up to LZMA_IN_REQUIRED bytes. This * wrapper function takes care of making the LZMA decoder's assumption safe. * * As long as there is plenty of input left to be decoded in the current LZMA * chunk, we decode directly from the caller-supplied input buffer until * there's LZMA_IN_REQUIRED bytes left. Those remaining bytes are copied into * s->temp.buf, which (hopefully) gets filled on the next call to this * function. We decode a few bytes from the temporary buffer so that we can * continue decoding from the caller-supplied input buffer again. */ static bool lzma2_lzma(struct xz_dec_lzma2 *s, struct xz_buf *b) { size_t in_avail; uint32_t tmp; in_avail = b->in_size - b->in_pos; if (s->temp.size > 0 || s->lzma2.compressed == 0) { tmp = 2 * LZMA_IN_REQUIRED - s->temp.size; if (tmp > s->lzma2.compressed - s->temp.size) tmp = s->lzma2.compressed - s->temp.size; if (tmp > in_avail) tmp = in_avail; memcpy(s->temp.buf + s->temp.size, b->in + b->in_pos, tmp); if (s->temp.size + tmp == s->lzma2.compressed) { memzero(s->temp.buf + s->temp.size + tmp, sizeof(s->temp.buf) - s->temp.size - tmp); s->rc.in_limit = s->temp.size + tmp; } else if (s->temp.size + tmp < LZMA_IN_REQUIRED) { s->temp.size += tmp; b->in_pos += tmp; return true; } else { s->rc.in_limit = s->temp.size + tmp - LZMA_IN_REQUIRED; } s->rc.in = s->temp.buf; s->rc.in_pos = 0; if (!lzma_main(s) || s->rc.in_pos > s->temp.size + tmp) return false; s->lzma2.compressed -= s->rc.in_pos; if (s->rc.in_pos < s->temp.size) { s->temp.size -= s->rc.in_pos; memmove(s->temp.buf, s->temp.buf + s->rc.in_pos, s->temp.size); return true; } b->in_pos += s->rc.in_pos - s->temp.size; s->temp.size = 0; } in_avail = b->in_size - b->in_pos; if (in_avail >= LZMA_IN_REQUIRED) { s->rc.in = b->in; s->rc.in_pos = b->in_pos; if (in_avail >= s->lzma2.compressed + LZMA_IN_REQUIRED) s->rc.in_limit = b->in_pos + s->lzma2.compressed; else s->rc.in_limit = b->in_size - LZMA_IN_REQUIRED; if (!lzma_main(s)) return false; in_avail = s->rc.in_pos - b->in_pos; if (in_avail > s->lzma2.compressed) return false; s->lzma2.compressed -= in_avail; b->in_pos = s->rc.in_pos; } in_avail = b->in_size - b->in_pos; if (in_avail < LZMA_IN_REQUIRED) { if (in_avail > s->lzma2.compressed) in_avail = s->lzma2.compressed; memcpy(s->temp.buf, b->in + b->in_pos, in_avail); s->temp.size = in_avail; b->in_pos += in_avail; } return true; } /* * Take care of the LZMA2 control layer, and forward the job of actual LZMA * decoding or copying of uncompressed chunks to other functions. */ enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, struct xz_buf *b) { uint32_t tmp; while (b->in_pos < b->in_size || s->lzma2.sequence == SEQ_LZMA_RUN) { switch (s->lzma2.sequence) { case SEQ_CONTROL: /* * LZMA2 control byte * * Exact values: * 0x00 End marker * 0x01 Dictionary reset followed by * an uncompressed chunk * 0x02 Uncompressed chunk (no dictionary reset) * * Highest three bits (s->control & 0xE0): * 0xE0 Dictionary reset, new properties and state * reset, followed by LZMA compressed chunk * 0xC0 New properties and state reset, followed * by LZMA compressed chunk (no dictionary * reset) * 0xA0 State reset using old properties, * followed by LZMA compressed chunk (no * dictionary reset) * 0x80 LZMA chunk (no dictionary or state reset) * * For LZMA compressed chunks, the lowest five bits * (s->control & 1F) are the highest bits of the * uncompressed size (bits 16-20). * * A new LZMA2 stream must begin with a dictionary * reset. The first LZMA chunk must set new * properties and reset the LZMA state. * * Values that don't match anything described above * are invalid and we return XZ_DATA_ERROR. */ tmp = b->in[b->in_pos++]; if (tmp == 0x00) return XZ_STREAM_END; if (tmp >= 0xE0 || tmp == 0x01) { s->lzma2.need_props = true; s->lzma2.need_dict_reset = false; dict_reset(&s->dict, b); } else if (s->lzma2.need_dict_reset) { return XZ_DATA_ERROR; } if (tmp >= 0x80) { s->lzma2.uncompressed = (tmp & 0x1F) << 16; s->lzma2.sequence = SEQ_UNCOMPRESSED_1; if (tmp >= 0xC0) { /* * When there are new properties, * state reset is done at * SEQ_PROPERTIES. */ s->lzma2.need_props = false; s->lzma2.next_sequence = SEQ_PROPERTIES; } else if (s->lzma2.need_props) { return XZ_DATA_ERROR; } else { s->lzma2.next_sequence = SEQ_LZMA_PREPARE; if (tmp >= 0xA0) lzma_reset(s); } } else { if (tmp > 0x02) return XZ_DATA_ERROR; s->lzma2.sequence = SEQ_COMPRESSED_0; s->lzma2.next_sequence = SEQ_COPY; } break; case SEQ_UNCOMPRESSED_1: s->lzma2.uncompressed += (uint32_t)b->in[b->in_pos++] << 8; s->lzma2.sequence = SEQ_UNCOMPRESSED_2; break; case SEQ_UNCOMPRESSED_2: s->lzma2.uncompressed += (uint32_t)b->in[b->in_pos++] + 1; s->lzma2.sequence = SEQ_COMPRESSED_0; break; case SEQ_COMPRESSED_0: s->lzma2.compressed = (uint32_t)b->in[b->in_pos++] << 8; s->lzma2.sequence = SEQ_COMPRESSED_1; break; case SEQ_COMPRESSED_1: s->lzma2.compressed += (uint32_t)b->in[b->in_pos++] + 1; s->lzma2.sequence = s->lzma2.next_sequence; break; case SEQ_PROPERTIES: if (!lzma_props(s, b->in[b->in_pos++])) return XZ_DATA_ERROR; s->lzma2.sequence = SEQ_LZMA_PREPARE; /* Fall through */ case SEQ_LZMA_PREPARE: if (s->lzma2.compressed < RC_INIT_BYTES) return XZ_DATA_ERROR; if (!rc_read_init(&s->rc, b)) return XZ_OK; s->lzma2.compressed -= RC_INIT_BYTES; s->lzma2.sequence = SEQ_LZMA_RUN; /* Fall through */ case SEQ_LZMA_RUN: /* * Set dictionary limit to indicate how much we want * to be encoded at maximum. Decode new data into the * dictionary. Flush the new data from dictionary to * b->out. Check if we finished decoding this chunk. * In case the dictionary got full but we didn't fill * the output buffer yet, we may run this loop * multiple times without changing s->lzma2.sequence. */ dict_limit(&s->dict, min_t(size_t, b->out_size - b->out_pos, s->lzma2.uncompressed)); if (!lzma2_lzma(s, b)) return XZ_DATA_ERROR; s->lzma2.uncompressed -= dict_flush(&s->dict, b); if (s->lzma2.uncompressed == 0) { if (s->lzma2.compressed > 0 || s->lzma.len > 0 || !rc_is_finished(&s->rc)) return XZ_DATA_ERROR; rc_reset(&s->rc); s->lzma2.sequence = SEQ_CONTROL; } else if (b->out_pos == b->out_size || (b->in_pos == b->in_size && s->temp.size < s->lzma2.compressed)) { return XZ_OK; } break; case SEQ_COPY: dict_uncompressed(&s->dict, b, &s->lzma2.compressed); if (s->lzma2.compressed > 0) return XZ_OK; s->lzma2.sequence = SEQ_CONTROL; break; } } return XZ_OK; } struct xz_dec_lzma2 *xz_dec_lzma2_create(enum xz_mode mode, uint32_t dict_max) { struct xz_dec_lzma2 *s = kmalloc(sizeof(*s), GFP_KERNEL); if (s == NULL) return NULL; s->dict.mode = mode; s->dict.size_max = dict_max; if (DEC_IS_PREALLOC(mode)) { s->dict.buf = vmalloc(dict_max); if (s->dict.buf == NULL) { kfree(s); return NULL; } } else if (DEC_IS_DYNALLOC(mode)) { s->dict.buf = NULL; s->dict.allocated = 0; } return s; } enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, uint8_t props) { /* This limits dictionary size to 3 GiB to keep parsing simpler. */ if (props > 39) return XZ_OPTIONS_ERROR; s->dict.size = 2 + (props & 1); s->dict.size <<= (props >> 1) + 11; if (DEC_IS_MULTI(s->dict.mode)) { if (s->dict.size > s->dict.size_max) return XZ_MEMLIMIT_ERROR; s->dict.end = s->dict.size; if (DEC_IS_DYNALLOC(s->dict.mode)) { if (s->dict.allocated < s->dict.size) { s->dict.allocated = s->dict.size; vfree(s->dict.buf); s->dict.buf = vmalloc(s->dict.size); if (s->dict.buf == NULL) { s->dict.allocated = 0; return XZ_MEM_ERROR; } } } } s->lzma.len = 0; s->lzma2.sequence = SEQ_CONTROL; s->lzma2.need_dict_reset = true; s->temp.size = 0; return XZ_OK; } void xz_dec_lzma2_end(struct xz_dec_lzma2 *s) { if (DEC_IS_MULTI(s->dict.mode)) vfree(s->dict.buf); kfree(s); } ================================================ FILE: lib/xz_lzma2/xz_lzma2.h ================================================ /* * LZMA2 definitions * * Authors: Lasse Collin * Igor Pavlov * * This file has been put into the public domain. * You can do whatever you want with this file. */ #ifndef XZ_LZMA2_H #define XZ_LZMA2_H /* Range coder constants */ #define RC_SHIFT_BITS 8 #define RC_TOP_BITS 24 #define RC_TOP_VALUE (1 << RC_TOP_BITS) #define RC_BIT_MODEL_TOTAL_BITS 11 #define RC_BIT_MODEL_TOTAL (1 << RC_BIT_MODEL_TOTAL_BITS) #define RC_MOVE_BITS 5 /* * Maximum number of position states. A position state is the lowest pb * number of bits of the current uncompressed offset. In some places there * are different sets of probabilities for different position states. */ #define POS_STATES_MAX (1 << 4) /* * This enum is used to track which LZMA symbols have occurred most recently * and in which order. This information is used to predict the next symbol. * * Symbols: * - Literal: One 8-bit byte * - Match: Repeat a chunk of data at some distance * - Long repeat: Multi-byte match at a recently seen distance * - Short repeat: One-byte repeat at a recently seen distance * * The symbol names are in from STATE_oldest_older_previous. REP means * either short or long repeated match, and NONLIT means any non-literal. */ enum lzma_state { STATE_LIT_LIT, STATE_MATCH_LIT_LIT, STATE_REP_LIT_LIT, STATE_SHORTREP_LIT_LIT, STATE_MATCH_LIT, STATE_REP_LIT, STATE_SHORTREP_LIT, STATE_LIT_MATCH, STATE_LIT_LONGREP, STATE_LIT_SHORTREP, STATE_NONLIT_MATCH, STATE_NONLIT_REP }; /* Total number of states */ #define STATES 12 /* The lowest 7 states indicate that the previous state was a literal. */ #define LIT_STATES 7 /* Indicate that the latest symbol was a literal. */ static inline void lzma_state_literal(enum lzma_state *state) { if (*state <= STATE_SHORTREP_LIT_LIT) *state = STATE_LIT_LIT; else if (*state <= STATE_LIT_SHORTREP) *state -= 3; else *state -= 6; } /* Indicate that the latest symbol was a match. */ static inline void lzma_state_match(enum lzma_state *state) { *state = *state < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH; } /* Indicate that the latest state was a long repeated match. */ static inline void lzma_state_long_rep(enum lzma_state *state) { *state = *state < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP; } /* Indicate that the latest symbol was a short match. */ static inline void lzma_state_short_rep(enum lzma_state *state) { *state = *state < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP; } /* Test if the previous symbol was a literal. */ static inline bool lzma_state_is_literal(enum lzma_state state) { return state < LIT_STATES; } /* Each literal coder is divided in three sections: * - 0x001-0x0FF: Without match byte * - 0x101-0x1FF: With match byte; match bit is 0 * - 0x201-0x2FF: With match byte; match bit is 1 * * Match byte is used when the previous LZMA symbol was something else than * a literal (that is, it was some kind of match). */ #define LITERAL_CODER_SIZE 0x300 /* Maximum number of literal coders */ #define LITERAL_CODERS_MAX (1 << 4) /* Minimum length of a match is two bytes. */ #define MATCH_LEN_MIN 2 /* Match length is encoded with 4, 5, or 10 bits. * * Length Bits * 2-9 4 = Choice=0 + 3 bits * 10-17 5 = Choice=1 + Choice2=0 + 3 bits * 18-273 10 = Choice=1 + Choice2=1 + 8 bits */ #define LEN_LOW_BITS 3 #define LEN_LOW_SYMBOLS (1 << LEN_LOW_BITS) #define LEN_MID_BITS 3 #define LEN_MID_SYMBOLS (1 << LEN_MID_BITS) #define LEN_HIGH_BITS 8 #define LEN_HIGH_SYMBOLS (1 << LEN_HIGH_BITS) #define LEN_SYMBOLS (LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS + LEN_HIGH_SYMBOLS) /* * Maximum length of a match is 273 which is a result of the encoding * described above. */ #define MATCH_LEN_MAX (MATCH_LEN_MIN + LEN_SYMBOLS - 1) /* * Different sets of probabilities are used for match distances that have * very short match length: Lengths of 2, 3, and 4 bytes have a separate * set of probabilities for each length. The matches with longer length * use a shared set of probabilities. */ #define DIST_STATES 4 /* * Get the index of the appropriate probability array for decoding * the distance slot. */ static inline uint32_t lzma_get_dist_state(uint32_t len) { return len < DIST_STATES + MATCH_LEN_MIN ? len - MATCH_LEN_MIN : DIST_STATES - 1; } /* * The highest two bits of a 32-bit match distance are encoded using six bits. * This six-bit value is called a distance slot. This way encoding a 32-bit * value takes 6-36 bits, larger values taking more bits. */ #define DIST_SLOT_BITS 6 #define DIST_SLOTS (1 << DIST_SLOT_BITS) /* Match distances up to 127 are fully encoded using probabilities. Since * the highest two bits (distance slot) are always encoded using six bits, * the distances 0-3 don't need any additional bits to encode, since the * distance slot itself is the same as the actual distance. DIST_MODEL_START * indicates the first distance slot where at least one additional bit is * needed. */ #define DIST_MODEL_START 4 /* * Match distances greater than 127 are encoded in three pieces: * - distance slot: the highest two bits * - direct bits: 2-26 bits below the highest two bits * - alignment bits: four lowest bits * * Direct bits don't use any probabilities. * * The distance slot value of 14 is for distances 128-191. */ #define DIST_MODEL_END 14 /* Distance slots that indicate a distance <= 127. */ #define FULL_DISTANCES_BITS (DIST_MODEL_END / 2) #define FULL_DISTANCES (1 << FULL_DISTANCES_BITS) /* * For match distances greater than 127, only the highest two bits and the * lowest four bits (alignment) is encoded using probabilities. */ #define ALIGN_BITS 4 #define ALIGN_SIZE (1 << ALIGN_BITS) #define ALIGN_MASK (ALIGN_SIZE - 1) /* Total number of all probability variables */ #define PROBS_TOTAL (1846 + LITERAL_CODERS_MAX * LITERAL_CODER_SIZE) /* * LZMA remembers the four most recent match distances. Reusing these * distances tends to take less space than re-encoding the actual * distance value. */ #define REPS 4 #endif ================================================ FILE: lib/xz_lzma2/xz_private.h ================================================ /* * Private includes and definitions * * Author: Lasse Collin * * This file has been put into the public domain. * You can do whatever you want with this file. */ #ifndef XZ_PRIVATE_H #define XZ_PRIVATE_H #include "xz_config.h" /* If no specific decoding mode is requested, enable support for all modes. */ #if !defined(XZ_DEC_SINGLE) && !defined(XZ_DEC_PREALLOC) \ && !defined(XZ_DEC_DYNALLOC) # define XZ_DEC_SINGLE # define XZ_DEC_PREALLOC # define XZ_DEC_DYNALLOC #endif /* * The DEC_IS_foo(mode) macros are used in "if" statements. If only some * of the supported modes are enabled, these macros will evaluate to true or * false at compile time and thus allow the compiler to omit unneeded code. */ #ifdef XZ_DEC_SINGLE # define DEC_IS_SINGLE(mode) ((mode) == XZ_SINGLE) #else # define DEC_IS_SINGLE(mode) (false) #endif #ifdef XZ_DEC_PREALLOC # define DEC_IS_PREALLOC(mode) ((mode) == XZ_PREALLOC) #else # define DEC_IS_PREALLOC(mode) (false) #endif #ifdef XZ_DEC_DYNALLOC # define DEC_IS_DYNALLOC(mode) ((mode) == XZ_DYNALLOC) #else # define DEC_IS_DYNALLOC(mode) (false) #endif #if !defined(XZ_DEC_SINGLE) # define DEC_IS_MULTI(mode) (true) #elif defined(XZ_DEC_PREALLOC) || defined(XZ_DEC_DYNALLOC) # define DEC_IS_MULTI(mode) ((mode) != XZ_SINGLE) #else # define DEC_IS_MULTI(mode) (false) #endif /* * Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used * before calling xz_dec_lzma2_run(). */ struct xz_dec_lzma2 *xz_dec_lzma2_create(enum xz_mode mode, uint32_t dict_max); /* * Decode the LZMA2 properties (one byte) and reset the decoder. Return * XZ_OK on success, XZ_MEMLIMIT_ERROR if the preallocated dictionary is not * big enough, and XZ_OPTIONS_ERROR if props indicates something that this * decoder doesn't support. */ enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, uint8_t props); /* Decode raw LZMA2 stream from b->in to b->out. */ enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, struct xz_buf *b); /* Free the memory allocated for the LZMA2 decoder. */ void xz_dec_lzma2_end(struct xz_dec_lzma2 *s); #endif ================================================ FILE: src/CV/EnvFollower.cpp ================================================ // Copyright (C)2021 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ENGINE_NAME:CV/EnvFollower;CV/Vactrol #include "../squares-and-circles-api.h" #include "../../lib/streams/follower.h" #include "../../lib/streams/vactrol.h" #include "../../lib/streams/audio_cv_meter.h" streams::Follower _follower; streams::Vactrol _vactrol; streams::AudioCvMeter _meter; int32_t attack_ = 0; int32_t decay_ = 0; int32_t mode_ = 0; float scale = 0.5f; float offset = 0; int16_t* out_cv = nullptr; struct { int8_t scope[128] = {}; int i = 0; void draw(int x0, int y) { for (int x = x0; x < 127; x++) { if (x % 3 == 0) gfx::setPixel(x, y); gfx::drawLine(x, y - scope[(i + x) % 128], x + 1, y - scope[(1 + i + x) % 128]); } } void push(int y) { scope[i++ % 128] = y; if (i > 127) i = 0; } } _scope; const char *mode_names[] = { "Follower", "Vactrol", ""}; void engine::setup() { if (!strcmp(engine::name(), "CV/Vactrol")) mode_ = 1; engine::addParam("Attack", &attack_, 0, UINT16_MAX); engine::addParam("AttVer", &scale, -1, 1); engine::addParam("Decay", &decay_, 0, INT16_MAX); engine::addParam("Offset", &offset, -1, 1); out_cv = engine::outputBuffer_i16(OUT_CV); decay_ = INT16_MAX / 2; engine::setMode(ENGINE_MODE_COMPACT); _meter.Init(); _follower.Init(); _vactrol.Init(); } void engine::process() { auto inputL = engine::inputBuffer<0>(); uint16_t gain; uint16_t freq; int32_t paramters[3] = {}; int32_t globals[3] = {}; globals[0] = attack_; globals[2] = decay_; paramters[1] = 0; if (mode_ == 0) { _follower.Configure(false, paramters, globals); for (int i = 0; i < FRAME_BUFFER_SIZE; i++) { _follower.Process(0, inputL[i] * INT16_MAX, &gain, &freq); out_cv[i] = gain >> 1; //_follower.process(inputL[i]) * 10.f; } } else { _vactrol.Configure(false, paramters, globals); for (int i = 0; i < FRAME_BUFFER_SIZE; i++) { _vactrol.Process(0, inputL[i] * INT16_MAX, &gain, &freq); out_cv[i] = gain >> 1; //_follower.process(inputL[i]) * 10.f; } } _meter.Process(inputL[0] * INT16_MAX); if ((engine::t() % 50) == 0) { int8_t v = out_cv[0] >> 9; CONSTRAIN(v, 0, 14); _scope.push(v); } for (int i = 0; i < FRAME_BUFFER_SIZE; i++) { out_cv[i] *= scale; out_cv[i] += (offset * PITCH_PER_OCTAVE * 5); } } void engine::draw() { _scope.draw(64, 58); gfx::drawRect(64, 44, 64, 15); gfx::drawRect(0, 44, 63, 15); gfx::fillRect(2, 46, (_meter.peak() >> 8), 11); } #include "../../lib/streams/svf.cc" #include "../../lib/streams/follower.cc" #include "../../lib/streams/vactrol.cc" #include "../../lib/streams/resources.cc" ================================================ FILE: src/CV/EnvGen.cpp ================================================ // Copyright (C)2021 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ENGINE_NAME:CV/EnvGen_AD;CV/EnvGen_ADSR // build_flags: -fno-inline -mfloat-abi=hard -mfpu=fpv5-d16 #include "../squares-and-circles-api.h" #define private public #include "lib/peaks/modulations/multistage_envelope.h" #include "lib/stmlib/utils/dsp.h" #include #ifndef PEAKS_RESOURCES_H_ #include "lib/peaks/modulations/multistage_envelope.cc" #include "lib/peaks/resources.cc" #endif peaks::MultistageEnvelope _processor; int32_t _attack = 0; int32_t _decay = UINT16_MAX / 2; int32_t _sustain = UINT16_MAX / 2; int32_t _release = UINT16_MAX / 2; float scale = 1.0f; float offset = 0; float scale2 = 0; float offset2 = 0; int32_t output = 0; int16_t* out_cv = nullptr; void engine::setup() { _processor.Init(); if (!strcmp(engine::name(), "CV/EnvGen_ADSR")) { engine::addParam("Attack", &_attack, 0, UINT16_MAX); engine::addParam("Decay", &_decay, 0, UINT16_MAX); engine::addParam("Sustain", &_sustain, 0, UINT16_MAX); engine::addParam("Release", &_release, 0, UINT16_MAX); engine::addParam("@Scale\n%+.1f", &scale, -1, 1); engine::addParam("@Offset\n%+.1fV", &offset, -5, 5); } else { engine::addParam("Attack", &_attack, 0, UINT16_MAX); engine::addParam("Decay", &_decay, 0, UINT16_MAX); engine::addParam("@Scale\n%+.1f", &scale, -2, 2); engine::addParam("@Offset\n%+.1fV", &offset, -5, 5); // AD - Mode _sustain = -1; _release = -1; } out_cv = engine::outputBuffer_i16(OUT_CV); engine::setMode(ENGINE_MODE_COMPACT); } void engine::process() { peaks::GateFlags flags[FRAME_BUFFER_SIZE]; uint16_t params[4]; scale2 = scale; offset2 = offset; params[0] = _attack; params[1] = _decay; if (_sustain >= 0) { params[2] = _sustain; params[3] = _release; _processor.Configure(params, peaks::CONTROL_MODE_FULL); } else { // AD - Mode _processor.Configure(params, peaks::CONTROL_MODE_HALF); } if (engine::trig()) { flags[0] = peaks::GATE_FLAG_RISING; std::fill(&flags[1], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_HIGH); } else if (engine::gate()) { std::fill(&flags[0], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_HIGH); } else { flags[0] = flags[0] == peaks::GATE_FLAG_HIGH ? peaks::GATE_FLAG_FALLING : peaks::GATE_FLAG_LOW; std::fill(&flags[1], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_LOW); } _processor.Process(flags, out_cv, FRAME_BUFFER_SIZE); output = out_cv[0]; for (int i = 0; i < FRAME_BUFFER_SIZE; i++) { out_cv[i] *= scale / 4.f; out_cv[i] += (offset * PITCH_PER_OCTAVE); } } void draw_envelope(int base_line = 58, int height = 16) { float sum_time = 0; for (size_t segment = 0; segment < _processor.num_segments_; segment++) sum_time += _processor.time_[segment]; float x = 0; for (size_t segment = 0; segment < _processor.segment_; segment++) x += _processor.time_[segment]; x += (float)_processor.phase_ / UINT32_MAX * _processor.time_[_processor.segment_]; x *= (128.f / sum_time); int last_y = 0; for (int i = 0; i < 127; i++) { int segment = 0; uint32_t phase = 0; float j = sum_time * (i + 1) / 128.f; for (segment = 0; segment < _processor.num_segments_; segment++) { if (j <= _processor.time_[segment]) { phase = j / _processor.time_[segment] * UINT32_MAX; break; } j -= _processor.time_[segment]; } int32_t start = _processor.level_[segment]; int32_t end = _processor.level_[segment + 1]; const uint16_t *lutt[] = {peaks::lut_env_linear, peaks::lut_env_expo, peaks::lut_env_quartic}; uint16_t t = stmlib::Interpolate824(lutt[_processor.shape_[segment]], phase); int16_t y = start + ((end - start) * (t >> 1) >> 15); y = ceil((float)y / INT16_MAX * height); int16_t y2 = ceil(1 + (float)output / INT16_MAX * height); gfx::drawLine(x, base_line, x, base_line - height); gfx::drawLine(i, base_line - last_y, i + 1, base_line - y); last_y = y; } } void engine::draw() { if (_processor.num_segments_ <= 2) { int gnd = 58; if (scale2 < 0) gnd -= 16; CONSTRAIN(scale2, -1, 1); draw_envelope(gnd, 16 * scale2); for (int i = 0; i < 127; i += 2) gfx::setPixel(i, gnd); } } void engine::screensaver() { gfx::clearRect(0, 0, 128, 64); for (int i = 0; i < 127; i += 2) gfx::setPixel(i, 32); draw_envelope(32 - (offset2 / 5 * 32), 32 * scale2); } ================================================ FILE: src/CV/LFO.cpp ================================================ // Copyright (C)2021 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // build_flags: -fno-inline -mfloat-abi=hard -mfpu=fpv5-d16 #include "../squares-and-circles-api.h" #include "lib/peaks/modulations/lfo.h" #include "lib/peaks/modulations/lfo.cc" #include "lib/peaks/resources.cc" #include "lib/stmlib/utils/random.cc" peaks::Lfo _processor; int32_t shape = peaks::LFO_SHAPE_SINE; int32_t rate = -INT16_MIN; int32_t waveform = -INT16_MIN; float scale = 0.5f; float offset = 0; int16_t* out_cv = nullptr; const char *shape_names[] = {"SIN", "TRI", "SQR", "STEPS", "NOISE"}; void engine::setup() { _processor.Init(); _processor.set_level(UINT16_MAX); _processor.set_rate(rate); _processor.set_parameter((waveform - 32768)); _processor.set_reset_phase(-INT16_MIN - 32768); engine::addParam("Freq.", &rate, 0, UINT16_MAX); engine::addParam("Shape", &shape, 0, peaks::LFO_SHAPE_LAST - 1, shape_names); engine::addParam("AttVer", &scale, -0.5f, 0.5f); engine::addParam("Wavefrm", &waveform, 0, UINT16_MAX); engine::addParam("Offset", &offset, -1, 1); out_cv = engine::outputBuffer_i16(OUT_CV); engine::setMode(ENGINE_MODE_COMPACT); } void engine::process() { peaks::GateFlags flags[FRAME_BUFFER_SIZE]; _processor.set_shape((peaks::LfoShape)shape); _processor.set_rate(rate); _processor.set_parameter((waveform - 32768)); if (engine::trig()) { flags[0] = peaks::GATE_FLAG_RISING; std::fill(&flags[1], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_HIGH); } else if (engine::gate()) { std::fill(&flags[0], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_HIGH); } else { flags[0] = flags[0] == peaks::GATE_FLAG_HIGH ? peaks::GATE_FLAG_FALLING : peaks::GATE_FLAG_LOW; std::fill(&flags[1], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_LOW); } _processor.Process(flags, out_cv, FRAME_BUFFER_SIZE); for (int i = 0; i < FRAME_BUFFER_SIZE; i++) { out_cv[i] >>= 1; out_cv[i] *= scale; out_cv[i] += (offset * PITCH_PER_OCTAVE * 5); } } void engine::draw() { gfx::drawWaveform(out_cv, 64); } ================================================ FILE: src/CV/V_OCT.cpp ================================================ // Copyright (C)2021 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" #include #define ONE_POLE(out, in, coefficient) out += (coefficient) * ((in) - out); float note = 0; int32_t tune = 0; int32_t cv0 = 0; int16_t cv_ = 0; float glide = 0; int16_t* out_cv = nullptr; void engine::setup() { engine::addParam(V_OCT, ¬e); engine::addParam("@Fine", &tune, INT8_MIN, INT8_MAX); engine::addParam("Slew", &glide, 0, 0.5f); out_cv = engine::outputBuffer_i16(OUT_VOCT); engine::setMode(ENGINE_MODE_COMPACT); } void engine::process() { cv0 = engine::cv_i32() // note is added internal + (PITCH_PER_OCTAVE * 2) + (tune << 2); ONE_POLE(cv_, cv0, powf(1 - glide, 10)); std::fill_n(out_cv, FRAME_BUFFER_SIZE, cv_); } void engine::draw() { char tmp[64]; sprintf(tmp, "INT: %d", cv0); gfx::drawString(2, 46, tmp, 0); sprintf(tmp, "OUT: %.3fV", ((float)cv_ / PITCH_PER_OCTAVE)); gfx::drawString(2, 52, tmp, 0); gfx::drawWaveform(out_cv, 64); } ================================================ FILE: src/DRUMS/808ish-BD.cpp ================================================ // Copyright (C)2021 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // build_flags: -fno-inline -mfloat-abi=hard -mfpu=fpv5-d16 #include "../squares-and-circles-api.h" #include "lib/peaks/drums/bass_drum.h" peaks::BassDrum _processor; int32_t _freq = UINT16_MAX / 2; int32_t _punch = UINT16_MAX / 2; int32_t _tone = UINT16_MAX / 2; int32_t _decay = UINT16_MAX / 2; int16_t* _out = engine::outputBuffer_i16(OUT_AUDIO); void engine::setup() { _processor.Init(); engine::addParam("Pitch", &_freq, 0, UINT16_MAX); engine::addParam("Punch", &_punch, 0, UINT16_MAX); engine::addParam("Tone", &_tone, 0, UINT16_MAX); engine::addParam("Decay", &_decay, 0, UINT16_MAX); } void engine::process() { peaks::GateFlags flags[FRAME_BUFFER_SIZE]; _processor.set_frequency(_freq - 32768); _processor.set_punch(_punch); _processor.set_tone(_tone); _processor.set_decay(_decay); if (engine::trig()) { flags[0] = peaks::GATE_FLAG_RISING; std::fill(&flags[1], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_HIGH); } else if (engine::gate()) { std::fill(&flags[0], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_HIGH); } else { flags[0] = flags[0] == peaks::GATE_FLAG_HIGH ? peaks::GATE_FLAG_FALLING : peaks::GATE_FLAG_LOW; std::fill(&flags[1], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_LOW); } _processor.Process(flags, _out, FRAME_BUFFER_SIZE); } #include "lib/peaks/drums/bass_drum.cc" #include "lib/peaks/resources.cc" ================================================ FILE: src/DRUMS/808ish-HiHat.cpp ================================================ // Copyright (C)2021 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // build_flags: -fno-inline -mfloat-abi=hard -mfpu=fpv5-d16 -ffast-math #include "../squares-and-circles-api.h" #define private public #include "lib/peaks/drums/high_hat.h" #include "lib/braids/envelope.h" peaks::HighHat _oh; peaks::HighHat _ch; braids::Envelope _ohEnv; braids::Envelope _chEnv; float _pitch = 0.5f; float _levelCH = 0.75f; float _decayCH = 0; float _decayOH = 0.5f; int16_t buffer[FRAME_BUFFER_SIZE]; peaks::GateFlags flags[FRAME_BUFFER_SIZE]; float* _out = engine::outputBuffer_f32(OUT_AUDIO); void engine::setup() { _oh.Init(); _ch.Init(); uint16_t decay = UINT16_MAX; _oh.Configure(&decay, peaks::CONTROL_MODE_FULL); _ch.Configure(&decay, peaks::CONTROL_MODE_FULL); _ohEnv.Init(); //TODO: Use _ch.vca_envelope_ instead - only 4 steps ???! _chEnv.Init(); std::fill(&flags[0], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_LOW); engine::addParam(".", &_pitch); engine::addParam("CH-Lev", &_levelCH); engine::addParam("CH-Dec", &_decayCH); engine::addParam("OH-Dec", &_decayOH); } void engine::process() { bool oh_mute = false; if (engine::trig() && !engine::accent()) { _chEnv.Trigger(braids::ENV_SEGMENT_ATTACK); _ch.vca_envelope_.Trigger(_levelCH * 32768 * 15); oh_mute = true; } _ch.Process(flags, buffer, FRAME_BUFFER_SIZE); _chEnv.Update(0, 32 + _decayCH * 95); auto ch_ad = (float)_chEnv.Render() / UINT16_MAX; for (size_t i = 0; i < FRAME_BUFFER_SIZE; i++) _out[i] = (float)buffer[i] / INT16_MAX * ch_ad; if (engine::accent()) { _ohEnv.Trigger(braids::ENV_SEGMENT_ATTACK); _oh.vca_envelope_.Trigger(32768 * 15); } _oh.Process(flags, buffer, FRAME_BUFFER_SIZE); _ohEnv.Update(0, oh_mute ? 0 : (32 + _decayOH * 95)); auto oh_ad = (float)_ohEnv.Render() / UINT16_MAX; for (size_t i = 0; i < FRAME_BUFFER_SIZE; i++) _out[i] += (float)buffer[i] / INT16_MAX * oh_ad; } #include "lib/peaks/drums/high_hat.cc" #include "lib/peaks/resources.cc" #include "lib/braids/resources.cc" ================================================ FILE: src/DRUMS/808ish-SD.cpp ================================================ // Copyright (C)2021 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // build_flags: -fno-inline -mfloat-abi=hard -mfpu=fpv5-d16 -ffast-math #include "../squares-and-circles-api.h" #include "lib/peaks/drums/snare_drum.h" peaks::SnareDrum _processor; int32_t _freq = UINT16_MAX / 2; int32_t _snappy = UINT16_MAX / 2; int32_t _tone = UINT16_MAX / 2; int32_t _decay = UINT16_MAX / 2; peaks::GateFlags flags[FRAME_BUFFER_SIZE]; int16_t* _out = engine::outputBuffer_i16(OUT_AUDIO); void engine::setup() { _processor.Init(); std::fill(&flags[0], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_LOW); engine::addParam("Pitch", &_freq, 0, UINT16_MAX); engine::addParam("Snappy", &_snappy, 0, UINT16_MAX); engine::addParam("Tone", &_tone, 0, UINT16_MAX); engine::addParam("Decay", &_decay, 0, UINT16_MAX); } void engine::process() { _processor.set_frequency(_freq - 32768); _processor.set_tone(_tone); _processor.set_snappy(_snappy); _processor.set_decay(_decay); if (engine::trig()) { flags[0] = peaks::GATE_FLAG_RISING; std::fill(&flags[1], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_HIGH); } else if (engine::gate()) { std::fill(&flags[0], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_HIGH); } else { flags[0] = flags[0] == peaks::GATE_FLAG_HIGH ? peaks::GATE_FLAG_FALLING : peaks::GATE_FLAG_LOW; std::fill(&flags[1], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_LOW); } _processor.Process(flags, _out, FRAME_BUFFER_SIZE); } #include "lib/peaks/drums/snare_drum.cc" #include "lib/stmlib/utils/random.cc" #include "lib/peaks/resources.cc" ================================================ FILE: src/DRUMS/Claps.cpp ================================================ // Copyright (C)2021 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" #include "lib/drumsynth/drumsynth.h" #include "lib/drumsynth/drumsynth_claps.h" #include "lib/misc/noise.hxx" static constexpr size_t n = 8; DrumSynth _inst = nullptr; float pitch = 1.f; float stereo = 0.5f; float stretch = 1.f; DrumModel inst[32] = {}; const uint8_t *packed_drumKit = drum_synth_claps; const size_t inst_count = 10; // packed_drumKit[0]; int32_t inst_selection = 0; DrumModel _cur_inst = {}; WhiteNoise r; uint32_t seed = 0; std::pair seeds[7] = { {0x6d17ceb4, 1.f}, {0x73623629, 1.f}, {0x23cb4e73, 0.5f}, {0x73C23C29, 0.5f}, {0x42D1EC10, 1.3f}, {0x5EFF9F17, 1.3f}, {0x082087A1, 1.3f}, }; void load_instrument(uint8_t num); int sprint_inst_name(char *tmp, int inst_selection) { if (inst_selection < 2) return sprintf(tmp, ">%s", inst[inst_selection].name); else if (inst_selection < inst_count) return sprintf(tmp, ">Clap%03X", inst_selection); else if ((inst_selection - inst_count) < (int)LEN_OF(seeds)) return sprintf(tmp, ">%X", seeds[inst_selection - inst_count].first); else return sprintf(tmp, ">%X", (unsigned int)seed); } char inst_name_buff[256] = {}; const char *inst_names[inst_count + LEN_OF(seeds)] = {}; void engine::setup() { // unpack const uint8_t *p = packed_drumKit; p += 4; for (size_t i = 0; i < packed_drumKit[0]; i++) { inst[i].name = reinterpret_cast(p); p += 12; inst[i].n = *reinterpret_cast(p); p += sizeof(inst[i].n); PartArgs *part = new PartArgs[inst[i].n]{}; inst[i].part = part; for (int j = 0; j < inst[i].n; j++) { part->flags = *reinterpret_cast(p); p += sizeof(part->flags); part->osc = *reinterpret_cast(p); p += sizeof(part->osc); part->osc_pitch.n = *reinterpret_cast(p); p += sizeof(part->osc_pitch.n); part->osc_pitch.xy = reinterpret_cast(p); p += sizeof(EnvXY) * 16; part->osc_amp.n = *reinterpret_cast(p); p += sizeof(part->osc_amp.n); part->osc_amp.xy = reinterpret_cast(p); p += sizeof(EnvXY) * 16; part->vca.n = *reinterpret_cast(p); p += sizeof(part->vca.n); part->vca.xy = reinterpret_cast(p); p += sizeof(EnvXY) * 16; part->bq1 = *reinterpret_cast(p); p += sizeof(BiquadArgs); part->bq2 = *reinterpret_cast(p); p += sizeof(BiquadArgs); part->ws.n = *reinterpret_cast(p); p += sizeof(part->ws.n); part->ws.xy = reinterpret_cast(p); p += sizeof(WS_XY) * 8; part->level = *reinterpret_cast(p); p += sizeof(part->level); part++; } } engine::addParam("Color", &pitch, 0.5f, 1.5f); char *tmp = inst_name_buff; for (int i = 0; i < (inst_count + LEN_OF(seeds)); i++) { inst_names[i] = tmp; tmp += sprint_inst_name(tmp, i) + 1; } engine::addParam("Clap", &inst_selection, 0, (inst_count + LEN_OF(seeds)) - 1, inst_names); engine::addParam("Decay", &stretch, 0.1f, 2.0f); engine::addParam("Stereo", &stereo); // param[0].init("Crispy", &crispy, crispy, -1.1f, 1.1f); // param[1].init("Decay", &decay, decay, 0, 2.f); // TODO: BitCrusher + Filter + Distortion load_instrument(inst_selection); } void free_instrument() { for (size_t i = 0; i < inst_count; i++) if (_cur_inst.part == inst[i].part) _cur_inst.part = nullptr; if (_cur_inst.part != nullptr) ::free((void *)_cur_inst.part); } void engine_free() { free_instrument(); drum_synth_deinit(_inst, ::free); } void load_instrument(uint8_t num) { int n = num - inst_count; if (n >= 0 && n < (int)LEN_OF(seeds)) r.seed = seed = seeds[n].first; else seed = r.seed; free_instrument(); if (inst_selection < inst_count) _cur_inst = inst[num]; else { seed = r.seed; float a = 1.f; for (auto &it : seeds) if (it.first == seed) a = it.second; auto partArgs = (PartArgs *)::malloc(_cur_inst.n * sizeof(PartArgs)); for (size_t i = 0; i < _cur_inst.n; i++) { size_t n = inst_count; DrumModel in = inst[r.next() % n]; partArgs[i] = in.part[r.next() % in.n]; in = inst[r.next() % n]; auto & = in.part[r.next() % in.n].osc_amp; if (amp.n > 0) partArgs[i].osc_amp = amp; in = inst[r.next() % n]; partArgs[i].osc_pitch = in.part[r.next() % in.n].osc_pitch; in = inst[r.next() % n]; auto &vca = in.part[r.next() % in.n].vca; if (vca.n > 0) partArgs[i].vca = vca; in = inst[r.next() % n]; partArgs[i].bq1 = in.part[r.next() % in.n].bq1; in = inst[r.next() % n]; partArgs[i].bq2 = in.part[r.next() % in.n].bq2; partArgs[i].level *= a; } _cur_inst.part = partArgs; } drum_synth_deinit(_inst, ::free); _inst = drum_synth_init(&_cur_inst, ::malloc); } uint32_t _t = UINT32_MAX; int32_t last_inst_selection = -1; void engine::process() { auto buffer = engine::outputBuffer<0>(); auto bufferAux = engine::outputBuffer<1>(); memset(buffer, 0, sizeof(float) * FRAME_BUFFER_SIZE); memset(bufferAux, 0, sizeof(float) * FRAME_BUFFER_SIZE); float tmpL[FRAME_BUFFER_SIZE]; float tmpR[FRAME_BUFFER_SIZE]; if (engine::trig()) { if (last_inst_selection != inst_selection) { last_inst_selection = inst_selection; load_instrument(inst_selection); } _t = 0; drum_synth_reset(_inst); } if (_t < UINT32_MAX) { DrumParams params = {_t, 0, stretch, stereo, 1.f, 1.f}; float f = pitch; // powf(2.f, (frame.qz_voltage(this->io, 0))); float a = stereo; float b = 1.f - a; for (size_t k = 0; k < _cur_inst.n; k++) { { drum_synth_process_frame(_inst, k, f, ¶ms, tmpL, tmpR, FRAME_BUFFER_SIZE); for (int i = 0; i < FRAME_BUFFER_SIZE; i++) { buffer[i] += tmpL[i]; bufferAux[i] += tmpR[i]; } } // bufferAux[i] += p._vca.value() * p._amp.value() * 0.99f; } _t += FRAME_BUFFER_SIZE; } } #include "lib/drumsynth/drumsynth.cpp" #include "lib/misc/Biquad.cpp" #include "lib/plaits/resources.cc" ================================================ FILE: src/DRUMS/Djembe.cpp ================================================ #include "../squares-and-circles-api.h" #include "faust/ui.hxx" #include "faust/djembe.dsp.h" static float *_trig = nullptr; void UIGlue::addButton(const char *ui, const char *label, float *zone) { if (_trig == nullptr) _trig = zone; } void UIGlue::addNumEntry(const char *ui, const char *label, float *zone, float init, float min, float max, float step) { } void UIGlue::addCheckButton(const char *ui, const char *label, float *zone) { addHorizontalSlider(ui, label, zone, 0, 0, 1, 1); } void UIGlue::addVerticalSlider(const char *ui, const char *label, float *zone, float init, float min, float max, float step) { addHorizontalSlider(ui, label, zone, init, min, max, step); } void UIGlue::addHorizontalSlider(const char *ui, const char *label, float *zone, float init, float min, float max, float step) { if (zone) { *zone = init; engine::addParam(label, zone, min, max); } } static FAUSTCLASS dsp; void engine::setup() { initmydsp(&dsp, SAMPLE_RATE); UIGlue ui; buildUserInterfacemydsp(&dsp, &ui); } void engine::process() { if (_trig != nullptr) *_trig = engine::trig(); auto outputL = engine::outputBuffer<0>(); float *outputs[] = {outputL, nullptr}; computemydsp(&dsp, FRAME_BUFFER_SIZE, nullptr, &outputs[0]); } ================================================ FILE: src/DRUMS/DrumSynth.cpp ================================================ // Copyright (C)2024 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // xuild_flags: -fno-inline -mfloat-abi=hard -mfpu=fpv5-d16 // ENGINE_NAME: DRUMS/@!RC8 #include "../../lib/drumsynth/drumsynth.h" #include "../squares-and-circles-api.h" // General MIDI Percussion Key Map: // MIDI Key Drum Sound MIDI Key Drum Sound // -------- ---------- ---------- ---------- // 35 Acoustic Bass Drum 59 Ride Cymbal 2 // 36 Bass Drum 1 60 Hi Bongo // 37 Side Stick 61 Low Bongo // 38 Acoustic Snare 62 Mute Hi Conga // 39 Hand Clap 63 Open Hi Conga // 40 Electric Snare 64 Low Conga // 41 Low Floor Tom 65 High Timbale // 42 Closed Hi-Hat 66 Low Timbale // 43 High Floor Tom 67 High Agogo // 44 Pedal Hi-Hat 68 Low Agogo // 45 Low Tom 69 Cabasa // 46 Open Hi-Hat 70 Maracas // 47 Low-Mid Tom 71 Short Whistle // 48 Hi-Mid Tom 72 Long Whistle // 49 Crash Cymbal 1 73 Short Guiro // 50 High Tom 74 Long Guiro // 51 Ride Cymbal 1 75 Claves // 52 Chinese Cymbal 76 Hi Wood Block // 53 Ride Bell 77 Low Wood Block // 54 Tambourine 78 Mute Cuica // 55 Splash Cymbal 79 Open Cuica // 56 Cowbell 80 Mute Triangle // 57 Crash Cymbal 2 81 Open Triangle // 58 Vibraslap static std::pair midi_key_map[] = { {35, -1}, // BD0 {36, -1}, // BD1 {37, -1}, // RM {38, -1}, // SD0 {39, -1}, // CP {40, -1}, // SD1 {41, -1}, // LT {42, -1}, // HH - Closed {43, -1}, // LT2 {44, -1}, // HH - Pedal {45, -1}, // MT {46, -1}, // HH - Open {47, -1}, // MT2 {48, -1}, // HT {49, -1}, // CR - Crash {50, -1}, // HT2 {51, -1}, // RD - Ride {52, -1}, // CY - Chinese {53, -1}, // RD2 - Ride Bell {54, -1}, // TMB {55, -1}, // CR2 - Crash Edge {56, -1}, // CB {57, -1}, // CR3 - Crash Bow {58, -1}, // VS - Vibraslap {59, -1}, // RD3 - Ride Edge {0, -1}, // FREE {0, -1}, // FREE {0, -1}, // FREE {0, -1}, // FREE {0, -1}, // FREE {0, -1}, // FREE {0xFF, 0}, // END }; uint8_t& midi_key_entry(uint8_t midi_note) { if(midi_note >= 35 && midi_note <= 59) { return midi_key_map[midi_note - 35].second; } for (size_t i = (60-35); i < LEN_OF(midi_key_map); i++) { if (midi_key_map[i].first == 0) { midi_key_map[i].first = midi_note; return midi_key_map[i].second; } } return midi_key_map[LEN_OF(midi_key_map) - 2].second; // invalid } void map_as_multiple(uint8_t a, uint8_t b) { uint8_t* aa = &midi_key_entry(a); uint8_t* bb = &midi_key_entry(b); if (*bb == 0xFF) *bb = *aa; if (*aa == 0xFF) *aa = *bb; } bool is_maped_as_multiple(uint8_t a, uint8_t b) { uint8_t aa = midi_key_entry(a); uint8_t bb = midi_key_entry(b); return aa == bb; } static constexpr size_t n = 8; float pitch = 1.f; float stereo = 0.5f; float stretch = 1.f; DrumModel _instModel[16] = {}; DrumSynth _inst[16] = {}; size_t inst_count = 0; int32_t inst_selection = 0; uint32_t _t[16] = {}; const char *inst_names[16] = {}; char __debug[128]; constexpr int MAX_T = UINT16_MAX * 4; int32_t _open_hihat = -1; void engine::setup() { const uint8_t *drumkit = __data; // unpack inst_count = drum_synth_load_models(drumkit, _instModel, ::malloc); if (inst_count > 0) { for (int i = 0; i < inst_count; i++) { inst_names[i] = _instModel[i].name; midi_key_entry(_instModel[i].midi_note) = i; _t[i] = MAX_T; _inst[i] = drum_synth_init(&_instModel[i], ::malloc); } map_as_multiple(35, 36); // BD map_as_multiple(38, 40); // SD map_as_multiple(42, 44); // Closed HH map_as_multiple(41, 43); // LT map_as_multiple(45, 47); // MT map_as_multiple(48, 50); // HT map_as_multiple(51, 59); // RD map_as_multiple(49, 55); // CR map_as_multiple(49, 51); // CR/RD _open_hihat = midi_key_entry(46); engine::addParam("Pitch", &pitch, 0.5f, 1.5f); engine::addParam(MULTI_TRIGS, &inst_selection, 0, inst_count - 1, inst_names); engine::addParam("Decay", &stretch, 0.1f, 2.0f); engine::addParam("Stereo", &stereo); } engine::setMultiTrigMidiKeyMap(midi_key_map); } void engine::release() { for (int i = 0; i < inst_count; i++) { ::free(_inst[i]); } } void engine::process() { auto buffer = engine::outputBuffer<0>(); auto bufferAux = engine::outputBuffer<1>(); memset(buffer, 0, sizeof(float) * FRAME_BUFFER_SIZE); memset(bufferAux, 0, sizeof(float) * FRAME_BUFFER_SIZE); float tmpL[FRAME_BUFFER_SIZE]; float tmpR[FRAME_BUFFER_SIZE]; for (int i = 0; i < inst_count; i++) { if (engine::trig() & (1 << i)) { _t[i] = 0; drum_synth_reset(_inst[i]); if(_open_hihat != -1 && _instModel[i].midi_note == 42 || _instModel[i].midi_note == 44) // closed hihat { _t[_open_hihat] = MAX_T; // mute open hihat } } if (_t[i] < MAX_T) { DrumParams params = {_t[i], 0, stretch, stereo, 0, 0}; if(i == _open_hihat) { params.decay = 0.1f + stretch + (-stretch * ((float)engine::getMidiCC(4) / 127.f)); } float f = pitch * powf(2.f, engine::cv()); float a = stereo; float b = 1.f - a; params.levelL = engine::mixLevelL(i) * engine::trigLevel(i); params.levelR = engine::mixLevelR(i) * engine::trigLevel(i); drum_synth_process_frame(_inst[i], -1, f, ¶ms, buffer, bufferAux, FRAME_BUFFER_SIZE); _t[i] += FRAME_BUFFER_SIZE; } } } void engine::draw() { } #include "../../lib/drumsynth/drumsynth.cpp" #include "../../lib/misc/Biquad.cpp" #include "../../lib/plaits/resources.cc" ================================================ FILE: src/DRUMS/FM-Drum.cpp ================================================ // Copyright (C)2021 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" #include "lib/peaks/drums/fm_drum.h" #include "lib/peaks/drums/fm_drum.cc" #include "lib/peaks/resources.cc" #include "lib/stmlib/utils/random.cc" static peaks::FmDrum _processor; static int32_t _freq = UINT16_MAX / 2; static int32_t _punch = UINT16_MAX / 2; static int32_t _tone = UINT16_MAX / 2; static int32_t _decay = UINT16_MAX / 2; peaks::GateFlags flags[FRAME_BUFFER_SIZE]; int16_t* _out = engine::outputBuffer_i16(OUT_AUDIO); void engine::setup() { _processor.Init(); std::fill(&flags[0], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_LOW); engine::addParam("Freq.", &_freq, 0, UINT16_MAX); engine::addParam("Noise", &_punch, 0, UINT16_MAX); engine::addParam("FM", &_tone, 0, UINT16_MAX); engine::addParam("Decay", &_decay, 0, UINT16_MAX); } void engine::process() { int32_t freq = (_freq) + (engine::cv_i32() / PITCH_PER_OCTAVE * INT16_MAX / 3); // CV or Midi Pitch ?! freq += (-2 * INT16_MAX / 3); CONSTRAIN(freq, 0, UINT16_MAX); // BUG: lower values? _processor.set_frequency(freq); _processor.set_fm_amount(((uint16_t)(_tone) >> 2) * 3); _processor.set_decay(_decay); _processor.set_noise(_punch); if (engine::trig()) { flags[0] = peaks::GATE_FLAG_RISING; std::fill(&flags[1], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_HIGH); } else if (engine::gate()) { std::fill(&flags[0], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_HIGH); } else { flags[0] = flags[0] == peaks::GATE_FLAG_HIGH ? peaks::GATE_FLAG_FALLING : peaks::GATE_FLAG_LOW; std::fill(&flags[1], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_LOW); } _processor.Process(flags, _out, FRAME_BUFFER_SIZE); } ================================================ FILE: src/DRUMS/RZ-1.cpp ================================================ #include "../squares-and-circles-api.h" #include // Casio RZ-1 sample ROMs // HN613256P CM5/CM6 = 256kbit (32KB each) Mask ROMs // Format: signed 8-bit, mono, 20,000 Hz // // ROM A (CM5): Toms 1~3, Kick, Snare, Rimshot, Closed Hi-Hat, Open Hi-Hat, Metronome Click // ROM B (CM6): Clap, Ride, Cowbell, Crash // // Sample offsets (from R-Massive's RZ-1 ROM Hacking article): // ROM A: // Tom 1 : 0 - 3791 (3791) // Tom 2 : 3791 - 7635 (3844) // Tom 3 : 7635 - 11722 (4087) // Kick : 11722 - 13349 (1627) // Snare : 13349 - 16573 (3224) // Rimshot : 16573 - 17876 (1303) // CH : 17876 - 19099 (1223) // OH : 19099 - 31108 (12009) // Click : 31108 - 31615 ( 507) // ROM B: // Clap : 0 - 2511 (2511) // Ride : 2511 - 16446 (13935) // Cowbell : 16446 - 18397 (1951) // Crash : 18397 - 32768 (14371) static std::pair midi_key_map[] = { {41, 0}, // TOM1 (low) {43, 0}, {45, 1}, // TOM2 (mid) {47, 1}, {48, 2}, // TOM3 (high) {50, 2}, {35, 3}, // BD {36, 3}, {38, 4}, // SD {40, 4}, {37, 5}, // RIM {42, 6}, // CH - Closed {44, 6}, // CH - Pedal {46, 7}, // OH - Open {33, 8}, // CLK - Metronome Click {39, 9}, // CP - Clap {51, 10}, // RD - Ride {53, 10}, // RD - Ride Bell {59, 10}, // RD - Ride Edge {56, 11}, // CB - Cowbell {49, 12}, // CR - Crash {55, 12}, {57, 12}, {0xFF, 0}, // END }; static float _pitch = 0.5f; static float _start = 0.f; static float _end = 1.f; static float _amp = 1.f; int32_t _select = 0; const char *sample_names[13] = {}; sample *sample_ptr[LEN_OF(sample_names)] = {}; #define SETUP_SAMPLE(name, ptr) \ sample_names[_select] = name; \ sample_ptr[_select] = ptr; \ ++_select void engine::setup() { auto ROM_A_bin = machine::fs_read("RZ1_ROMA"); auto ROM_B_bin = machine::fs_read("RZ1_ROMB"); if (ROM_A_bin == nullptr || ROM_B_bin == nullptr) return; auto TOM1 = &ROM_A_bin[0]; auto TOM2 = &ROM_A_bin[3791]; auto TOM3 = &ROM_A_bin[7635]; auto BD = &ROM_A_bin[11722]; auto SD = &ROM_A_bin[13349]; auto RM = &ROM_A_bin[16573]; auto CH = &ROM_A_bin[17876]; auto OH = &ROM_A_bin[19099]; auto CLK = &ROM_A_bin[31108]; auto CP = &ROM_B_bin[0]; auto RD = &ROM_B_bin[2511]; auto CB = &ROM_B_bin[16446]; auto CR = &ROM_B_bin[18397]; SETUP_SAMPLE("BD", sample_s8(BD, 1627, 20000, 0)); // 3 SETUP_SAMPLE("SD", sample_s8(SD, 3224, 20000, 0)); // 4 SETUP_SAMPLE("CP", sample_s8(CP, 2511, 20000, 0)); // 9 SETUP_SAMPLE("RM", sample_s8(RM, 1303, 20000, 0)); // 5 SETUP_SAMPLE("CB", sample_s8(CB, 1951, 20000, 0)); // 11 SETUP_SAMPLE("CLK", sample_s8(CLK, 507, 20000, 0)); // 8 SETUP_SAMPLE("TM1", sample_s8(TOM1, 3791, 20000, 0)); // 0 SETUP_SAMPLE("TM2", sample_s8(TOM2, 3844, 20000, 0)); // 1 SETUP_SAMPLE("TM3", sample_s8(TOM3, 4087, 20000, 0)); // 2 SETUP_SAMPLE("CH", sample_s8(CH, 1223, 20000, 0)); // 6 SETUP_SAMPLE("OH", sample_s8(OH, 12009, 20000, 0)); // 7 SETUP_SAMPLE("RD", sample_s8(RD, 13935, 20000, 0)); // 10 SETUP_SAMPLE("CR", sample_s8(CR, 14371, 20000, 0)); // 12 engine::addParam("Pitch", &_pitch); engine::addParam(MULTI_TRIGS, &_select, 0, _select - 1, sample_names); // . = hidden _select = 0; engine::addParam("Start", &_start); engine::addParam("End", &_end); engine::setMultiTrigMidiKeyMap(midi_key_map); } void engine::process() { if (sample_ptr[0] == nullptr) return; auto outputL = engine::outputBuffer<0>(); memset(outputL, 0, sizeof(float) * FRAME_BUFFER_SIZE); auto outputR = engine::outputBuffer<1>(); memset(outputR, 0, sizeof(float) * FRAME_BUFFER_SIZE); for (uint32_t i = 0; i < LEN_OF(sample_ptr) && sample_ptr[i] != nullptr; i++) { if (engine::trig() & (1 << i)) { if (i == 6) // CH { if (!(engine::trig() & (1 << (i + 1)))) // OH { sample_set_pos(sample_ptr[i], _start, 0.7f * engine::trigLevel(i), 0.2f); sample_set_pos(sample_ptr[i + 1], _start, 0, 1.0f); } } else if (i == 7) // OH { sample_set_pos(sample_ptr[i], _start, engine::trigLevel(i), 1.f - (float)engine::getMidiCC(4) / 127.f); } else { sample_set_pos(sample_ptr[i], _start, engine::trigLevel(i), 1.f); } } float tmp[FRAME_BUFFER_SIZE] = {}; float v_oct = (-2.f + _pitch * 4) + engine::cv(); sample_process(sample_ptr[i], _start, _end, 1.f, v_oct, tmp); float levelL = engine::mixLevelL(i); float levelR = engine::mixLevelR(i); for (size_t i = 0; i < FRAME_BUFFER_SIZE; i++) { outputL[i] += tmp[i] * levelL; outputR[i] += tmp[i] * levelR; } } } void engine::draw() { if (sample_ptr[0] == nullptr) gfx::drawString(20, 20, "ROMS NOT FOUND\n \n RZ1_ROMA\n RZ1_ROMB"); else gfx::drawWaveform(sample_ptr[_select]); } ================================================ FILE: src/DRUMS/TR707.cpp ================================================ #include "../squares-and-circles-api.h" #include // #include "eproms/tr707/IC34_TR707_SNDROM.h" // #include "eproms/tr707/IC35_TR707_SNDROM.h" static std::pair midi_key_map[] = { {35, 0}, // BD0 {36, 1}, // BD1 {38, 2}, // SD0 {40, 3}, // SD1 {39, 4}, // CP {54, 5}, // TMB {37, 6}, // RM {56, 7}, // CB {41, 8}, // LT {43, 8}, // LT {45, 9}, // MT {47, 9}, // MT {48, 10}, // HT {50, 10}, // HT {42, 11}, // HH - Closed {44, 11}, // HH - Pedal {46, 12}, // HH - Open {51, 13}, // RD - Ride {59, 13}, // RD - Ride Edge {53, 13}, // RD - Ride Bell {49, 14}, // CR - Crash {55, 14}, // CR - Crash Edge {57, 14}, // CR - Crash Bow {0xFF, 0}, // END }; static float _pitch = 0.5f; static float _start = 0.f; static float _end = 1.f; static float _amp = 1.f; int32_t _select = 0; const char *sample_names[15] = {}; sample *sample_ptr[LEN_OF(sample_names)] = {}; #define SETUP_SAMPLE(name, ptr) \ sample_names[_select] = name; \ sample_ptr[_select] = ptr; \ ++_select void engine::setup() { auto IC34_TR707_SNDROM_bin = machine::fs_read("707_IC34"); auto IC35_TR707_SNDROM_bin = machine::fs_read("707_IC35"); auto IC19_Crash = machine::fs_read("707_IC19"); auto IC22_Ride = machine::fs_read("707_IC22"); if (IC34_TR707_SNDROM_bin == nullptr || IC35_TR707_SNDROM_bin == nullptr) return; auto BD0 = &IC34_TR707_SNDROM_bin[0x0000]; auto BD1 = &IC34_TR707_SNDROM_bin[0x0001]; auto SD0 = &IC34_TR707_SNDROM_bin[0x2000]; auto SD1 = &IC34_TR707_SNDROM_bin[0x2001]; auto RM = &IC35_TR707_SNDROM_bin[0x4000]; auto CB = &IC35_TR707_SNDROM_bin[0x4001]; auto CP = &IC35_TR707_SNDROM_bin[0x6000]; auto TMB = &IC35_TR707_SNDROM_bin[0x6001]; auto LT = &IC34_TR707_SNDROM_bin[0x4000]; auto MT = &IC34_TR707_SNDROM_bin[0x6000]; auto HT = &IC35_TR707_SNDROM_bin[0x0000]; auto HH = &IC35_TR707_SNDROM_bin[0x2000]; SETUP_SAMPLE("BD0", sample_u8(BD0, 0x1000, 25000, 1)); // 0 SETUP_SAMPLE("BD1", sample_u8(BD1, 0x1000, 25000, 1)); // 1 SETUP_SAMPLE("SD0", sample_u8(SD0, 0x1000, 25000, 1)); // 2 SETUP_SAMPLE("SD1", sample_u8(SD1, 0x1000, 25000, 1)); // 3 SETUP_SAMPLE("CP", sample_u8(CP, 0x1000, 25000, 1)); // 4 SETUP_SAMPLE("TMB", sample_u8(TMB, 0x1000, 25000, 1)); // 5 SETUP_SAMPLE("RM", sample_u8(RM, 0x1000, 25000, 1)); // 6 SETUP_SAMPLE("CB", sample_u8(CB, 0x1000, 25000, 1)); // 7 SETUP_SAMPLE("LT", sample_u8(LT, 0x1000, 12500, 0)); // 8 SETUP_SAMPLE("MT", sample_u8(MT, 0x1000, 12500, 0)); // 9 SETUP_SAMPLE("HT", sample_u8(HT, 0x1000, 12500, 0)); // 10 SETUP_SAMPLE("CH", sample_u8(HH, 0x1000, 25000, 0)); // 11 SETUP_SAMPLE("OH", sample_u8(HH, 0x1000, 25000, 0)); // 12 if (IC22_Ride != nullptr) { SETUP_SAMPLE("RD", sample_u8(IC22_Ride, 0x8000, 25000, 0)); // 14 } if (IC19_Crash != nullptr) { SETUP_SAMPLE("CR", sample_u8(IC19_Crash, 0x8000, 25000, 0)); // 13 } engine::addParam("Pitch", &_pitch); engine::addParam(MULTI_TRIGS, &_select, 0, _select - 1, sample_names); // . = hidden _select = 0; engine::addParam("Start", &_start); engine::addParam("End", &_end); engine::setMultiTrigMidiKeyMap(midi_key_map); } void engine::process() { if (sample_ptr[0] == nullptr) return; auto outputL = engine::outputBuffer<0>(); memset(outputL, 0, sizeof(float) * FRAME_BUFFER_SIZE); auto outputR = engine::outputBuffer<1>(); memset(outputR, 0, sizeof(float) * FRAME_BUFFER_SIZE); for (uint32_t i = 0; i < LEN_OF(sample_ptr) && sample_ptr[i] != nullptr; i++) { if (engine::trig() & (1 << i)) { if (i == 11) // CH { if (!(engine::trig() & (1 << (i + 1)))) // OH { sample_set_pos(sample_ptr[i], _start, 0.7f * engine::trigLevel(i), 0.2f); sample_set_pos(sample_ptr[i + 1], _start, 0, 1.0f); } } else if (i == 12) // OH { sample_set_pos(sample_ptr[i], _start, engine::trigLevel(i), 1.f - (float)engine::getMidiCC(4) / 127.f); } else { sample_set_pos(sample_ptr[i], _start, engine::trigLevel(i), 1.f); } } float tmp[FRAME_BUFFER_SIZE] = {}; float v_oct = (-2.f + _pitch * 4) + engine::cv(); sample_process(sample_ptr[i], _start, _end, 1.f, v_oct, tmp); float levelL = engine::mixLevelL(i); float levelR = engine::mixLevelR(i); for (size_t i = 0; i < FRAME_BUFFER_SIZE; i++) { outputL[i] += tmp[i] * levelL; outputR[i] += tmp[i] * levelR; } } } void engine::draw() { if (sample_ptr[0] == nullptr) gfx::drawString(20, 20, "ROMS NOT FOUND\n \n 707_IC34\n 707_IC35"); else gfx::drawWaveform(sample_ptr[_select]); } ================================================ FILE: src/DRUMS/TR909-HiHat.cpp ================================================ #include "../squares-and-circles-api.h" static float _ch_vol = 1.f; static float _ch_dec = 0.2f; static float _oh_vol = 1.f; static float _oh_dec = 0.5f; static float _rd_vol = 1.f; static float _rd_dec = 0.5f; int32_t _select; const char *sample_names[] = {"CH", "OH", "RD"}; // void *_samples[3] = {}; sample *_ch = nullptr; sample *_oh = nullptr; sample *_rd = nullptr; static std::pair midi_key_map[] = { {42, 0}, // HH - Closed {44, 0}, // HH - Pedal {46, 1}, // HH - Open {51, 2}, // RD - Ride {59, 2}, // RD - Ride Edge {53, 2}, // RD - Ride Bell // {49, 3}, // CR - Crash // {55, 3}, // CR - Crash Edge // {57, 3}, // CR - Crash Bow {0xFF, 0}, // END }; float *_outputL = nullptr; float *_outputR = nullptr; void engine::setup() { const uint8_t *HiHats_bin = machine::fs_read("909_HIGH"); const uint8_t *Ride_bin = machine::fs_read("909_RIDE"); if (HiHats_bin == nullptr || Ride_bin == nullptr) return; const int ch_start = 24576; _ch = sample_u8(HiHats_bin + ch_start, 32768 - ch_start, 32000, 0); _oh = sample_u8(HiHats_bin, 24576, 32000, 0); _rd = sample_u8(Ride_bin, 32768, 32000, 0); engine::addParam("CH-Lev", &_ch_vol); engine::addParam("CH-Dec", &_ch_dec); engine::addParam("OH-Lev", &_oh_vol); engine::addParam("OH-Dec", &_oh_dec); engine::addParam("RD-Lev", &_rd_vol); engine::addParam("RD-Dec", &_rd_dec); _outputL = engine::outputBuffer_f32(OUT_AUDIO_L); _outputR = engine::outputBuffer_f32(OUT_AUDIO_R); engine::setupMultiTrigs(3, sample_names, midi_key_map); } void engine::process() { if (_oh == nullptr) return; if (engine::trig() & (1 << 1)) // OH { sample_set_pos(_oh, 0, _oh_vol, _oh_dec); } else if (engine::trig() & (1 << 0)) // CH { sample_set_pos(_ch, 0, _ch_vol, _ch_dec); sample_set_pos(_oh, 0, 0, _oh_dec); } if (engine::trig() & (1 << 2)) // RD { sample_set_pos(_rd, 0, _rd_vol, _rd_dec); } memset(_outputL, 0, sizeof(float) * FRAME_BUFFER_SIZE); memset(_outputR, 0, sizeof(float) * FRAME_BUFFER_SIZE); sample *_samples[] = {_ch, _oh, _rd}; for (size_t i = 0; i < LEN_OF(_samples) && _samples[i] != nullptr; i++) { float tmp[FRAME_BUFFER_SIZE] = {}; sample_process(_samples[i], 0, 1, 1.f, engine::cv(), tmp); float levelL = engine::mixLevelL(i); float levelR = engine::mixLevelR(i); for (size_t j = 0; j < FRAME_BUFFER_SIZE; j++) { _outputL[j] += tmp[j] * levelL; _outputR[j] += tmp[j] * levelR; } } } void engine::draw() { if (_oh == nullptr) gfx::drawString(20, 20, "ROMS NOT FOUND\n \n 909_HIGH"); } ================================================ FILE: src/FILTER/MoogLadder.cpp ================================================ // Copyright (C)2025 - E.Heidt // // Author: eh2k@gmx.de // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" #define tanh fast_tanh #define protected public #include "MoogLadders/src/ImprovedModel.h" #include "plaits/dsp/envelope.h" #include "stmlib/dsp/units.cc" #include using namespace stmlib; using namespace plaits; const float a0 = (440.0f / 8.0f) / SAMPLE_RATE; inline float NoteToFrequency(float midi_note) { midi_note -= 9.0f; CONSTRAIN(midi_note, -128.0f, 127.0f); return a0 * 0.25f * SemitonesToRatio(midi_note); } float _cutoff = 0.5f; float _resonance = 0.5f; float _envMod = 0.5f; float _envDecay = 0.5f; DecayEnvelope decay_envelope_; ImprovedMoog filter0(SAMPLE_RATE * 2); void engine::setup() { decay_envelope_.Init(); engine::addParam("Cutoff", &_cutoff); engine::addParam("Res.", &_resonance); engine::addParam("EnvMod", &_envMod); engine::addParam("Decay", &_envDecay); } float tmp[FRAME_BUFFER_SIZE * 2] = {}; float last_input = 0.f; void engine::process() { auto inputL = engine::inputBuffer<0>(); auto inputR = engine::inputBuffer<1>(); auto outputL = engine::outputBuffer<0>(); auto outputR = engine::outputBuffer<1>(); if (engine::trig()) decay_envelope_.Trigger(); const float short_decay = (200.0f * FRAME_BUFFER_SIZE) / SAMPLE_RATE * SemitonesToRatio(-96.0f * _envDecay); decay_envelope_.Process(short_decay); float cutoff = _cutoff + _envMod * decay_envelope_.value(); CONSTRAIN(cutoff, 0.f, 1.f); const float f0 = NoteToFrequency(DEFAULT_NOTE + (engine::cv() * 12)); cutoff = f0 * SemitonesToRatio((cutoff - 0.2f) * 120.0f); filter0.SetCutoff(cutoff * SAMPLE_RATE / 2); filter0.SetResonance(_resonance); if (filter0.sampleRate > SAMPLE_RATE) { for (int i = 0; i < (FRAME_BUFFER_SIZE * 2); i += 2) { float input = inputL[i / 2] + inputR[i / 2]; tmp[i] = (last_input + input) * 0.5f; tmp[i + 1] = input; last_input = input; } filter0.Process(tmp, FRAME_BUFFER_SIZE * 2); for (int i = 0; i < FRAME_BUFFER_SIZE * 2; i += 2) { outputL[i / 2] = (tmp[i] + tmp[i + 1]) / 2; } } else { std::copy_n(inputL, FRAME_BUFFER_SIZE, outputL); filter0.Process(outputL, FRAME_BUFFER_SIZE); } std::copy_n(outputL, FRAME_BUFFER_SIZE, outputR); } ================================================ FILE: src/FILTER/SVF.cpp ================================================ // Copyright (C)2025 - E.Heidt // // Author: eh2k@gmx.de // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // https://www.earlevel.com/main/2003/03/02/the-digital-state-variable-filter/ #include "../squares-and-circles-api.h" #include #include #include #include "stmlib/dsp/units.h" inline float clamp(float x, float a, float b) { return fmax(a, fmin(x, b)); } // https://www.musicdsp.org/en/latest/Filters/142-state-variable-filter-chamberlin-version.html struct SVFilter { float lastLp = 0, lastHp = 0, lastBp = 0; inline void process(float input, float kf, float kq) { auto lp = lastLp + kf * lastBp; auto hp = input - lp - kq * lastBp; auto bp = lastBp + kf * hp; lastLp = lp; lastHp = hp; lastBp = bp; } }; class Filter { SVFilter f[2]; float kf = 0.1f, kq = .3f; public: void set_f_q(float f, float q) { kq = q; kf = stmlib::Pow2Fast<1>(std::min(0.f, f)); // kf = std::pow(2.f, std::min(0.f, f)); } inline auto process(float input) { // 2x oversampling f[0].process(input, kf, kq); f[1].process(f[0].lastLp, kf, kq); f[0].process(input, kf, kq); f[1].process(f[0].lastLp, kf, kq); return f[1].lastLp; } }; float venv = 0, fenv = 0; float att = 0, aenv = 0; float _cutoff = 0.28f; float _resonance = 0.6f; float _envmod = 0.3f; float _decay = 0.f; float _overdrive = 0.f; Filter flt[2] = {}; float *audio_out[2] = {nullptr, nullptr}; float *audio_in[2] = {nullptr, nullptr}; void engine::setup() { audio_out[0] = engine::outputBuffer_f32(OUT_AUDIO_L); audio_out[1] = engine::outputBuffer_f32(OUT_AUDIO_R); engine::addParam("Cutoff", &_cutoff); engine::addParam("Reso", &_resonance); engine::addParam("EnvMod", &_envmod); engine::addParam("Decay", &_decay); engine::addParam("Overdrive", &_overdrive); } void engine::process() { audio_in[0] = engine::inputBuffer<0>(); audio_in[1] = engine::inputBuffer<1>(); if (engine::trig()) { fenv = 1; att = 0; aenv = engine::accent() ? 1.f : 0.f; } for (size_t i = 0; i < FRAME_BUFFER_SIZE; i++) { att = std::min(att + 2000.f / SAMPLE_RATE, 1.f); if (engine::gate() || !engine::hasTrig()) venv = 1; venv *= .995f; fenv *= std::exp(-(1.f - _decay) * .004f); for (int ch = 0; ch < 2; ++ch) { float v = audio_in[ch][i]; flt[ch].set_f_q(_cutoff * 5.f - 5.f + fenv * _envmod * 5.f + aenv * .4f, 1.f - _resonance * .8f - aenv * .1f); v = flt[ch].process(v); v *= venv * att * (aenv + 1.f) * .5f; if (_overdrive > 0) v = tanhf(v * (1 + _overdrive * 8.f)); audio_out[ch][i] = v; } aenv *= .999f; } } ================================================ FILE: src/FILTER/TeeBee.cpp ================================================ // Copyright (C)2025 - E.Heidt // // Author: eh2k@gmx.de // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // Adapted from: rosic_Open303.cpp/rosic_Open303.h f // See also: https://www.timstinchcombe.co.uk/index.php?pge=diode2 #include "../squares-and-circles-api.h" #undef SAMPLE_RATE #define REAL_T_IS_DOUBLE #include "open303/src/rosic_BiquadFilter.cpp" #include "open303/src/rosic_DecayEnvelope.cpp" #include "open303/src/rosic_EllipticQuarterBandFilter.cpp" #include "open303/src/rosic_LeakyIntegrator.cpp" #include "open303/src/rosic_OnePoleFilter.cpp" #include "open303/src/rosic_TeeBeeFilter.cpp" using namespace rosic; #ifdef REAL_T_IS_DOUBLE static_assert(sizeof(real_t) == sizeof(double), "real_t is double"); #else static_assert(sizeof(real_t) == sizeof(float), "real_t is float"); #endif struct TB303_filter { rosic::TeeBeeFilter filter; rosic::LeakyIntegrator rc1; rosic::LeakyIntegrator rc2; rosic::DecayEnvelope mainEnv; rosic::EllipticQuarterBandFilter antiAliasFilter; rosic::OnePoleFilter highpass1, highpass2, allpass; rosic::BiquadFilter notch; real_t envScaler = 0; real_t envOffset = 0; int32_t oversampling = 1; void init(int32_t _oversampling = 1) { oversampling = _oversampling; highpass1.setSampleRate(SAMPLE_RATE * oversampling); highpass2.setSampleRate(SAMPLE_RATE); filter.setSampleRate(SAMPLE_RATE * oversampling); allpass.setSampleRate(SAMPLE_RATE); notch.setSampleRate(SAMPLE_RATE); mainEnv.setSampleRate(SAMPLE_RATE); rc1.setSampleRate(SAMPLE_RATE); rc2.setSampleRate(SAMPLE_RATE); filter.setMode(rosic::TeeBeeFilter::TB_303); filter.setFeedbackHighpassCutoff(150.0); highpass1.setMode(OnePoleFilter::HIGHPASS); highpass2.setMode(OnePoleFilter::HIGHPASS); allpass.setMode(OnePoleFilter::ALLPASS); notch.setMode(BiquadFilter::BANDREJECT); // tweakables: highpass1.setCutoff(44.486); highpass2.setCutoff(24.167); allpass.setCutoff(14.008); notch.setFrequency(7.5164); notch.setBandwidth(4.7); rc1.setTimeConstant(0.0); rc2.setTimeConstant(30.0); highpass1.reset(); highpass2.reset(); filter.reset(); notch.reset(); antiAliasFilter.reset(); } void calculateEnvModScalerAndOffset(real_t cutoff, real_t envMod) // Open303::calculateEnvModScalerAndOffset() { // define some constants that arise from the measurements: const real_t c0 = 3.138152786059267e+002; // lowest nominal cutoff const real_t c1 = 2.394411986817546e+003; // highest nominal cutoff const real_t oF = 0.048292930943553; // factor in line equation for offset const real_t oC = 0.294391201442418; // constant in line equation for offset const real_t sLoF = 3.773996325111173; // factor in line eq. for scaler at low cutoff const real_t sLoC = 0.736965594166206; // constant in line eq. for scaler at low cutoff const real_t sHiF = 4.194548788411135; // factor in line eq. for scaler at high cutoff const real_t sHiC = 0.864344900642434; // constant in line eq. for scaler at high cutoff // do the calculation of the scaler and offset: real_t e = envMod; // linToLin(envMod, 0.0, 100.0, 0.0, 1.0); real_t c = cutoff; // expToLin(cutoff, c0, c1, 0.0, 1.0); real_t sLo = sLoF * e + sLoC; real_t sHi = sHiF * e + sHiC; envScaler = (1 - c) * sLo + c * sHi; envOffset = oF * c + oC; } void process(bool trig, float _cutoff, float _q, float _envMod, float _accent, float _decay, const float *intput_frame, float *output_frame) { mainEnv.setDecayTimeConstant(rosic::linToExp(_decay, 0.0, 1.0, 200.0, 2000.0)); if (trig) mainEnv.trigger(); calculateEnvModScalerAndOffset(_cutoff, _envMod); float cutoff = rosic::linToExp(_cutoff, 0.0, 1.0, 313.0, 2394.0); float q = 1.f + _q * 99.f; filter.setResonance(q, false); filter.setDrive(8.f); real_t n2 = 1.f; // LeakyIntegrator::getNormalizer(mainEnv.getDecayTimeConstant(), rc2.getTimeConstant(), SAMPLE_RATE); real_t n1 = 1.f; // LeakyIntegrator::getNormalizer(mainEnv.getDecayTimeConstant(), rc1.getTimeConstant(), SAMPLE_RATE); for (size_t i = 0; i < FRAME_BUFFER_SIZE; ++i) { real_t mainEnvOut = mainEnv.getSample(); real_t tmp1 = n1 * rc1.getSample(mainEnvOut); real_t tmp2 = 0.0; if (_accent > 0.0) tmp2 = mainEnvOut; tmp2 = n2 * rc2.getSample(tmp2); tmp1 = envScaler * (tmp1 - envOffset); // seems not to work yet tmp2 = _accent * tmp2; real_t instCutoff = cutoff * powf(2.0f, tmp1 + tmp2); filter.setCutoff(instCutoff); real_t tmp = intput_frame[i]; for (int i = 1; i <= oversampling; i++) { tmp = highpass1.getSample(tmp); tmp = filter.getSample(tmp); //tmp = antiAliasFilter.getSample(tmp); } tmp = allpass.getSample(tmp); tmp = highpass2.getSample(tmp); tmp = notch.getSample(tmp); output_frame[i] = tmp * 3.f; } } } _left, _right; float _cutoff = 0.5f; float _q = 0.5f; float _envMod = 0.5f; float _decay = 0.5f; float _accent = 1.0f; int32_t _oversampling = 1; void engine::setup() { _left.init(); _right.init(); engine::addParam("Cutoff", &_cutoff); engine::addParam("Res", &_q); engine::addParam("EnvMode", &_envMod); engine::addParam("Decay", &_decay); engine::addParam("Accent", &_accent); } void engine::process() { auto inputL = engine::inputBuffer<0>(); auto inputR = engine::inputBuffer<1>(); auto outputL = engine::outputBuffer<0>(); auto outputR = engine::outputBuffer<1>(); _left.process(engine::trig(), _cutoff, _q, _envMod, _accent, _decay, inputL, outputL); _right.process(engine::trig(), _cutoff, _q, _envMod, _accent, _decay, inputR, outputR); } ================================================ FILE: src/FX/Delay.cpp ================================================ // Copyright (C)2021 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" #include "stmlib/dsp/filter.h" #include "stmlib/dsp/delay_line.h" #include #define clamp(value, min, max) \ (value > max ? max : value < min ? min \ : value) int32_t time_steps = 16; float raw = 1.f; float time = 0.5f; float color = 0.5f; float level = 0.5f; float pan = 0.5f; constexpr static int delay_len = 48000; // 1s stmlib::DelayLine delay_mem0; stmlib::DelayLine delay_mem1; stmlib::OnePole filterLP0; stmlib::OnePole filterLP1; stmlib::OnePole filterHP0; stmlib::OnePole filterHP1; inline const float DelayRead(stmlib::DelayLine *line_, float delay) { return static_cast(static_cast(line_->Read(delay))) / 32768.0f; } inline void DelayWrite(stmlib::DelayLine *line_, const float sample) { line_->Write(static_cast( stmlib::Clip16(static_cast(sample * 32768.0f)))); } char time_info[64] = "Time"; void engine::setup() { delay_mem0.Init(); delay_mem1.Init(); filterLP0.Init(); filterLP1.Init(); filterHP0.Init(); filterHP1.Init(); engine::addParam("D/W", &raw); engine::addParam(time_info, &time_steps, 1, 128); engine::addParam("Feedb", &level); engine::addParam("Color", &color); engine::addParam("Pan", &pan); } float delay = 0; float t_32 = 0; void calc_t_step32() { uint32_t clk_bpm = engine_sync::clk_bpm();// / 100; if (clk_bpm > 0) { uint32_t bpm = clk_bpm; auto t_per_beat = 6000.f / bpm; // * machine::SAMPLE_RATE t_32 = t_per_beat / 32; } else { t_32 = 1.f / 128.f; } } void sync_params() { calc_t_step32(); time = time_steps * t_32; float colorFreq = powf(100.f, 2.f * color - 1.f); float lowpassFreq = clamp(20000.f * colorFreq, 20.f, 20000.f) / SAMPLE_RATE; float highpassFreq = clamp(20.f * colorFreq, 20.f, 20000.f) / SAMPLE_RATE; filterLP0.set_f(lowpassFreq); filterLP1.set_f(lowpassFreq); filterHP0.set_f(highpassFreq); filterHP1.set_f(highpassFreq); } void engine::process() { sync_params(); int n = time / t_32; float d = n * t_32 * SAMPLE_RATE; if (fabsf(d - delay) > SAMPLE_RATE / 10) delay = d; else ONE_POLE(delay, d, 0.01f); auto inputL = engine::inputBuffer<0>(); auto inputR = engine::inputBuffer<1>(); auto outputL = engine::outputBuffer<0>(); auto outputR = engine::outputBuffer<1>(); for (int i = 0; i < FRAME_BUFFER_SIZE; i++) { float readL = DelayRead(&delay_mem0, (int)delay); float readR = DelayRead(&delay_mem1, (int)delay); auto inL = inputL[i]; auto inR = inputR[i]; inL = filterLP0.Process(inL); inL = filterHP0.Process(inL); inR = filterLP1.Process(inR); inR = filterHP1.Process(inR); DelayWrite(&delay_mem0, (readR + inL * (0 + pan) * 2) * level); DelayWrite(&delay_mem1, (readL + inR * (1 - pan) * 2) * level); outputL[i] = readL + inputL[i]; outputR[i] = readR + inputR[i]; outputL[i] = raw * outputL[i] + (1 - raw) * inputL[i]; outputR[i] = raw * outputR[i] + (1 - raw) * inputR[i]; } } void engine::draw() { if (engine_sync::clk_bpm() > 0) { sprintf(time_info, ">t=%d", time_steps); } else sprintf(time_info, ">T:%d ms", (int)(time * 1000)); } ================================================ FILE: src/FX/JU60_chorus.cpp ================================================ // Copyright (C)2022 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // // Credits to Andy Harman and JP Cimalando for Juno 60 chorus research, and Émilie Gillet for stmlib. // https://github.com/pendragon-andyh/Juno60/blob/master/Chorus/README.md // https://github.com/pendragon-andyh/Juno60/issues/2 // https://github.com/jpcima/rc-effect-playground/issues/2#issuecomment-541340615 // https://github.com/jpcima/string-machine/tree/master/sources/bbd #include "../squares-and-circles-api.h" #ifdef ONE_POLE #undef ONE_POLE #endif #include #include "bbd/bbd_line.h" #include "stmlib/dsp/filter.h" #include "stmlib/dsp/delay_line.h" #include "stmlib/dsp/dsp.h" #include "bbd/bbd_line.cc" #include "bbd/bbd_filter.cc" struct Juno60_Chorus { static constexpr size_t delay_size = (1 + SAMPLE_RATE * 0.0054); // max delay time stmlib::DelayLine delay_; stmlib::Svf pre_lpf, post_lpf_l, post_lpf_r; float phase_ = 0; float lfo_tri(float phase_inc_) { float t = -1.0f + (2.0f * phase_); phase_ += phase_inc_; if (phase_ > 1.0f) phase_ -= 1.0f; return fabsf(t); } struct Mode { float freq; float dry; float minDelayL; float maxDelayL; float minDelayR; float maxDelayR; bool stereo; }; const Mode modes_[4] = { {0.513, 1.0, 0.00154, 0.00515, 0.00151, 0.0054, true}, // Off {0.513, 0.44, 0.00154, 0.00515, 0.00151, 0.0054, true}, // Mode I {0.863, 0.44, 0.00154, 0.00515, 0.00151, 0.0054, true}, // Mode II {9.75, 0.44, 0.00322, 0.00356, 0.00328, 0.00365, false}, // Mode I+II }; Mode mode_ = modes_[1]; float lmin, la; float rmin, ra; void setMode(const Mode &mode) { mode_ = mode; lmin = mode_.minDelayL * SAMPLE_RATE; la = (mode_.maxDelayL - mode_.minDelayL) * SAMPLE_RATE; rmin = mode_.minDelayR * SAMPLE_RATE; ra = (mode_.maxDelayR - mode_.minDelayR) * SAMPLE_RATE; } Juno60_Chorus() { delay_.Init(); pre_lpf.Init(); post_lpf_l.Init(); post_lpf_r.Init(); pre_lpf.set_f_q(7237.f / SAMPLE_RATE, 1.f); post_lpf_l.set_f_q(10644.f / SAMPLE_RATE, 1.f); post_lpf_r.set_f_q(10644.f / SAMPLE_RATE, 1.f); } void process(float *inOut, float *outR, uint32_t len) { float wet = 1.f - mode_.dry; float f = mode_.freq / SAMPLE_RATE; while (len-- > 0) { float lfo_val = lfo_tri(f); *inOut = *outR = *inOut * mode_.dry; delay_.Write(pre_lpf.Process(stmlib::SoftLimit(*inOut))); auto l = delay_.Read(lmin + la * lfo_val); *inOut++ += post_lpf_l.Process(l * wet); auto r = delay_.Read(rmin + ra * (mode_.stereo ? (1.f - lfo_val) : lfo_val)); *outR++ += post_lpf_r.Process(r * wet); } } }; struct Juno60_Chorus_BBD { // https://github.com/jpcima/bbd-delay-experimental // Not sure if the emulation of the correct MN3009 BBD chips ? // But it sounds better than the naive emulation ;-) // For details - see also https://github.com/jpcima/bbd-delay-experimental/issues/1 static constexpr int bbd_stages = 185; // the TCA-350-Y IC BBD_Line _delayL; BBD_Line _delayR; BBD_Filter_Coef fin; BBD_Filter_Coef fout; struct Mode { float freq; float dry; float minDelayL; float maxDelayL; float minDelayR; float maxDelayR; bool stereo; }; // https://github.com/pendragon-andyh/Juno60/blob/master/Chorus/README.md const Mode modes_[4] = { {0.513, 1.0, 0.00154, 0.00515, 0.00151, 0.0054, true}, // Off {0.513, 0.44, 0.00154, 0.00515, 0.00151, 0.0054, true}, // Mode I {0.863, 0.44, 0.00154, 0.00515, 0.00151, 0.0054, true}, // Mode II {9.75, 0.44, 0.00322, 0.00356, 0.00328, 0.00365, false}, // Mode I+II }; Mode mode_ = modes_[1]; float minL, maxL, minR, maxR; void setMode(const Mode &mode) { mode_ = mode; minL = BBD_Line::hz_rate_for_delay(mode_.minDelayL, bbd_stages) / SAMPLE_RATE; maxL = BBD_Line::hz_rate_for_delay(mode_.maxDelayL, bbd_stages) / SAMPLE_RATE; minR = BBD_Line::hz_rate_for_delay(mode_.minDelayR, bbd_stages) / SAMPLE_RATE; maxR = BBD_Line::hz_rate_for_delay(mode_.maxDelayR, bbd_stages) / SAMPLE_RATE; } Juno60_Chorus_BBD() { const unsigned interp_size = 128; fin = BBD::compute_filter(SAMPLE_RATE, interp_size, bbd_fin_j60); fout = BBD::compute_filter(SAMPLE_RATE, interp_size, bbd_fout_j60); _delayL.setup(bbd_stages, fin, fout); _delayR.setup(bbd_stages, fin, fout); _delayL.clear(); _delayR.clear(); } float phase_ = 0; void lfo_tri(float phase_inc_, float *out) { for (size_t i = 0; i < FRAME_BUFFER_SIZE; i++) { float t = -1.0f + (2.0f * phase_); *out++ = fabsf(t); phase_ += phase_inc_; if (phase_ > 1.0f) phase_ -= 1.0f; } } void process(float *inOut, float *outR, uint32_t len) { float wet = 1.f - mode_.dry; float f = mode_.freq / SAMPLE_RATE; float dry[FRAME_BUFFER_SIZE]; float clockL[FRAME_BUFFER_SIZE]; float clockR[FRAME_BUFFER_SIZE]; memcpy(dry, inOut, len * sizeof(float)); lfo_tri(f, clockL); for (size_t i = 0; i < FRAME_BUFFER_SIZE; i++) { dry[i] = stmlib::SoftLimit(dry[i]); auto lfo = clockL[i]; clockL[i] = minL + lfo * (maxL - minL); clockR[i] = minR + (mode_.stereo ? (1.f - lfo) : lfo) * (maxR - minR); } _delayL.process(FRAME_BUFFER_SIZE, dry, inOut, clockL); _delayR.process(FRAME_BUFFER_SIZE, dry, outR, clockR); for (size_t i = 0; i < FRAME_BUFFER_SIZE; i++) { inOut[i] = inOut[i] * wet + dry[i] * mode_.dry; outR[i] = outR[i] * wet + dry[i] * mode_.dry; } } }; static Juno60_Chorus_BBD _chorus = {}; static int32_t mode = 1; static const char *modes[] = { "Off", "Mode I", "Mode II", "Mode I+II"}; static float raw = 1.f; void engine::setup() { engine::addParam("Amount", &raw); engine::addParam(">Modes", &mode, 0, 3, modes); } void set(float *target, const float *src, float amp) { for (size_t i = 0; i < FRAME_BUFFER_SIZE; i++) target[i] = src[i] * amp; } void mix(float *target, const float *src, float amp) { for (size_t i = 0; i < FRAME_BUFFER_SIZE; i++) target[i] += src[i] * amp; } void engine::process() { auto inputL = engine::inputBuffer<0>(); auto inputR = engine::inputBuffer<1>(); auto outputL = engine::outputBuffer<0>(); auto outputR = engine::outputBuffer<1>(); set(outputL, inputL, raw); set(outputR, inputR, raw); _chorus.setMode(_chorus.modes_[mode]); _chorus.process(outputL, outputR, FRAME_BUFFER_SIZE); mix(outputL, inputL, 1.f - raw); mix(outputR, inputR, 1.f - raw); } ================================================ FILE: src/FX/Rev-Dattorro.cpp ================================================ #include "../squares-and-circles-api.h" #include "faust/ui.hxx" #include "faust/rev_dattorro.dsp.h" void UIGlue::addButton(const char *ui, const char *label, float *zone) { engine::addParam("TRIG", zone); } void UIGlue::addNumEntry(const char *ui, const char *label, float *zone, float init, float min, float max, float step) { } void UIGlue::addCheckButton(const char *ui, const char *label, float *zone) { addHorizontalSlider(ui, label, zone, 0, 0, 1, 1); } void UIGlue::addVerticalSlider(const char *ui, const char *label, float *zone, float init, float min, float max, float step) { addHorizontalSlider(ui, label, zone, init, min, max, step); } void UIGlue::addHorizontalSlider(const char *ui, const char *label, float *zone, float init, float min, float max, float step) { if (zone) { *zone = init; engine::addParam(label, zone, min, max); } } static FAUSTCLASS dsp; void engine::setup() { initmydsp(&dsp, SAMPLE_RATE); UIGlue ui; buildUserInterfacemydsp(&dsp, &ui); } void engine::process() { float *tmp[4]; tmp[0] = engine::inputBuffer<0>(); tmp[1] = engine::inputBuffer<1>(); tmp[2] = engine::outputBuffer<0>(); tmp[3] = engine::outputBuffer<1>(); computemydsp(&dsp, FRAME_BUFFER_SIZE, &tmp[0], &tmp[2]); } ================================================ FILE: src/FX/Reverb.cpp ================================================ // Copyright (C)2021 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" #include "clouds/dsp/fx/reverb.h" float raw = 1.f; float reverb_amount = 0.75f; float feedback = 0.5f; float gain = 1.f; uint16_t buffer[16384] = {}; clouds::Reverb fx_; void engine::setup() { fx_.Init(buffer); engine::addParam("D/W", &raw); engine::addParam("Reverb", &reverb_amount); engine::addParam("Damp", &feedback); engine::addParam("Gain", &gain); } void engine::process() { auto inputL = engine::inputBuffer<0>(); auto inputR = engine::inputBuffer<1>(); auto outputL = engine::outputBuffer<0>(); auto outputR = engine::outputBuffer<1>(); fx_.set_amount(reverb_amount * 0.54f); fx_.set_diffusion(0.7f); fx_.set_time(0.35f + 0.63f * reverb_amount); fx_.set_input_gain(gain * 0.1f); // 0.1f); fx_.set_lp(0.6f + 0.37f * feedback); for (int i = 0; i < FRAME_BUFFER_SIZE; i++) { outputL[i] = inputL[i]; outputR[i] = inputR[i]; } fx_.Process(outputL, outputR, FRAME_BUFFER_SIZE); for (int i = 0; i < FRAME_BUFFER_SIZE; ++i) { outputL[i] = raw * outputL[i] + (1 - raw) * inputL[i]; outputR[i] = raw * outputR[i] + (1 - raw) * inputR[i]; } } ================================================ FILE: src/FX/ReverbSC.cpp ================================================ // Copyright (C)2022 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" #include "soundpipe/revsc.c" static sp_data sp_data_ = {}; static sp_revsc sp_revsc_ = {}; static uint8_t mem[107440]; // sp_revsc_.aux.size static float raw = 1.f; void engine::setup() { sp_data_.sr = SAMPLE_RATE; sp_data_.aux.ptr = &mem[0]; sp_data_.aux.size = sizeof(mem); sp_revsc_init(&sp_data_, &sp_revsc_); sp_revsc_.feedback = 0.97f; sp_revsc_.lpfreq = 10000; engine::addParam("D/W", &raw); engine::addParam("Feedback", &sp_revsc_.feedback); engine::addParam("LpFreq", &sp_revsc_.lpfreq, 0, (SAMPLE_RATE / 2)); } void engine::process() { auto inputL = engine::inputBuffer<0>(); auto inputR = engine::inputBuffer<1>(); auto outputL = engine::outputBuffer<0>(); auto outputR = engine::outputBuffer<1>(); for (int i = 0; i < FRAME_BUFFER_SIZE; ++i) { sp_revsc_compute(&sp_data_, &sp_revsc_, &inputL[i], &inputR[i], &outputL[i], &outputR[i]); outputL[i] = raw * outputL[i] + (1 - raw) * inputL[i]; outputR[i] = raw * outputR[i] + (1 - raw) * inputR[i]; } } ================================================ FILE: src/GND/FFT.cpp ================================================ // Copyright (C)2024 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" #include "../lib/stmlib/utils/ring_buffer.h" extern "C" { #include "../lib/fft/fft4g.h" #include "../lib/fft/fft4g.c" } #include #include static float apmlitude = 1.f; static int32_t band = 0; static const char *sbands[3] = {" 16", " 32", " 64"}; struct Complex { float re; float im; }; const size_t N = 1024; stmlib::RingBuffer spectrum; float w[N * 2]; constexpr int sq_n = 32; // sqrt(N); int ip[4 + sq_n]; // new int[(int)ceil(4.0 + sqrt((real_t)N))]; float magnitudes[N / 2] = {}; float window[N]; int count = 0; void engine::setup() { apmlitude = 1.f; engine::addParam("_Scale", &apmlitude, 0.f, 2.f); engine::addParam("_Bands", &band, 0, 2, sbands); engine::setMode(ENGINE_MODE_COMPACT); ip[0] = 0; // indicate that re-initialization is necesarry spectrum.Init(); for (int n = 0; n < N; n++) window[n] = 0.5f * (1.f - cosf((2.f * M_PI * n) / N)); } void set(float *target, const float *src, float amp, float offset) { for (size_t i = 0; i < FRAME_BUFFER_SIZE; i++) target[i] = src[i] * amp + offset; } void engine::process() { const float m_offset = log10f(N); auto inputL = engine::inputBuffer<0>(); auto inputR = engine::inputBuffer<1>(); auto outputL = engine::outputBuffer<0>(); auto outputR = engine::outputBuffer<1>(); set(outputL, inputL, apmlitude, 0); set(outputR, inputR, apmlitude, 0); for (size_t i = 0; i < FRAME_BUFFER_SIZE; i += 2) { if (spectrum.readable() == (N / 2)) { float *buff = const_cast(&spectrum.ImmediateReadPtr(0)->re); rdft(N, 1, buff, ip, w); // for some reason, this routine returns the second half of the spectrum (the complex conjugate // values of the desired first half), so we need to take the complex conjugates: for (int n = 3; n < N; n += 2) // start at n=3 (imaginary part of the first bin after DC) buff[n] = -buff[n]; magnitudes[0] = buff[0]; for (int k = 1; k < N / 2; k++) { float re = buff[2 * k]; float im = buff[2 * k + 1]; magnitudes[k] += sqrtf(re * re + im * im); // auto db = sqrtf(re * re + im * im); // auto db = 20 * log10f(db); // auto db = logf(re * re + im * im); // magnitudes[k] = db; } count++; spectrum.Flush(); } else { float h = (float)window[spectrum.readable() * 2]; float h2 = (float)window[spectrum.readable() * 2 + 1]; Complex v = { outputL[i] * h / sq_n, outputL[i + 1] * h2 / sq_n, }; spectrum.Overwrite(v); } } } float fft_read(int s, int e) { float sum = 0; while (s <= e) sum += magnitudes[s++]; return (sum / count); } float level2[64]; float level[64]; void draw_spectrum(int yy, int hh) { float logN2 = logf(N / 2); int bands = 16; if (band == 1) bands = 32; else if (band == 2) bands = 64; int to = int(expf(logN2 * 0 / bands)); for (int b = 0; b < bands; b++) { int fr = to; to = int(expf(logN2 * (b + 1) / bands)); if (level2[b] > 0) level2[b] -= 0.1f; else level2[b] = 0; level[b] = 10.f / hh + log10f(fft_read(fr, to)); level2[b] = std::max(level[b], level2[b]); } int w = (128 / bands); for (size_t i = 0; i < bands; i++) { auto y = level[i] * hh; gfx::fillRect(i * w, yy - y, w - 1, y); y = level2[i] * hh; gfx::fillRect(i * w, yy - 1 - y, w - 1, 1); } // uint32_t ylim = 58; // for (uint32_t i = 0; i < 128; i++) // { // auto y = 40 + -(magnitudes[i] / 2); // gfx::drawLine(i, 58, i, y); // }; for (uint32_t i = 0; i < (N / 2); i++) magnitudes[i] = 0; count = 0; } void engine::draw() { draw_spectrum(60, 32); } void engine::screensaver() { gfx::clearRect(0, 0, 128, 64); draw_spectrum(64, 48); } ================================================ FILE: src/GND/Scope.cpp ================================================ // Copyright (C)2024 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" #include float apmlitude = 1.f; int32_t x_scale = 32; float offset = 0.f; float input = 0.f; float output = 0.f; float *inputL = nullptr; float *inputR = nullptr; float *outputL = nullptr; float *outputR = nullptr; float scope[FRAME_BUFFER_SIZE] = {}; void engine::setup() { apmlitude = 1.f; engine::addParam("_Y-Scale", &apmlitude, 0.f, 2.f); engine::addParam("_Offset", &offset, -1.f, 1.f); engine::addParam("_X-Scale", &x_scale, 0, 63); engine::setMode(ENGINE_MODE_COMPACT); } void set(float *target, const float *src, float amp, float offset) { for (size_t i = 0; i < FRAME_BUFFER_SIZE; i++) target[i] = src[i] * amp + offset; } void engine::process() { inputL = engine::inputBuffer<0>(); inputR = engine::inputBuffer<1>(); outputL = engine::outputBuffer<0>(); outputR = engine::outputBuffer<1>(); input = (inputL[0] + inputR[0]) / 2.f; set(outputL, inputL, apmlitude, offset); set(outputR, inputR, apmlitude, offset); output = (outputL[0] + outputR[0]) / 2.f; for (size_t j = 0; j < FRAME_BUFFER_SIZE; j++) scope[j] = (outputL[j] + outputR[j]) / 2.f; } void engine::draw() { gfx::drawScope(38, scope, x_scale); char tmp[64]; sprintf(tmp, "IN:%+1.2fV", input * 5); gfx::drawString(0, 54, tmp, 0); sprintf(tmp, "OUT:%+1.2fV", output * 5); gfx::drawString(64, 54, tmp, 0); } void engine::screensaver() { gfx::clearRect(0, 0, 128, 64); gfx::drawScope(32, scope, x_scale); } ================================================ FILE: src/M-OSC/Waveforms.cpp ================================================ // Copyright (C)2021 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // xuild_flags: -fno-inline -mfloat-abi=soft -mfpu=fpv5-d16 #include "../squares-and-circles-api.h" #include "stmlib/stmlib.h" #define private public #include "braids/macro_oscillator.h" #include "braids/envelope.h" #include "braids/settings.h" #include "braids/vco_jitter_source.h" #include "braids/quantizer.h" #define SemitonesToRatioFast #include "lib/plaits/dsp/chords/chord_bank.cc" plaits::ChordBank chords_; int32_t chords_mem[(plaits::kChordNumChords * plaits::kChordNumNotes) + plaits::kChordNumChords + plaits::kChordNumNotes]; braids::MacroOscillator osc1; braids::MacroOscillator osc2; braids::Envelope envelope; braids::VcoJitterSource jitter_source; braids::Quantizer quantizer; constexpr int32_t DEFAULT_PITCH = PITCH_PER_OCTAVE * 6; namespace braids { uint8_t ex_chord[7] = {}; extern const uint8_t diatonic_chords[8][6]; extern const uint8_t *custom_chord; void Quantizer::Init() { } bool Quantizer::enabled() { return engine::qz_enabled(); } int32_t Quantizer::Process(int32_t pitch, int32_t root, int8_t *note) { pitch -= root + DEFAULT_PITCH; auto ret = engine::qz_process(pitch, note); ret += root + DEFAULT_PITCH; return ret; } int16_t Quantizer::Lookup(uint8_t index) { return engine::qz_lookup(index) + DEFAULT_PITCH; } } uint8_t sync_samples[FRAME_BUFFER_SIZE] = {}; int32_t _pitch = 0; int32_t _shape = 0; int32_t _timbre = UINT16_MAX / 2; int32_t _color = UINT16_MAX / 2; int32_t _stereo = 0; int32_t _decay = UINT16_MAX / 2; auto _out_l = engine::outputBuffer_i16(OUT_AUDIO_L); auto _out_r = engine::outputBuffer_i16(OUT_AUDIO_R); int32_t last_color = -1; int32_t last_shape = -1; int32_t last_qz = -1; void engine::setup() { stmlib::BufferAllocator allocator; allocator.Init(chords_mem, sizeof(chords_mem)); chords_.Init(&allocator); chords_.chord_index_quantizer_.hysteresis_ = 0; // input => output chords_.Reset(); braids::settings.Init(); osc1.Init(); osc2.Init(); jitter_source.Init(); envelope.Init(); quantizer.Init(); // std::fill(&sync_samples[0], &sync_samples[FRAME_BUFFER_SIZE], 0); // settings.SetValue(SETTING_AD_VCA, true); braids::settings.SetValue(braids::SETTING_SAMPLE_RATE, 5); braids::settings.SetValue(braids::SETTING_PITCH_RANGE, braids::PITCH_RANGE_EXTERNAL); engine::addParam(V_OCT, &_pitch, -4 * PITCH_PER_OCTAVE, 4 * PITCH_PER_OCTAVE); // is added internal to engine::cv engine::addParam("Shape", &_shape, braids::MACRO_OSC_SHAPE_CSAW, braids::MACRO_OSC_SHAPE_LAST - 1, (const char **)braids::settings.metadata(braids::Setting::SETTING_OSCILLATOR_SHAPE).strings); engine::addParam("Timbre", &_timbre, 0, UINT16_MAX); engine::addParam("Color", &_color, 0, UINT16_MAX); engine::addParam("Decay", &_decay, 0, UINT16_MAX); engine::addParam("Stereo", &_stereo, 0, UINT16_MAX); } char color_vals[64]; void engine::process() { if (last_shape != _shape || last_qz != engine::qz()) { last_qz = engine::qz(); last_shape = _shape; engine::draw(); } envelope.Update(0, _decay / 512); if (engine::trig()) { osc1.Strike(); osc2.Strike(); envelope.Trigger(braids::ENV_SEGMENT_ATTACK); } if (engine::gate()) { // Not working witch Attack > 0 // envelope.Trigger(braids::ENV_SEGMENT_DECAY); } uint32_t ad_value = envelope.Render(); int32_t pitch = engine::cv_i32(); pitch += DEFAULT_PITCH; // if (!settings.meta_modulation()) // { // pitch += settings.adc_to_fm(adc_3); // } pitch += jitter_source.Render(braids::settings.vco_drift()); pitch += ad_value * braids::settings.GetValue(braids::SETTING_AD_FM) >> 7; CONSTRAIN(pitch, 0, 16383); if (braids::settings.vco_flatten()) pitch = stmlib::Interpolate88(braids::lut_vco_detune, pitch << 2); uint32_t gain = _decay < UINT16_MAX ? ad_value : UINT16_MAX; if (!engine::hasTrig()) gain = _decay; // No Trigger patched - use Decay as VCA... if ((engine::t() % 12) != 0) osc1.set_shape((braids::MacroOscillatorShape)_shape); else if ((engine::t() % 12) != 6) osc2.set_shape((braids::MacroOscillatorShape)_shape); osc1.set_parameters(_timbre >> 1, _color >> 1); if (_shape >= 48 && _shape < (48 + 5) && engine::qz() > 0) { if (engine::qz() == 1) { if (last_color != _color) { last_color = _color; chords_.set_chord((float)_color / (plaits::kChordNumChords - 1)); // chords_.Sort(); memset(braids::ex_chord, 0, sizeof(braids::ex_chord)); for (int i = 0; i < chords_.num_notes(); i++) { braids::ex_chord[i] = log2f(chords_.ratio(i)) * 12; } braids::custom_chord = braids::ex_chord; } } else { osc1.set_parameters(_timbre >> 1, _color << 12); braids::custom_chord = nullptr; } } osc1.set_pitch(pitch); osc1.Render(sync_samples, _out_l, FRAME_BUFFER_SIZE); for (int i = 0; i < FRAME_BUFFER_SIZE; i++) _out_l[i] = (gain * _out_l[i]) / UINT16_MAX; if (_stereo > 0) // Stereo { const int32_t f = _stereo >> 8; int32_t stereo = (f * f * f) / (255 * 255); int32_t timbre = _timbre + stereo; if (timbre > UINT16_MAX) timbre = _timbre - stereo; int32_t color = _color + stereo; if (color > UINT16_MAX) color = _color - stereo; osc2.set_parameters(osc1.parameter_[0], osc1.parameter_[1]); osc2.set_pitch(pitch + stereo); osc2.Render(sync_samples, _out_r, FRAME_BUFFER_SIZE); for (int i = 0; i < FRAME_BUFFER_SIZE; i++) _out_r[i] = (gain * _out_r[i]) / UINT16_MAX; } else { memcpy(_out_r, _out_l, FRAME_BUFFER_SIZE * sizeof(int16_t)); } } void engine::draw() { if (_shape >= 48 && _shape < (48 + 5) && engine::qz() > 0) { if (engine::qz() == 1) { engine::addParam(".", &_color, 0, plaits::kChordNumChords - 1, (const char **)plaits::chord_names); } else { char *p = color_vals; p += sprintf(p, "Chord-%d\t1", _color + 1); for (int i = 1; i < LEN_OF(braids::diatonic_chords[_color]); i++) { if (braids::diatonic_chords[_color][i] != 0) { p += sprintf(p, "+%d", 1 + braids::diatonic_chords[_color][i]); } } engine::addParam("Color", &_color, 0, 7); engine::setParamName(&_color, color_vals); } } else { engine::addParam("Color", &_color, 0, UINT16_MAX); } if (!engine::hasTrig()) { engine::setParamName(&_decay, "Level"); } else if (_decay < UINT16_MAX) { engine::setParamName(&_decay, "Decay"); } else { engine::setParamName(&_decay, "VCA-off"); } } #include "braids/analog_oscillator.cc" #define kHighestNote kHighestNote2 #define kPitchTableStart kPitchTableStart2 #define kOctave kOctave2 #include "braids/digital_oscillator.cc" #include "braids/settings.cc" #include "braids/macro_oscillator.cc" #include "braids/resources.cc" #include "stmlib/utils/random.cc" #define chords chords2 #define mini_wave_line mini_wave_line2 #include "braids/chords_stack.cc" ================================================ FILE: src/MIDI/Clock.cpp ================================================ // Copyright (C)2021 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // build_flags: -fno-inline -mfloat-abi=soft -mfpu=fpv5-d16 #include "../squares-and-circles-api.h" #include static int32_t bpm = 120; static int32_t ppqn = 0; static const char *ppqn_names[]{ "4ppqn", "8ppqn", "24ppqn"}; static int32_t offset = 0; static int32_t impulse = 1; static int count_down = 0; static uint32_t next = UINT32_MAX; static uint32_t last_t = 0; int16_t* out_clk; int16_t* out_reset; void engine::setup() { // 24, 8 or 4 ppqn bpm = 120; // machine::midi_bpm() / 100; engine::addParam("@BPM\n%d", &bpm, 60, 250); engine::addParam("@MODE\n%s", &ppqn, 0, 2, ppqn_names); engine::addParam("@Impulse\n%dms", &impulse, 1, 5); engine::addParam("@Offset\n%dms", &offset, 0, 127); out_clk = engine::outputBuffer_i16(OUT_TRIG "CLK"); out_reset = engine::outputBuffer_i16(OUT_TRIG "RST"); } uint8_t last_clk = 0; uint8_t clk_change(uint8_t clk) { if (last_clk != clk) { last_clk = clk; return last_clk; } else return 0; } void engine::process() { bpm = engine_sync::clk_bpm() / 100; uint8_t clk = clk_change(engine_sync::ppn()); if (clk) last_t = engine::t(); uint32_t div = ppqn == 0 ? 6 : (ppqn == 1 ? 3 : 1); if ((clk % div) == 1 || (ppqn > 1 && clk)) { next = engine::t() + (offset * 2); } if (engine::t() == next) { next = UINT32_MAX; count_down = (impulse * 2); } int16_t a = count_down-- > 0 ? (5 * PITCH_PER_OCTAVE) : 0; std::fill_n(out_clk, FRAME_BUFFER_SIZE, a); std::fill_n(out_reset, FRAME_BUFFER_SIZE, clk == engine_sync::CLOCK_RESET ? (5 * PITCH_PER_OCTAVE) : 0); } void engine::draw() { } ================================================ FILE: src/MIDI/Monitor.cpp ================================================ #include "../squares-and-circles-api.h" #include "../lib/stmlib/algorithms/voice_allocator.h" static uint8_t voice[4] = {}; static uint8_t velocity[4] = {}; static stmlib::VoiceAllocator allocator = {}; static int16_t pitch = 0; static uint8_t cc[128] = {}; void engine::setup() { allocator.Init(); allocator.set_size(LEN_OF(voice)); engine::setMode(ENGINE_MODE_MIDI_IN); for (auto &c : cc) c = 0xFF; } void engine::process() { } void engine::draw() { gfx::drawString(1, 12, "VOICE KEY VEL", 0); gfx::drawString(66, 12, "CONTROL", 0); for (int x = 0; x < 128; x += 3) gfx::setPixel(x, 18); char tmp[30]; for (size_t i = 0; i < LEN_OF(voice); i++) { sprintf(tmp, "#%ld", i); gfx::drawString(2, 20 + i * 6, tmp, 0); sprintf(tmp, "%4d", voice[i]); gfx::drawString(27, 20 + i * 6, tmp, 0); sprintf(tmp, "%4d", velocity[i]); gfx::drawString(46, 20 + i * 6, tmp, 0); } for (int y = 12; y < 60; y += 3) gfx::setPixel(64, y); int bpm = engine_sync::clk_bpm(); int bpm2 = ((bpm % 100) / 10); sprintf(tmp, "clock: %3d.%d", bpm / 100, bpm2); gfx::drawString(66, 20, tmp, 0); sprintf(tmp, "pitch: %4d", pitch); gfx::drawString(66, 26, tmp, 0); int y = 32; for (int i = 0; i < 128; i++) { if (cc[i] < 0xFF) { sprintf(tmp, "cc-%d: %4d", i, cc[i]); gfx::drawString(66, y, tmp, 0); y += 6; } } } void engine::onMidiNote(uint8_t key, uint8_t vel) // NoteOff: velocity == 0 { if (vel > 0) { auto ni = allocator.NoteOn(key); voice[ni] = key; velocity[ni] = vel; } else { auto ni = allocator.NoteOff(key); voice[ni] = 0; } } void engine::onMidiPitchbend(int16_t value) { pitch = value; } void engine::onMidiCC(uint8_t ccc, uint8_t value) { cc[ccc % 128] = value; } void engine::onMidiSysex(uint8_t byte) { } void engine::onMidiRTM(uint8_t code) { } ================================================ FILE: src/MIDI/VAx6.cpp ================================================ // Copyright (C)2021 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" // #include "../lib/plaits/dsp/engine/virtual_analog_engine.h" // no virtual functions hack #define PLAITS_DSP_ENGINE_VIRTUAL_ANALOG_ENGINE_H_ #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/oscillator/variable_saw_oscillator.h" #include "plaits/dsp/oscillator/variable_shape_oscillator.h" #define VA_VARIANT 2 namespace plaits { class VirtualAnalogEngine { public: VirtualAnalogEngine() {} ~VirtualAnalogEngine() {} void Init(stmlib::BufferAllocator *allocator); void Reset(); void LoadUserData(const uint8_t *user_data) {} void Render(const EngineParameters ¶meters, float *out, float *aux, size_t size, bool *already_enveloped); private: float ComputeDetuning(float detune) const; VariableShapeOscillator primary_; VariableShapeOscillator auxiliary_; VariableShapeOscillator sync_; VariableSawOscillator variable_saw_; float auxiliary_amount_; float xmod_amount_; float *temp_buffer_; DISALLOW_COPY_AND_ASSIGN(VirtualAnalogEngine); }; } // namespace plaits #include "../lib/plaits/dsp/envelope.h" #include "../lib/stmlib/algorithms/voice_allocator.h" #include "../lib/stmlib/utils/random.h" #include "stmlib/dsp/units.cc" #include "stmlib/utils/random.cc" #include "../lib/plaits/dsp/engine/virtual_analog_engine.cc" plaits::VirtualAnalogEngine voice[6] = {}; uint8_t buffer[LEN_OF(voice) * plaits::kMaxBlockSize * sizeof(float)] = {}; plaits::EngineParameters parameters[LEN_OF(voice)] = {}; plaits::LPGEnvelope lpg[LEN_OF(voice)] = {}; bool enveloped[LEN_OF(voice)] = {}; stmlib::VoiceAllocator allocator; float timbre = 0.5f; float morph = 0.5f; float harmonics = 0.5f; float pitch = 0; float pitch_bend = 0; float decay = 0.5f; float hf = 1.f; float pan[LEN_OF(voice)] = {}; float stereo = 0.5f; float voiceBuff[FRAME_BUFFER_SIZE] = {}; float dummy[FRAME_BUFFER_SIZE] = {}; void engine::setup() { allocator.Init(); allocator.set_size(LEN_OF(voice)); engine::addParam(V_OCT, &pitch); engine::addParam("Harmo", &harmonics); engine::addParam("Timbre", &timbre); engine::addParam("Morph", &morph); engine::addParam("Decay", &decay); engine::addParam("Stereo", &stereo); engine::setMode(ENGINE_MODE_MIDI_IN); stmlib::BufferAllocator buffAllocator; buffAllocator.Init(buffer, sizeof(buffer)); for (size_t i = 0; i < LEN_OF(voice); i++) { lpg[i].Init(); voice[i].Init(&buffAllocator); } } void engine::process() { auto polyBuffL = engine::outputBuffer<0>(); auto polyBuffR = engine::outputBuffer<1>(); std::fill_n(polyBuffL, FRAME_BUFFER_SIZE, 0); std::fill_n(polyBuffR, FRAME_BUFFER_SIZE, 0); const float short_decay = (200.0f * FRAME_BUFFER_SIZE) / SAMPLE_RATE * stmlib::SemitonesToRatio(-96.0f * decay); const float decay_tail = (20.0f * FRAME_BUFFER_SIZE) / SAMPLE_RATE * stmlib::SemitonesToRatio(-72.0f * decay + 12.0f * hf) - short_decay; for (size_t i = 0; i < LEN_OF(voice); i++) { auto p = parameters[i]; p.note += (pitch * 12.f) + pitch_bend; p.timbre = timbre; p.morph = morph; p.harmonics = harmonics; voice[i].Render(p, voiceBuff, dummy, FRAME_BUFFER_SIZE, &enveloped[i]); lpg[i].ProcessPing(0.5f, short_decay, decay_tail, hf); float l = cosf(pan[i] * M_PI / 2); float r = sinf(pan[i] * M_PI / 2); for (int s = 0; s < FRAME_BUFFER_SIZE; s++) { polyBuffL[s] += (voiceBuff[s] * lpg[i].gain()) * l; polyBuffR[s] += (voiceBuff[s] * lpg[i].gain()) * r; } parameters[i].trigger = plaits::TriggerState::TRIGGER_LOW; } } void engine::draw() { } void engine::onMidiNote(uint8_t key, uint8_t velocity) // NoteOff: velocity == 0 { if (velocity > 0) { auto ni = allocator.NoteOn(key); parameters[ni].trigger = plaits::TriggerState::TRIGGER_RISING_EDGE; parameters[ni].note = key; parameters[ni].accent = velocity > 100; pan[ni] = 0.5f + stereo * (stmlib::Random::GetFloat() - 0.5f); lpg[ni].Trigger(); } else { allocator.NoteOff(key); } } void engine::onMidiPitchbend(int16_t pitch) { pitch_bend = ((float)pitch / 8192) * 12; } void engine::onMidiCC(uint8_t ccc, uint8_t value) { // nothing implemented.. } void engine::onMidiSysex(uint8_t byte) { } void engine::onMidiRTM(uint8_t code) { } ================================================ FILE: src/NOISE/808_squares.cpp ================================================ // Copyright (C)2022 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" #include "misc/nes_noise.hxx" #include "stmlib/dsp/filter.h" class SquareOscillator { public: inline void reset() { phase_ = 0.5f; } inline void freq(float freq) { phase_inc_ = freq / SAMPLE_RATE; } inline void duty(float duty) { pw_ = duty; } // float fm = 2.f; // float fm_amp = 0.05f; // float fm_phase = 0.5f; inline void process(float &out2) { float out = phase_ < pw_ ? 1.f : -1.f; // float fm_ = stmlib::Interpolate(plaits::lut_sine, fm_phase, 1024.0f) * fm_amp; // fm_phase += phase_inc_ / fm; // if (fm_phase > 1.0f) // fm_phase -= 1.00f; phase_ += phase_inc_; // * (1.f + fm_); if (phase_ > 1.0f) phase_ -= 1.00f; out2 += out; } private: float phase_ = 0.5f; float phase_inc_ = 0; float pw_ = 0.5f; }; SquareOscillator _osc[6] = {}; stmlib::DCBlocker _dc_blocker; float f = 1.f; float f0 = 540; float f1 = 800; float gain = 1.f; float duty = 0.5f; int32_t n = 6; void update_oscillators() { // 119, 176, 214, 303, 363, 666 // 205.3, 369.6, 404.4, 522.7, 359.4–1149.9, and 254.3–627.2 Hz constexpr float _808[] = {540, 800, 205.3f, 369.6f, 404.4f, 522.7f}; _osc[0].freq(f0 * f); _osc[1].freq(f1 * f); for (size_t i = 2; i < 6; i++) _osc[i].freq(_808[i] * f); } void engine::setup() { _dc_blocker.Init(0.999f); engine::addParam("Level", &gain); engine::addParam("@N", &n, 2, 6); engine::addParam("F0", &f0, 254.3f, 627.2f); engine::addParam("F1", &f1, 359.4f, 1149.9f); update_oscillators(); } void engine::process() { float cv = engine::cv(); auto buffer = engine::outputBuffer<0>(); f = powf(2.f, cv); update_oscillators(); for (int i = 0; i < FRAME_BUFFER_SIZE; i++) { buffer[i] = 0; for (size_t j = 0; j < n; j++) { _osc[j].process(buffer[i]); } buffer[i] *= gain / n; } _dc_blocker.Process(&buffer[0], FRAME_BUFFER_SIZE); } ================================================ FILE: src/NOISE/NES.cpp ================================================ // Copyright (C)2022 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" #include "misc/nes_noise.hxx" #include "stmlib/dsp/filter.h" static NESNoise _nes_noise; static stmlib::DCBlocker _dc_blocker; static const int32_t max_level = 15; static int32_t gain = max_level; static int32_t period_index = _nes_noise.period_index; static int32_t mode_bit = _nes_noise.mode_bit; void engine::setup() { engine::addParam("@Level", &gain, 0, max_level); engine::addParam("@Period", &period_index, 0, 15); engine::addParam("@ModeBit", &mode_bit, 0, 1); _nes_noise.init(1); _dc_blocker.Init(0.999f); } void engine::process() { _nes_noise.period_index = period_index; _nes_noise.mode_bit = mode_bit; auto buffer = engine::outputBuffer<0>(); for (int i = 0; i < FRAME_BUFFER_SIZE; i++) { buffer[i] = _nes_noise.generateSample(1.f / max_level) * gain; } _dc_blocker.Process(&buffer[0], FRAME_BUFFER_SIZE); } void engine::draw() { gfx::drawRect(75, 37, 47, 14); for (size_t bit = 0; bit < 15; bit++) { if ((_nes_noise.shift_reg & (1 << bit)) != 0) gfx::fillRect(76 + (bit * 3), 38, 3, 12); } } ================================================ FILE: src/NOISE/WhitePink.cpp ================================================ // Copyright (C)2022 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ENGINE_NAME:NOISE/WhitePink #include "../squares-and-circles-api.h" #include "misc/noise.hxx" const char *modes[3] = {">White", ">Pink", ">Brown"}; PinkNoise<> pinkL; PinkNoise<> pinkR; BrownNoise brownL; BrownNoise brownR; float gain = 1.f; int32_t mode = 0; float stereo = 0.f; void engine::setup() { engine::addParam("Level", &gain); engine::addParam("@Mode", &mode, 0, LEN_OF(modes) - 1, modes); engine::addParam("Stereo", &stereo); brownL.init(); brownR.init(); } void engine::process() { auto bufferL = engine::outputBuffer<0>(); auto bufferR = engine::outputBuffer<1>(); for (int i = 0; i < FRAME_BUFFER_SIZE; i++) { switch (mode) { case 0: bufferL[i] = pinkL.white.nextf(-1.f, 1.f) * gain; bufferR[i] = pinkR.white.nextf(-1.f, 1.f) * gain; break; case 1: bufferL[i] = pinkL.nextf(-1.f, 1.f) * gain; bufferR[i] = pinkR.nextf(-1.f, 1.f) * gain; break; case 2: bufferL[i] = brownL.nextf(-1.f, 1.f) * gain; bufferR[i] = brownR.nextf(-1.f, 1.f) * gain; break; } float tmp = (bufferL[i] + bufferR[i]) / 2.f * (1 - stereo); bufferL[i] = bufferL[i] * stereo + tmp; bufferR[i] = bufferR[i] * stereo + tmp; } } ================================================ FILE: src/SEQ/303-Patterns.cpp ================================================ // Copyright (C)2021 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // xbuild_flags: -fno-inline -mfloat-abi=hard -mfpu=fpv5-d16 #include "../squares-and-circles-api.h" #include "../lib/stmlib/utils/dsp.h" #include "../lib/misc/noise.hxx" #include "../lib/misc/patterns_303.h" #include uint8_t seq_pos = UINT8_MAX; int32_t pattern_select = 2; int32_t pattern_shift = 0; int32_t pattern_len = 16; int32_t gate_len = 3; // https://www.firstpr.com.au/rwi/dfish/303-slide.html int16_t *out_gate; int16_t *out_voct; int16_t *out_accent; int16_t *out_slide; // https://xbm.jazzychad.net/ const uint8_t xmb_note_6x8[8] = {0xc8, 0xd8, 0xe8, 0xd8, 0xe8, 0xce, 0xcf, 0xc6}; const uint8_t xmb_rest_6x8[8] = {0xd6, 0xde, 0xd0, 0xd6, 0xde, 0xd0, 0xd0, 0xd0}; const uint8_t xmb_arrow_up_5x6[6] = {0xe4, 0xee, 0xff, 0xe4, 0xe4, 0xe4}; const uint8_t xmb_arrow_dn_5x6[6] = {0xe4, 0xe4, 0xe4, 0xf5, 0xee, 0xe4}; const uint8_t xmb_circle_7x7[7] = {0x9c, 0xa2, 0xc1, 0xc1, 0xc1, 0xa2, 0x9c}; const uint8_t xmb_filled_circle_7x7[7] = {0x80, 0x88, 0x9c, 0xbe, 0x9c, 0x88, 0x80}; uint8_t pattern[16]; int32_t last_val[4] = {-1, -1, -1, -1}; inline int32_t note_to_voct(uint8_t note) { int32_t tmp = ((int32_t)(note & NOTE_MASK) - C4); tmp *= (PITCH_PER_OCTAVE / 12); return tmp; } inline uint8_t voct_to_note(int32_t voct) { return C4 + voct / (PITCH_PER_OCTAVE / 12); } inline uint8_t &pattern_at(int pos) { pos %= pattern_len; pos += 16 - engine::getParamValueModulated_i32(&pattern_shift); return pattern[pos % LEN_OF(pattern)]; } void engine::setup() { engine::addParam("#PAT", &pattern_select, 0, LEN_OF(x0xb0x_patterns) - 1); engine::addParam("#SHFT", &pattern_shift, -16, 16); engine::addParam("#LEN", &pattern_len, 0, 16); engine::addParam("#GATE", &gate_len, 1, 6); out_gate = engine::outputBuffer_i16(OUT_GATE); out_accent = engine::outputBuffer_i16(OUT_ACCENT); out_slide = engine::outputBuffer_i16("SLIDE"); out_voct = engine::outputBuffer_i16(OUT_VOCT); } uint32_t phase_; uint32_t phase_inc = 0; uint32_t t_ = 0; uint32_t gate_until_t = 0; int32_t last_pattern_select = -1; uint8_t curr_note, prev_note = 0; int16_t _gate = 0; int16_t _acc = 0; int16_t _slide = 0; int32_t _voct = 0.f; void engine::process() { if(pattern_len == 0) { std::fill_n(out_gate, FRAME_BUFFER_SIZE, 0); std::fill_n(out_voct, FRAME_BUFFER_SIZE, 0); std::fill_n(out_accent, FRAME_BUFFER_SIZE, 0); std::fill_n(out_slide, FRAME_BUFFER_SIZE, 0); return; } if (pattern_shift < 0) pattern_shift += 16; else if (pattern_shift >= 16) pattern_shift -= 16; if (pattern_select != last_pattern_select) { last_pattern_select = pattern_select; memcpy(pattern, x0xb0x_patterns[pattern_select], sizeof(pattern)); size_t l = 0; for (l = 0; l < LEN_OF(pattern); l++) if (pattern[l] == 0xff) break; for (size_t i = l; i < LEN_OF(pattern); i++) pattern[i] = pattern[i - l]; } if (engine_sync::stepChanged()) { seq_pos = engine_sync::step() % pattern_len; prev_note = curr_note; curr_note = pattern_at(seq_pos); phase_ = UINT32_MAX; float n = 1 + (engine::t() - t_); gate_until_t = n * (float)gate_len / 6; t_ = engine::t(); } if (prev_note & SLIDE) { auto cv = engine::qz_process(note_to_voct(curr_note)); float delta = (cv - _voct); CONSTRAIN(delta, -PITCH_PER_OCTAVE, PITCH_PER_OCTAVE); _voct += delta / 100; _slide = 5 * PITCH_PER_OCTAVE; } else { _slide = 0; _voct = engine::qz_process(note_to_voct(curr_note)); } if (((curr_note & NOTE_MASK) && gate_until_t > 0) || (curr_note & SLIDE)) _gate = 5 * PITCH_PER_OCTAVE; else _gate = 0; if (curr_note & ACCENT) _acc = 5 * PITCH_PER_OCTAVE; else _acc = 0; if (gate_until_t > 0) --gate_until_t; auto voct = engine::cv_i32() + _voct + (2 * PITCH_PER_OCTAVE); std::fill_n(out_gate, FRAME_BUFFER_SIZE, _gate); std::fill_n(out_voct, FRAME_BUFFER_SIZE, voct); std::fill_n(out_accent, FRAME_BUFFER_SIZE, _acc); std::fill_n(out_slide, FRAME_BUFFER_SIZE, (curr_note & SLIDE) ? (5 * PITCH_PER_OCTAVE) : 0); } char tmp[16]; void engine::draw() { uint8_t cur_pos = engine_sync::ppn() ? seq_pos : -1; auto len_mod = engine::getParamValueModulated_i32(&pattern_len); for (int i = 0, r = 0; r < 4 && i < len_mod; r++) { for (int k = 0; k < 8 && i < len_mod; k++) { int x = 24 + (k * 10) + (k < 1 ? 1 : 1); int y = 0 + 13 + (r * 10) + (len_mod <= 8 ? 5 : 0); int r = 4; if (pattern_at((len_mod + i - 1) % len_mod) & SLIDE) gfx::drawCircle(x + r, y + r, r); else if (pattern_at(i) & NOTE_MASK) { gfx::drawCircle(x + r, y + r, r); if (i != cur_pos) gfx::fillCircle(x + r, y + r, r); } else gfx::fillRect(x + 1, y + r - 1, r + r - 1, 3); if (i == cur_pos) { gfx::drawCircle(x + r, y + r, r - 1); } i++; } } int y = 35 + 8; gfx::drawPiano(24, y, (float)_voct / PITCH_PER_OCTAVE); y -= 1; if (curr_note == 0) gfx::drawXbm(62 + 10, y - 1, 6, 8, xmb_rest_6x8); else gfx::drawXbm(62 + 10, y - 1, 6, 8, xmb_note_6x8); if (curr_note & SLIDE) gfx::drawString(62 + 16, y, "-S"); if (curr_note & ACCENT) gfx::drawString(62 + 16, y, " -A"); } void engine::screensaver() { gfx::clearRect(0, 0, 128, 64); engine::draw(); } ================================================ FILE: src/SEQ/EuclidArp.cpp ================================================ // Copyright (C)2021 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" #include "lib/misc/euclidean.h" #include "lib/misc/patterns_303.h" #include #include #include "lib/plaits/dsp/engine2/arpeggiator.h" #define private public #define SemitonesToRatioFast #include "lib/plaits/dsp/chords/chord_bank.cc" #include "lib/stmlib/utils/random.cc" #include "lib/stmlib/utils/dsp.h" #ifndef PEAKS_RESOURCES_H_ #include "lib/peaks/resources.cc" #endif // This app is copiled with soft-fpu - for running on teensy3.2 & teensy 4.x /* https://www.nullhardware.com/blog/fixed-point-sine-and-cosine-for-embedded-systems/ Implements the 5-order polynomial approximation to sin(x). @param i angle (with 2^15 units/circle) @return 16 bit fixed point Sine value (4.12) (ie: +4096 = +1 & -4096 = -1) The result is accurate to within +- 1 count. ie: +/-2.44e-4. */ int16_t fpsin(int16_t i) { /* Convert (signed) input to a value between 0 and 8192. (8192 is pi/2, which is the region of the curve fit). */ /* ------------------------------------------------------------------- */ i <<= 1; uint8_t c = i < 0; // set carry for output pos/neg if (i == (i | 0x4000)) // flip input value to corresponding value in range [0..8192) i = (1 << 15) - i; i = (i & 0x7FFF) >> 1; /* ------------------------------------------------------------------- */ /* The following section implements the formula: = y * 2^-n * ( A1 - 2^(q-p)* y * 2^-n * y * 2^-n * [B1 - 2^-r * y * 2^-n * C1 * y]) * 2^(a-q) Where the constants are defined as follows: */ uint32_t A1 = 3370945099UL, B1 = 2746362156UL, C1 = 292421UL; uint32_t n = 13, p = 32, q = 31, r = 3, a = 12; uint32_t y = (C1 * ((uint32_t)i)) >> n; y = B1 - (((uint32_t)i * y) >> r); y = (uint32_t)i * (y >> n); y = (uint32_t)i * (y >> n); y = A1 - (y >> (p - q)); y = (uint32_t)i * (y >> n); y = (y + (1UL << (q - a - 1))) >> (q - a); // Rounding return c ? -y : y; } // Cos(x) = sin(x + pi/2) inline int16_t fpcos(int16_t i) { return fpsin((int16_t)(((uint16_t)(i)) + 8192U)); } // https://xbm.jazzychad.net/ const uint8_t xmb_note_6x8[8] = {0xc8, 0xd8, 0xe8, 0xd8, 0xe8, 0xce, 0xcf, 0xc6}; const uint8_t xmb_rest_6x8[8] = {0xd6, 0xde, 0xd0, 0xd6, 0xde, 0xd0, 0xd0, 0xd0}; const uint8_t xmb_arrow_up_5x6[6] = {0xe4, 0xee, 0xff, 0xe4, 0xe4, 0xe4}; const uint8_t xmb_arrow_dn_5x6[6] = {0xe4, 0xe4, 0xe4, 0xf5, 0xee, 0xe4}; const uint8_t xmb_circle_7x7[7] = {0x9c, 0xa2, 0xc1, 0xc1, 0xc1, 0xa2, 0x9c}; const uint8_t xmb_filled_circle_7x7[7] = {0x9c, 0xa2, 0xdd, 0xdd, 0xdd, 0xa2, 0x9c}; const uint8_t xbm_play_11x11[] = {0x03, 0xf8, 0x0d, 0xf8, 0x31, 0xf8, 0xc1, 0xf8, 0x01, 0xfb, 0x01, 0xfc, 0x01, 0xfb, 0xc1, 0xf8, 0x31, 0xf8, 0x0d, 0xf8, 0x03, 0xf8}; const uint8_t xbm_stop_7x11[] = {0x80, 0xf7, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xf7, 0x80}; int32_t len = 16; int32_t pulses = 4; int32_t rotate = 0; int32_t swing = 128; int16_t *out_gate; int16_t *out_cv; int32_t seq_pos = UINT8_MAX; bool playing = true; bool pre_start = false; void draw_eclid_cyrcle(int x, int y, uint8_t pattern[64], int _len, int rot, bool current_gate) { auto pattern2 = pattern; int xx = x; int yy = y; if (_len > 0 && (fpsin((INT16_MAX / (_len))) / 194) > 6) { gfx::drawCircle(xx + 3, 31 + 3, 21); for (int i = 0; i < _len; i++) { int a = (INT16_MAX / (_len)) * i; if (MOD(i, 2) == 1) a += (-128 + swing) * (INT16_MAX / _len) / 6; int x = fpsin(a) / 194; int y = -fpcos(a) / 194; x += xx; y += yy; gfx::clearCircle(x + 3, y + 3, 3); } } for (int i = 0; i < _len; i++) { int a = (INT16_MAX / (_len)) * i; if (MOD(i, 2) == 1) a += (-128 + swing) * (INT16_MAX / _len) / 6; int dx = fpsin(a); int dy = -fpcos(a); int x = xx + dx / 194; int y = yy + dy / 194; if (pattern[i] || pattern2[i]) gfx::fillRect(x + 2, y + 2, 3, 3); // gfx::drawXbm(x, y, 7, 7, xmb_filled_circle_7x7); if (i == rot) gfx::drawRect(x, y, 7, 7); else gfx::drawCircle(x + 3, y + 3, 3); // bool cursor = i == MOD(seq_pos, _len); if (cursor && !pre_start) gfx::drawRect(x + 1, y + 1, 5, 5); } if (playing && pre_start && MOD(millis(), 300) > 150) { } else { int x = xx - 2; int y = 40 - 7; if (current_gate) // pattern[seq_pos % _len] && (engine::clock() % 6) < 3 { if (x < 64) gfx::fillRect(x - 3, y - 7, 17, 17); else gfx::fillCircle(x + 5, y + 1, 8); } else { if (x < 64) gfx::drawRect(x - 2, y - 7, 16, 16); else gfx::drawCircle(x + 5, y + 1, 8); } } } float arp_root = 0; int32_t mode = 0; int32_t chord = 0; plaits::Arpeggiator arpeggiator_; plaits::ChordBank chords_; int32_t chords_mem[(plaits::kChordNumChords * plaits::kChordNumNotes) + plaits::kChordNumChords + plaits::kChordNumNotes]; int32_t octaves = 1; int32_t _slide = 0; const char *smodes[] = { "UP", "DOWN", "CYCLE", "RAND", }; const char *soctaves[] = { "1-OCT", "2-OCT", "3-OCT", "4-OCT", }; const char *slides[] = { "OFF", "ON", "RND25", "RND50", "RND75", }; void engine::setup() { arpeggiator_.Init(); stmlib::BufferAllocator allocator; allocator.Init(chords_mem, sizeof(chords_mem)); chords_.Init(&allocator); chords_.chord_index_quantizer_.hysteresis_ = 0; // input => output chords_.Reset(); engine::addParam("#LEN", &len, 0, 20); engine::addParam(V_OCT, &arp_root); // arp_root ist automatically added to engine::cv() engine::addParam("#HIT", &pulses, 0, 16); engine::addParam("Mode", &mode, 0, LEN_OF(smodes) - 1, smodes); engine::addParam("#ROT", &rotate, 0, 32); engine::addParam("CHRD", &chord, 0, plaits::kChordNumChords - 1, (const char **)plaits::chord_names); engine::addParam("RNGE", &octaves, 0, LEN_OF(soctaves) - 1, soctaves); engine::addParam("SLIDE", &_slide, 0, LEN_OF(slides) - 1, slides); out_gate = engine::outputBuffer_i16(OUT_TRIG); out_cv = engine::outputBuffer_i16(OUT_VOCT); } uint8_t pattern[64] = {}; uint8_t patternCV[64] = {}; uint8_t patternSlide[64] = {}; int8_t scope[64] = {}; int scope_pos = 0; int32_t gate_until_t = 0; static int32_t key = 1; int32_t _len = len; // for mod vizualization int32_t _swing = swing; // for mod vizualization char debug[128] = {}; static int32_t _last_len = -1; static auto _last_pulses = pulses; static auto _last_rotate = rotate; static auto _last_mode = mode; static auto _last_octaves = octaves; static auto _last_chord = chord; static auto _last_slide = _slide; static uint32_t _slide_phase = UINT32_MAX; static uint32_t _slide_phase_inc = 0; float _last_cv = 0; float _cv = 0; float _cv_out = 0; void update_seq_pattern() { _swing = swing; if ((mode == plaits::ArpeggiatorMode::ARPEGGIATOR_MODE_RANDOM | _slide > 1) && engine_sync::stepChanged() && MOD(engine_sync::step(), len) == 0) _last_mode = -1; // randomize!!! if (_last_len != len || _last_pulses != pulses || _last_rotate != rotate || _last_mode != mode || _last_octaves != octaves || _last_chord != chord || _last_slide != _slide) { _last_len = len; _last_pulses = pulses; _last_rotate = rotate; _last_mode = mode; _last_octaves = octaves; _last_chord = chord; _last_slide = _slide; pre_start = false; _len = len; make_pattern(pattern, len, pulses, rotate); if (len == 16 && pulses == 16 && mode == plaits::ArpeggiatorMode::ARPEGGIATOR_MODE_RANDOM && chord == 0 && octaves == 0) { // Easter EGG ;-) for (int i = 0; i < len; i++) { patternCV[(i + rotate) % 64] = DEFAULT_NOTE + ((da_funk[i] & NOTE_MASK) - C4) + 12; patternSlide[(i + rotate) % 64] = (da_funk[i] & SLIDE); } } else { arpeggiator_.set_mode((plaits::ArpeggiatorMode)(mode % plaits::ARPEGGIATOR_MODE_LAST)); arpeggiator_.set_range(1 + octaves); chords_.set_chord((float)chord / (plaits::kChordNumChords - 1)); chords_.Sort(); bool first = true; for (int i = 0; i < 64; i++) { patternSlide[(i + rotate) % 64] = 0; if (pattern[(i + rotate) % 64]) { if (first) { first = false; arpeggiator_.Reset(); } else arpeggiator_.Clock(chords_.num_notes()); if (_slide == 2 && (rand() % 100) < 25) patternSlide[(i + rotate) % 64] = true; else if (_slide == 3 && (rand() % 100) < 50) patternSlide[(i + rotate) % 64] = true; else if (_slide == 4 && (rand() % 100) > 25) patternSlide[(i + rotate) % 64] = true; } const float octave = float(1 << arpeggiator_.octave()); const float ratio = chords_.sorted_ratio(arpeggiator_.note()) * octave; patternCV[(i + rotate) % 64] = DEFAULT_NOTE + log2f(ratio) * 12; } } for (int i = len; i < 64; i++) { pattern[i] = pattern[i - len]; patternCV[i] = patternCV[i - len]; } } if (len > 0 && engine_sync::stepChanged()) { seq_pos = MOD(engine_sync::step(), len); bool trig = pattern[seq_pos]; _cv = (float)(patternCV[seq_pos] - DEFAULT_NOTE) / 12; _last_cv = (float)(patternCV[MOD(len + seq_pos - 1, len)] - DEFAULT_NOTE) / 12; if (trig) { uint32_t n = (engine_sync::samples_per_step() / FRAME_BUFFER_SIZE) / 2; // if (n > 50) // n = 0; if (_slide == 1 || patternSlide[seq_pos]) { // int m = n * 3; // for (int i = seq_pos; !pattern[(i + 1) % _len]; i++) // m += n * 2; _slide_phase = 0; _slide_phase_inc = UINT32_MAX / n; gate_until_t = INT32_MAX; } else { gate_until_t = n; // 10ms trigger } key++; } } } void engine::process() { if (!playing) { gate_until_t = 0; seq_pos = len - 1; pre_start = true; return; } update_seq_pattern(); int32_t trig = 0; if (gate_until_t > 0) { --gate_until_t; trig = 5 * PITCH_PER_OCTAVE; // 5V } if (_slide_phase < (UINT32_MAX - _slide_phase_inc)) { float e = stmlib::Interpolate824(peaks::lut_env_expo, _slide_phase); _slide_phase += _slide_phase_inc; _cv_out = _last_cv + ((_cv - _last_cv) * (e / UINT16_MAX)); } else { _cv_out = _cv; } _cv_out = (float)engine::qz_process(engine::cv_i32() + _cv_out * PITCH_PER_OCTAVE, nullptr) / PITCH_PER_OCTAVE; if (engine::t() % 20 == 0) { scope[scope_pos++] = (engine::cv() + _cv_out) * 12; if (scope_pos >= LEN_OF(scope)) scope_pos -= LEN_OF(scope); } std::fill_n(out_cv, FRAME_BUFFER_SIZE, _cv_out * PITCH_PER_OCTAVE); std::fill_n(out_gate, FRAME_BUFFER_SIZE, trig); } void engine::draw() { draw_eclid_cyrcle(36, 31, pattern, _last_len, _last_rotate, gate_until_t > 0); } void engine::screensaver() { gfx::clearRect(0, 0, 128, 64); draw_eclid_cyrcle(36 - 4, 31, pattern, _last_len, _last_rotate, gate_until_t > 0); char tmp[64]; for (int i = 0; i < _last_len; i++) { sprintf(tmp, "%d", (int)((float)patternCV[i] + engine::cv() * 12)); gfx::drawString(64 + 15 * (i % 4) + 3, 12 + 10 * (i / 4) + 1, tmp, 0); if (i == seq_pos) gfx::drawRect(64 + 15 * (i % 4), 10 + 10 * (i / 4), 15, 10); } for (int i = 0; i < (LEN_OF(scope) - 1); i++) { int a = -(scope[(scope_pos + i) % LEN_OF(scope)] >> 3); int b = -(scope[(scope_pos + i + 1) % LEN_OF(scope)] >> 3); gfx::drawLine(64 + i, 32 + 24 + a, 64 + i + 1, 32 + 24 + b); } } ================================================ FILE: src/SEQ/EuclidRythm.cpp ================================================ // Copyright (C)2021 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../lib/misc/euclidean.h" #include "../squares-and-circles-api.h" #include #include // build_flags: -fno-inline -mfloat-abi=soft -mfpu=fpv5-d16 // This app is copiled with soft-fpu - for running on teensy3.2 & teensy 4.x /* https://www.nullhardware.com/blog/fixed-point-sine-and-cosine-for-embedded-systems/ Implements the 5-order polynomial approximation to sin(x). @param i angle (with 2^15 units/circle) @return 16 bit fixed point Sine value (4.12) (ie: +4096 = +1 & -4096 = -1) The result is accurate to within +- 1 count. ie: +/-2.44e-4. */ int16_t fpsin(int16_t i) { /* Convert (signed) input to a value between 0 and 8192. (8192 is pi/2, which is the region of the curve fit). */ /* ------------------------------------------------------------------- */ i <<= 1; uint8_t c = i < 0; // set carry for output pos/neg if (i == (i | 0x4000)) // flip input value to corresponding value in range [0..8192) i = (1 << 15) - i; i = (i & 0x7FFF) >> 1; /* ------------------------------------------------------------------- */ /* The following section implements the formula: = y * 2^-n * ( A1 - 2^(q-p)* y * 2^-n * y * 2^-n * [B1 - 2^-r * y * 2^-n * C1 * y]) * 2^(a-q) Where the constants are defined as follows: */ uint32_t A1 = 3370945099UL, B1 = 2746362156UL, C1 = 292421UL; uint32_t n = 13, p = 32, q = 31, r = 3, a = 12; uint32_t y = (C1 * ((uint32_t)i)) >> n; y = B1 - (((uint32_t)i * y) >> r); y = (uint32_t)i * (y >> n); y = (uint32_t)i * (y >> n); y = A1 - (y >> (p - q)); y = (uint32_t)i * (y >> n); y = (y + (1UL << (q - a - 1))) >> (q - a); // Rounding return c ? -y : y; } // Cos(x) = sin(x + pi/2) inline int16_t fpcos(int16_t i) { return fpsin((int16_t)(((uint16_t)(i)) + 8192U)); } // https://xbm.jazzychad.net/ const uint8_t xmb_note_6x8[8] = {0xc8, 0xd8, 0xe8, 0xd8, 0xe8, 0xce, 0xcf, 0xc6}; const uint8_t xmb_rest_6x8[8] = {0xd6, 0xde, 0xd0, 0xd6, 0xde, 0xd0, 0xd0, 0xd0}; const uint8_t xmb_arrow_up_5x6[6] = {0xe4, 0xee, 0xff, 0xe4, 0xe4, 0xe4}; const uint8_t xmb_arrow_dn_5x6[6] = {0xe4, 0xe4, 0xe4, 0xf5, 0xee, 0xe4}; const uint8_t xmb_circle_7x7[7] = {0x9c, 0xa2, 0xc1, 0xc1, 0xc1, 0xa2, 0x9c}; const uint8_t xmb_filled_circle_7x7[7] = {0x9c, 0xa2, 0xdd, 0xdd, 0xdd, 0xa2, 0x9c}; const uint8_t xbm_play_11x11[] = {0x03, 0xf8, 0x0d, 0xf8, 0x31, 0xf8, 0xc1, 0xf8, 0x01, 0xfb, 0x01, 0xfc, 0x01, 0xfb, 0xc1, 0xf8, 0x31, 0xf8, 0x0d, 0xf8, 0x03, 0xf8}; const uint8_t xbm_stop_7x11[] = {0x80, 0xf7, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xf7, 0x80}; bool playing = true; bool pre_start = false; uint8_t seq_pos = UINT8_MAX; int32_t swing = 128; void draw_eclid_cyrcle(int x, int y, uint8_t pattern[64], int _len, int rot) { auto pattern2 = pattern; int xx = x; int yy = y; if (_len > 0 && (fpsin((INT16_MAX / (_len))) / 194) > 6) { gfx::drawCircle(xx + 3, 31 + 3, 21); for (int i = 0; i < _len; i++) { int a = (INT16_MAX / (_len)) * i; if (MOD(i, 2) == 1) a += (-128 + swing) * (INT16_MAX / _len) / 6; int x = fpsin(a) / 194; int y = -fpcos(a) / 194; x += xx; y += yy; gfx::clearCircle(x + 3, y + 3, 3); } } for (int i = 0; i < _len; i++) { int a = (INT16_MAX / (_len)) * i; if (MOD(i, 2) == 1) a += (-128 + swing) * (INT16_MAX / _len) / 6; int dx = fpsin(a); int dy = -fpcos(a); int x = xx + dx / 194; int y = yy + dy / 194; if (pattern[i] || pattern2[i]) gfx::fillRect(x + 2, y + 2, 3, 3); // gfx::drawXbm(x, y, 7, 7, xmb_filled_circle_7x7); if (i == rot) gfx::drawRect(x, y, 7, 7); else gfx::drawCircle(x + 3, y + 3, 3); // bool cursor = i == MOD(seq_pos, _len); if (cursor && !pre_start) gfx::drawRect(x + 1, y + 1, 5, 5); } if (playing && pre_start && MOD(millis(), 300) > 150) { } else { int x = xx - 2; int y = 40 - 7; if (_len > 0 && pattern[seq_pos % _len]) { if (x < 64) gfx::fillRect(x - 3, y - 7, 17, 17); else gfx::fillCircle(x + 5, y + 1, 8); } else { if (x < 64) gfx::drawRect(x - 2, y - 7, 16, 16); else gfx::drawCircle(x + 5, y + 1, 8); } } } int32_t len = 16; int32_t pulses = 4; int32_t rotate = 0; int32_t lenB = 16; int32_t pulsesB = 4; int32_t rotateB = 0; int16_t *out_trig0; int16_t *out_trig1; int16_t *out_trig_or; int16_t *out_trig_and; void engine::setup() { engine::addParam("#LEN", &len, 0, 20); engine::addParam("#LEN", &lenB, 0, 20); engine::addParam("#HIT", &pulses, 0, 16); engine::addParam("#HIT", &pulsesB, 0, 16); engine::addParam("#ROT", &rotate, 0, 32); engine::addParam("#ROT", &rotateB, 0, 32); out_trig0 = engine::outputBuffer_i16(OUT_TRIG "1"); out_trig1 = engine::outputBuffer_i16(OUT_TRIG "2"); out_trig_or = engine::outputBuffer_i16(OUT_TRIG "S-OR"); out_trig_and = engine::outputBuffer_i16(OUT_TRIG "S-AND"); } uint8_t pattern[64] = {}; uint8_t pattern2[64] = {}; uint8_t gate_until_t = 0; uint8_t gate_until2_t = 0; uint8_t next_clock = 1; int hit1 = 0; int hit2 = 0; char debug[128] = {}; static int32_t _last_len = -1; static auto _last_pulses = pulses; static auto _last_rotate = rotate; static int32_t _last_lenB = -1; static auto _last_pulsesB = pulsesB; static auto _last_rotateB = rotateB; void update_seq_pattern() { if (_last_len != len || _last_pulses != pulses || _last_rotate != rotate || _last_lenB != lenB || _last_pulsesB != pulsesB || _last_rotateB != rotateB) { _last_len = len; _last_pulses = pulses; _last_rotate = rotate; _last_lenB = lenB; _last_pulsesB = pulsesB; _last_rotateB = rotateB; pre_start = false; make_pattern(pattern, len, pulses, rotate); make_pattern(pattern2, lenB, pulsesB, rotateB); } if (engine_sync::stepChanged()) { seq_pos = engine_sync::step(); bool trig = len > 0 ? pattern[seq_pos % len] : false; if (trig) { hit1 = 64; gate_until_t += 2; // 10ms trigger } bool trig2 = lenB > 0 ? pattern2[seq_pos % lenB] : false; if (trig2) { hit2 = 64; gate_until2_t += 2; } } } void engine::process() { if (!playing) { gate_until_t = gate_until2_t = 0; seq_pos = len - 1; next_clock = 1; pre_start = true; return; } update_seq_pattern(); int32_t trig = 0; if (gate_until_t > 0) { --gate_until_t; trig = 5 * PITCH_PER_OCTAVE; // 5V } std::fill_n(out_trig0, FRAME_BUFFER_SIZE, trig); trig = 0; if (gate_until2_t > 0) { --gate_until2_t; trig = 5 * PITCH_PER_OCTAVE; // 5V } std::fill_n(out_trig1, FRAME_BUFFER_SIZE, trig); for (size_t i = 0; i < FRAME_BUFFER_SIZE; i++) { out_trig_or[i] = std::max(out_trig0[i], out_trig1[i]); out_trig_and[i] = std::min(out_trig0[i], out_trig1[i]); } } void engine::draw() { char tmp[16]; sprintf(tmp, "%02d", engine_sync::step()); gfx::drawStringCenter(64, 12, tmp, 0); draw_eclid_cyrcle(36, 31, pattern, _last_len, _last_rotate); draw_eclid_cyrcle(36 + 49, 31, pattern2, _last_lenB, _last_rotateB); } void engine::screensaver() { gfx::clearRect(0, 0, 128, 64); draw_eclid_cyrcle(36 - 4, 31, pattern, _last_len, _last_rotate); draw_eclid_cyrcle(36 + 49 + 4, 31, pattern2, _last_lenB, _last_rotateB); } ================================================ FILE: src/SEQ/TuringMachine.cpp ================================================ // Copyright (C)2024 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // build_flags: -fno-inline -mfloat-abi=soft -mfpu=fpv5-d16 #include "../squares-and-circles-api.h" #include static int32_t _turing_prob = 50; static int32_t _turing_length = 8; static uint8_t _turing_byte = 0; static int32_t _turing_shift_reg = 0x8000; static int32_t _pulse1 = 0; static int32_t _pulse2 = 15; int16_t *out_cv1; int16_t *out_cv2; struct { int32_t _shift_reg = 0; int32_t _rng_seed = 20071204; } _reset_state; uint32_t _rng_state; inline void Seed(uint32_t seed) { _rng_state = seed; } inline uint32_t Rand() { _rng_state = _rng_state * 1664525L + 1013904223L; return _rng_state; } const char *pulse_modes[21] = {}; int32_t note_from_scale(uint8_t bits) { // origin: // https://github.com/Chysn/O_C-HemisphereSuite/blob/893deeb27ecacddad638ff9180f244a411623e35/software/o_c_REV/enigma/EnigmaOutput.h#L104 uint8_t mask = 0; for (uint8_t s = 0; s < bits; s++) mask |= (0x01 << s); int note_shift = bits == 7 ? 0 : 64; // Note types under 7-bit start at Middle C int note_number = (_turing_byte & mask) + note_shift; CONSTRAIN(note_number, 0, 127); return engine::qz_lookup(note_number); } int32_t output(uint32_t mode, const char **name) { #define _OR(b) (((_turing_byte & b) != 0) ? INT16_MAX : 0); #define _AND(b) (((_turing_byte & b) == b) ? INT16_MAX : 0); switch (mode) { case 0: { *name = "Pulse:1"; return _OR(0b10000000); } case 1: { *name = "P:1+2"; return _OR(0b11000000); } case 2: { *name = "P:1&2"; return _AND(0b11000000); } case 3: { *name = "Pulse:2"; return _OR(0b01000000); } case 4: { *name = "P:2+4"; return _OR(0b01010000); } case 5: { *name = "P:2&4"; return _AND(0b01010000); } case 6: { *name = "Pulse:3"; return _AND(0b00100000); } case 7: { *name = "Pulse:4"; return _AND(0b00010000); } case 8: { *name = "Pulse:5"; return _AND(0b00001000); } case 9: { *name = "P:4+7"; return _OR(0b00010010); } case 10: { *name = "P:4&7"; return _AND(0b00010010); } case 11: { *name = "Pulse:6"; return _AND(0b00000100); } case 12: { *name = "P:+1247"; return _OR(0b11010010); } case 13: { *name = "P:&1247"; return _AND(0b11010010); } case 14: { *name = "Pulse:7"; return _AND(0b00000010); } case 15: { *name = "CV_5V"; return (int32_t)_turing_byte * (5 * PITCH_PER_OCTAVE / 255); } case 16: { *name = "NOTE-7"; return note_from_scale(7); } case 17: { *name = "NOTE-6"; return note_from_scale(6); } case 18: { *name = "NOTE-5"; return note_from_scale(5); } case 19: { *name = "NOTE-4"; return note_from_scale(4); } case 20: { *name = "NOTE-3"; return note_from_scale(3); } case LEN_OF(pulse_modes): { break; } } return 0; } void engine::setup() { Seed(reinterpret_cast(&_turing_shift_reg)); for (int i = 0; i < LEN_OF(pulse_modes); i++) output(i, &pulse_modes[i]); engine::addParam("@Prob\n%d%%", &_turing_prob, 0, 100); engine::addParam("@Length\n%d", &_turing_length, 0, 16); engine::addParam("@Out1\n%s", &_pulse1, 0, LEN_OF(pulse_modes) - 1, pulse_modes); engine::addParam("@Out2\n%s", &_pulse2, 0, LEN_OF(pulse_modes) - 1, pulse_modes); out_cv1 = engine::outputBuffer_i16("Out1"); out_cv2 = engine::outputBuffer_i16("Out2"); engine::setPatchStateEx(&_reset_state, sizeof(_reset_state)); engine::setMode(ENGINE_MODE_COMPACT); } static int32_t trig_pulse1 = 0; static int32_t trig_pulse2 = 0; static int32_t cv1 = 0; static int32_t cv2 = 0; static int32_t _last_prob = -1; // do not save on first run... static int32_t _last_steps = -1; static bool _inited = false; void engine::process() { if (_last_prob != _turing_prob || _last_steps != _turing_length) { if (_inited) { // save state on change (skip first time) _reset_state._rng_seed = _rng_state; _reset_state._shift_reg = _turing_shift_reg; } else _inited = true; _last_prob = _turing_prob; _last_steps = _turing_length; } if (_turing_length > 0 && engine_sync::stepChanged()) { if (engine_sync::stepReset()) // Second Trig! { _rng_state = _reset_state._rng_seed; _turing_shift_reg = _reset_state._shift_reg; } bool next_bit = (_turing_shift_reg & (0x8000 >> (_turing_length - 1))) ? 1 : 0; _turing_shift_reg = _turing_shift_reg >> 1; if ((Rand() % 100) < _turing_prob) next_bit = 1 - next_bit; if (next_bit) _turing_shift_reg |= 0x8000; _turing_byte = (_turing_shift_reg >> 8) & static_cast(0xFF); const char *dummy; cv1 = output(_pulse1, &dummy); cv2 = output(_pulse2, &dummy); if (cv1 == INT16_MAX) { cv1 = 5 * PITCH_PER_OCTAVE; trig_pulse1 = engine_sync::samples_per_step() / 2; } else cv1 += engine::cv_i32(); if (cv2 == INT16_MAX) { cv2 = 5 * PITCH_PER_OCTAVE; trig_pulse2 = engine_sync::samples_per_step() / 2; } else cv2 += engine::cv_i32(); } if (trig_pulse1 > 0) { trig_pulse1 -= FRAME_BUFFER_SIZE; if (trig_pulse1 <= 0) cv1 = 0; } if (trig_pulse2 > 0) { trig_pulse2 -= FRAME_BUFFER_SIZE; if (trig_pulse2 <= 0) cv2 = 0; } std::fill_n(out_cv1, FRAME_BUFFER_SIZE, cv1); std::fill_n(out_cv2, FRAME_BUFFER_SIZE, cv2); } void engine::draw() { gfx::drawCircle(2 + 42, 2 + 28, 2); if (cv1 > 0) gfx::fillCircle(2 + 42, 2 + 28, 2); gfx::drawCircle(2 + 42 + 64, 2 + 28, 2); if (cv2 > 0) gfx::fillCircle(2 + 42 + 64, 2 + 28, 2); for (size_t bit = 0; bit < 8; bit++) { if ((_turing_byte & (0x80 >> bit)) != 0) gfx::fillRect(2 + bit * 16, 46, 12, 12); else gfx::drawRect(2 + bit * 16, 46, 12, 12); } } void engine::screensaver() { gfx::clearRect(0, 0, 128, 64); for (size_t bit = 0; bit < 8; bit++) { if ((_turing_byte & (0x80 >> bit)) != 0) gfx::fillRect(2 + bit * 16, 32, 12, 12); else gfx::drawRect(2 + bit * 16, 32, 12, 12); } } ================================================ FILE: src/SPEECH/LPC.cpp ================================================ #include "../squares-and-circles-api.h" #include "stmlib/stmlib.h" #include "stmlib/dsp/units.h" #define private public #include "plaits/dsp/speech/lpc_speech_synth_controller.h" #include "plaits/dsp/speech/lpc_speech_synth_words.h" #include "plaits/dsp/speech/lpc_speech_synth_controller.cc" #include "plaits/dsp/speech/lpc_speech_synth_words.cc" #include "plaits/dsp/speech/lpc_speech_synth_phonemes.cc" #include "plaits/dsp/speech/lpc_speech_synth.cc" #include "stmlib/dsp/units.cc" #include "stmlib/utils/random.cc" // from #include "plaits/resources.cc" namespace plaits { const int8_t lut_lpc_excitation_pulse[] FLASHMEM = { 0, 0, 0, 0, 1, 1, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 17, 19, 21, 23, 25, 28, 30, 33, 36, 38, 41, 44, 48, 51, 54, 57, 61, 64, 68, 71, 75, 78, 82, 85, 89, 92, 95, 99, 102, 105, 108, 110, 113, 115, 118, 120, 121, 123, 124, 125, 126, 127, 127, 127, 127, 126, 125, 124, 122, 121, 118, 116, 113, 110, 107, 104, 100, 96, 92, 87, 83, 78, 73, 68, 63, 58, 53, 47, 42, 37, 31, 26, 21, 16, 11, 6, 1, -3, -8, -12, -16, -20, -23, -26, -29, -32, -35, -37, -39, -40, -42, -43, -43, -44, -44, -44, -44, -44, -43, -42, -41, -40, -39, -38, -36, -35, -33, -32, -30, -29, -27, -26, -24, -23, -22, -20, -19, -18, -18, -17, -16, -16, -16, -16, -16, -16, -17, -17, -18, -19, -20, -21, -23, -24, -26, -27, -29, -30, -32, -34, -35, -37, -39, -40, -42, -43, -44, -46, -47, -48, -48, -49, -49, -50, -50, -50, -49, -49, -48, -47, -46, -45, -44, -42, -41, -39, -37, -35, -33, -31, -29, -27, -25, -23, -20, -18, -16, -14, -13, -11, -9, -8, -7, -6, -5, -4, -3, -3, -3, -3, -3, -4, -5, -6, -7, -9, -10, -12, -14, -16, -18, -21, -23, -26, -29, -32, -34, -37, -40, -43, -46, -49, -51, -54, -56, -59, -61, -63, -65, -67, -68, -70, -71, -72, -72, -73, -73, -73, -73, -72, -72, -71, -70, -69, -67, -66, -64, -63, -61, -59, -57, -54, -52, -50, -48, -45, -43, -41, -39, -37, -35, -33, -31, -29, -27, -26, -25, -23, -22, -21, -20, -20, -19, -19, -19, -18, -18, -18, -19, -19, -19, -20, -20, -21, -21, -22, -22, -23, -23, -24, -24, -25, -25, -25, -26, -26, -26, -25, -25, -25, -24, -24, -23, -22, -21, -20, -19, -18, -16, -15, -13, -12, -10, -8, -6, -4, -3, -1, 1, 3, 5, 7, 8, 10, 12, 13, 15, 16, 17, 18, 19, 20, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 21, 21, 20, 19, 19, 18, 17, 16, 15, 14, 14, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 33, 34, 35, 35, 35, 36, 36, 36, 36, 35, 35, 35, 34, 34, 33, 33, 32, 31, 30, 30, 29, 28, 27, 26, 25, 25, 24, 23, 22, 22, 21, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 27, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 31, 30, 30, 30, 29, 29, 28, 28, 27, 26, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 15, 14, 13, 12, 12, 11, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 12, 12, 11, 10, 9, 8, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -4, -5, -6, -6, -7, -7, -8, -8, -8, -9, -9, -9, -9, -9, -9, -9, -9, -8, -8, -8, -7, -7, -7, -6, -6, -5, -5, -5, -4, -4, -4, -3, -3, -3, -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, }; } const float a0 = (440.0f / 8.0f) / 48000.0f; inline float NoteToFrequency(float midi_note) { midi_note -= 9.0f; CONSTRAIN(midi_note, -128.0f, 127.0f); return a0 * 0.25f * stmlib::SemitonesToRatio(midi_note); } static float _pitch = 0.f; static int32_t _word = 0; static float _speed = 0.3f; static float _formant_shift = 0.5f; static float _prosody = 0.5f; static float _out_aux_mix = 0.0f; struct { uint8_t bank; float addr; } _words[92]; static plaits::LPCSpeechSynthController lpc_speech_synth_controller_; static plaits::LPCSpeechSynthWordBank lpc_speech_synth_word_bank_; static uint8_t buffer[16384] = {}; static stmlib::BufferAllocator allocator; void engine::setup() { allocator.Init(buffer, 16384); lpc_speech_synth_word_bank_.Init(plaits::word_banks_, LPC_SPEECH_SYNTH_NUM_WORD_BANKS, &allocator); int j = 0; for (uint8_t i = 0; i < LPC_SPEECH_SYNTH_NUM_WORD_BANKS; i++) { lpc_speech_synth_word_bank_.Load(i); for (int l = 0; l < lpc_speech_synth_word_bank_.num_words_; l++) _words[j++] = {i, 1.f / lpc_speech_synth_word_bank_.num_words_ * l}; } lpc_speech_synth_controller_.Init(&lpc_speech_synth_word_bank_); engine::addParam(V_OCT, &_pitch); engine::addParam("Word", &_word, 0, LEN_OF(_words) - 1); engine::addParam("Speed", &_speed); engine::addParam("Form.Shift", &_formant_shift); engine::addParam("Prosody", &_prosody); engine::addParam("AuxMix", &_out_aux_mix); } void engine::process() { auto note = (float)DEFAULT_NOTE; note += engine::cv() * 12; const float f0 = NoteToFrequency(note); auto _out = engine::outputBuffer<0>(); auto _aux = engine::outputBuffer<1>(); lpc_speech_synth_controller_.Render(false, engine::trig(), _words[_word].bank, // Bank f0, _prosody, _speed, // Speed _words[_word].addr, // Word _formant_shift, 1.0f, _aux, _out, FRAME_BUFFER_SIZE); for (int i = 0; i < FRAME_BUFFER_SIZE; i++) _out[i] = stmlib::Crossfade(_out[i], _aux[i], _out_aux_mix); } ================================================ FILE: src/SPEECH/SAM.cpp ================================================ // Copyright (C)2022 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" #include #include #include #include extern "C" { #include "SAM/sam.c" #include "SAM/render.c" #include "SAM/reciter.c" } // static const char *_words[2]; static const char *_words[] = { "ELECTRO", "TECHNO", "MODULAR", "SYNTHESIZER", "OSCILLATOR", "EURORACK", "RND_0-9", }; static char _phenoms[LEN_OF(_words)][256]; static void init_phenoms() { for (size_t i = 0; i < LEN_OF(_words); i++) { // char input[256] = {}; // int i = 0; // auto text = _words[_word]; // for (; text[i] != 0; i++) // input[i] = (int)text[i]; // toupper // input[i] = '['; size_t len = strlen(_words[i]); memcpy(_phenoms[i], _words[i], len); _phenoms[i][len] = '['; _phenoms[i][len + 1] = 0; // auto len = snprintf(_phenoms[i], 256, "%s[", _words[i]); TextToPhonemes((unsigned char *)_phenoms[i]); } } static int32_t _word = 0; static float _speed = 0.75f; static float _mouth = 0.5f; static float _pitch = 0.5f; static float _throat = 0.5f; static uint8_t _buffer[48000]; static size_t _buffer_len = 0; static uint32_t _buffer_pos = 0; void say() { if (_word == LEN_OF(_phenoms) - 1) { sprintf(_phenoms[_word], "%d[]", rand() % 10); TextToPhonemes((unsigned char *)_phenoms[_word]); } SAM_write_buffer = [](int pos, char value) { if (pos < (int)LEN_OF(_buffer)) { _buffer_len = pos + 1; _buffer[pos] = value; } }; SetSpeed((1.f - _speed) * 255); SetMouth(_mouth * 255); SetPitch(_pitch * 255); SetThroat(_throat * 255); SetInput(_phenoms[_word]); SAMMain(); _buffer_pos = 0; } void engine::setup() { // param_init("PTICH", &_pitch); engine::addParam("Speed", &_speed); engine::addParam("@Words", &_word, 0, LEN_OF(_words) - 1, _words); engine::addParam("Mouth", &_mouth); engine::addParam("Throat", &_throat); init_phenoms(); } void engine::process() { auto outputL = engine::outputBuffer<0>(); if (engine::trig()) { say(); } if (_buffer_pos + 12 < _buffer_len) { for (int j = 0; j < 24; j += 2) { float sample = ((float)_buffer[_buffer_pos] - 127) / 128; outputL[j] = outputL[j + 1] = sample; ++_buffer_pos; } } else std::fill_n(outputL, FRAME_BUFFER_SIZE, 0); } ================================================ FILE: src/SYNTH/DxFM.cpp ================================================ /* * Copyright (C)2023 - E.Heidt * * 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. */ // ENGINE_NAME:SYNTH/DxFM;SYNTH/DxFM_BNK1-3 #include "../squares-and-circles-api.h" #include "stmlib/utils/ring_buffer.h" #include "msfa/controllers.h" #include "msfa/dx7note.h" #include "msfa/lfo.h" #include "msfa/synth.h" #include "msfa/fm_core.h" #include "msfa/synth.h" #include "msfa/exp2.h" #include "msfa/sin.h" #include "msfa/freqlut.h" #include "msfa/porta.h" #include "msfa/patch.h" #include #include #include "plaits/resources.h" struct dxfm { int note = 0; int key_down = 0; Lfo lfo; FmCore fm_core; Dx7Note dx7_note; stmlib::RingBuffer buffer; }; static dxfm voices[2] = {}; static Controllers controllers = {}; static float _pitch = 0; static int32_t _prog = 0; static char _progName[16] = {}; static int32_t _progSelect = 0; static float _hold = 0; static float _rate = 0; static float _stereolize = 0; static dxfm *active_voice = nullptr; static dxfm *other_voice = nullptr; const uint8_t *fm_patches_table[4] = {}; static char patch[128] = { // MARIMBA 0x00, 0x3f, 0x37, 0x00, 0x4e, 0x4e, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x38, 0x08, 0x63, 0x08, 0x0d, 0x63, 0x4b, 0x00, 0x08, 0x52, 0x30, 0x00, 0x00, 0x36, 0x00, 0x2e, 0x00, 0x38, 0x08, 0x5d, 0x00, 0x32, 0x63, 0x4b, 0x00, 0x52, 0x52, 0x30, 0x00, 0x00, 0x36, 0x00, 0x2e, 0x00, 0x38, 0x08, 0x55, 0x0a, 0x00, 0x5f, 0x21, 0x31, 0x29, 0x63, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x04, 0x63, 0x00, 0x00, 0x63, 0x48, 0x00, 0x00, 0x52, 0x30, 0x00, 0x00, 0x36, 0x00, 0x2e, 0x00, 0x38, 0x08, 0x60, 0x06, 0x00, 0x5f, 0x28, 0x31, 0x37, 0x63, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x5f, 0x00, 0x00, 0x5e, 0x43, 0x5f, 0x3c, 0x32, 0x32, 0x32, 0x32, 0x06, 0x08, 0x23, 0x00, 0x00, 0x00, 0x31, 0x18, 0x4d, 0x41, 0x52, 0x49, 0x4d, 0x42, 0x41, 0x20, 0x20, 0x20}; static uint8_t data[156] = {}; #define OP_ENV_RATE(op, i) data[op * 21 + i] #define OP_ENV_LEVEL(op, i) data[op * 21 + 4 + i] #define OP_kbd_lev_scl_brk_pt(op) data[op * 21 + 8] #define OP_kbd_lev_scl_lft_depth(op) data[op * 21 + 9] #define OP_kbd_lev_scl_rht_depth(op) data[op * 21 + 10] #define OP_kbd_lev_scl_lft_curve(op) data[op * 21 + 11] #define OP_kbd_lev_scl_rht_curve(op) data[op * 21 + 12] #define OP_kbd_rate_scaling(op) data[op * 21 + 13] #define OP_amp_mod_sensitivity(op) data[op * 21 + 14] #define OP_key_vel_sensitivity(op) data[op * 21 + 15] #define OP_output_level(op) data[op * 21 + 16] #define OP_osc_mode(op) data[op * 21 + 17] #define OP_osc_freq_coarse(op) data[op * 21 + 18] #define OP_osc_freq_fine(op) data[op * 21 + 19] #define OP_osc_detune(op) data[op * 21 + 20] #define PE_rate(i) data[6 * 21 + i] #define PE_level(i) data[6 * 21 + 4 + i] #define ALGORITHM() data[6 * 21 + 8] #define FEEDBACK() data[6 * 21 + 9] #define OSC_SYNC() data[6 * 21 + 10] #define LFO_RATE() data[(6 * 21 + 11)] #define LFO_DELAY() data[6 * 21 + 12] #define LFO_PITCH_MOD_DEPTH() data[6 * 21 + 13] #define LFO_AMP_MOD_DEPTH() data[6 * 21 + 14] #define LFO_SYNC() data[6 * 21 + 15] #define LFO_WAVEFORM() data[6 * 21 + 16] #define PITCH_MOD_SENSITIVITY() data[6 * 21 + 17] #define TRANSPOSE() data[6 * 21 + 18] #define NAME() ((const char *)&data[6 * 21 + 19]) static void initControllers() { controllers.values_[kControllerPitch] = 0x2000; controllers.values_[kControllerPitchRange] = 0; controllers.values_[kControllerPitchStep] = 0; controllers.modwheel_cc = 0; controllers.foot_cc = 0; controllers.breath_cc = 0; controllers.aftertouch_cc = 0; controllers.refresh(); } static uint8_t loadDXPatch(uint8_t prog) { uint8_t load = prog; const uint8_t *sysexData = fm_patches_table[prog / 32]; prog = prog % 32; if (sysexData) { bool invalid = false; for (int i = 0; i < sizeof(patch); i++) invalid |= sysexData[i + prog * 128] & 0x80; if (!invalid) { memcpy(patch, (const char *)sysexData + (prog * 128), sizeof(patch)); UnpackPatch(patch, (char *)data); char *name = _progName; memset(_progName, 0, sizeof(_progName)); for (int i = 0; i < 10; i++) { *name = NAME()[i]; if (*name >= ' ' && *name <= '~') { if (i == 0 || *name != ' ' || *(name - 1) != *name) name++; } else { *name = 0; break; } } return load; } } return 0; } static void applyRate(float rate) { for (int op = 0; op < 6; op++) { auto opData = &patch[op * 17]; for (int j = 1; j < 4; j++) { auto v = min(opData[j] & 0x7f, 99); OP_ENV_RATE(op, j) = min((int)(v * -rate), 99); } // for (int j = 1; j < 4; j++) // { // auto v = min(opData[j + 4] & 0x7f, 99); // if (_rate < 0) // OP_ENV_LEVEL(op, j) = v - (99 - v) * -_rate; // else // OP_ENV_LEVEL(op, j) = v - v * -_rate; // } } } void engine::setup() { UnpackPatch(patch, (char *)data); uint8_t nprogs = 0; if (!strcmp(engine::name(), "SYNTH/DxFM_BNK1-3")) { if (fm_patches_table[nprogs / 32] = plaits::fm_patches_table[0]) nprogs += 32; if (fm_patches_table[nprogs / 32] = plaits::fm_patches_table[1]) nprogs += 32; if (fm_patches_table[nprogs / 32] = plaits::fm_patches_table[2]) nprogs += 32; } else { if (fm_patches_table[nprogs / 32] = machine::fs_read("DXFMSYX0")) nprogs += 32; } if (nprogs > 96) _progSelect = 96; for (size_t prog = 0; prog < nprogs; prog++) { const uint8_t *sysexData = fm_patches_table[prog / 32]; } engine::addParam(V_OCT, &_pitch); if (nprogs == 0) { nprogs = 1; } snprintf(_progName, 12, NAME()); engine::addParam(_progName, &_progSelect, 0, nprogs - 1); _rate = -1.0f; engine::addParam("Rate", &_rate, -1.5f, -0.5f); _hold = 0; engine::addParam("Hold", &_hold, 0, SAMPLE_RATE / FRAME_BUFFER_SIZE); engine::addParam("Stereo", &_stereolize); Exp2::init(); Tanh::init(); Sin::init(); Freqlut::init(SAMPLE_RATE); Lfo::init(SAMPLE_RATE); PitchEnv::init(SAMPLE_RATE); Env::init_sr(SAMPLE_RATE); Porta::init_sr(SAMPLE_RATE); initControllers(); controllers.masterTune = 0; controllers.opSwitch = 0x3f; // all operators active_voice = &voices[0]; other_voice = &voices[1]; for (auto &voice : voices) voice.buffer.Init(); loadDXPatch(0); // If patch available, select first } static uint8_t _trig = 0; void engine::process() { applyRate(_rate); // * ((float)rand() / INT32_MAX * 0.1f)); int velo = 127; if (engine::trig()) { _trig |= 1; } else if (engine::gate()) { // keep key down } else { for (auto &voice : voices) if (voice.key_down > 1) --voice.key_down; } if (voices[0].buffer.readable() < N) { // see midinote_to_logfreq float note = (2.f + engine::cv()) * 12.f + DEFAULT_NOTE; if (_progSelect != _prog) { _prog = loadDXPatch(_progSelect); for (auto &voice : voices) { voice.dx7_note.keyup(); voice.lfo.reset(&LFO_RATE()); voice.dx7_note.update(data, voice.note, velo); } } for (auto &voice : voices) { if ((_trig & 1) && &voice == other_voice) { voice.key_down = 2 + _hold; voice.note = note; voice.lfo.keydown(); voice.dx7_note.keyup(); float r = _rate + 1.5f; // 0..1 if (r < 0.5f) velo = 64 + 64 * (r * 2); voice.dx7_note.init(data, voice.note, velo); if (OSC_SYNC()) voice.dx7_note.oscSync(); _trig = 0; // if (other_voice && active_voice->key_down) // { // voice.dx7_note.transferSignal(active_voice->dx7_note); // voice.dx7_note.transferState(active_voice->dx7_note); // } std::swap(active_voice, other_voice); } else if (voice.key_down == 1) { voice.key_down = 0; voice.dx7_note.keyup(); } int32_t lfovalue = voice.lfo.getsample(); int32_t lfodelay = voice.lfo.getdelay(); auto p = voice.buffer.OverwritePtr(N); memset(p, 0, sizeof(int32_t) * N); float diff_note = (note - voice.note) / 12.f; controllers.masterTune = diff_note * (1 << 24); voice.dx7_note.compute(p, &voice.fm_core, lfovalue, lfodelay, &controllers); } _trig = 0; } auto bufferL = engine::outputBuffer<0>(); auto bufferR = engine::outputBuffer<1>(); int v = 0; float stereo = (1.f - _stereolize); for (auto &voice : voices) { auto p = voice.buffer.ImmediateReadPtr(FRAME_BUFFER_SIZE); if (v++ % 2 == 0) { for (int i = 0; i < FRAME_BUFFER_SIZE; i++) { float s = (float)*p++ / INT32_MAX * 8; bufferL[i] = s * stereo; bufferR[i] = s; } } else { for (int i = 0; i < FRAME_BUFFER_SIZE; i++) { float s = (float)*p++ / INT32_MAX * 8; bufferL[i] += s; bufferR[i] += s * stereo; } } } } void engine::draw() { if (fm_patches_table[0] == nullptr) { gfx::clearRect(4, 16, 120, 38); gfx::drawRect(4, 16, 120, 38); gfx::drawRect(5, 17, 118, 36); gfx::drawStringCenter(64, 26, "NO DXFM.SYX FOUND!", 1); gfx::drawString(10, 38, "Please load a syx file", 0); gfx::drawString(10, 38 + 7, " with the Webflasher! ", 0); } } #include "msfa/sin.cc" #include "msfa/pitchenv.cc" #include "msfa/fm_op_kernel.cc" #include "msfa/fm_core.cc" #include "msfa/lfo.cc" #include "msfa/dx7note.cc" #include "msfa/freqlut.cc" #include "msfa/patch.cc" #include "msfa/porta.cc" #include "msfa/env.cc" #include "msfa/exp2.cc" #include "plaits/resources.cc" ================================================ FILE: src/SYNTH/Open303.cpp ================================================ // Copyright (C)2022 - Eduard Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // #include "../squares-and-circles-api.h" #undef SAMPLE_RATE #define protected public #include "open303/src/rosic_AnalogEnvelope.cpp" #include "open303/src/rosic_EllipticQuarterBandFilter.cpp" #include "open303/src/rosic_DecayEnvelope.cpp" #include "open303/src/rosic_LeakyIntegrator.cpp" #include "open303/src/wavetable_gen/rosic_MipMappedWaveTable.cpp" #include "open303/src/wavetable_gen/rosic_FourierTransformerRadix2.cpp" #include "open303/src/wavetable_gen/rosic_Complex.cpp" #include "open303/src/rosic_RealFunctions.cpp" #include "open303/src/rosic_Open303.cpp" #include "open303/src/rosic_FunctionTemplates.cpp" #include "open303/src/GlobalFunctions.cpp" #include "open303/src/rosic_BlendOscillator.cpp" #include "open303/src/rosic_BiquadFilter.cpp" #include "open303/src/rosic_NumberManipulations.cpp" #include "open303/src/rosic_OnePoleFilter.cpp" #include "open303/src/rosic_MidiNoteEvent.cpp" #include "open303/src/rosic_TeeBeeFilter.cpp" #include "stmlib/stmlib.h" #include "open303/src/rosic_Open303.h" #include "open303/src/wavetable_gen/rosic_MipMappedWaveTable.h" // static __attribute__((aligned(32))) uint8_t open303_mem[sizeof(rosic::Open303)]; static rosic::WaveTable square_wave; static rosic::Open303 open303(&square_wave, &square_wave); static float _pitch = -1; static float _acc = 1.0f; static float _cutoff = 0.25f; static float _res = 0.33f; static float _env = 0.25f; static float _dec = 0.5f; static float _note; static uint8_t _waveform = 1; static bool _gate; void engine::setup() { engine::addParam(V_OCT, &_pitch); // pitch is summed with CV and quantized engine::addParam("Acc", &_acc); engine::addParam("Cutoff", &_cutoff); engine::addParam("Reso", &_res); engine::addParam("EnvMod", &_env); engine::addParam("Dec", &_dec); // param[6].init("WAVEFORM", &_waveform, _waveform, 0, 1); // param[6].print_value = [&](char *val) // { // sprintf(val, _waveform ? "SQR" : "SAW"); // }; // square_wave = (uint8_t *)malloc(sizeof(rosic::WaveTable)); rosic::MipMappedWaveTable tmp; tmp.fillWithSquare303(); tmp.generateMipMap(square_wave); // open303.oscillator.setWaveTables(_square, _square); open303.setSampleRate(SAMPLE_RATE, 1); open303.setWaveform(_waveform); open303.setTuning(open303.tuning); open303.setAmpSustain(0); open303.setAccentAttack(open303.accentAttack); open303.setPitchBend(0); open303.setSlideTime(open303.slideTime); open303.setVolume(-12); open303.filter.setMode(rosic::TeeBeeFilter::TB_303); } void engine::process() { open303.setWaveform(_waveform); open303.setAccent(1.f + _acc * 99.f); open303.setCutoff(rosic::linToExp(_cutoff, 0.0, 1.0, 314.0, 2394.0)); open303.setResonance(1.f + _res * 99.f); open303.setEnvMod(1.f + _env * 99.f); open303.setDecay(rosic::linToExp(_dec, 0.0, 1.0, 200.0, 2000.0)); if (_acc > 0) open303.setAccentDecay(rosic::linToExp(_dec, 0.0, 1.0, 200.0, 2000.0)); _note = (float)DEFAULT_NOTE + 24 + engine::cv() * 12; CONSTRAIN(_note, 0, 128); _gate |= engine::gate(); if (engine::trig() > 0) open303.triggerNote(_note, _acc > 0); else if (!engine::gate()) { open303.releaseNote(_note); _gate = false; } else open303.oscFreq = rosic::pitchToFreq(_note, open303.tuning); auto buffer = engine::outputBuffer<0>(); for (int i = 0; i < FRAME_BUFFER_SIZE; i++) buffer[i] = open303.getSample(); } void engine::screensaver() { static uint32_t _r = 0; static const uint8_t _screenSaver[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, //> 0x00, 0x80, 0x0f, 0xe0, 0x01, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x07, 0x00, 0x00, 0x30, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x06, 0x00, 0x00, 0x60, 0x00, 0x00, 0x03, 0x00, 0x00, 0x80, 0x00, 0x80, 0x01, 0x06, 0xc0, 0x00, 0x01, 0xc0, 0x00, 0x0f, 0xe0, 0x01, 0x03, 0x60, 0x00, 0x0f, 0xe0, 0x01, 0x06, 0x30, 0x80, 0x1f, 0xf0, 0x03, 0x0c, 0x10, 0x80, 0x1f, 0xf0, 0x03, 0x08, 0x18, 0x80, 0x1f, 0xf0, 0x03, 0x18, 0x08, 0x80, 0x1f, 0xf0, 0x03, 0x10, 0x08, 0x80, 0x1f, 0xf0, 0x03, 0x30, 0x04, 0x80, 0x1f, 0xf0, 0x03, 0x20, 0x04, 0x80, 0x1f, 0xf0, 0x03, 0x20, 0x04, 0x80, 0x1f, 0xf0, 0x03, 0x60, 0x06, 0x00, 0x0f, 0xe0, 0x01, 0x40, 0x02, 0x00, 0x0f, 0xe0, 0x01, 0x40, 0x02, 0x00, 0x06, 0xc0, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe2, 0x07, 0x00, 0x00, 0xe0, 0x47, 0xc2, 0x03, 0x00, 0x00, 0xc0, 0x43, 0x82, 0x01, 0x00, 0x00, 0x80, 0x41, 0x82, 0x01, 0x00, 0x00, 0x80, 0x41, 0x86, 0x01, 0x00, 0x00, 0xc0, 0x60, 0x04, 0x03, 0x00, 0x00, 0xc0, 0x60, 0x04, 0x07, 0x00, 0x00, 0xc0, 0x20, 0x0c, 0x06, 0x00, 0x00, 0x60, 0x20, 0x08, 0x0e, 0x00, 0x00, 0x70, 0x30, 0x08, 0x1c, 0x00, 0x00, 0x30, 0x10, 0x18, 0x38, 0x00, 0x00, 0x1c, 0x18, 0x10, 0x70, 0x00, 0x00, 0x0e, 0x08, 0x20, 0xe0, 0x00, 0x00, 0x0f, 0x0c, 0x60, 0xc0, 0x03, 0xc0, 0x03, 0x06, 0xc0, 0x00, 0x0f, 0xf0, 0x00, 0x02, 0x80, 0x01, 0xfc, 0x3f, 0x00, 0x01, 0x00, 0x03, 0xe0, 0x07, 0xc0, 0x00, 0x00, 0x06, 0x00, 0x00, 0x60, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80, 0x0f, 0xf0, 0x01, 0x00, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, //> 0x00, 0xe0, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf0, 0x0f, 0xe0, 0x1f, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xf0, 0x00, 0x80, 0x07, 0x06, 0xc0, 0xe0, 0x01, 0xc0, 0x03, 0x0f, 0xe0, 0x81, 0x03, 0xe0, 0x81, 0x1f, 0xf0, 0x83, 0x07, 0xf0, 0x80, 0x1f, 0xf0, 0x03, 0x0f, 0x78, 0xc0, 0x3f, 0xf8, 0x07, 0x1e, 0x38, 0xc0, 0x3f, 0xf8, 0x07, 0x1c, 0x3c, 0xc0, 0x3f, 0xf8, 0x07, 0x3c, 0x1c, 0xc0, 0x3f, 0xf8, 0x07, 0x38, 0x1c, 0xc0, 0x3f, 0xf8, 0x07, 0x78, 0x0e, 0xc0, 0x3f, 0xf8, 0x07, 0x70, 0x0e, 0xc0, 0x3f, 0xf8, 0x07, 0x70, 0x0e, 0xc0, 0x1f, 0xf0, 0x07, 0xf0, 0x0f, 0x80, 0x1f, 0xf0, 0x03, 0xe0, 0x07, 0x80, 0x0f, 0xe0, 0x03, 0xe0, 0x07, 0x00, 0x0f, 0xe0, 0x01, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xe7, 0x07, 0x00, 0x00, 0xe0, 0xe7, 0xf7, 0x07, 0x00, 0x00, 0xe0, 0xef, 0xe7, 0x07, 0x00, 0x00, 0xe0, 0xe7, 0xc7, 0x03, 0x00, 0x00, 0xc0, 0xe3, 0xc7, 0x03, 0x00, 0x00, 0xc0, 0xe3, 0xcf, 0x03, 0x00, 0x00, 0xe0, 0xf1, 0x8e, 0x07, 0x00, 0x00, 0xe0, 0xf1, 0x8e, 0x0f, 0x00, 0x00, 0xe0, 0x71, 0x1e, 0x0f, 0x00, 0x00, 0xf0, 0x70, 0x1c, 0x1f, 0x00, 0x00, 0xf8, 0x78, 0x1c, 0x3e, 0x00, 0x00, 0x7c, 0x38, 0x3c, 0x7c, 0x00, 0x00, 0x3e, 0x3c, 0x38, 0xf8, 0x00, 0x00, 0x1f, 0x1c, 0x70, 0xf0, 0x03, 0xc0, 0x1f, 0x1e, 0xf0, 0xe0, 0x0f, 0xf0, 0x0f, 0x0f, 0xe0, 0xc1, 0xff, 0xff, 0x03, 0x07, 0xc0, 0x03, 0xff, 0xff, 0xc0, 0x03, 0x80, 0x07, 0xfc, 0x3f, 0xe0, 0x01, 0x00, 0x0f, 0xe0, 0x07, 0xf0, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x7c, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf0, 0x0f, 0xf0, 0x1f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00}; gfx::clearRect(0, 0, 128, 64); for (int i = 23; i > 0; i--) { if ((_r & (1 << i))) gfx::drawCircle(64, 32, 26 + powf(i, 1.3f)); } if (_gate) { _r |= 1; gfx::drawXbm(40, 8, 48, 48, &_screenSaver[sizeof(_screenSaver) / 2]); } else gfx::drawXbm(40, 8, 48, 48, &_screenSaver[0]); _r <<= 1; } ================================================ FILE: src/SYNTH/Resonator.cpp ================================================ #include "../squares-and-circles-api.h" #include "stmlib/dsp/units.cc" #include "stmlib/utils/random.cc" #include "rings/resources.cc" #include "rings/dsp/string.cc" #include "rings/dsp/resonator.cc" #include "rings/dsp/fm_voice.cc" #include "rings/dsp/part.cc" #include "rings/dsp/string_synth_part.cc" #include "rings/dsp/strummer.h" static int32_t _model = rings::ResonatorModel::RESONATOR_MODEL_MODAL; static const char* _models[] = { "Modal\tmono", "Sympath.\tmono", "String\tmono", "FM\tmono", "StrQuant.\tmono", "Modal\tduo", "Sympath.\tduo", "String\tduo", "FM\tduo", "StrQuant\tduo", "Modal\tquadro", "Sympath.\tquadro", "String\tquadro", "FM\tquadro", "StrQuant.\tquadro", }; static rings::Strummer strummer = {}; static rings::Part part; static rings::Patch patch = {}; static rings::PerformanceState performance_state = {}; static float _pitch = 0; void engine::setup() { patch.structure = 0.5f; patch.brightness = 0.5f; patch.damping = 0.5f; patch.position = 0.5f; strummer.Init(0.01f, SAMPLE_RATE / FRAME_BUFFER_SIZE); part.Init(); part.set_model(rings::ResonatorModel::RESONATOR_MODEL_MODAL); part.set_polyphony(3); engine::addParam(V_OCT, &_pitch); // pitch is summed with CV and quantized engine::addParam("@Model", &_model, 0, LEN_OF(_models) - 1, (const char**)_models); engine::addParam("Struc.", &patch.structure); engine::addParam("Brighn.", &patch.brightness); engine::addParam("Damping", &patch.damping); engine::addParam("Pos", &patch.position); } void engine::process() { auto inputL = engine::inputBuffer<0>(); auto bufferOut = engine::outputBuffer<0>(); auto bufferAux = engine::outputBuffer<1>(); part.set_model((rings::ResonatorModel)(_model % 5)); int32_t polyphony = 1; if (_model < 5) polyphony = 1; else if (_model < 10) polyphony = 2; else polyphony = 4; if (polyphony != part.polyphony()) part.set_polyphony(polyphony); performance_state.strum = engine::trig() > 0; performance_state.internal_strum = false; performance_state.internal_note = true; performance_state.internal_exciter = true; performance_state.tonic = 0.2f; performance_state.chord = 0; performance_state.note = DEFAULT_NOTE; performance_state.note += engine::cv() * 12; strummer.Process(inputL, FRAME_BUFFER_SIZE, &performance_state); part.Process(performance_state, patch, inputL, bufferOut, bufferAux, FRAME_BUFFER_SIZE); } ================================================ FILE: src/SYNTH/plaits.cpp ================================================ // Copyright (C)2022 - E.Heidt // // Author: Eduard Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // // ENGINE_NAME: M-OSC/Virt.Analog // ENGINE_NAME: M-OSC/Waveshaping // ENGINE_NAME: M-OSC/2-OP-FM // ENGINE_NAME: M-OSC/Grain // ENGINE_NAME: M-OSC/Harmonic // ENGINE_NAME: M-OSC/Wavetable // ENGINE_NAME: M-OSC/Chord // ENGINE_NAME: DRUMS/Analog BD // ENGINE_NAME: DRUMS/Analog SD // ENGINE_NAME: DRUMS/Analog HH2 // ENGINE_NAME: DRUMS/Analog HH // ENGINE_NAME: DRUMS/909ish-BD // ENGINE_NAME: DRUMS/909ish-SD // ENGINE_NAME: SYNTH/ClassicVAVCF #include "../squares-and-circles-api.h" #define private public // ;-) #include "plaits/dsp/voice.h" #include "stmlib/dsp/dsp.h" using namespace machine; plaits::Modulations modulations; plaits::Voice voice; plaits::Patch patch; float bufferOut[FRAME_BUFFER_SIZE]; float bufferAux[FRAME_BUFFER_SIZE]; float out_aux_mix = 0.5f; float _pitch = 0; float _v_oct = 0; float _base_pitch = DEFAULT_NOTE; struct { int engine; int output; // output=0 -> out, output=1 -> aux, output=3 -> stereo } _mode = {}; uint8_t *_buffer = nullptr; plaits::Engine *_plaitsEngine = nullptr; constexpr int WAVETABLE_ENGINE = 5; constexpr int CHORD_ENGINE = 6; constexpr int CLASSIC_VAVCF_ENGINE = 16; void engine_free() { free(_plaitsEngine); free(_buffer); } template void alloc_engine(size_t mem = 48) { _plaitsEngine = new (malloc(sizeof(T))) T(); _buffer = (uint8_t *)malloc(mem * sizeof(float)); stmlib::BufferAllocator allocator; allocator.Init(_buffer, mem * sizeof(float)); _plaitsEngine->Init(&allocator); } float harmonics, timbre, morph; bool is_drum() { return _mode.engine == 13 || _mode.engine == 14 || _mode.engine == 15; } void init_params(float hh, float tt, float mm, const plaits::PostProcessingSettings &settings) { patch.harmonics = harmonics = hh; patch.timbre = timbre = tt; patch.morph = morph = mm; if (_plaitsEngine) _plaitsEngine->post_processing_settings = settings; } void engine::setup() { const char *name = engine::name(); while (*name++ != '/') ; if (!strcmp(name, "Virt.Analog")) _mode = {0, 0}; else if (!strcmp(name, "Waveshaping")) _mode = {1, 0}; else if (!strcmp(name, "2-OP-FM")) _mode = {2, 0}; else if (!strcmp(name, "Grain")) _mode = {3, 2}; else if (!strcmp(name, "Harmonic")) _mode = {4, 2}; else if (!strcmp(name, "Wavetable")) _mode = {5, 2}; else if (!strcmp(name, "Chord")) _mode = {6, 0}; else if (!strcmp(name, "Analog BD")) _mode = {13, 0}; else if (!strcmp(name, "Analog SD")) _mode = {14, 0}; else if (!strcmp(name, "Analog HH2")) _mode = {15, 1}; else if (!strcmp(name, "Analog HH")) _mode = {15, 0}; else if (!strcmp(name, "909ish-BD")) _mode = {13, 1}; else if (!strcmp(name, "909ish-SD")) _mode = {14, 1}; else if (!strcmp(name, "ClassicVAVCF")) _mode = {16, 2}; else _mode = {0, 0}; voice.Init(); patch.engine = 0; memset(&patch, 0, sizeof(patch)); patch.note = DEFAULT_NOTE + _pitch * 12.f; modulations.timbre_patched = true; patch.timbre_modulation_amount = 0; modulations.frequency_patched = true; patch.frequency_modulation_amount = 0; modulations.morph_patched = true; patch.morph_modulation_amount = 0; memset(&modulations, 0, sizeof(modulations)); patch.lpg_colour = 0.5; patch.decay = 0.5; modulations.trigger_patched = true; // trigger; // modulations.level_patched = true; // modulations.level = 1; switch (_mode.engine) { case 0: alloc_engine(); init_params(0.5f, 0.5f, 0.5f, {0.8f, 0.8f, false}); engine::addParam(V_OCT, &_v_oct); engine::addParam("Detune", &harmonics); engine::addParam("Square", &timbre); engine::addParam("CSAW", &morph); engine::addParam("Decay", &patch.decay); if (_mode.output == 2) engine::addParam("AuxMix", &out_aux_mix, out_aux_mix); else engine::addParam("Color", &patch.lpg_colour); break; case 1: alloc_engine(); init_params(0.8f, 0.8f, 0.75f, {0.7f, 0.6f, false}); engine::addParam(V_OCT, &_v_oct); engine::addParam("Waveform", &harmonics); engine::addParam("Fold", &timbre); engine::addParam("Asym", &morph); engine::addParam("Decay", &patch.decay); if (_mode.output == 2) engine::addParam("AuxMix", &out_aux_mix, out_aux_mix); else engine::addParam("Color", &patch.lpg_colour); break; case 2: alloc_engine(); init_params(0.8f, 0.8f, 0.75f, {0.6f, 0.6f, false}); engine::addParam(V_OCT, &_v_oct); engine::addParam("Ratio", &harmonics); engine::addParam("Mod", &timbre); engine::addParam("Feedb.", &morph); engine::addParam("Decay", &patch.decay); if (_mode.output == 2) engine::addParam("AuxMix", &out_aux_mix, out_aux_mix); else engine::addParam("Color", &patch.lpg_colour); break; case 3: alloc_engine(); init_params(0.8f, 0.8f, 0.75f, {0.7f, 0.6f, false}); engine::addParam(V_OCT, &_v_oct); engine::addParam("Ratio", &harmonics); engine::addParam("Frm/Fq.", &timbre); engine::addParam("Width", &morph); engine::addParam("Decay", &patch.decay); engine::addParam("PD-Mix", &out_aux_mix, out_aux_mix); break; case 4: alloc_engine(); init_params(0.8f, 0.8f, 0.75f, {0.8f, 0.8f, false}); engine::addParam(V_OCT, &_v_oct); engine::addParam("Bump", &harmonics); engine::addParam("Peak", &timbre); engine::addParam("Shape", &morph); engine::addParam("Decay", &patch.decay); if (_mode.output == 2) engine::addParam("AuxMix", &out_aux_mix, out_aux_mix); else engine::addParam("Color", &patch.lpg_colour); break; case WAVETABLE_ENGINE: alloc_engine(64 * sizeof(const int16_t *)); init_params(0.f, 0.8f, 0.75f, {0.6f, 0.6f, false}); engine::addParam(V_OCT, &_v_oct); engine::addParam("Bank", &harmonics, 0.f, 0.5f); engine::addParam("Row", &timbre); engine::addParam("Column", &morph); engine::addParam("Decay", &patch.decay); if (_mode.output == 2) engine::addParam("AuxMix", &out_aux_mix, out_aux_mix); else engine::addParam("Color", &patch.lpg_colour); _plaitsEngine->LoadUserData(nullptr); break; case CHORD_ENGINE: { alloc_engine(plaits::kChordNumChords * plaits::kChordNumNotes + plaits::kChordNumChords + plaits::kChordNumNotes); init_params(0.5f, 0.5f, 0.5f, {0.8f, 0.8f, false}); engine::addParam(V_OCT, &_v_oct); int32_t *pchord = (int32_t *)&static_cast(_plaitsEngine)->chords_.chord_index_quantizer_.quantized_value_; *pchord = 8; engine::addParam("Chord", pchord, 0, static_cast(_plaitsEngine)->chords_.chord_index_quantizer_.num_steps() - 1, (const char **)plaits::chord_names); engine::addParam("Inv.", &timbre); engine::addParam("Shape", &morph); engine::addParam("Decay", &patch.decay); if (_mode.output == 2) engine::addParam("AuxMix", &out_aux_mix, out_aux_mix); else engine::addParam("Color", &patch.lpg_colour); } break; // case 15: // speech_engine_ // alloc_engine(false, 0.8f, 0.8f); // break; // case 8: // swarm_engine_ // alloc_engine(false, -3.0f, 1.0f); // break; // case 9: // noise_engine_ // alloc_engine(false, -1.0f, -1.0f); // break; // case 10: // particle_engine_ // alloc_engine(false, -2.0f, 1.0f); // break; // case 11: // string_engine_ // alloc_engine(true, -1.0f, 0.8f); // break; // case 12: // modal_engine_ // alloc_engine(true, -0.5f, 0.8f); // break; case 13: _base_pitch += -24.f; alloc_engine(); init_params(0.8f, 0.5f, 0.5f, {0.8f, 0.8f, true}); engine::addParam("Pitch", &_pitch, -1.f, 1.f); engine::addParam(_mode.output == 0 ? "Drive" : "Punch", &harmonics); engine::addParam("Tone", &timbre); engine::addParam("Decay", &morph); break; case 14: alloc_engine(); init_params(0.5f, 0.5f, 0.5f, {0.8f, 0.8f, true}); engine::addParam("Pitch", &_pitch, -1.f, 1.f); engine::addParam("Snappy", &harmonics); engine::addParam("Tone", &timbre); engine::addParam("Decay", &morph); break; case 15: alloc_engine(); init_params(0.5f, 0.9f, 0.6f, {0.8f, 0.8f, true}); engine::addParam("Pitch", &_pitch, -1.f, 1.f); engine::addParam("Noise", &harmonics); engine::addParam("Tone", &timbre); engine::addParam("Decay", &morph); break; // engines 2 case CLASSIC_VAVCF_ENGINE: alloc_engine(); init_params(0.5f, 0.5f, 0.5f, {1.f, 1.f, false}); engine::addParam(V_OCT, &_v_oct); engine::addParam("Morph", &morph); engine::addParam("Cutoff", &timbre); engine::addParam("Harsh", &harmonics); out_aux_mix = 0; modulations.timbre_patched = false; patch.timbre_modulation_amount = 0; engine::addParam("EnvMod", &patch.timbre_modulation_amount, -1.f, 1.f); patch.decay = 0.5f; engine::addParam("Decay", &patch.decay, 0.f, 0.99f); break; #if 0 // TODO.... case 17: alloc_engine(plaits::kMaxBlockSize * 4); _plaitsEngine->post_processing_settings = {0.7f, 0.7f, false}; break; case 18: case 19: case 20: alloc_engine( plaits::kMaxBlockSize * 4 + plaits::kMaxBlockSize * plaits::kNumSixOpVoices + sizeof(plaits::fm::Patch) * 96 / sizeof(float)); init_params("", 0.0f, "Mod", 0.5f, "Env", 0.5f, {1.f, 1.f, false}); param[1].init_presets("Preset", &static_cast(_plaitsEngine)->patch_index, 0, 0, 95); param[1].print_value = [&](char *name) { auto i = static_cast(_plaitsEngine)->patch_index; sprintf(name, ">%.10s", static_cast(_plaitsEngine)->patches_[i].name); }; _plaitsEngine->LoadUserData(plaits::fm_patches_table[0]); modulations.morph_patched = false; param[5].init("EnvMod", &patch.morph_modulation_amount, 0.0f, -1.f, 1.f); modulations.timbre_patched = false; param[4].init("ModMod", &patch.timbre_modulation_amount, 0.0f, -1.f, 1.f); break; case 21: alloc_engine(plaits::kMaxBlockSize * 4); _plaitsEngine->post_processing_settings = {0.7f, 0.7f, false}; patch.engine = (engine - 16); break; case 22: alloc_engine(16 + 3 * (1024 + 265)); _plaitsEngine->post_processing_settings = {0.8f, 0.8f, false}; patch.engine = (engine - 16); break; case 23: alloc_engine(plaits::kChordNumChords * plaits::kChordNumNotes + plaits::kChordNumChords + plaits::kChordNumNotes); _plaitsEngine->post_processing_settings = {0.5f, 0.5f, false}; patch.engine = (engine - 16); break; #endif } if (_mode.engine >= 16) patch.engine = (_mode.engine - 16); _plaitsEngine->Reset(); } void engine::process() { float a = bufferOut[0] / 256.f; ONE_POLE(patch.harmonics, harmonics + a, 0.1f); ONE_POLE(patch.timbre, timbre + a, 0.1f); ONE_POLE(patch.morph, morph + a, 0.1f); modulations.level_patched = false; modulations.level = 1.f; patch.note = _base_pitch + (_pitch + engine::cv()) * 12; float last_decay = patch.decay; float last_morph = patch.morph; // if (!frame.trigger && frame.gate) // { // if (is_drum()) // patch.morph = 1; // else // patch.decay = 1; // modulations.level = 1.f; // // modulations.level_patched = true; // } modulations.engine = patch.engine; modulations.trigger = engine::trig() ? 1 : 0; if (!is_drum()) modulations.trigger_patched = patch.decay < 1.f; if (!engine::hasTrig()) { modulations.trigger_patched = false; modulations.level_patched = true; modulations.level = patch.decay; patch.decay = 0.001f; } else { modulations.trigger_patched = true; } modulations.note = 0; voice.Render(_plaitsEngine, patch, modulations, bufferOut, bufferAux, FRAME_BUFFER_SIZE); patch.decay = last_decay; patch.morph = last_morph; switch (_mode.output) { case 0: std::copy_n(bufferOut, FRAME_BUFFER_SIZE, engine::outputBuffer<0>()); std::copy_n(bufferOut, FRAME_BUFFER_SIZE, engine::outputBuffer<1>()); break; case 1: std::copy_n(bufferAux, FRAME_BUFFER_SIZE, engine::outputBuffer<0>()); std::copy_n(bufferAux, FRAME_BUFFER_SIZE, engine::outputBuffer<1>()); break; case 2: for (int i = 0; i < FRAME_BUFFER_SIZE; i++) bufferOut[i] = stmlib::Crossfade(bufferOut[i], bufferAux[i], out_aux_mix); std::copy_n(bufferOut, FRAME_BUFFER_SIZE, engine::outputBuffer<0>()); std::copy_n(bufferOut, FRAME_BUFFER_SIZE, engine::outputBuffer<1>()); break; case 3: std::copy_n(bufferOut, FRAME_BUFFER_SIZE, engine::outputBuffer<0>()); std::copy_n(bufferAux, FRAME_BUFFER_SIZE, engine::outputBuffer<1>()); break; } } void engine::draw() { engine::setParamName(&patch.decay, engine::hasTrig() ? "Decay" : "Level"); } #include "stmlib/utils/random.cc" #include "lib/stmlib/dsp/units.cc" //${SCRIPT_PATH}/main.cc $(find lib/plaits/ -type f -name "*.cc") #include "lib/plaits/resources.cc" // lib/plaits/dsp/speech/sam_speech_synth.cc // lib/plaits/dsp/speech/lpc_speech_synth_controller.cc // lib/plaits/dsp/speech/lpc_speech_synth_words.cc // lib/plaits/dsp/speech/lpc_speech_synth_phonemes.cc // lib/plaits/dsp/speech/naive_speech_synth.cc // lib/plaits/dsp/speech/lpc_speech_synth.cc #include "lib/plaits/dsp/engine/string_engine.cc" #include "lib/plaits/dsp/engine/swarm_engine.cc" #include "lib/plaits/dsp/engine/chord_engine.cc" #include "lib/plaits/dsp/engine/waveshaping_engine.cc" #include "lib/plaits/dsp/engine/modal_engine.cc" #include "lib/plaits/dsp/engine/fm_engine.cc" #include "lib/plaits/dsp/engine/snare_drum_engine.cc" // #include "lib/plaits/dsp/engine/speech_engine.cc" #include "lib/plaits/dsp/engine/grain_engine.cc" #include "lib/plaits/dsp/engine/virtual_analog_engine.cc" #include "lib/plaits/dsp/engine/wavetable_engine.cc" #include "lib/plaits/dsp/engine/additive_engine.cc" #include "lib/plaits/dsp/engine/noise_engine.cc" #include "lib/plaits/dsp/engine/hi_hat_engine.cc" #include "lib/plaits/dsp/engine/particle_engine.cc" #include "lib/plaits/dsp/engine/bass_drum_engine.cc" // lib/plaits/dsp/engine2/chiptune_engine.cc // lib/plaits/dsp/engine2/six_op_engine.cc // lib/plaits/dsp/engine2/wave_terrain_engine.cc // lib/plaits/dsp/engine2/string_machine_engine.cc // lib/plaits/dsp/engine2/phase_distortion_engine.cc #include "lib/plaits/dsp/engine2/virtual_analog_vcf_engine.cc" #include "lib/plaits/dsp/chords/chord_bank.cc" #include "lib/plaits/dsp/physical_modelling/string_voice.cc" #include "lib/plaits/dsp/physical_modelling/string.cc" #include "lib/plaits/dsp/physical_modelling/modal_voice.cc" #include "lib/plaits/dsp/physical_modelling/resonator.cc" #include "lib/plaits/dsp/fm/algorithms.cc" #include "lib/plaits/dsp/fm/dx_units.cc" #include "lib/plaits/dsp/voice.cc" ================================================ FILE: src/build.sh ================================================ #!/usr/bin/bash set -e #-eo pipefail SCRIPT_PATH="$(realpath $(dirname $0))" cd ${SCRIPT_PATH}/.. [[ -d .venv ]] || python3 -m venv .venv [[ -f .venv/bin/activate ]] && source .venv/bin/activate [[ -f .venv/Scripts/activate ]] && source .venv/Scripts/activate pip install -r src/requirements.txt if [[ ! -d ./.build/xpack-arm-none-eabi-gcc-10.3.1-2.1 ]] ; then mkdir -p ./.build cd ./.build if which winver; then [[ -f ./xpack-arm-none-eabi-gcc-10.3.1-2.1-win32-x64.zip ]] || curl -fLO https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases/download/v10.3.1-2.1/xpack-arm-none-eabi-gcc-10.3.1-2.1-win32-x64.zip unzip xpack-arm-none-eabi-gcc-10.3.1-2.1-win32-x64.zip -d . else [[ -f ./xpack-arm-none-eabi-gcc-10.3.1-2.1-linux-x64.tar.gz ]] || curl -fLO https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases/download/v10.3.1-2.1/xpack-arm-none-eabi-gcc-10.3.1-2.1-linux-x64.tar.gz cat xpack-arm-none-eabi-gcc-10.3.1-2.1-linux-x64.tar.gz | tar xvz -C . > /dev/null fi cd - fi export GCC_PATH=$(realpath ./.build/xpack-arm-none-eabi-gcc-10.3.1-2.1/bin/) export PATH="${PATH}:${GCC_PATH}" if [[ ! -d ./.build/udynlink ]]; then git clone https://github.com/eh2k/udynlink.git ./.build/udynlink/ fi mkmodule=$(realpath ./.build/udynlink/scripts/mkmodule) if ! which arm-none-eabi-gcc; then echo arm-none-eabi-gcc not found! exit 1 fi if [[ "$1" == "--rebuild" ]]; then find "${SCRIPT_PATH}/../app/" -type f -name "*.bin" -print0 -exec touch {} + rm -f ${SCRIPT_PATH}/apps.txt fi for f in $(find "${SCRIPT_PATH}" -mindepth 2 -maxdepth 2 -type f -name '*.cpp'); do X="${f%.*}" if [ -f $oo ] && [ "$(date -R -r ${X/src/app}.bin)" = "$(date -R -r $f)" ]; then continue fi #-fno-rtti NAME="$(grep "ENGINE_NAME:" $f | cut -d':' -f2 | sed 's/^ *//g')" NAME=${NAME//$'\n'/';'} #replace \n with '' NAME=${NAME:-"$(realpath --relative-to=${SCRIPT_PATH} $X)"} echo ----- "$NAME" ----- BUILD_FLAGS=$(grep "build_flags:" $X.cpp | cut -d':' -f2- | xargs) BUILD_FLAGS=${BUILD_FLAGS:-"-mfloat-abi=hard -mfpu=fpv5-d16 -ffast-math"} echo "BUILD_FLAGS:$BUILD_FLAGS" SRC_FILES=$(grep "src_files" $X.cpp | cut -d':' -f2 | xargs) find "$(dirname $X.cpp)" -type f -name '*.o' -delete #--no-opt \ #-felide-constructors -fno-rtti -std=gnu++14 -Wno-error=narrowing -fno-threadsafe-statics $mkmodule $(realpath $X.cpp --relative-base=.) \ --no-opt \ --build_flags="-fsingle-precision-constant -DNDEBUG -pedantic -fno-exceptions $BUILD_FLAGS -I. -I./lib/ " \ --public-symbols="setup,process,draw,screensaver,__ui_event_handler,__midi_event_handler" \ --name="$NAME" $SRC_FILES> $X.log sed -i "s|$(realpath .)|.|" $X.log touch -d "$(date -R -r $X.cpp)" $X.bin mkdir -p $(dirname "${X/src/app}") mv "$X.bin" "${X/src/app}.bin" mv "$X.elf" "${X/src/app}.elf" mv "$X.log" "${X/src/app}.log" X="${X/src/app}" #cat $X.log | arm-none-eabi-c++filt -t > ${X}2.log arm-none-eabi-objdump -Dztr --source $X.elf | arm-none-eabi-c++filt -t > $X.elf.txt #arm-none-eabi-nm -l -t d -S -C --size-sort --synthetic --special-syms --with-symbol-versions --reverse-sort ./$X.elf > $X.log python -m elf_size_analyze -t arm-none-eabi- $(realpath $X.elf --relative-base=.) -F -R --no-color >> $X.log ${SCRIPT_PATH}/dump.py "$(realpath $X.bin --relative-base=.)" | tee -a $X.log #rm $X.elf if [[ "$1" == "--rebuild" ]]; then ${SCRIPT_PATH}/dump.py "$(realpath $X.bin --relative-base=.)" >> ${SCRIPT_PATH}/../app/apps.txt fi grep "__aeabi_" $X.log && exit 1 #xxd -i $X.bin > ./$X.bin.h #sed -i "s/unsigned char/const uint8_t/g" ./$X.bin.h #sed -i "s/\[\]/\[\] FLASHMEM __attribute__((aligned(32)))/g" ./$X.bin.h # arm-none-eabi-gcc -fPIE -msingle-pic-base -mcpu=cortex-m4 -mthumb -Wl,--unresolved-symbols=ignore-in-object-files -fdump-lang-class -I. -I../lib/ $X.cpp # arm-none-eabi-objdump --disassemble-all --no-addresses ./$X.elf > $X.s # arm-none-eabi-objdump --disassemble-all ./$X.elf > $X.adr.s #/home/master/git/udynlink/tests/xpack-qemu-arm-7.2.5-1/bin/qemu-system-gnuarmeclipse -board STM32F429I-Discovery -image $X.elf -nographic done cd ${SCRIPT_PATH} pwd find . -type f -name '*.o' -delete cd ../app/ find . -type f -name '*.bin' -exec stat --printf="%-20n\t%6s\n" -- {} \; du -ch */*.bin | grep total #find . -type f -name '*.bin' -delete find . -type f -name '*.bin' | cut -c 3- | sort | jq -R -s -c 'split("\n")[:-1] | {apps: .} ' | jq > index.json if [[ "$1" == "--upload" || "$2" == "--upload" ]]; then python ../app/upload.py fi ================================================ FILE: src/dump.py ================================================ #!/usr/bin/env python3 import sys, zlib, hashlib def md5sum(data): h = hashlib.md5() h.update(data) return h.hexdigest() f = open(sys.argv[1], "rb") data = f.read() f.close() #print(data[0:4]) # sign l = int.from_bytes(data[4:6], byteorder='little')#num_lot r = int.from_bytes(data[6:8], byteorder='little'); #num_rels a = int.from_bytes(data[8:12], byteorder='little'); #symt_size b = int.from_bytes(data[12:16], byteorder='little'); #code_size c = int.from_bytes(data[16:20], byteorder='little'); #data_size d = int.from_bytes(data[20:24], byteorder='little'); #bss_size h = 24 + (r * 8) + a print("---------------------------------------------") print("FILE_NAME", f.name) print("RAM_SIZE", (l * 4) + c + d) print("BIN_SIZE", h + b + c) print("FILE_LEN", len(data)) crc32sum = zlib.crc32(data[0:-1]) print("CRC32 %x" % crc32sum) print("MD5 %s" % md5sum(data)) ================================================ FILE: src/squares-and-circles-api.h ================================================ // Copyright (C)2023 - E.Heidt // // Author: E.Heidt (eh2k@gmx.de) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // See http://creativecommons.org/licenses/MIT/ for more information. // //////////////////////////////////////////////////////////////////////////////// // Work in Progress: API will have breaking changes !!!! //////////////////////////////////////////////////////////////////////////////// #pragma once #include #include #include #include #include #include #define V_OCT "V_OCT" #define V_QTZ "V_QTZ" #define SEQ_SWING "$SWING" #define MULTI_TRIGS ">TRIGS" #define OUT_CV "CV" #define OUT_VOCT "VOCT" #define OUT_TRIG "TRIG" #define OUT_GATE "GATE" #define OUT_ACCENT "ACCENT" #define OUT_AUDIO "AUDIO" #define OUT_AUDIO_L "AUDIO_L" #define OUT_AUDIO_R "AUDIO_R" constexpr uint32_t ENGINE_MODE_COMPACT = 1 << 5; constexpr uint32_t ENGINE_MODE_MIDI_IN = 1 << 7; #ifndef EXTERN_C #define EXTERN_C extern "C" #endif #ifndef FLASHMEM #define FLASHMEM #endif #ifndef M_PI_2 #define M_PI_2 1.57079632679489661923 #endif #ifndef MOD #define MOD(x, y) ((y > 0 ? (x % y) : 0)) #endif #ifndef CONSTRAIN #define CONSTRAIN(var, min, max) \ if (var < (min)) \ { \ var = (min); \ } \ else if (var > (max)) \ { \ var = (max); \ } #endif #ifndef MACHINE_INTERNAL #define LEN_OF(x) (sizeof(x) / sizeof(x[0])) #ifdef __cplusplus #ifdef __GNUC__ /* poision memory functions */ // # pragma GCC poison _ZSt17__throw_bad_allocv // # pragma GCC poison new delete // # pragma GCC poison malloc new // # pragma GCC poison virtual #endif EXTERN_C uint32_t micros(); EXTERN_C uint32_t millis(); EXTERN_C uint32_t crc32(uint32_t crc, const void *buf, size_t size); inline float linToExp(float in, float inMin, float inMax, float outMin, float outMax) { float tmp = (in - inMin) / (inMax - inMin); return outMin * expf(tmp * (logf(outMax / outMin))); } #endif #ifndef DEFAULT_NOTE #define DEFAULT_NOTE 60 #endif #ifndef SAMPLE_RATE #define SAMPLE_RATE 48000 #endif #ifndef FRAME_BUFFER_SIZE #define FRAME_BUFFER_SIZE 24 #endif #ifndef PITCH_PER_OCTAVE #define PITCH_PER_OCTAVE (12 << 7) #endif #ifndef engine EXTERN_C { extern const char *__name; extern const uint8_t *__data; extern uint32_t *__t; extern uint8_t *__clock; extern uint8_t *__step; extern uint32_t *__step_changed; extern uint32_t *__samples_per_step; extern uint32_t *__trig; extern uint32_t *__gate; extern uint32_t *__accent; extern int32_t *__cv; extern float *__output_l_fp; extern float *__output_r_fp; extern uint8_t *__trig_level; extern uint8_t *__midi_cc; extern uint8_t *__mixer_level; extern uint8_t *__mixer_pan; extern uint32_t *__multi_trigs_mask; extern float **__audio_in_l_fpp; extern float **__audio_in_r_fpp; extern uint8_t *__display_buffer_u8_p; extern uint32_t *__engine_props; extern float *__adc_voltage_f_p; extern uint32_t __adc_count; extern float *__dac_voltage_fp_p; extern uint32_t __dac_count; extern uint32_t *__digital_inputs_u32_p; extern uint32_t *__bpm; struct UI_EVENT_t { uint16_t type; uint16_t control; int16_t value; uint16_t mask; bool handled; }; extern UI_EVENT_t *__ui_event; typedef bool (*uiHandler)(uint16_t type, uint16_t control, int16_t value, uint16_t mask); #ifndef NO_UI_EVENT_HANDLER uiHandler __ui_event_handler_ptr = nullptr; /* EXPORT */ void __ui_event_handler() { if (__ui_event_handler_ptr) __ui_event->handled = __ui_event_handler_ptr(__ui_event->type, __ui_event->control, __ui_event->value, __ui_event->mask); } #endif struct MIDI_EVENT_t { uint8_t type; uint8_t key; int16_t value; }; extern MIDI_EVENT_t *__midi_event; #ifndef NO_MIDI_EVENT_HANDLER void (*__midi_event_handler_ptr)() = nullptr; /* EXPORT */ void __midi_event_handler() { if (__midi_event_handler_ptr) __midi_event_handler_ptr(); } #endif extern uint8_t *__io_tr; extern uint8_t *__io_qz; } namespace engine { inline const char *name() { return __name; } inline uint32_t t() { return *__t; } inline uint32_t trig() { return *__trig; } inline bool hasTrig() { return *__io_tr; } inline uint8_t qz() { return *__io_qz; } inline uint32_t gate() { return *__gate; } inline uint32_t accent() { return *__accent; } inline float cv() { return (float)*__cv / PITCH_PER_OCTAVE; } inline int32_t cv_i32() { return *__cv; } template inline float *outputBuffer(); template <> inline float *outputBuffer<0>() { return __output_l_fp; } template <> inline float *outputBuffer<1>() { return __output_r_fp; } template inline float *inputBuffer(); template <> inline float *inputBuffer<0>() { return *__audio_in_l_fpp; } template <> inline float *inputBuffer<1>() { return *__audio_in_r_fpp; } inline float trigLevel(int ch) { return ((4.f / UINT16_MAX) * __trig_level[ch] * __trig_level[ch]); } inline float mixLevel(int ch) { return ((4.f / UINT16_MAX) * __mixer_level[ch]) * __mixer_level[ch]; } // exp range 0 - 4 inline float mixLevelL(int ch) { return cosf((float)__mixer_pan[ch] / 255.f * (float)M_PI_2) * mixLevel(ch); } inline float mixLevelR(int ch) { return sinf((float)__mixer_pan[ch] / 255.f * (float)M_PI_2) * mixLevel(ch); } EXTERN_C void setup(); EXTERN_C void process(); EXTERN_C void draw(); EXTERN_C void screensaver(); EXTERN_C void release(); ///// inline void setUIHandler(uiHandler handler) { __ui_event_handler_ptr = nullptr; __ui_event_handler(); __ui_event_handler_ptr = handler; } constexpr uint8_t MIDI_RTM_STOP = 252; constexpr uint8_t MIDI_RTM_START = 250; constexpr uint8_t MIDI_RTM_CONTINUE = 251; void __attribute__((weak)) onMidiNote(uint8_t key, uint8_t velocity); // NoteOff: velocity == 0 void __attribute__((weak)) onMidiPitchbend(int16_t pitch); void __attribute__((weak)) onMidiCC(uint8_t ccc, uint8_t value); void __attribute__((weak)) onMidiSysex(uint8_t byte); void __attribute__((weak)) onMidiRTM(uint8_t code); EXTERN_C void setupMultiTrigs(size_t count, const char **names, const std::pair *keyMap); EXTERN_C void setMultiTrigMidiKeyMap(const std::pair *keyMap); inline uint8_t getMidiCC(uint8_t ccc) { return __midi_cc[ccc]; } // 1V == 1.f, 5V = 5.f EXTERN_C float *outputBuffer_f32(const char *name); // 1V == PITCH_PER_OCTAVE, 5V == 5 * PITCH_PER_OCTAVE EXTERN_C int16_t *outputBuffer_i16(const char *name); // 1V == 1.f, 5V = 5.f EXTERN_C float *inputBuffer_f32(const char *name); // 1V == PITCH_PER_OCTAVE, 5V == 5 * PITCH_PER_OCTAVE EXTERN_C int16_t *inputBuffer_i16(const char *name); EXTERN_C void addParam_f32(const char *name, float *value, float min = 0.f, float max = 1.f); // min...max EXTERN_C void addParam_i32(const char *name, int32_t *value, int32_t min, int32_t max, const char **valueMap); // 0...max inline void addParam(const char *name, int32_t *value, int32_t min, int32_t max, const char **valueMap = nullptr) // 0...max { addParam_i32(name, value, min, max, &valueMap[0]); } inline void addParam(const char *name, float *value, float min = 0.f, float max = 1.f) // 0...max { addParam_f32(name, value, min, max); } EXTERN_C void setPatchStateEx(void *ptr, size_t size); inline void setMode(uint32_t mode) // 1: compact_mode, 2: sample_view { *__engine_props |= mode; if (mode & ENGINE_MODE_MIDI_IN) { __midi_event_handler_ptr = []() { switch (__midi_event->type) { case 0: onMidiNote(__midi_event->key, __midi_event->value); return; case 1: onMidiPitchbend(__midi_event->value); return; case 2: onMidiCC(__midi_event->key, __midi_event->value); return; case 3: onMidiSysex(__midi_event->key); return; case 4: engine::onMidiRTM(__midi_event->key); return; } }; } } constexpr uint32_t PARAM_SELECTED = 0x1; constexpr uint32_t PARAM_MODULATION = 0x2; EXTERN_C float getParamValueModulated_f32(const void *valuePtr); EXTERN_C int32_t getParamValueModulated_i32(const void *valuePtr); EXTERN_C uint32_t getParamFlags(const void *valuePtr); EXTERN_C void selectParam(const void *val); inline uint32_t isParamModulated(const void *valuePtr) { return getParamFlags(valuePtr) & PARAM_MODULATION; } inline uint32_t isParamSelected(const void *valuePtr) { return getParamFlags(valuePtr) & PARAM_SELECTED; } EXTERN_C void setParamName(const void *valuePtr, const char *name); EXTERN_C bool qz_enabled(); EXTERN_C const char *qz_name(); EXTERN_C int32_t qz_process(int32_t pitch, int8_t *note = nullptr); EXTERN_C int16_t qz_lookup(int8_t note); // 0-127 note-values } // namespace engine enum EventType : uint16_t { EVENT_NONE, EVENT_BUTTON_UP = 2, EVENT_BUTTON_HOLD, EVENT_ENCODER, }; constexpr uint16_t BUTTON_L = (1 << 0); constexpr uint16_t BUTTON_R = (1 << 1); constexpr uint16_t ENCODER_L = (1 << 8); constexpr uint16_t ENCODER_R = (1 << 9); namespace engine_sync { constexpr uint8_t CLOCK_RESET = 97; inline uint8_t ppn() { return *__clock; } inline uint32_t samples_per_step() { return *__samples_per_step; } inline uint32_t clk_bpm() // BPM x 100 { return *__bpm; } inline void clk_bpm(uint32_t bpm) { *__bpm = bpm; } inline uint8_t step() { return *__step; } inline bool stepChanged() { return *__step_changed != 0; } inline bool stepReset() { return *__step_changed > 1; } } // namespace engine_sync namespace machine { EXTERN_C const uint8_t *fs_read(const char *blobName, size_t *blobSize = nullptr); inline uint32_t raw_digital_inputs() { return *__digital_inputs_u32_p; } inline float *raw_adc_voltage(uint32_t index) { if (index < __adc_count) return &__adc_voltage_f_p[index]; else return nullptr; } inline float *raw_dac_buffer(uint32_t index) { if (index < __dac_count) return &__dac_voltage_fp_p[index]; else return nullptr; } } // namespace machine #else using namespace ui; using namespace UI; #endif #ifndef GFX_API namespace gfx { EXTERN_C void drawCircle(int x, int y, int r); EXTERN_C void fillCircle(int x, int y, int r); EXTERN_C void clearCircle(int x, int y, int r); EXTERN_C void drawRect(int x, int y, int w, int h); EXTERN_C void fillRect(int x, int y, int w, int h); EXTERN_C void clearRect(int x, int y, int w, int h); EXTERN_C void invertRect(int x, int y, int w, int h); EXTERN_C void drawString(int x, int y, const char *s, uint8_t font = 1); EXTERN_C void drawStringEx(int x, int y, uint8_t font, const char *fmt, ...); EXTERN_C void drawStringCenter(int x, int y, const char *s, uint8_t font = 1); EXTERN_C void drawLine(int x1, int y1, int x2, int y2); EXTERN_C void setPixel(int x, int y); EXTERN_C void drawXbm(int x, int y, int width, int height, const uint8_t *xbm); EXTERN_C void drawWaveform(void *wavefrom, int x = 0, int y = -1); EXTERN_C void message(const char *msg); EXTERN_C void drawPiano(int x, int y, float note); EXTERN_C void drawMessageBox(const char *title, const char *message); EXTERN_C void drawScope(int y, float *inputFrame, int x_scale = 32 /* 0 - 63*/, int y_scale = 63 /* 0 - 63*/); inline uint8_t *displayBuffer() { return __display_buffer_u8_p; } } // namespace gfx #endif #ifndef SERIAL_API namespace machine { EXTERN_C void serial_write(void const *buffer, uint32_t bufsiz); EXTERN_C uint32_t serial_read(void *buffer, uint32_t length); EXTERN_C uint32_t serial_available(); EXTERN_C void get_device_id(uint8_t *mac); EXTERN_C float cpu_load_percent(); EXTERN_C uint8_t *engine_malloc(uint32_t size); EXTERN_C void engine_start(uint32_t args); EXTERN_C void engine_stop(uint32_t result); } // namespace machine #endif #endif // MACHINE_INTERNAL struct sample; struct sample_info { const char *name; uint32_t len; uint16_t sample_rate; uint8_t channels; const char *labels[32]; float label_pos[32]; uint8_t label_num; }; EXTERN_C sample *sample_s8(const uint8_t *data, int len, int sample_rate, int addr_shift); EXTERN_C sample *sample_u8(const uint8_t *data, int len, int sample_rate, int addr_shift); EXTERN_C sample *sample_Am6070(const uint8_t *data, int len, int sample_rate, int amp_mul); EXTERN_C sample *sample_wav(const uint8_t *data, int len); EXTERN_C sample *sample_wav_from_file(const char *filepath, sample *dispose_reuse_mem = nullptr); EXTERN_C void sample_dispose(sample *smpl); EXTERN_C void sample_set_pos(sample *smpl, float pos, float amplitude, float decay); EXTERN_C void sample_process(sample *smpl, float start, float end, float speed, float cv, float *outputL_frame, float *outputR_frame = nullptr); EXTERN_C bool sample_get_info(sample *smpl, sample_info *info); // fatfs api -- ff.h enum FRESULT : int { FR_OK = 0, FR_DISK_ERR = 1, FR_INT_ERR = 2, FR_NO_FILE = 4, FR_INVALID_OBJECT = 9, FR_NOT_ENOUGH_CORE = 17, /* NOT ENOUGH RAM */ FR_TOO_MANY_OPEN_FILES = 18, FR_INVALID_PARAMETER = 19, }; struct FIL_IMPL; typedef struct { FIL_IMPL *impl; } FIL; typedef unsigned int UINT; /* int must be 16-bit or 32-bit */ typedef unsigned char BYTE; /* char must be 8-bit */ typedef uint16_t WORD; /* 16-bit unsigned integer */ typedef uint32_t DWORD; /* 32-bit unsigned integer */ typedef uint64_t QWORD; /* 64-bit unsigned integer */ typedef WORD WCHAR; /* UTF-16 character type */ typedef DWORD FSIZE_t; #define FA_READ 0x01 #define FA_WRITE 0x02 #define FA_OPEN_EXISTING 0x00 #define FA_CREATE_NEW 0x04 #define FA_CREATE_ALWAYS 0x08 #define FA_OPEN_ALWAYS 0x10 #define FA_OPEN_APPEND 0x30 EXTERN_C FRESULT f_open(FIL *fp, const char *name, uint32_t mode); EXTERN_C FRESULT f_read(FIL *fp, void *p, UINT size, UINT *bytes_read); EXTERN_C FSIZE_t f_tell(FIL *fp); EXTERN_C FSIZE_t f_size(FIL *fp); // EXTERN_C FRESULT f_truncate(FIL *fp); // EXTERN_C FRESULT f_lseek(FIL *fp, FSIZE_t ofs); EXTERN_C FRESULT f_close(FIL *fp); EXTERN_C FRESULT f_write(FIL *fp, const void *buff, UINT btw, UINT *bw); struct DIR_IMPL; typedef struct { DIR_IMPL *impl; } DIR; #define AM_DIR 0x10 /* Directory */ typedef struct { FSIZE_t fsize; BYTE fattrib; char fname[256 + 1]; /* Object name */ } FILINFO; EXTERN_C FRESULT f_opendir(DIR *dp, /* [OUT] Pointer to the directory object structure */ const char *path /* [IN] Directory name */ ); EXTERN_C FRESULT f_closedir(DIR *dp /* [IN] Pointer to the directory object */ ); EXTERN_C FRESULT f_findnext(DIR *dp, /* [IN] Poninter to the directory object */ FILINFO *fno /* [OUT] Pointer to the file information structure */ ); EXTERN_C const char *stristr(const char *str1, const char *str2); ================================================ FILE: src/test.cxx ================================================ #include #include #include #include #include #include #include #include "../lib/misc/noise.hxx" #include "../lib/plaits/dsp/oscillator/oscillator.h" #include "../lib/plaits/resources.h" #define ASSERT_EQ(val1, val2) \ if (((val1) != (val2))) \ { \ std::cout << "ASSERT FAILED: " << __FILE__ << ":" << __LINE__ << ": " << #val1 << " != " << val2 << std::endl; \ exit(1); \ } \ else \ std::cout << "ASSERT OK: " << __FILE__ << ":" << __LINE__ << ": " << #val1 << " == " << val2 << std::endl; #define ASSERT_NEQ(val1, val2) \ if (((val1) == (val2))) \ { \ std::cout << "ASSERT FAILED: " << __FILE__ << ":" << __LINE__ << ": " << #val1 << " != " << val2 << std::endl; \ exit(1); \ } \ else \ std::cout << "ASSERT OK: " << __FILE__ << ":" << __LINE__ << ": " << #val1 << " == " << val2 << std::endl; void write_wav(const std::vector &buffer, int nchannels, const std::string &fileName) { typedef struct WAV_HEADER { /* RIFF Chunk Descriptor */ uint8_t RIFF[4] = {'R', 'I', 'F', 'F'}; // RIFF Header Magic header uint32_t ChunkSize; // RIFF Chunk Size uint8_t WAVE[4] = {'W', 'A', 'V', 'E'}; // WAVE Header /* "fmt" sub-chunk */ uint8_t fmt[4] = {'f', 'm', 't', ' '}; // FMT header uint32_t Subchunk1Size = 16; // Size of the fmt chunk uint16_t AudioFormat = 1; // Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM // Mu-Law, 258=IBM A-Law, 259=ADPCM uint16_t NumOfChan = 1; // Number of channels 1=Mono 2=Sterio uint32_t SamplesPerSec = 48000; // Sampling Frequency in Hz uint32_t bytesPerSec = 48000 * 2; // bytes per second uint16_t blockAlign = 2; // 2=16-bit mono, 4=16-bit stereo uint16_t bitsPerSample = 16; // Number of bits per sample /* "data" sub-chunk */ uint8_t Subchunk2ID[4] = {'d', 'a', 't', 'a'}; // "data" string uint32_t Subchunk2Size; // Sampled data length } wav_hdr; static_assert(sizeof(wav_hdr) == 44, ""); auto fsize = buffer.size() * sizeof(int16_t); std::string in_name = "test.bin"; // raw pcm data without wave header wav_hdr wav; wav.NumOfChan = nchannels; wav.blockAlign *= nchannels; wav.ChunkSize = -1; //fsize + sizeof(wav_hdr) - 8; wav.Subchunk2Size = -1; //fsize; std::ofstream out(fileName, std::ios::binary); out.write(reinterpret_cast(&wav), sizeof(wav)); out.write(reinterpret_cast(&buffer[0]), fsize); } int nchannels = 1; std::vector buffer; #define clock scclock extern void (*__midi_event_handler_ptr)(); extern void (*__ui_event_handler_ptr)(); void __ui_event_handler() { } #define NO_UI_EVENT_HANDLER #define NO_MIDI_EVENT_HANDLER #include "squares-and-circles-api.h" UI_EVENT_t *__ui_event = nullptr; MIDI_EVENT_t *__midi_event = nullptr; uint8_t *__clock = new uint8_t[1]; uint8_t *__step = new uint8_t[1]; uint32_t *__step_changed = new uint32_t[1]; float *__audio_in_l_fp = new float[FRAME_BUFFER_SIZE]; float *__audio_in_r_fp = new float[FRAME_BUFFER_SIZE]; float **__audio_in_l_fpp = &__audio_in_l_fp; float **__audio_in_r_fpp = &__audio_in_r_fp; uint32_t *__engine_props = new uint32_t[1]; uint32_t *__trig = new uint32_t[1]; uint32_t *__gate = new uint32_t[1]; uint32_t *__accent = new uint32_t[1]; int32_t *__cv = new int32_t[1]; uint32_t *__t = new uint32_t[1]{0}; uint32_t *__samples_per_step = new uint32_t[1]{3000 / 2}; // 120BPM int32_t *_paramP = nullptr; int32_t _paramMax = 0; EXTERN_C { void addParam_f32(const char *name, float *value, float min = 0.f, float max = 1.f) // min...max { } void addParam_i32(const char *name, int32_t *value, int32_t min, int32_t max, const char **valueMap) // 0...max { if (_paramP == nullptr) { _paramP = value; _paramMax = max; } } void setParamName(const void *valuePtr, const char *name) { } void drawRect(int x, int y, int w, int h) { } void drawLine(int x0, int y0, int x1, int y1) { } void drawString(int x, int y, const char *text, uint8_t font) { } void fillRect(int x, int y, int w, int h) { } void drawCircle(int x, int y, int r) { } void drawXbm(int x, int y, int width, int height, const uint8_t *xbm) { } void clearRect(int x, int y, int w, int h) { } uint32_t getParamFlags(const void *valuePtr) { return 0; } bool qz_enabled() { return true; } int16_t qz_lookup(int8_t note) { // return ((int32_t)note - 64) << 7; return ((int32_t)note - DEFAULT_NOTE) * (PITCH_PER_OCTAVE / 12); } int32_t qz_process(int32_t pitch, int8_t *note) { return pitch; } void drawWaveform(void *wavefrom, int x = 0, int y = -1) { } // 1V == PITCH_PER_OCTAVE, 5V == 5 * PITCH_PER_OCTAVE float *__output_f32[6] = {}; int16_t *__output_i16[6] = {}; float *outputBuffer_f32(const char *name) { for (auto &o : __output_f32) { if (o == nullptr) { o = new float[FRAME_BUFFER_SIZE]; return o; } } } int _oi = -1; int16_t *outputBuffer_i16(const char *name) { for (auto &o : __output_i16) { if (o == nullptr) { o = new int16_t[FRAME_BUFFER_SIZE]; return o; } } } } #define ENGINE_MODE_CV_OUT 1 void write_frame() { if (__output_i16[0] != nullptr) { for (int k = 0; k < FRAME_BUFFER_SIZE; k++) { auto v = (float)(__output_i16[0][k]) / (5 * PITCH_PER_OCTAVE); buffer.push_back(v * INT16_MAX); if (__output_i16[1] != nullptr) { nchannels = 2; v = (float)(__output_i16[1][k]) / (5 * PITCH_PER_OCTAVE); buffer.push_back(v * INT16_MAX); } } } else { for (int k = 0; k < FRAME_BUFFER_SIZE; k++) { auto v = (__output_f32[0][k] * INT16_MAX); CONSTRAIN(v, INT16_MIN, INT16_MAX); buffer.push_back(v); if (__output_f32[1] != nullptr) { nchannels = 2; v = (__output_f32[1][k] * INT16_MAX); CONSTRAIN(v, INT16_MIN, INT16_MAX); buffer.push_back(v); } } } } #include "extern/eproms/lm2/CLAP.BIN.h" #include "../machine/src/base/sample.hxx" int main() { std::ofstream out("LM2-CLAP.bin", std::ios::binary); sample s(SAMPLE_FORMAT_AM6070, "", CLAP_BIN, sizeof(CLAP_BIN), 48000, 1); for(size_t i = 0; i < sizeof(CLAP_BIN); i++) { auto f = s.get_i16(i); out.write(reinterpret_cast(&f), sizeof(f)); } return 0; engine::setup(); // engine::process(); WhiteNoise noise; plaits::Oscillator osc; osc.Init(); float phase_inc_ = 440.f / 2 / SAMPLE_RATE; __cv[0] = 0; //-PITCH_PER_OCTAVE * 2; // if (_paramP) // _paramP[0]--; for (size_t i = 0; i < SAMPLE_RATE * 10; i += FRAME_BUFFER_SIZE) { __step_changed[0] = (i % 24000) == FRAME_BUFFER_SIZE ? 1 : 0; for (size_t j = 0; j < FRAME_BUFFER_SIZE; j++) { __audio_in_l_fp[j] = noise.nextf(-1, 1); __audio_in_r_fp[j] = noise.nextf(-1, 1); } osc.Render(phase_inc_, 0.5f, __audio_in_l_fp, FRAME_BUFFER_SIZE); memcpy(__audio_in_r_fp, __audio_in_l_fp, sizeof(float) * FRAME_BUFFER_SIZE); __trig[0] = (i % (SAMPLE_RATE / 2)) == 0; __gate[0] = (i % (SAMPLE_RATE / 2)) < SAMPLE_RATE / 3; // if (((i / SAMPLE_RATE) % 2) == 1) // __cv[0] = PITCH_PER_OCTAVE; // else // __cv[0] = 0; // if (i % (SAMPLE_RATE) == 0) // { // if (_paramP) // { // _paramP[0]++; // if (_paramP[0] > _paramMax) // break; // } // __cv[0] = -PITCH_PER_OCTAVE * 2; // } engine::process(); __t[0]++; if (__step_changed[0]) { __step[0]++; __step[0] %= 96; } write_frame(); } for (int i = 0; i < FRAME_BUFFER_SIZE; i++) printf("%x ", buffer[i]); printf("\n"); write_wav(buffer, nchannels, "test.wav"); return 0; } ================================================ FILE: src/test.sh ================================================ cd $(dirname $0)/.. set -ex export GCC_PATH=$(realpath .)/.build/gcc_mingw64/bin/ export PATH="${PATH}:${GCC_PATH}" COVERAGE="" #"-coverage" g++ -pg -g -m64 -O0 -coverage -I. -I./lib/ -I./extern/ -fpermissive -DTEST src/test.cxx src/SYNTH/DT303.cpp -o test.exe ./test.exe #rm test.exe; if [[ $COVERAGE != "" ]]; then [ -d .build/lcov-1.16/ ] || curl -L https://github.com/linux-test-project/lcov/releases/download/v1.16/lcov-1.16.tar.gz | tar xvz -C .build/ .build/lcov-1.16/bin/lcov --directory . --capture --output-file coverage.info .build/lcov-1.16/bin/genhtml --demangle-cpp --dark-mode -o .test coverage.info fi rm *.gcda *.gcno gmon.out coverage.info ================================================ FILE: test/test_midi.sh ================================================ set -e int=$(amidi -l | tail -n -1 | cut -d' ' -f 3) amidi -p $int -S "F34D" # set CH 1,2,3,4 RANDOM=1 I=0 N=52 while true; do for i in $(seq 0 100); do PROG1=$((1 + $RANDOM % $N)) PROG2=$((1 + $RANDOM % $N)) PROG3=$((1 + $RANDOM % $N)) PROG4=$((1 + $RANDOM % $N)) #if [[ $PROG == "x35" || $PROG == "33" || $PROG == "39" || $PROG == "40" || $PROG == "x41" ]]; then continue; fi echo "$I: $C -> $PROG1, $PROG2, $PROG3, $PROG4" amidi -p $int -S "$(printf "C%x%02x" 0 $PROG1)" amidi -p $int -S "$(printf "C%x%02x" 1 $PROG2)" amidi -p $int -S "$(printf "C%x%02x" 2 $PROG3)" amidi -p $int -S "$(printf "C%x%02x" 3 $PROG4)" I=$(($I + 1)) #sleep 0.001 done amidi -p $int -S "F372" #NEXT (press L) done