瀏覽代碼

Merge pull request #1 from PaulStoffregen/master

Merging updates from PaulStoffregen/Audio to my fork
dds
Michele Perla 9 年之前
父節點
當前提交
d0e0cbfac2
共有 100 個檔案被更改,包括 11360 行新增4703 行删除
  1. +54
    -0
      .travis.yml
  2. +0
    -2817
      Audio.cpp
  3. +82
    -472
      Audio.h
  4. +48
    -0
      AudioControl.h
  5. +48
    -11
      README.md
  6. +131
    -0
      analyze_fft1024.cpp
  7. +102
    -0
      analyze_fft1024.h
  8. +129
    -0
      analyze_fft256.cpp
  9. +117
    -0
      analyze_fft256.h
  10. +53
    -0
      analyze_peak.cpp
  11. +62
    -0
      analyze_peak.h
  12. +100
    -0
      analyze_print.cpp
  13. +54
    -0
      analyze_print.h
  14. +170
    -0
      analyze_tonedetect.cpp
  15. +72
    -0
      analyze_tonedetect.h
  16. +996
    -0
      control_sgtl5000.cpp
  17. +121
    -0
      control_sgtl5000.h
  18. +136
    -0
      control_wm8731.cpp
  19. +51
    -0
      control_wm8731.h
  20. +26
    -1
      data_ulaw.c
  21. +123
    -0
      data_waveforms.c
  22. +1618
    -0
      data_windows.c
  23. +96
    -0
      effect_bitcrusher.cpp
  24. +57
    -0
      effect_bitcrusher.h
  25. +126
    -0
      effect_chorus.cpp
  26. +56
    -0
      effect_chorus.h
  27. +135
    -0
      effect_delay.cpp
  28. +98
    -0
      effect_delay.h
  29. +255
    -0
      effect_delay_ext.cpp
  30. +86
    -0
      effect_delay_ext.h
  31. +156
    -0
      effect_envelope.cpp
  32. +94
    -0
      effect_envelope.h
  33. +97
    -0
      effect_fade.cpp
  34. +56
    -0
      effect_fade.h
  35. +219
    -0
      effect_flange.cpp
  36. +58
    -0
      effect_flange.h
  37. +89
    -0
      effect_multiply.cpp
  38. +41
    -0
      effect_multiply.h
  39. +256
    -0
      examples/Analysis/DialTone_7segment/DialTone_7segment.ino
  40. +230
    -0
      examples/Analysis/DialTone_Serial/DialTone_Serial.ino
  41. +78
    -0
      examples/Analysis/FFT/FFT.ino
  42. +46
    -0
      examples/Analysis/PeakMeterMono/PeakMeterMono.ino
  43. +64
    -0
      examples/Analysis/PeakMeterStereo/PeakMeterStereo.ino
  44. +143
    -0
      examples/Analysis/SpectrumAnalyzerBasic/SpectrumAnalyzerBasic.ino
  45. +202
    -0
      examples/Effects/Bitcrusher/Bitcrusher.ino
  46. +186
    -0
      examples/Effects/Chorus/Chorus.ino
  47. +54
    -0
      examples/Effects/Chorus/effects_info.h
  48. +61
    -0
      examples/Effects/Delay/Delay.ino
  49. +42
    -0
      examples/Effects/Filter/Filter.ino
  50. +175
    -0
      examples/Effects/Filter_FIR/Filter_FIR.ino
  51. +108
    -0
      examples/Effects/Filter_FIR/bandp_1200_1700.h
  52. +8
    -0
      examples/Effects/Filter_FIR/filters.cpp
  53. +5
    -0
      examples/Effects/Filter_FIR/filters.h
  54. +109
    -0
      examples/Effects/Filter_FIR/lopass_1000_44100.h
  55. 二進制
      examples/Effects/Filter_FIR/screencap_bandpass.jpg
  56. 二進制
      examples/Effects/Filter_FIR/screencap_lowpass.jpg
  57. +179
    -0
      examples/Effects/Flange/Flange.ino
  58. +54
    -0
      examples/Effects/Flange/effects_info.h
  59. +0
    -50
      examples/FFT/FFT.ino
  60. +0
    -53
      examples/Filter/Filter.ino
  61. +34
    -0
      examples/HardwareTesting/PassThroughMono/PassThroughMono.ino
  62. +50
    -0
      examples/HardwareTesting/PassThroughStereo/PassThroughStereo.ino
  63. +66
    -0
      examples/HardwareTesting/SGTL5000/CalcBiquadToneControlDAP/CalcBiquadToneControlDAP.ino
  64. +66
    -0
      examples/HardwareTesting/SGTL5000/balanceDAC/balanceDAC.ino
  65. +66
    -0
      examples/HardwareTesting/SGTL5000/balanceHP/balanceHP.ino
  66. +63
    -0
      examples/HardwareTesting/SGTL5000/dap_avc_agc/dap_avc_agc.ino
  67. +64
    -0
      examples/HardwareTesting/SGTL5000/dap_bass_enhance/dap_bass_enhance.ino
  68. +283
    -0
      examples/HardwareTesting/SdCardTest/SdCardTest.ino
  69. +84
    -0
      examples/HardwareTesting/ToneSweep/ToneSweep.ino
  70. +51
    -0
      examples/HardwareTesting/WM8731MikroSine/WM8731MikroSine.ino
  71. +154
    -0
      examples/MemoryAndCpuUsage/MemoryAndCpuUsage.ino
  72. +0
    -50
      examples/PassThrough/PassThrough.ino
  73. +0
    -40
      examples/PassThroughAnalog/PassThroughAnalog.ino
  74. +0
    -94
      examples/PassThroughPlusTone/PassThroughPlusTone.ino
  75. +0
    -110
      examples/PlayMidiTones/MidiTones.ino
  76. +0
    -636
      examples/PlayMidiTones/william_tell_overture.c
  77. +0
    -60
      examples/PlaySineMikroe/PlaySineMikroe.ino
  78. +0
    -43
      examples/PlayWavFromSdCard/PlayWavFromSdCard.ino
  79. +194
    -0
      examples/Recorder/Recorder.ino
  80. +0
    -0
      examples/SamplePlayer/AudioSampleCashregister.cpp
  81. +0
    -0
      examples/SamplePlayer/AudioSampleCashregister.h
  82. +0
    -0
      examples/SamplePlayer/AudioSampleGong.cpp
  83. +0
    -0
      examples/SamplePlayer/AudioSampleGong.h
  84. +0
    -0
      examples/SamplePlayer/AudioSampleHihat.cpp
  85. +0
    -0
      examples/SamplePlayer/AudioSampleHihat.h
  86. +0
    -0
      examples/SamplePlayer/AudioSampleKick.cpp
  87. +0
    -0
      examples/SamplePlayer/AudioSampleKick.h
  88. +0
    -0
      examples/SamplePlayer/AudioSampleSnare.cpp
  89. +0
    -0
      examples/SamplePlayer/AudioSampleSnare.h
  90. +0
    -0
      examples/SamplePlayer/AudioSampleTomtom.cpp
  91. +0
    -0
      examples/SamplePlayer/AudioSampleTomtom.h
  92. +3
    -1
      examples/SamplePlayer/SamplePlayer.ino
  93. +0
    -126
      examples/SdCardTest/SdCardTest.ino
  94. +0
    -139
      examples/SpectrumAnalyzer/SpectrumAnalyzer.ino
  95. +70
    -0
      examples/Synthesis/PlaySynthMusic/PlaySynthMusic.h
  96. +256
    -0
      examples/Synthesis/PlaySynthMusic/PlaySynthMusic.ino
  97. +5
    -0
      examples/Synthesis/PlaySynthMusic/miditones/Makefile
  98. +975
    -0
      examples/Synthesis/PlaySynthMusic/miditones/miditonesV1.6.c
  99. +864
    -0
      examples/Synthesis/PlaySynthMusic/william_tell_overture.c
  100. +0
    -0
      examples/Synthesis/pulseWidth/pulseWidth.ino

+ 54
- 0
.travis.yml 查看文件

@@ -0,0 +1,54 @@
language: python
python:
- "2.7"

# Cache PlatformIO packages using Travis CI container-based infrastructure
sudo: false
cache:
directories:
- "~/.platformio"

env:
- PLATFORMIO_CI_SRC=examples/MemoryAndCpuUsage
- PLATFORMIO_CI_SRC=examples/Recorder
- PLATFORMIO_CI_SRC=examples/SamplePlayer
- PLATFORMIO_CI_SRC=examples/WavFilePlayer
- PLATFORMIO_CI_SRC=examples/Analysis/DialTone_7segment
- PLATFORMIO_CI_SRC=examples/Analysis/DialTone_Serial
- PLATFORMIO_CI_SRC=examples/Analysis/FFT
- PLATFORMIO_CI_SRC=examples/Analysis/PeakMeterMono
- PLATFORMIO_CI_SRC=examples/Analysis/PeakMeterStereo
- PLATFORMIO_CI_SRC=examples/Analysis/SpectrumAnalyzerBasic
- PLATFORMIO_CI_SRC=examples/Effects/Bitcrusher
- PLATFORMIO_CI_SRC=examples/Effects/Chorus
- PLATFORMIO_CI_SRC=examples/Effects/Delay
- PLATFORMIO_CI_SRC=examples/Effects/Filter
- PLATFORMIO_CI_SRC=examples/Effects/Filter_FIR
- PLATFORMIO_CI_SRC=examples/Effects/Flange
- PLATFORMIO_CI_SRC=examples/HardwareTesting/PassThroughMono
- PLATFORMIO_CI_SRC=examples/HardwareTesting/PassThroughStereo
- PLATFORMIO_CI_SRC=examples/HardwareTesting/SdCardTest
- PLATFORMIO_CI_SRC=examples/HardwareTesting/ToneSweep
- PLATFORMIO_CI_SRC=examples/HardwareTesting/WM8731MikroSine
- PLATFORMIO_CI_SRC=examples/Synthesis/PlaySynthMusic
- PLATFORMIO_CI_SRC=examples/Synthesis/pulseWidth
- PLATFORMIO_CI_SRC=examples/Tutorial/Part_1_02_Hardware_Test
- PLATFORMIO_CI_SRC=examples/Tutorial/Part_1_03_Playing_Music
- PLATFORMIO_CI_SRC=examples/Tutorial/Part_1_04_Blink_While_Playing
- PLATFORMIO_CI_SRC=examples/Tutorial/Part_1_05_Do_More_While_Playing

install:
- pip install -U platformio

# install dependent libraries
# http://platformio.org/#!/lib/show/539/SerialFlash
- platformio lib install 539
- export PLATFORMIO_BUILD_FLAGS=-larm_cortexM4l_math

# remove unused items
- rm -r extras
- rm -r examples/Synthesis/PlaySynthMusic/miditones

script:
- platformio ci --lib=. --board=teensy31

+ 0
- 2817
Audio.cpp
文件差異過大導致無法顯示
查看文件


+ 82
- 472
Audio.h 查看文件

@@ -1,5 +1,45 @@
#include "AudioStream.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 Audio_h_
#define Audio_h_

#if TEENSYDUINO < 120
#error "Teensyduino version 1.20 or later is required to compile the Audio library."
#endif
#ifdef __AVR__
#error "The Audio Library only works with Teensy 3.X. Teensy 2.0 is unsupported."
#endif

#include "DMAChannel.h"
#if !defined(DMACHANNEL_HAS_BEGIN) || !defined(DMACHANNEL_HAS_BOOLEAN_CTOR)
#error "You need to update DMAChannel.h & DMAChannel.cpp"
#error "https://github.com/PaulStoffregen/cores/blob/master/teensy3/DMAChannel.h"
#error "https://github.com/PaulStoffregen/cores/blob/master/teensy3/DMAChannel.cpp"
#endif

// When changing multiple audio object settings that must update at
// the same time, these functions allow the audio library interrupt
@@ -11,479 +51,49 @@
// library to update with AudioInterrupts(). Both changes will happen
// at the same time, because AudioNoInterrupts() prevents any updates
// while you make changes.
//
#define AudioNoInterrupts() (NVIC_DISABLE_IRQ(IRQ_SOFTWARE))
#define AudioInterrupts() (NVIC_ENABLE_IRQ(IRQ_SOFTWARE))

// include all the library headers, so a sketch can use a single
// #include <Audio.h> to get the whole library
//
#include "analyze_fft256.h"
#include "analyze_fft1024.h"
#include "analyze_print.h"
#include "analyze_tonedetect.h"
#include "analyze_peak.h"
#include "control_sgtl5000.h"
#include "control_wm8731.h"
#include "effect_bitcrusher.h"
#include "effect_chorus.h"
#include "effect_fade.h"
#include "effect_flange.h"
#include "effect_envelope.h"
#include "effect_multiply.h"
#include "effect_delay.h"
#include "effect_delay_ext.h"
#include "filter_biquad.h"
#include "filter_fir.h"
#include "filter_variable.h"
#include "input_adc.h"
#include "input_i2s.h"
#include "mixer.h"
#include "output_dac.h"
#include "output_i2s.h"
#include "output_pwm.h"
#include "output_spdif.h"
#include "play_memory.h"
#include "play_queue.h"
#include "play_sd_raw.h"
#include "play_sd_wav.h"
#include "play_serialflash_raw.h"
#include "record_queue.h"
#include "synth_tonesweep.h"
#include "synth_sine.h"
#include "synth_waveform.h"
#include "synth_dc.h"
#include "synth_whitenoise.h"
#include "synth_pinknoise.h"

// waveforms.c
extern "C" {
extern const int16_t AudioWaveformSine[257];
extern const int16_t AudioWaveformTriangle[257];
extern const int16_t AudioWaveformSquare[257];
extern const int16_t AudioWaveformSawtooth[257];
}

// windows.c
extern "C" {
extern const int16_t AudioWindowHanning256[];
extern const int16_t AudioWindowBartlett256[];
extern const int16_t AudioWindowBlackman256[];
extern const int16_t AudioWindowFlattop256[];
extern const int16_t AudioWindowBlackmanHarris256[];
extern const int16_t AudioWindowNuttall256[];
extern const int16_t AudioWindowBlackmanNuttall256[];
extern const int16_t AudioWindowWelch256[];
extern const int16_t AudioWindowHamming256[];
extern const int16_t AudioWindowCosine256[];
extern const int16_t AudioWindowTukey256[];
}

class AudioAnalyzeFFT256 : public AudioStream
{
public:
AudioAnalyzeFFT256(uint8_t navg = 8, const int16_t *win = AudioWindowHanning256)
: AudioStream(1, inputQueueArray), outputflag(false),
prevblock(NULL), count(0), naverage(navg), window(win) { init(); }

bool available() {
if (outputflag == true) {
outputflag = false;
return true;
}
return false;
}
virtual void update(void);
//uint32_t cycles;
int32_t output[128] __attribute__ ((aligned (4)));
private:
void init(void);
const int16_t *window;
audio_block_t *prevblock;
int16_t buffer[512] __attribute__ ((aligned (4)));
uint8_t count;
uint8_t naverage;
bool outputflag;
audio_block_t *inputQueueArray[1];
};



class AudioSynthWaveform : public AudioStream
{
public:
AudioSynthWaveform(const int16_t *waveform)
: AudioStream(0, NULL), wavetable(waveform), magnitude(0), phase(0) { }
void frequency(float freq) {
if (freq > AUDIO_SAMPLE_RATE_EXACT / 2 || freq < 0.0) return;
phase_increment = (freq / AUDIO_SAMPLE_RATE_EXACT) * 4294967296.0f;
}
void amplitude(float n) { // 0 to 1.0
if (n < 0) n = 0;
else if (n > 1.0) n = 1.0;
magnitude = n * 32767.0;
}
virtual void update(void);
private:
const int16_t *wavetable;
uint16_t magnitude;
uint32_t phase;
uint32_t phase_increment;
};




#if 0
class AudioSineWaveMod : public AudioStream
{
public:
AudioSineWaveMod() : AudioStream(1, inputQueueArray) {}
void frequency(float freq);
//void amplitude(q15 n);
virtual void update(void);
private:
uint32_t phase;
uint32_t phase_increment;
uint32_t modulation_factor;
audio_block_t *inputQueueArray[1];
};
#endif





class AudioOutputPWM : public AudioStream
{
public:
AudioOutputPWM(void) : AudioStream(1, inputQueueArray) { begin(); }
virtual void update(void);
void begin(void);
friend void dma_ch3_isr(void);
private:
static audio_block_t *block_1st;
static audio_block_t *block_2nd;
static uint32_t block_offset;
static bool update_responsibility;
static uint8_t interrupt_count;
audio_block_t *inputQueueArray[1];
};





class AudioOutputAnalog : public AudioStream
{
public:
AudioOutputAnalog(void) : AudioStream(1, inputQueueArray) { begin(); }
virtual void update(void);
void begin(void);
void analogReference(int ref);
friend void dma_ch4_isr(void);
private:
static audio_block_t *block_left_1st;
static audio_block_t *block_left_2nd;
static bool update_responsibility;
audio_block_t *inputQueueArray[1];
};





class AudioPrint : public AudioStream
{
public:
AudioPrint(const char *str) : AudioStream(1, inputQueueArray), name(str) {}
virtual void update(void);
private:
const char *name;
audio_block_t *inputQueueArray[1];
};





















class AudioInputI2S : public AudioStream
{
public:
AudioInputI2S(void) : AudioStream(0, NULL) { begin(); }
virtual void update(void);
void begin(void);
friend void dma_ch1_isr(void);
protected:
AudioInputI2S(int dummy): AudioStream(0, NULL) {} // to be used only inside AudioInputI2Sslave !!
static bool update_responsibility; // TODO: implement and test this.
private:
static audio_block_t *block_left;
static audio_block_t *block_right;
static uint16_t block_offset;
};


class AudioOutputI2S : public AudioStream
{
public:
AudioOutputI2S(void) : AudioStream(2, inputQueueArray) { begin(); }
virtual void update(void);
void begin(void);
friend void dma_ch0_isr(void);
friend class AudioInputI2S;
protected:
AudioOutputI2S(int dummy): AudioStream(2, inputQueueArray) {} // to be used only inside AudioOutputI2Sslave !!
static void config_i2s(void);
static audio_block_t *block_left_1st;
static audio_block_t *block_right_1st;
static bool update_responsibility;
private:
static audio_block_t *block_left_2nd;
static audio_block_t *block_right_2nd;
static uint16_t block_left_offset;
static uint16_t block_right_offset;
audio_block_t *inputQueueArray[2];
};


class AudioInputI2Sslave : public AudioInputI2S
{
public:
AudioInputI2Sslave(void) : AudioInputI2S(0) { begin(); }
void begin(void);
friend void dma_ch1_isr(void);
};


class AudioOutputI2Sslave : public AudioOutputI2S
{
public:
AudioOutputI2Sslave(void) : AudioOutputI2S(0) { begin(); } ;
void begin(void);
friend class AudioInputI2Sslave;
friend void dma_ch0_isr(void);
protected:
static void config_i2s(void);
};





class AudioInputAnalog : public AudioStream
{
public:
AudioInputAnalog(unsigned int pin) : AudioStream(0, NULL) { begin(pin); }
virtual void update(void);
void begin(unsigned int pin);
friend void dma_ch2_isr(void);
private:
static audio_block_t *block_left;
static uint16_t block_offset;
uint16_t dc_average;
//static bool update_responsibility; // TODO: implement and test this.
};




















#include "SD.h"

class AudioPlaySDcardWAV : public AudioStream
{
public:
AudioPlaySDcardWAV(void) : AudioStream(0, NULL) { begin(); }
void begin(void);

bool play(const char *filename);
void stop(void);
bool start(void);
virtual void update(void);
private:
File wavfile;
bool consume(void);
bool parse_format(void);
uint32_t header[5];
uint32_t data_length; // number of bytes remaining in data section
audio_block_t *block_left;
audio_block_t *block_right;
uint16_t block_offset;
uint8_t buffer[512];
uint16_t buffer_remaining;
uint8_t state;
uint8_t state_play;
uint8_t leftover_bytes;
};


class AudioPlaySDcardRAW : public AudioStream
{
public:
AudioPlaySDcardRAW(void) : AudioStream(0, NULL) { begin(); }
void begin(void);
bool play(const char *filename);
void stop(void);
virtual void update(void);
private:
File rawfile;
audio_block_t *block;
bool playing;
bool paused;
};



class AudioPlayMemory : public AudioStream
{
public:
AudioPlayMemory(void) : AudioStream(0, NULL), playing(0) { }
void play(const unsigned int *data);
void stop(void);
virtual void update(void);
private:
const unsigned int *next;
uint32_t length;
int16_t prior;
volatile uint8_t playing;
};










class AudioMixer4 : public AudioStream
{
public:
AudioMixer4(void) : AudioStream(4, inputQueueArray) {
for (int i=0; i<4; i++) multiplier[i] = 65536;
}
virtual void update(void);
void gain(unsigned int channel, float gain) {
if (channel >= 4) return;
if (gain > 32767.0f) gain = 32767.0f;
else if (gain < 0.0f) gain = 0.0f;
multiplier[channel] = gain * 65536.0f; // TODO: proper roundoff?
}
private:
int32_t multiplier[4];
audio_block_t *inputQueueArray[4];
};






class AudioFilterBiquad : public AudioStream
{
public:
AudioFilterBiquad(int *parameters)
: AudioStream(1, inputQueueArray), definition(parameters) { }
virtual void update(void);
private:
int *definition;
audio_block_t *inputQueueArray[1];
};






// TODO: more audio processing objects....
// N-channel mixer, adjustable gain on each channel
// sine wave with frequency modulation (phase)
// non-sine oscillators, ramp, triangle, square/pulse, etc
// envelope: attack-decay-sustain-release, maybe other more complex?
// filters, low pass, high pass, bandpass, notch
// frequency analysis - FFT, single frequency (eg, filter for DTMF)
// MP3 decoding - it is possible with optimized code?
// other decompression, ADPCM, Vorbis, Speex, etc?




// A base class for all Codecs, DACs and ADCs, so at least the
// most basic functionality is consistent.

#define AUDIO_INPUT_LINEIN 0
#define AUDIO_INPUT_MIC 1

class AudioControl
{
public:
virtual bool enable(void) = 0;
virtual bool disable(void) = 0;
virtual bool volume(float volume) = 0; // volume 0.0 to 100.0
virtual bool inputLevel(float volume) = 0; // volume 0.0 to 100.0
virtual bool inputSelect(int n) = 0;
};



class AudioControlWM8731 : public AudioControl
{
public:
bool enable(void);
bool disable(void) { return false; }
bool volume(float n) { return volumeInteger(n * 0.8 + 47.499); }
bool inputLevel(float n) { return false; }
bool inputSelect(int n) { return false; }
protected:
bool write(unsigned int reg, unsigned int val);
bool volumeInteger(unsigned int n); // range: 0x2F to 0x7F
};

class AudioControlWM8731master : public AudioControlWM8731
{
public:
bool enable(void);
};


class AudioControlSGTL5000 : public AudioControl
{
public:
bool enable(void);
bool disable(void) { return false; }
bool volume(float n) { return volumeInteger(n * 1.29 + 0.499); }
bool inputLevel(float n) {return false;}
bool muteHeadphone(void) { return write(0x0024, ana_ctrl | (1<<4)); }
bool unmuteHeadphone(void) { return write(0x0024, ana_ctrl & ~(1<<4)); }
bool muteLineout(void) { return write(0x0024, ana_ctrl | (1<<8)); }
bool unmuteLineout(void) { return write(0x0024, ana_ctrl & ~(1<<8)); }
bool inputSelect(int n) {
if (n == AUDIO_INPUT_LINEIN) {
return write(0x0024, ana_ctrl | (1<<2));
} else if (n == AUDIO_INPUT_MIC) {
//return write(0x002A, 0x0172) && write(0x0024, ana_ctrl & ~(1<<2));
return write(0x002A, 0x0173) && write(0x0024, ana_ctrl & ~(1<<2)); // +40dB
} else {
return false;
}
}
//bool inputLinein(void) { return write(0x0024, ana_ctrl | (1<<2)); }
//bool inputMic(void) { return write(0x002A, 0x0172) && write(0x0024, ana_ctrl & ~(1<<2)); }
protected:
bool muted;
bool volumeInteger(unsigned int n); // range: 0x00 to 0x80
uint16_t ana_ctrl;



unsigned int read(unsigned int reg);
bool write(unsigned int reg, unsigned int val);
};

















+ 48
- 0
AudioControl.h 查看文件

@@ -0,0 +1,48 @@
/* 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 AudioControl_h_
#define AudioControl_h_

#include <stdint.h>

// A base class for all Codecs, DACs and ADCs, so at least the
// most basic functionality is consistent.

#define AUDIO_INPUT_LINEIN 0
#define AUDIO_INPUT_MIC 1

class AudioControl
{
public:
virtual bool enable(void) = 0;
virtual bool disable(void) = 0;
virtual bool volume(float volume) = 0; // volume 0.0 to 1.0
virtual bool inputLevel(float volume) = 0; // volume 0.0 to 1.0
virtual bool inputSelect(int n) = 0;
};

#endif

+ 48
- 11
README.md 查看文件

@@ -1,18 +1,55 @@
Audio
=====
Teensy Audio Library
====================

Audio library for Teensy 3.0 &amp; 3.1
[![Build Status](https://travis-ci.org/PaulStoffregen/Audio.svg?branch=master)](https://travis-ci.org/PaulStoffregen/Audio)

This is *BETA* status code. It works pretty well, but it's still under very active
development.
16 bit, 44.1 kHz streaming audio library for Teensy 3.x, featuring:

* Polyphonic Playback
* Recording
* Synthesis
* Analysis
* Effects
* Filtering
* Mixing
* Multiple Simultaneous Inputs & Outputs
* Flexible signal routing between library objects
* Automatic Streaming while your Arduino sketch runs

Main Audio Library Page
-----------------------

http://www.pjrc.com/teensy/td_libs_Audio.html


Audio System Design Tool
------------------------

Use this graphical tool to design your audio project. Easily browse the library's many features, connect objects, export to Arduino code, and quickly access details for the functions each object provides for you to control it from your Arduino sketch!

http://www.pjrc.com/teensy/gui/


Supported Hardware
------------------

[Audio Adaptor Board](http://www.pjrc.com/store/teensy3_audio.html) for 16 bit stereo input and output.

![Inputs](/gui/img/audioshield_inputs.jpg) ![Outputs](/gui/img/audioshield_outputs.jpg)

[Teensy 3.1](http://www.pjrc.com/store/teensy31.html) 12 bit DAC

![DAC Output](/gui/img/dacpin.jpg)

[Teensy 3.1](http://www.pjrc.com/store/teensy31.html) or [3.0](http://www.pjrc.com/store/teensy3.html) ADC Input

![ADC Input](/gui/img/adccircuit.png)

[Teensy 3.1](http://www.pjrc.com/store/teensy31.html) or [3.0](http://www.pjrc.com/store/teensy3.html) PWM Output

![PWM Output](/gui/img/pwmdualcircuit.jpg)

**APIs are likely to incompatibly change**.

Please discuss any issues here.
code

http://forum.pjrc.com/threads/24793-Audio-Library

Always try to post *reproducible* bug reports, with complete code and details
necessary to recreate the problem.


+ 131
- 0
analyze_fft1024.cpp 查看文件

@@ -0,0 +1,131 @@
/* 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.
*/

#include "analyze_fft1024.h"
#include "sqrt_integer.h"
#include "utility/dspinst.h"


// 140312 - PAH - slightly faster copy
static void copy_to_fft_buffer(void *destination, const void *source)
{
const uint16_t *src = (const uint16_t *)source;
uint32_t *dst = (uint32_t *)destination;

for (int i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
*dst++ = *src++; // real sample plus a zero for imaginary
}
}

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;
}

}

void AudioAnalyzeFFT1024::update(void)
{
audio_block_t *block;

block = receiveReadOnly();
if (!block) return;

#if defined(KINETISK)
switch (state) {
case 0:
blocklist[0] = block;
state = 1;
break;
case 1:
blocklist[1] = block;
state = 2;
break;
case 2:
blocklist[2] = block;
state = 3;
break;
case 3:
blocklist[3] = block;
state = 4;
break;
case 4:
blocklist[4] = block;
state = 5;
break;
case 5:
blocklist[5] = block;
state = 6;
break;
case 6:
blocklist[6] = block;
state = 7;
break;
case 7:
blocklist[7] = block;
// TODO: perhaps distribute the work over multiple update() ??
// github pull requsts welcome......
copy_to_fft_buffer(buffer+0x000, blocklist[0]->data);
copy_to_fft_buffer(buffer+0x100, blocklist[1]->data);
copy_to_fft_buffer(buffer+0x200, blocklist[2]->data);
copy_to_fft_buffer(buffer+0x300, blocklist[3]->data);
copy_to_fft_buffer(buffer+0x400, blocklist[4]->data);
copy_to_fft_buffer(buffer+0x500, blocklist[5]->data);
copy_to_fft_buffer(buffer+0x600, blocklist[6]->data);
copy_to_fft_buffer(buffer+0x700, blocklist[7]->data);
if (window) apply_window_to_fft_buffer(buffer, window);
arm_cfft_radix4_q15(&fft_inst, buffer);
// TODO: support averaging multiple copies
for (int i=0; i < 512; i++) {
uint32_t tmp = *((uint32_t *)buffer + i); // real & imag
uint32_t magsq = multiply_16tx16t_add_16bx16b(tmp, tmp);
output[i] = sqrt_uint32_approx(magsq);
}
outputflag = true;
release(blocklist[0]);
release(blocklist[1]);
release(blocklist[2]);
release(blocklist[3]);
blocklist[0] = blocklist[4];
blocklist[1] = blocklist[5];
blocklist[2] = blocklist[6];
blocklist[3] = blocklist[7];
state = 4;
break;
}
#else
release(block);
#endif
}



+ 102
- 0
analyze_fft1024.h 查看文件

@@ -0,0 +1,102 @@
/* 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 analyze_fft1024_h_
#define analyze_fft1024_h_

#include "AudioStream.h"
#include "arm_math.h"

// windows.c
extern "C" {
extern const int16_t AudioWindowHanning1024[];
extern const int16_t AudioWindowBartlett1024[];
extern const int16_t AudioWindowBlackman1024[];
extern const int16_t AudioWindowFlattop1024[];
extern const int16_t AudioWindowBlackmanHarris1024[];
extern const int16_t AudioWindowNuttall1024[];
extern const int16_t AudioWindowBlackmanNuttall1024[];
extern const int16_t AudioWindowWelch1024[];
extern const int16_t AudioWindowHamming1024[];
extern const int16_t AudioWindowCosine1024[];
extern const int16_t AudioWindowTukey1024[];
}

class AudioAnalyzeFFT1024 : public AudioStream
{
public:
AudioAnalyzeFFT1024() : AudioStream(1, inputQueueArray),
window(AudioWindowHanning1024), state(0), outputflag(false) {
arm_cfft_radix4_init_q15(&fft_inst, 1024, 0, 1);
}
bool available() {
if (outputflag == true) {
outputflag = false;
return true;
}
return false;
}
float read(unsigned int binNumber) {
if (binNumber > 511) return 0.0;
return (float)(output[binNumber]) * (1.0 / 16384.0);
}
float read(unsigned int binFirst, unsigned int binLast) {
if (binFirst > binLast) {
unsigned int tmp = binLast;
binLast = binFirst;
binFirst = tmp;
}
if (binFirst > 511) return 0.0;
if (binLast > 511) binLast = 511;
uint32_t sum = 0;
do {
sum += output[binFirst++];
} while (binFirst <= binLast);
return (float)sum * (1.0 / 16384.0);
}
void averageTogether(uint8_t n) {
// not implemented yet (may never be, 86 Hz output rate is ok)
}
void windowFunction(const int16_t *w) {
window = w;
}
virtual void update(void);
uint16_t output[512] __attribute__ ((aligned (4)));
private:
void init(void);
const int16_t *window;
audio_block_t *blocklist[8];
int16_t buffer[2048] __attribute__ ((aligned (4)));
//uint32_t sum[512];
//uint8_t count;
uint8_t state;
//uint8_t naverage;
volatile bool outputflag;
audio_block_t *inputQueueArray[1];
arm_cfft_radix4_instance_q15 fft_inst;
};

#endif

+ 129
- 0
analyze_fft256.cpp 查看文件

@@ -0,0 +1,129 @@
/* 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.
*/

#include "analyze_fft256.h"
#include "sqrt_integer.h"
#include "utility/dspinst.h"


// 140312 - PAH - slightly faster copy
static void copy_to_fft_buffer(void *destination, const void *source)
{
const uint16_t *src = (const uint16_t *)source;
uint32_t *dst = (uint32_t *)destination;

for (int i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
*dst++ = *src++; // real sample plus a zero for imaginary
}
}

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 < 256; i++) {
int32_t val = *buf * *win++;
//*buf = signed_saturate_rshift(val, 16, 15);
*buf = val >> 15;
buf += 2;
}
}

void AudioAnalyzeFFT256::update(void)
{
audio_block_t *block;

block = receiveReadOnly();
if (!block) return;
#if AUDIO_BLOCK_SAMPLES == 128
if (!prevblock) {
prevblock = block;
return;
}
copy_to_fft_buffer(buffer, prevblock->data);
copy_to_fft_buffer(buffer+256, block->data);
//window = AudioWindowBlackmanNuttall256;
//window = NULL;
if (window) apply_window_to_fft_buffer(buffer, window);
arm_cfft_radix4_q15(&fft_inst, buffer);
// G. Heinzel's paper says we're supposed to average the magnitude
// squared, then do the square root at the end.
if (count == 0) {
for (int i=0; i < 128; i++) {
uint32_t tmp = *((uint32_t *)buffer + i);
uint32_t magsq = multiply_16tx16t_add_16bx16b(tmp, tmp);
sum[i] = magsq / naverage;
}
} else {
for (int i=0; i < 128; i++) {
uint32_t tmp = *((uint32_t *)buffer + i);
uint32_t magsq = multiply_16tx16t_add_16bx16b(tmp, tmp);
sum[i] += magsq / naverage;
}
}
if (++count == naverage) {
count = 0;
for (int i=0; i < 128; i++) {
output[i] = sqrt_uint32_approx(sum[i]);
}
outputflag = true;
}
release(prevblock);
prevblock = block;
#elif AUDIO_BLOCK_SAMPLES == 64
if (prevblocks[2] == NULL) {
prevblocks[2] = prevblocks[1];
prevblocks[1] = prevblocks[0];
prevblocks[0] = block;
return;
}
if (count == 0) {
count = 1;
copy_to_fft_buffer(buffer, prevblocks[2]->data);
copy_to_fft_buffer(buffer+128, prevblocks[1]->data);
copy_to_fft_buffer(buffer+256, prevblocks[1]->data);
copy_to_fft_buffer(buffer+384, block->data);
if (window) apply_window_to_fft_buffer(buffer, window);
arm_cfft_radix4_q15(&fft_inst, buffer);
} else {
count = 2;
const uint32_t *p = (uint32_t *)buffer;
for (int i=0; i < 128; i++) {
uint32_t tmp = *p++;
int16_t v1 = tmp & 0xFFFF;
int16_t v2 = tmp >> 16;
output[i] = sqrt_uint32_approx(v1 * v1 + v2 * v2);
}
}
release(prevblocks[2]);
prevblocks[2] = prevblocks[1];
prevblocks[1] = prevblocks[0];
prevblocks[0] = block;
#endif
}



+ 117
- 0
analyze_fft256.h 查看文件

@@ -0,0 +1,117 @@
/* 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 analyze_fft256_h_
#define analyze_fft256_h_

#include "AudioStream.h"
#include "arm_math.h"

// windows.c
extern "C" {
extern const int16_t AudioWindowHanning256[];
extern const int16_t AudioWindowBartlett256[];
extern const int16_t AudioWindowBlackman256[];
extern const int16_t AudioWindowFlattop256[];
extern const int16_t AudioWindowBlackmanHarris256[];
extern const int16_t AudioWindowNuttall256[];
extern const int16_t AudioWindowBlackmanNuttall256[];
extern const int16_t AudioWindowWelch256[];
extern const int16_t AudioWindowHamming256[];
extern const int16_t AudioWindowCosine256[];
extern const int16_t AudioWindowTukey256[];
}

class AudioAnalyzeFFT256 : public AudioStream
{
public:
AudioAnalyzeFFT256() : AudioStream(1, inputQueueArray),
window(AudioWindowHanning256), count(0), outputflag(false) {
arm_cfft_radix4_init_q15(&fft_inst, 256, 0, 1);
#if AUDIO_BLOCK_SAMPLES == 128
prevblock = NULL;
naverage = 8;
#elif AUDIO_BLOCK_SAMPLES == 64
prevblocks[0] = NULL;
prevblocks[1] = NULL;
prevblocks[2] = NULL;
#endif
}
bool available() {
if (outputflag == true) {
outputflag = false;
return true;
}
return false;
}
float read(unsigned int binNumber) {
if (binNumber > 127) return 0.0;
return (float)(output[binNumber]) * (1.0 / 16384.0);
}
float read(unsigned int binFirst, unsigned int binLast) {
if (binFirst > binLast) {
unsigned int tmp = binLast;
binLast = binFirst;
binFirst = tmp;
}
if (binFirst > 127) return 0.0;
if (binLast > 127) binLast = 127;
uint32_t sum = 0;
do {
sum += output[binFirst++];
} while (binFirst <= binLast);
return (float)sum * (1.0 / 16384.0);
}
void averageTogether(uint8_t n) {
#if AUDIO_BLOCK_SAMPLES == 128
if (n == 0) n = 1;
naverage = n;
#endif
}
void windowFunction(const int16_t *w) {
window = w;
}
virtual void update(void);
uint16_t output[128] __attribute__ ((aligned (4)));
private:
const int16_t *window;
#if AUDIO_BLOCK_SAMPLES == 128
audio_block_t *prevblock;
#elif AUDIO_BLOCK_SAMPLES == 64
audio_block_t *prevblocks[3];
#endif
int16_t buffer[512] __attribute__ ((aligned (4)));
#if AUDIO_BLOCK_SAMPLES == 128
uint32_t sum[128];
uint8_t naverage;
#endif
uint8_t count;
bool outputflag;
audio_block_t *inputQueueArray[1];
arm_cfft_radix4_instance_q15 fft_inst;
};

#endif

+ 53
- 0
analyze_peak.cpp 查看文件

@@ -0,0 +1,53 @@
/* 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.
*/

#include "analyze_peak.h"

void AudioAnalyzePeak::update(void)
{
audio_block_t *block;
const int16_t *p, *end;
int32_t min, max;

block = receiveReadOnly();
if (!block) {
return;
}
p = block->data;
end = p + AUDIO_BLOCK_SAMPLES;
min = min_sample;
max = max_sample;
do {
int16_t d=*p++;
if (d<min) min=d;
if (d>max) max=d;
} while (p < end);
min_sample = min;
max_sample = max;
new_output = true;
release(block);
}


+ 62
- 0
analyze_peak.h 查看文件

@@ -0,0 +1,62 @@
/* 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 analyze_peakdetect_h_
#define analyze_peakdetect_h_

#include "AudioStream.h"

class AudioAnalyzePeak : public AudioStream
{
public:
AudioAnalyzePeak(void) : AudioStream(1, inputQueueArray) {
min_sample = 32767;
max_sample = -32768;
}
bool available(void) {
__disable_irq();
bool flag = new_output;
if (flag) new_output = false;
__enable_irq();
return flag;
}
float read(void) {
__disable_irq();
int diff = max_sample - min_sample;
min_sample = 32767;
max_sample = -32768;
__enable_irq();
return diff / 65535.0;
}
virtual void update(void);
private:
audio_block_t *inputQueueArray[1];
volatile bool new_output;
int16_t min_sample;
int16_t max_sample;
};

#endif

+ 100
- 0
analyze_print.cpp 查看文件

@@ -0,0 +1,100 @@
/* 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.
*/

#include "analyze_print.h"

#define STATE_IDLE 0 // doing nothing
#define STATE_WAIT_TRIGGER 1 // looking for trigger condition
#define STATE_DELAY 2 // waiting from trigger to print
#define STATE_PRINTING 3 // printing data

void AudioAnalyzePrint::update(void)
{
audio_block_t *block;
uint32_t offset = 0;
uint32_t remain, n;

block = receiveReadOnly();
if (!block) return;

while (offset < AUDIO_BLOCK_SAMPLES) {
remain = AUDIO_BLOCK_SAMPLES - offset;
switch (state) {
case STATE_WAIT_TRIGGER:
// TODO: implement this....
offset = AUDIO_BLOCK_SAMPLES;
break;

case STATE_DELAY:
//Serial.printf("STATE_DELAY, count = %u\n", count);
if (remain < count) {
count -= remain;
offset = AUDIO_BLOCK_SAMPLES;
} else {
offset += count;
count = print_length;
state = STATE_PRINTING;
}
break;

case STATE_PRINTING:
n = count;
if (n > remain) n = remain;
count -= n;
while (n > 0) {
Serial.println(block->data[offset++]);
n--;
}
if (count == 0) state = STATE_IDLE;
break;

default: // STATE_IDLE
offset = AUDIO_BLOCK_SAMPLES;
break;
}
}
release(block);
}

void AudioAnalyzePrint::trigger(void)
{
uint32_t n = delay_length;

if (n > 0) {
Serial.print("trigger ");
if (myname) Serial.print(myname);
Serial.print(", delay=");
Serial.println(n);
count = n;
state = 2;
} else {
Serial.print("trigger ");
if (myname) Serial.println(myname);
count = print_length;
state = 3;
}
}


+ 54
- 0
analyze_print.h 查看文件

@@ -0,0 +1,54 @@
/* 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 analyze_print_h_
#define analyze_print_h_

#include "AudioStream.h"

class AudioAnalyzePrint : public AudioStream
{
public:
AudioAnalyzePrint(void) : AudioStream(1, inputQueueArray),
myname(NULL), state(0), trigger_edge(0), delay_length(0), print_length(500) {}
virtual void update(void);
void name(const char *str) { myname = str; }
void trigger(void);
void trigger(float level, int edge);
void delay(uint32_t num) { delay_length = num; }
void length(uint32_t num) { print_length = num; }
private:
const char *myname;
uint8_t state;
uint8_t trigger_edge; // trigger type, 0=none, 2=RISING, 3=FALLING
int16_t trigger_level;
uint32_t delay_length; // number of samples between trigger and printing
uint32_t print_length; // number of samples to print
uint32_t count;
audio_block_t *inputQueueArray[1];
};

#endif

+ 170
- 0
analyze_tonedetect.cpp 查看文件

@@ -0,0 +1,170 @@
/* 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.
*/

#include "analyze_tonedetect.h"
#include "utility/dspinst.h"

#if defined(KINETISK)

static inline int32_t multiply_32x32_rshift30(int32_t a, int32_t b) __attribute__((always_inline));
static inline int32_t multiply_32x32_rshift30(int32_t a, int32_t b)
{
return ((int64_t)a * (int64_t)b) >> 30;
}

//#define TONE_DETECT_FAST

void AudioAnalyzeToneDetect::update(void)
{
audio_block_t *block;
int32_t q0, q1, q2, coef;
const int16_t *p, *end;
uint16_t n;

block = receiveReadOnly();
if (!block) return;
if (!enabled) {
release(block);
return;
}
p = block->data;
end = p + AUDIO_BLOCK_SAMPLES;
n = count;
coef = coefficient;
q1 = s1;
q2 = s2;
do {
// the Goertzel algorithm is kinda magical ;-)
#ifdef TONE_DETECT_FAST
q0 = (*p++) + (multiply_32x32_rshift32_rounded(coef, q1) << 2) - q2;
#else
q0 = (*p++) + multiply_32x32_rshift30(coef, q1) - q2;
// TODO: is this only 1 cycle slower? if so, always use it
#endif
q2 = q1;
q1 = q0;
if (--n == 0) {
out1 = q1;
out2 = q2;
q1 = 0; // TODO: does clearing these help or hinder?
q2 = 0;
new_output = true;
n = length;
}
} while (p < end);
count = n;
s1 = q1;
s2 = q2;
release(block);
}

void AudioAnalyzeToneDetect::set_params(int32_t coef, uint16_t cycles, uint16_t len)
{
__disable_irq();
coefficient = coef;
ncycles = cycles;
length = len;
count = len;
s1 = 0;
s2 = 0;
enabled = true;
__enable_irq();
//Serial.printf("Tone: coef=%d, ncycles=%d, length=%d\n", coefficient, ncycles, length);
}

float AudioAnalyzeToneDetect::read(void)
{
int32_t coef, q1, q2, power;
uint16_t len;

__disable_irq();
coef = coefficient;
q1 = out1;
q2 = out2;
len = length;
__enable_irq();
#ifdef TONE_DETECT_FAST
power = multiply_32x32_rshift32_rounded(q2, q2);
power = multiply_accumulate_32x32_rshift32_rounded(power, q1, q1);
power = multiply_subtract_32x32_rshift32_rounded(power,
multiply_32x32_rshift30(q1, q2), coef);
power <<= 4;
#else
int64_t power64;
power64 = (int64_t)q2 * (int64_t)q2;
power64 += (int64_t)q1 * (int64_t)q1;
power64 -= (((int64_t)q1 * (int64_t)q2) >> 30) * (int64_t)coef;
power = power64 >> 28;
#endif
return sqrtf((float)power) / (float)len;
}


AudioAnalyzeToneDetect::operator bool()
{
int32_t coef, q1, q2, power, trigger;
uint16_t len;

__disable_irq();
coef = coefficient;
q1 = out1;
q2 = out2;
len = length;
__enable_irq();
#ifdef TONE_DETECT_FAST
power = multiply_32x32_rshift32_rounded(q2, q2);
power = multiply_accumulate_32x32_rshift32_rounded(power, q1, q1);
power = multiply_subtract_32x32_rshift32_rounded(power,
multiply_32x32_rshift30(q1, q2), coef);
power <<= 4;
#else
int64_t power64;
power64 = (int64_t)q2 * (int64_t)q2;
power64 += (int64_t)q1 * (int64_t)q1;
power64 -= (((int64_t)q1 * (int64_t)q2) >> 30) * (int64_t)coef;
power = power64 >> 28;
#endif
trigger = (uint32_t)len * thresh;
trigger = multiply_32x32_rshift32(trigger, trigger);

//Serial.printf("bool: power=%d, trig=%d\n", power, trigger);
return (power >= trigger);
// TODO: this should really remember if it's retuned true previously,
// so it can give a single true response each time a tone is seen.
}


#elif defined(KINETISL)

void AudioAnalyzeToneDetect::update(void)
{
audio_block_t *block;
block = receiveReadOnly();
if (block) release(block);
}

#endif


+ 72
- 0
analyze_tonedetect.h 查看文件

@@ -0,0 +1,72 @@
/* 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 analyze_tonedetect_h_
#define analyze_tonedetect_h_

#include "AudioStream.h"

class AudioAnalyzeToneDetect : public AudioStream
{
public:
AudioAnalyzeToneDetect(void)
: AudioStream(1, inputQueueArray), thresh(6554), enabled(false) { }
void frequency(float freq, uint16_t cycles=10) {
set_params((int32_t)(cos((double)freq
* (2.0 * 3.14159265358979323846 / AUDIO_SAMPLE_RATE_EXACT))
* (double)2147483647.999), cycles,
(float)AUDIO_SAMPLE_RATE_EXACT / freq * (float)cycles + 0.5f);
}
void set_params(int32_t coef, uint16_t cycles, uint16_t len);
bool available(void) {
__disable_irq();
bool flag = new_output;
if (flag) new_output = false;
__enable_irq();
return flag;
}
float read(void);
void threshold(float level) {
if (level < 0.01f) thresh = 655;
else if (level > 0.99f) thresh = 64881;
else thresh = level * 65536.0f + 0.5f;
}
operator bool(); // true if at or above threshold, false if below
virtual void update(void);
private:
int32_t coefficient; // Goertzel algorithm coefficient
int32_t s1, s2; // Goertzel algorithm state
int32_t out1, out2; // Goertzel algorithm state output
uint16_t length; // number of samples to analyze
uint16_t count; // how many left to analyze
uint16_t ncycles; // number of waveform cycles to seek
uint16_t thresh; // threshold, 655 to 64881 (1% to 99%)
bool enabled;
volatile bool new_output;
audio_block_t *inputQueueArray[1];
};

#endif

+ 996
- 0
control_sgtl5000.cpp 查看文件

@@ -0,0 +1,996 @@
/* 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.
*/

#include "control_sgtl5000.h"
#include "Wire.h"

#define CHIP_ID 0x0000
// 15:8 PARTID 0xA0 - 8 bit identifier for SGTL5000
// 7:0 REVID 0x00 - revision number for SGTL5000.

#define CHIP_DIG_POWER 0x0002
// 6 ADC_POWERUP 1=Enable, 0=disable the ADC block, both digital & analog,
// 5 DAC_POWERUP 1=Enable, 0=disable the DAC block, both analog and digital
// 4 DAP_POWERUP 1=Enable, 0=disable the DAP block
// 1 I2S_OUT_POWERUP 1=Enable, 0=disable the I2S data output
// 0 I2S_IN_POWERUP 1=Enable, 0=disable the I2S data input

#define CHIP_CLK_CTRL 0x0004
// 5:4 RATE_MODE Sets the sample rate mode. MCLK_FREQ is still specified
// relative to the rate in SYS_FS
// 0x0 = SYS_FS specifies the rate
// 0x1 = Rate is 1/2 of the SYS_FS rate
// 0x2 = Rate is 1/4 of the SYS_FS rate
// 0x3 = Rate is 1/6 of the SYS_FS rate
// 3:2 SYS_FS Sets the internal system sample rate (default=2)
// 0x0 = 32 kHz
// 0x1 = 44.1 kHz
// 0x2 = 48 kHz
// 0x3 = 96 kHz
// 1:0 MCLK_FREQ Identifies incoming SYS_MCLK frequency and if the PLL should be used
// 0x0 = 256*Fs
// 0x1 = 384*Fs
// 0x2 = 512*Fs
// 0x3 = Use PLL
// The 0x3 (Use PLL) setting must be used if the SYS_MCLK is not
// a standard multiple of Fs (256, 384, or 512). This setting can
// also be used if SYS_MCLK is a standard multiple of Fs.
// Before this field is set to 0x3 (Use PLL), the PLL must be
// powered up by setting CHIP_ANA_POWER->PLL_POWERUP and
// CHIP_ANA_POWER->VCOAMP_POWERUP. Also, the PLL dividers must
// be calculated based on the external MCLK rate and
// CHIP_PLL_CTRL register must be set (see CHIP_PLL_CTRL register
// description details on how to calculate the divisors).

#define CHIP_I2S_CTRL 0x0006
// 8 SCLKFREQ Sets frequency of I2S_SCLK when in master mode (MS=1). When in slave
// mode (MS=0), this field must be set appropriately to match SCLK input
// rate.
// 0x0 = 64Fs
// 0x1 = 32Fs - Not supported for RJ mode (I2S_MODE = 1)
// 7 MS Configures master or slave of I2S_LRCLK and I2S_SCLK.
// 0x0 = Slave: I2S_LRCLK an I2S_SCLK are inputs
// 0x1 = Master: I2S_LRCLK and I2S_SCLK are outputs
// NOTE: If the PLL is used (CHIP_CLK_CTRL->MCLK_FREQ==0x3),
// the SGTL5000 must be a master of the I2S port (MS==1)
// 6 SCLK_INV Sets the edge that data (input and output) is clocked in on for I2S_SCLK
// 0x0 = data is valid on rising edge of I2S_SCLK
// 0x1 = data is valid on falling edge of I2S_SCLK
// 5:4 DLEN I2S data length (default=1)
// 0x0 = 32 bits (only valid when SCLKFREQ=0),
// not valid for Right Justified Mode
// 0x1 = 24 bits (only valid when SCLKFREQ=0)
// 0x2 = 20 bits
// 0x3 = 16 bits
// 3:2 I2S_MODE Sets the mode for the I2S port
// 0x0 = I2S mode or Left Justified (Use LRALIGN to select)
// 0x1 = Right Justified Mode
// 0x2 = PCM Format A/B
// 0x3 = RESERVED
// 1 LRALIGN I2S_LRCLK Alignment to data word. Not used for Right Justified mode
// 0x0 = Data word starts 1 I2S_SCLK delay after I2S_LRCLK
// transition (I2S format, PCM format A)
// 0x1 = Data word starts after I2S_LRCLK transition (left
// justified format, PCM format B)
// 0 LRPOL I2S_LRCLK Polarity when data is presented.
// 0x0 = I2S_LRCLK = 0 - Left, 1 - Right
// 1x0 = I2S_LRCLK = 0 - Right, 1 - Left
// The left subframe should be presented first regardless of
// the setting of LRPOL.

#define CHIP_SSS_CTRL 0x000A
// 14 DAP_MIX_LRSWAP DAP Mixer Input Swap
// 0x0 = Normal Operation
// 0x1 = Left and Right channels for the DAP MIXER Input are swapped.
// 13 DAP_LRSWAP DAP Mixer Input Swap
// 0x0 = Normal Operation
// 0x1 = Left and Right channels for the DAP Input are swapped
// 12 DAC_LRSWAP DAC Input Swap
// 0x0 = Normal Operation
// 0x1 = Left and Right channels for the DAC are swapped
// 10 I2S_LRSWAP I2S_DOUT Swap
// 0x0 = Normal Operation
// 0x1 = Left and Right channels for the I2S_DOUT are swapped
// 9:8 DAP_MIX_SELECT Select data source for DAP mixer
// 0x0 = ADC
// 0x1 = I2S_IN
// 0x2 = Reserved
// 0x3 = Reserved
// 7:6 DAP_SELECT Select data source for DAP
// 0x0 = ADC
// 0x1 = I2S_IN
// 0x2 = Reserved
// 0x3 = Reserved
// 5:4 DAC_SELECT Select data source for DAC (default=1)
// 0x0 = ADC
// 0x1 = I2S_IN
// 0x2 = Reserved
// 0x3 = DAP
// 1:0 I2S_SELECT Select data source for I2S_DOUT
// 0x0 = ADC
// 0x1 = I2S_IN
// 0x2 = Reserved
// 0x3 = DAP

#define CHIP_ADCDAC_CTRL 0x000E
// 13 VOL_BUSY_DAC_RIGHT Volume Busy DAC Right
// 0x0 = Ready
// 0x1 = Busy - This indicates the channel has not reached its
// programmed volume/mute level
// 12 VOL_BUSY_DAC_LEFT Volume Busy DAC Left
// 0x0 = Ready
// 0x1 = Busy - This indicates the channel has not reached its
// programmed volume/mute level
// 9 VOL_RAMP_EN Volume Ramp Enable (default=1)
// 0x0 = Disables volume ramp. New volume settings take immediate
// effect without a ramp
// 0x1 = Enables volume ramp
// This field affects DAC_VOL. The volume ramp effects both
// volume settings and mute When set to 1 a soft mute is enabled.
// 8 VOL_EXPO_RAMP Exponential Volume Ramp Enable
// 0x0 = Linear ramp over top 4 volume octaves
// 0x1 = Exponential ramp over full volume range
// This bit only takes effect if VOL_RAMP_EN is 1.
// 3 DAC_MUTE_RIGHT DAC Right Mute (default=1)
// 0x0 = Unmute
// 0x1 = Muted
// If VOL_RAMP_EN = 1, this is a soft mute.
// 2 DAC_MUTE_LEFT DAC Left Mute (default=1)
// 0x0 = Unmute
// 0x1 = Muted
// If VOL_RAMP_EN = 1, this is a soft mute.
// 1 ADC_HPF_FREEZE ADC High Pass Filter Freeze
// 0x0 = Normal operation
// 0x1 = Freeze the ADC high-pass filter offset register. The
// offset continues to be subtracted from the ADC data stream.
// 0 ADC_HPF_BYPASS ADC High Pass Filter Bypass
// 0x0 = Normal operation
// 0x1 = Bypassed and offset not updated

#define CHIP_DAC_VOL 0x0010
// 15:8 DAC_VOL_RIGHT DAC Right Channel Volume. Set the Right channel DAC volume
// with 0.5017 dB steps from 0 to -90 dB
// 0x3B and less = Reserved
// 0x3C = 0 dB
// 0x3D = -0.5 dB
// 0xF0 = -90 dB
// 0xFC and greater = Muted
// If VOL_RAMP_EN = 1, there is an automatic ramp to the
// new volume setting.
// 7:0 DAC_VOL_LEFT DAC Left Channel Volume. Set the Left channel DAC volume
// with 0.5017 dB steps from 0 to -90 dB
// 0x3B and less = Reserved
// 0x3C = 0 dB
// 0x3D = -0.5 dB
// 0xF0 = -90 dB
// 0xFC and greater = Muted
// If VOL_RAMP_EN = 1, there is an automatic ramp to the
// new volume setting.

#define CHIP_PAD_STRENGTH 0x0014
// 9:8 I2S_LRCLK I2S LRCLK Pad Drive Strength (default=1)
// Sets drive strength for output pads per the table below.
// VDDIO 1.8 V 2.5 V 3.3 V
// 0x0 = Disable
// 0x1 = 1.66 mA 2.87 mA 4.02 mA
// 0x2 = 3.33 mA 5.74 mA 8.03 mA
// 0x3 = 4.99 mA 8.61 mA 12.05 mA
// 7:6 I2S_SCLK I2S SCLK Pad Drive Strength (default=1)
// 5:4 I2S_DOUT I2S DOUT Pad Drive Strength (default=1)
// 3:2 CTRL_DATA I2C DATA Pad Drive Strength (default=3)
// 1:0 CTRL_CLK I2C CLK Pad Drive Strength (default=3)
// (all use same table as I2S_LRCLK)

#define CHIP_ANA_ADC_CTRL 0x0020
// 8 ADC_VOL_M6DB ADC Volume Range Reduction
// This bit shifts both right and left analog ADC volume
// range down by 6.0 dB.
// 0x0 = No change in ADC range
// 0x1 = ADC range reduced by 6.0 dB
// 7:4 ADC_VOL_RIGHT ADC Right Channel Volume
// Right channel analog ADC volume control in 1.5 dB steps.
// 0x0 = 0 dB
// 0x1 = +1.5 dB
// ...
// 0xF = +22.5 dB
// This range is -6.0 dB to +16.5 dB if ADC_VOL_M6DB is set to 1.
// 3:0 ADC_VOL_LEFT ADC Left Channel Volume
// (same scale as ADC_VOL_RIGHT)

#define CHIP_ANA_HP_CTRL 0x0022
// 14:8 HP_VOL_RIGHT Headphone Right Channel Volume (default 0x18)
// Right channel headphone volume control with 0.5 dB steps.
// 0x00 = +12 dB
// 0x01 = +11.5 dB
// 0x18 = 0 dB
// ...
// 0x7F = -51.5 dB
// 6:0 HP_VOL_LEFT Headphone Left Channel Volume (default 0x18)
// (same scale as HP_VOL_RIGHT)

#define CHIP_ANA_CTRL 0x0024
// 8 MUTE_LO LINEOUT Mute, 0 = Unmute, 1 = Mute (default 1)
// 6 SELECT_HP Select the headphone input, 0 = DAC, 1 = LINEIN
// 5 EN_ZCD_HP Enable the headphone zero cross detector (ZCD)
// 0x0 = HP ZCD disabled
// 0x1 = HP ZCD enabled
// 4 MUTE_HP Mute the headphone outputs, 0 = Unmute, 1 = Mute (default)
// 2 SELECT_ADC Select the ADC input, 0 = Microphone, 1 = LINEIN
// 1 EN_ZCD_ADC Enable the ADC analog zero cross detector (ZCD)
// 0x0 = ADC ZCD disabled
// 0x1 = ADC ZCD enabled
// 0 MUTE_ADC Mute the ADC analog volume, 0 = Unmute, 1 = Mute (default)

#define CHIP_LINREG_CTRL 0x0026
// 6 VDDC_MAN_ASSN Determines chargepump source when VDDC_ASSN_OVRD is set.
// 0x0 = VDDA
// 0x1 = VDDIO
// 5 VDDC_ASSN_OVRD Charge pump Source Assignment Override
// 0x0 = Charge pump source is automatically assigned based
// on higher of VDDA and VDDIO
// 0x1 = the source of charge pump is manually assigned by
// VDDC_MAN_ASSN If VDDIO and VDDA are both the same
// and greater than 3.1 V, VDDC_ASSN_OVRD and
// VDDC_MAN_ASSN should be used to manually assign
// VDDIO as the source for charge pump.
// 3:0 D_PROGRAMMING Sets the VDDD linear regulator output voltage in 50 mV steps.
// Must clear the LINREG_SIMPLE_POWERUP and STARTUP_POWERUP bits
// in the 0x0030 (CHIP_ANA_POWER) register after power-up, for
// this setting to produce the proper VDDD voltage.
// 0x0 = 1.60
// 0xF = 0.85

#define CHIP_REF_CTRL 0x0028 // bandgap reference bias voltage and currents
// 8:4 VAG_VAL Analog Ground Voltage Control
// These bits control the analog ground voltage in 25 mV steps.
// This should usually be set to VDDA/2 or lower for best
// performance (maximum output swing at minimum THD). This VAG
// reference is also used for the DAC and ADC voltage reference.
// So changing this voltage scales the output swing of the DAC
// and the output signal of the ADC.
// 0x00 = 0.800 V
// 0x1F = 1.575 V
// 3:1 BIAS_CTRL Bias control
// These bits adjust the bias currents for all of the analog
// blocks. By lowering the bias current a lower quiescent power
// is achieved. It should be noted that this mode can affect
// performance by 3-4 dB.
// 0x0 = Nominal
// 0x1-0x3=+12.5%
// 0x4=-12.5%
// 0x5=-25%
// 0x6=-37.5%
// 0x7=-50%
// 0 SMALL_POP VAG Ramp Control
// Setting this bit slows down the VAG ramp from ~200 to ~400 ms
// to reduce the startup pop, but increases the turn on/off time.
// 0x0 = Normal VAG ramp
// 0x1 = Slow down VAG ramp

#define CHIP_MIC_CTRL 0x002A // microphone gain & internal microphone bias
// 9:8 BIAS_RESISTOR MIC Bias Output Impedance Adjustment
// Controls an adjustable output impedance for the microphone bias.
// If this is set to zero the micbias block is powered off and
// the output is highZ.
// 0x0 = Powered off
// 0x1 = 2.0 kohm
// 0x2 = 4.0 kohm
// 0x3 = 8.0 kohm
// 6:4 BIAS_VOLT MIC Bias Voltage Adjustment
// Controls an adjustable bias voltage for the microphone bias
// amp in 250 mV steps. This bias voltage setting should be no
// more than VDDA-200 mV for adequate power supply rejection.
// 0x0 = 1.25 V
// ...
// 0x7 = 3.00 V
// 1:0 GAIN MIC Amplifier Gain
// Sets the microphone amplifier gain. At 0 dB setting the THD
// can be slightly higher than other paths- typically around
// ~65 dB. At other gain settings the THD are better.
// 0x0 = 0 dB
// 0x1 = +20 dB
// 0x2 = +30 dB
// 0x3 = +40 dB

#define CHIP_LINE_OUT_CTRL 0x002C
// 11:8 OUT_CURRENT Controls the output bias current for the LINEOUT amplifiers. The
// nominal recommended setting for a 10 kohm load with 1.0 nF load cap
// is 0x3. There are only 5 valid settings.
// 0x0=0.18 mA
// 0x1=0.27 mA
// 0x3=0.36 mA
// 0x7=0.45 mA
// 0xF=0.54 mA
// 5:0 LO_VAGCNTRL LINEOUT Amplifier Analog Ground Voltage
// Controls the analog ground voltage for the LINEOUT amplifiers
// in 25 mV steps. This should usually be set to VDDIO/2.
// 0x00 = 0.800 V
// ...
// 0x1F = 1.575 V
// ...
// 0x23 = 1.675 V
// 0x24-0x3F are invalid

#define CHIP_LINE_OUT_VOL 0x002E
// 12:8 LO_VOL_RIGHT LINEOUT Right Channel Volume (default=4)
// Controls the right channel LINEOUT volume in 0.5 dB steps.
// Higher codes have more attenuation.
// 4:0 LO_VOL_LEFT LINEOUT Left Channel Output Level (default=4)
// Used to normalize the output level of the left line output
// to full scale based on the values used to set
// LINE_OUT_CTRL->LO_VAGCNTRL and CHIP_REF_CTRL->VAG_VAL.
// In general this field should be set to:
// 40*log((VAG_VAL)/(LO_VAGCNTRL)) + 15
// Suggested values based on typical VDDIO and VDDA voltages.
// VDDA VAG_VAL VDDIO LO_VAGCNTRL LO_VOL_*
// 1.8 V 0.9 3.3 V 1.55 0x06
// 1.8 V 0.9 1.8 V 0.9 0x0F
// 3.3 V 1.55 1.8 V 0.9 0x19
// 3.3 V 1.55 3.3 V 1.55 0x0F
// After setting to the nominal voltage, this field can be used
// to adjust the output level in +/-0.5 dB increments by using
// values higher or lower than the nominal setting.

#define CHIP_ANA_POWER 0x0030 // power down controls for the analog blocks.
// The only other power-down controls are BIAS_RESISTOR in the MIC_CTRL register
// and the EN_ZCD control bits in ANA_CTRL.
// 14 DAC_MONO While DAC_POWERUP is set, this allows the DAC to be put into left only
// mono operation for power savings. 0=mono, 1=stereo (default)
// 13 LINREG_SIMPLE_POWERUP Power up the simple (low power) digital supply regulator.
// After reset, this bit can be cleared IF VDDD is driven
// externally OR the primary digital linreg is enabled with
// LINREG_D_POWERUP
// 12 STARTUP_POWERUP Power up the circuitry needed during the power up ramp and reset.
// After reset this bit can be cleared if VDDD is coming from
// an external source.
// 11 VDDC_CHRGPMP_POWERUP Power up the VDDC charge pump block. If neither VDDA or VDDIO
// is 3.0 V or larger this bit should be cleared before analog
// blocks are powered up.
// 10 PLL_POWERUP PLL Power Up, 0 = Power down, 1 = Power up
// When cleared, the PLL is turned off. This must be set before
// CHIP_CLK_CTRL->MCLK_FREQ is programmed to 0x3. The
// CHIP_PLL_CTRL register must be configured correctly before
// setting this bit.
// 9 LINREG_D_POWERUP Power up the primary VDDD linear regulator, 0 = Power down, 1 = Power up
// 8 VCOAMP_POWERUP Power up the PLL VCO amplifier, 0 = Power down, 1 = Power up
// 7 VAG_POWERUP Power up the VAG reference buffer.
// Setting this bit starts the power up ramp for the headphone
// and LINEOUT. The headphone (and/or LINEOUT) powerup should
// be set BEFORE clearing this bit. When this bit is cleared
// the power-down ramp is started. The headphone (and/or LINEOUT)
// powerup should stay set until the VAG is fully ramped down
// (200 to 400 ms after clearing this bit).
// 0x0 = Power down, 0x1 = Power up
// 6 ADC_MONO While ADC_POWERUP is set, this allows the ADC to be put into left only
// mono operation for power savings. This mode is useful when
// only using the microphone input.
// 0x0 = Mono (left only), 0x1 = Stereo
// 5 REFTOP_POWERUP Power up the reference bias currents
// 0x0 = Power down, 0x1 = Power up
// This bit can be cleared when the part is a sleep state
// to minimize analog power.
// 4 HEADPHONE_POWERUP Power up the headphone amplifiers
// 0x0 = Power down, 0x1 = Power up
// 3 DAC_POWERUP Power up the DACs
// 0x0 = Power down, 0x1 = Power up
// 2 CAPLESS_HEADPHONE_POWERUP Power up the capless headphone mode
// 0x0 = Power down, 0x1 = Power up
// 1 ADC_POWERUP Power up the ADCs
// 0x0 = Power down, 0x1 = Power up
// 0 LINEOUT_POWERUP Power up the LINEOUT amplifiers
// 0x0 = Power down, 0x1 = Power up

#define CHIP_PLL_CTRL 0x0032
// 15:11 INT_DIVISOR
// 10:0 FRAC_DIVISOR

#define CHIP_CLK_TOP_CTRL 0x0034
// 11 ENABLE_INT_OSC Setting this bit enables an internal oscillator to be used for the
// zero cross detectors, the short detect recovery, and the
// charge pump. This allows the I2S clock to be shut off while
// still operating an analog signal path. This bit can be kept
// on when the I2S clock is enabled, but the I2S clock is more
// accurate so it is preferred to clear this bit when I2S is present.
// 3 INPUT_FREQ_DIV2 SYS_MCLK divider before PLL input
// 0x0 = pass through
// 0x1 = SYS_MCLK is divided by 2 before entering PLL
// This must be set when the input clock is above 17 Mhz. This
// has no effect when the PLL is powered down.

#define CHIP_ANA_STATUS 0x0036
// 9 LRSHORT_STS This bit is high whenever a short is detected on the left or right
// channel headphone drivers.
// 8 CSHORT_STS This bit is high whenever a short is detected on the capless headphone
// common/center channel driver.
// 4 PLL_IS_LOCKED This bit goes high after the PLL is locked.

#define CHIP_ANA_TEST1 0x0038 // intended only for debug.
#define CHIP_ANA_TEST2 0x003A // intended only for debug.

#define CHIP_SHORT_CTRL 0x003C
// 14:12 LVLADJR Right channel headphone short detector in 25 mA steps.
// 0x3=25 mA
// 0x2=50 mA
// 0x1=75 mA
// 0x0=100 mA
// 0x4=125 mA
// 0x5=150 mA
// 0x6=175 mA
// 0x7=200 mA
// This trip point can vary by ~30% over process so leave plenty
// of guard band to avoid false trips. This short detect trip
// point is also effected by the bias current adjustments made
// by CHIP_REF_CTRL->BIAS_CTRL and by CHIP_ANA_TEST1->HP_IALL_ADJ.
// 10:8 LVLADJL Left channel headphone short detector in 25 mA steps.
// (same scale as LVLADJR)
// 6:4 LVLADJC Capless headphone center channel short detector in 50 mA steps.
// 0x3=50 mA
// 0x2=100 mA
// 0x1=150 mA
// 0x0=200 mA
// 0x4=250 mA
// 0x5=300 mA
// 0x6=350 mA
// 0x7=400 mA
// 3:2 MODE_LR Behavior of left/right short detection
// 0x0 = Disable short detector, reset short detect latch,
// software view non-latched short signal
// 0x1 = Enable short detector and reset the latch at timeout
// (every ~50 ms)
// 0x2 = This mode is not used/invalid
// 0x3 = Enable short detector with only manual reset (have
// to return to 0x0 to reset the latch)
// 1:0 MODE_CM Behavior of capless headphone central short detection
// (same settings as MODE_LR)

#define DAP_CONTROL 0x0100
#define DAP_PEQ 0x0102
#define DAP_BASS_ENHANCE 0x0104
#define DAP_BASS_ENHANCE_CTRL 0x0106
#define DAP_AUDIO_EQ 0x0108
#define DAP_SGTL_SURROUND 0x010A
#define DAP_FILTER_COEF_ACCESS 0x010C
#define DAP_COEF_WR_B0_MSB 0x010E
#define DAP_COEF_WR_B0_LSB 0x0110
#define DAP_AUDIO_EQ_BASS_BAND0 0x0116 // 115 Hz
#define DAP_AUDIO_EQ_BAND1 0x0118 // 330 Hz
#define DAP_AUDIO_EQ_BAND2 0x011A // 990 Hz
#define DAP_AUDIO_EQ_BAND3 0x011C // 3000 Hz
#define DAP_AUDIO_EQ_TREBLE_BAND4 0x011E // 9900 Hz
#define DAP_MAIN_CHAN 0x0120
#define DAP_MIX_CHAN 0x0122
#define DAP_AVC_CTRL 0x0124
#define DAP_AVC_THRESHOLD 0x0126
#define DAP_AVC_ATTACK 0x0128
#define DAP_AVC_DECAY 0x012A
#define DAP_COEF_WR_B1_MSB 0x012C
#define DAP_COEF_WR_B1_LSB 0x012E
#define DAP_COEF_WR_B2_MSB 0x0130
#define DAP_COEF_WR_B2_LSB 0x0132
#define DAP_COEF_WR_A1_MSB 0x0134
#define DAP_COEF_WR_A1_LSB 0x0136
#define DAP_COEF_WR_A2_MSB 0x0138
#define DAP_COEF_WR_A2_LSB 0x013A

#define SGTL5000_I2C_ADDR 0x0A // CTRL_ADR0_CS pin low (normal configuration)
//#define SGTL5000_I2C_ADDR 0x2A // CTRL_ADR0_CS pin high



bool AudioControlSGTL5000::enable(void)
{
muted = true;
Wire.begin();
delay(5);
//Serial.print("chip ID = ");
//delay(5);
//unsigned int n = read(CHIP_ID);
//Serial.println(n, HEX);

write(CHIP_ANA_POWER, 0x4060); // VDDD is externally driven with 1.8V
write(CHIP_LINREG_CTRL, 0x006C); // VDDA & VDDIO both over 3.1V
write(CHIP_REF_CTRL, 0x01F2); // VAG=1.575, normal ramp, +12.5% bias current
write(CHIP_LINE_OUT_CTRL, 0x0F22); // LO_VAGCNTRL=1.65V, OUT_CURRENT=0.54mA
write(CHIP_SHORT_CTRL, 0x4446); // allow up to 125mA
write(CHIP_ANA_CTRL, 0x0137); // enable zero cross detectors
write(CHIP_ANA_POWER, 0x40FF); // power up: lineout, hp, adc, dac
write(CHIP_DIG_POWER, 0x0073); // power up all digital stuff
delay(400);
write(CHIP_LINE_OUT_VOL, 0x1D1D); // default approx 1.3 volts peak-to-peak
write(CHIP_CLK_CTRL, 0x0004); // 44.1 kHz, 256*Fs
write(CHIP_I2S_CTRL, 0x0130); // SCLK=32*Fs, 16bit, I2S format
// default signal routing is ok?
write(CHIP_SSS_CTRL, 0x0010); // ADC->I2S, I2S->DAC
write(CHIP_ADCDAC_CTRL, 0x0000); // disable dac mute
write(CHIP_DAC_VOL, 0x3C3C); // digital gain, 0dB
write(CHIP_ANA_HP_CTRL, 0x7F7F); // set volume (lowest level)
write(CHIP_ANA_CTRL, 0x0036); // enable zero cross detectors
//mute = false;
semi_automated = true;
return true;
}

unsigned int AudioControlSGTL5000::read(unsigned int reg)
{
unsigned int val;
Wire.beginTransmission(SGTL5000_I2C_ADDR);
Wire.write(reg >> 8);
Wire.write(reg);
if (Wire.endTransmission(false) != 0) return 0;
if (Wire.requestFrom(SGTL5000_I2C_ADDR, 2) < 2) return 0;
val = Wire.read() << 8;
val |= Wire.read();
return val;
}

bool AudioControlSGTL5000::write(unsigned int reg, unsigned int val)
{
if (reg == CHIP_ANA_CTRL) ana_ctrl = val;
Wire.beginTransmission(SGTL5000_I2C_ADDR);
Wire.write(reg >> 8);
Wire.write(reg);
Wire.write(val >> 8);
Wire.write(val);
if (Wire.endTransmission() == 0) return true;
return false;
}

unsigned int AudioControlSGTL5000::modify(unsigned int reg, unsigned int val, unsigned int iMask)
{
unsigned int val1 = (read(reg)&(~iMask))|val;
if(!write(reg,val1)) return 0;
return val1;
}

bool AudioControlSGTL5000::volumeInteger(unsigned int n)
{
if (n == 0) {
muted = true;
write(CHIP_ANA_HP_CTRL, 0x7F7F);
return muteHeadphone();
} else if (n > 0x80) {
n = 0;
} else {
n = 0x80 - n;
}
if (muted) {
muted = false;
unmuteHeadphone();
}
n = n | (n << 8);
return write(CHIP_ANA_HP_CTRL, n); // set volume
}

bool AudioControlSGTL5000::volume(float left, float right)
{
unsigned short m=((0x7F-calcVol(right,0x7F))<<8)|(0x7F-calcVol(left,0x7F));
return write(CHIP_ANA_HP_CTRL, m);
}

bool AudioControlSGTL5000::micGain(unsigned int dB)
{
unsigned int preamp_gain, input_gain;

if (dB >= 40) {
preamp_gain = 3;
dB -= 40;
} else if (dB >= 30) {
preamp_gain = 2;
dB -= 30;
} else if (dB >= 20) {
preamp_gain = 1;
dB -= 20;
} else {
preamp_gain = 0;
}
input_gain = (dB * 2) / 3;
if (input_gain > 15) input_gain = 15;

return write(CHIP_MIC_CTRL, 0x0170 | preamp_gain)
&& write(CHIP_ANA_ADC_CTRL, (input_gain << 4) | input_gain);
}

// CHIP_ANA_ADC_CTRL
// Actual measured full-scale peak-to-peak sine wave input for max signal
// 0: 3.12 Volts p-p
// 1: 2.63 Volts p-p
// 2: 2.22 Volts p-p
// 3: 1.87 Volts p-p
// 4: 1.58 Volts p-p
// 5: 1.33 Volts p-p
// 6: 1.11 Volts p-p
// 7: 0.94 Volts p-p
// 8: 0.79 Volts p-p
// 9: 0.67 Volts p-p
// 10: 0.56 Volts p-p
// 11: 0.48 Volts p-p
// 12: 0.40 Volts p-p
// 13: 0.34 Volts p-p
// 14: 0.29 Volts p-p
// 15: 0.24 Volts p-p
bool AudioControlSGTL5000::lineInLevel(uint8_t left, uint8_t right)
{
if (left > 15) left = 15;
if (right > 15) right = 15;
return write(CHIP_ANA_ADC_CTRL, (left << 4) | right);
}

// CHIP_LINE_OUT_VOL
// Actual measured full-scale peak-to-peak sine wave output voltage:
// 0-12: output has clipping
// 13: 3.16 Volts p-p
// 14: 2.98 Volts p-p
// 15: 2.83 Volts p-p
// 16: 2.67 Volts p-p
// 17: 2.53 Volts p-p
// 18: 2.39 Volts p-p
// 19: 2.26 Volts p-p
// 20: 2.14 Volts p-p
// 21: 2.02 Volts p-p
// 22: 1.91 Volts p-p
// 23: 1.80 Volts p-p
// 24: 1.71 Volts p-p
// 25: 1.62 Volts p-p
// 26: 1.53 Volts p-p
// 27: 1.44 Volts p-p
// 28: 1.37 Volts p-p
// 29: 1.29 Volts p-p
// 30: 1.22 Volts p-p
// 31: 1.16 Volts p-p
unsigned short AudioControlSGTL5000::lineOutLevel(uint8_t n)
{
if (n > 31) n = 31;
else if (n < 13) n = 13;
return modify(CHIP_LINE_OUT_VOL,(n<<8)|n,(31<<8)|31);
}

unsigned short AudioControlSGTL5000::lineOutLevel(uint8_t left, uint8_t right)
{
if (left > 31) left = 31;
else if (left < 13) left = 13;
if (right > 31) right = 31;
else if (right < 13) right = 13;
return modify(CHIP_LINE_OUT_VOL,(right<<8)|left,(31<<8)|31);
}

unsigned short AudioControlSGTL5000::dacVolume(float n) // set both directly
{
if ((read(CHIP_ADCDAC_CTRL)&(3<<2)) != ((n>0 ? 0:3)<<2)) {
modify(CHIP_ADCDAC_CTRL,(n>0 ? 0:3)<<2,3<<2);
}
unsigned char m=calcVol(n,0xC0);
return modify(CHIP_DAC_VOL,((0xFC-m)<<8)|(0xFC-m),65535);
}
unsigned short AudioControlSGTL5000::dacVolume(float left, float right)
{
unsigned short adcdac=((right>0 ? 0:2)|(left>0 ? 0:1))<<2;
if ((read(CHIP_ADCDAC_CTRL)&(3<<2)) != adcdac) {
modify(CHIP_ADCDAC_CTRL,adcdac,1<<2);
}
unsigned short m=(0xFC-calcVol(right,0xC0))<<8|(0xFC-calcVol(left,0xC0));
return modify(CHIP_DAC_VOL,m,65535);
}

unsigned short AudioControlSGTL5000::adcHighPassFilterEnable(void)
{
return modify(CHIP_ADCDAC_CTRL, 0, 3);
}

unsigned short AudioControlSGTL5000::adcHighPassFilterFreeze(void)
{
return modify(CHIP_ADCDAC_CTRL, 2, 3);
}

unsigned short AudioControlSGTL5000::adcHighPassFilterDisable(void)
{
return modify(CHIP_ADCDAC_CTRL, 1, 3);
}


// DAP_CONTROL

unsigned short AudioControlSGTL5000::audioPreProcessorEnable(void)
{
// audio processor used to pre-process analog input before Teensy
return write(DAP_CONTROL, 1) && write(CHIP_SSS_CTRL, 0x0013);
}

unsigned short AudioControlSGTL5000::audioPostProcessorEnable(void)
{
// audio processor used to post-process Teensy output before headphones/lineout
return write(DAP_CONTROL, 1) && write(CHIP_SSS_CTRL, 0x0070);
}

unsigned short AudioControlSGTL5000::audioProcessorDisable(void)
{
return write(CHIP_SSS_CTRL, 0x0010) && write(DAP_CONTROL, 0);
}


// DAP_PEQ
unsigned short AudioControlSGTL5000::eqFilterCount(uint8_t n) // valid to n&7, 0 thru 7 filters enabled.
{
return modify(DAP_PEQ,(n&7),7);
}

// DAP_AUDIO_EQ
unsigned short AudioControlSGTL5000::eqSelect(uint8_t n) // 0=NONE, 1=PEQ (7 IIR Biquad filters), 2=TONE (tone), 3=GEQ (5 band EQ)
{
return modify(DAP_AUDIO_EQ,n&3,3);
}

unsigned short AudioControlSGTL5000::eqBand(uint8_t bandNum, float n)
{
if(semi_automated) automate(1,3);
return dap_audio_eq_band(bandNum, n);
}
void AudioControlSGTL5000::eqBands(float bass, float mid_bass, float midrange, float mid_treble, float treble)
{
if(semi_automated) automate(1,3);
dap_audio_eq_band(0,bass);
dap_audio_eq_band(1,mid_bass);
dap_audio_eq_band(2,midrange);
dap_audio_eq_band(3,mid_treble);
dap_audio_eq_band(4,treble);
}
void AudioControlSGTL5000::eqBands(float bass, float treble) // dap_audio_eq(2);
{
if(semi_automated) automate(1,2);
dap_audio_eq_band(0,bass);
dap_audio_eq_band(4,treble);
}

// SGTL5000 PEQ Coefficient loader
void AudioControlSGTL5000::eqFilter(uint8_t filterNum, int *filterParameters)
{
// TODO: add the part that selects 7 PEQ filters.
if(semi_automated) automate(1,1,filterNum+1);
modify(DAP_FILTER_COEF_ACCESS,(uint16_t)filterNum,15);
write(DAP_COEF_WR_B0_MSB,(*filterParameters>>4)&65535);
write(DAP_COEF_WR_B0_LSB,(*filterParameters++)&15);
write(DAP_COEF_WR_B1_MSB,(*filterParameters>>4)&65535);
write(DAP_COEF_WR_B1_LSB,(*filterParameters++)&15);
write(DAP_COEF_WR_B2_MSB,(*filterParameters>>4)&65535);
write(DAP_COEF_WR_B2_LSB,(*filterParameters++)&15);
write(DAP_COEF_WR_A1_MSB,(*filterParameters>>4)&65535);
write(DAP_COEF_WR_A1_LSB,(*filterParameters++)&15);
write(DAP_COEF_WR_A2_MSB,(*filterParameters>>4)&65535);
write(DAP_COEF_WR_A2_LSB,(*filterParameters++)&15);
write(DAP_FILTER_COEF_ACCESS,(uint16_t)0x100|filterNum);
}

/* Valid values for dap_avc parameters

maxGain; Maximum gain that can be applied
0 - 0 dB
1 - 6.0 dB
2 - 12 dB
lbiResponse; Integrator Response
0 - 0 mS
1 - 25 mS
2 - 50 mS
3 - 100 mS
hardLimit
0 - Hard limit disabled. AVC Compressor/Expander enabled.
1 - Hard limit enabled. The signal is limited to the programmed threshold (signal saturates at the threshold)
threshold
floating point in range 0 to -96 dB
attack
floating point figure is dB/s rate at which gain is increased
decay
floating point figure is dB/s rate at which gain is reduced
*/
unsigned short AudioControlSGTL5000::autoVolumeControl(uint8_t maxGain, uint8_t lbiResponse, uint8_t hardLimit, float threshold, float attack, float decay)
{
//if(semi_automated&&(!read(DAP_CONTROL)&1)) audioProcessorEnable();
if(maxGain>2) maxGain=2;
lbiResponse&=3;
hardLimit&=1;
uint8_t thresh=(pow(10,threshold/20)*0.636)*pow(2,15);
uint8_t att=(1-pow(10,-(attack/(20*44100))))*pow(2,19);
uint8_t dec=(1-pow(10,-(decay/(20*44100))))*pow(2,23);
write(DAP_AVC_THRESHOLD,thresh);
write(DAP_AVC_ATTACK,att);
write(DAP_AVC_DECAY,dec);
return modify(DAP_AVC_CTRL,maxGain<<12|lbiResponse<<8|hardLimit<<5,3<<12|3<<8|1<<5);
}
unsigned short AudioControlSGTL5000::autoVolumeEnable(void)
{
return modify(DAP_AVC_CTRL, 1, 1);
}
unsigned short AudioControlSGTL5000::autoVolumeDisable(void)
{
return modify(DAP_AVC_CTRL, 0, 1);
}

unsigned short AudioControlSGTL5000::enhanceBass(float lr_lev, float bass_lev)
{
return modify(DAP_BASS_ENHANCE_CTRL,((0x3F-calcVol(lr_lev,0x3F))<<8) | (0x7F-calcVol(bass_lev,0x7F)), (0x3F<<8) | 0x7F);
}
unsigned short AudioControlSGTL5000::enhanceBass(float lr_lev, float bass_lev, uint8_t hpf_bypass, uint8_t cutoff)
{
modify(DAP_BASS_ENHANCE,(hpf_bypass&1)<<8|(cutoff&7)<<4,1<<8|7<<4);
return enhanceBass(lr_lev,bass_lev);
}
unsigned short AudioControlSGTL5000::enhanceBassEnable(void)
{
return modify(DAP_BASS_ENHANCE, 1, 1);
}
unsigned short AudioControlSGTL5000::enhanceBassDisable(void)
{
return modify(DAP_BASS_ENHANCE, 0, 1);
}
unsigned short AudioControlSGTL5000::surroundSound(uint8_t width)
{
return modify(DAP_SGTL_SURROUND,(width&7)<<4,7<<4);
}
unsigned short AudioControlSGTL5000::surroundSound(uint8_t width, uint8_t select)
{
return modify(DAP_SGTL_SURROUND,((width&7)<<4)|(select&3), (7<<4)|3);
}
unsigned short AudioControlSGTL5000::surroundSoundEnable(void)
{
return modify(DAP_SGTL_SURROUND, 3, 3);
}
unsigned short AudioControlSGTL5000::surroundSoundDisable(void)
{
return modify(DAP_SGTL_SURROUND, 0, 3);
}

unsigned char AudioControlSGTL5000::calcVol(float n, unsigned char range)
{
// n=(n*(((float)range)/100))+0.499;
n=(n*(float)range)+0.499;
if ((unsigned char)n>range) n=range;
return (unsigned char)n;
}

// DAP_AUDIO_EQ_BASS_BAND0 & DAP_AUDIO_EQ_BAND1 & DAP_AUDIO_EQ_BAND2 etc etc
unsigned short AudioControlSGTL5000::dap_audio_eq_band(uint8_t bandNum, float n) // by signed percentage -100/+100; dap_audio_eq(3);
{
n=(n*48)+0.499;
if(n<-47) n=-47;
if(n>48) n=48;
n+=47;
return modify(DAP_AUDIO_EQ_BASS_BAND0+(bandNum*2),(unsigned int)n,127);
}

void AudioControlSGTL5000::automate(uint8_t dap, uint8_t eq)
{
//if((dap!=0)&&(!(read(DAP_CONTROL)&1))) audioProcessorEnable();
if((read(DAP_AUDIO_EQ)&3) != eq) eqSelect(eq);
}

void AudioControlSGTL5000::automate(uint8_t dap, uint8_t eq, uint8_t filterCount)
{
automate(dap,eq);
if (filterCount > (read(DAP_PEQ)&7)) eqFilterCount(filterCount);
}


// if(SGTL5000_PEQ) quantization_unit=524288; if(AudioFilterBiquad) quantization_unit=2147483648;
void calcBiquad(uint8_t filtertype, float fC, float dB_Gain, float Q, uint32_t quantization_unit, uint32_t fS, int *coef)
{

// I used resources like http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
// to make this routine, I tested most of the filter types and they worked. Such filters have limits and
// before calling this routine with varying values the end user should check that those values are limited
// to valid results.

float A;
if(filtertype<FILTER_PARAEQ) A=pow(10,dB_Gain/20); else A=pow(10,dB_Gain/40);
float W0 = 2*3.14159265358979323846*fC/fS;
float cosw=cosf(W0);
float sinw=sinf(W0);
//float alpha = sinw*sinh((log(2)/2)*BW*W0/sinw);
//float beta = sqrt(2*A);
float alpha = sinw / (2 * Q);
float beta = sqrtf(A)/Q;
float b0,b1,b2,a0,a1,a2;

switch(filtertype) {
case FILTER_LOPASS:
b0 = (1.0F - cosw) * 0.5F; // =(1-COS($H$2))/2
b1 = 1.0F - cosw;
b2 = (1.0F - cosw) * 0.5F;
a0 = 1.0F + alpha;
a1 = 2.0F * cosw;
a2 = alpha - 1.0F;
break;
case FILTER_HIPASS:
b0 = (1.0F + cosw) * 0.5F;
b1 = -(cosw + 1.0F);
b2 = (1.0F + cosw) * 0.5F;
a0 = 1.0F + alpha;
a1 = 2.0F * cosw;
a2 = alpha - 1.0F;
break;
case FILTER_BANDPASS:
b0 = alpha;
b1 = 0.0F;
b2 = -alpha;
a0 = 1.0F + alpha;
a1 = 2.0F * cosw;
a2 = alpha - 1.0F;
break;
case FILTER_NOTCH:
b0=1;
b1=-2*cosw;
b2=1;
a0=1+alpha;
a1=2*cosw;
a2=-(1-alpha);
break;
case FILTER_PARAEQ:
b0 = 1 + (alpha*A);
b1 =-2 * cosw;
b2 = 1 - (alpha*A);
a0 = 1 + (alpha/A);
a1 = 2 * cosw;
a2 =-(1-(alpha/A));
break;
case FILTER_LOSHELF:
b0 = A * ((A+1.0F) - ((A-1.0F)*cosw) + (beta*sinw));
b1 = 2.0F * A * ((A-1.0F) - ((A+1.0F)*cosw));
b2 = A * ((A+1.0F) - ((A-1.0F)*cosw) - (beta*sinw));
a0 = (A+1.0F) + ((A-1.0F)*cosw) + (beta*sinw);
a1 = 2.0F * ((A-1.0F) + ((A+1.0F)*cosw));
a2 = -((A+1.0F) + ((A-1.0F)*cosw) - (beta*sinw));
break;
case FILTER_HISHELF:
b0 = A * ((A+1.0F) + ((A-1.0F)*cosw) + (beta*sinw));
b1 = -2.0F * A * ((A-1.0F) + ((A+1.0F)*cosw));
b2 = A * ((A+1.0F) + ((A-1.0F)*cosw) - (beta*sinw));
a0 = (A+1.0F) - ((A-1.0F)*cosw) + (beta*sinw);
a1 = -2.0F * ((A-1.0F) - ((A+1.0F)*cosw));
a2 = -((A+1.0F) - ((A-1.0F)*cosw) - (beta*sinw));
default:
b0 = 0.5;
b1 = 0.0;
b2 = 0.0;
a0 = 1.0;
a1 = 0.0;
a2 = 0.0;
}

a0=(a0*2)/(float)quantization_unit; // once here instead of five times there...
b0/=a0;
*coef++=(int)(b0+0.499);
b1/=a0;
*coef++=(int)(b1+0.499);
b2/=a0;
*coef++=(int)(b2+0.499);
a1/=a0;
*coef++=(int)(a1+0.499);
a2/=a0;
*coef++=(int)(a2+0.499);
}


+ 121
- 0
control_sgtl5000.h 查看文件

@@ -0,0 +1,121 @@
/* 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 control_sgtl5000_h_
#define control_sgtl5000_h_

#include "AudioControl.h"

class AudioControlSGTL5000 : public AudioControl
{
public:
bool enable(void);
bool disable(void) { return false; }
bool volume(float n) { return volumeInteger(n * 129 + 0.499); }
bool inputLevel(float n) {return false;}
bool muteHeadphone(void) { return write(0x0024, ana_ctrl | (1<<4)); }
bool unmuteHeadphone(void) { return write(0x0024, ana_ctrl & ~(1<<4)); }
bool muteLineout(void) { return write(0x0024, ana_ctrl | (1<<8)); }
bool unmuteLineout(void) { return write(0x0024, ana_ctrl & ~(1<<8)); }
bool inputSelect(int n) {
if (n == AUDIO_INPUT_LINEIN) {
return write(0x0020, 0x055) // +7.5dB gain (1.3Vp-p full scale)
&& write(0x0024, ana_ctrl | (1<<2)); // enable linein
} else if (n == AUDIO_INPUT_MIC) {
return write(0x002A, 0x0173) // mic preamp gain = +40dB
&& write(0x0020, 0x088) // input gain +12dB (is this enough?)
&& write(0x0024, ana_ctrl & ~(1<<2)); // enable mic
} else {
return false;
}
}
bool volume(float left, float right);
bool micGain(unsigned int dB);
bool lineInLevel(uint8_t n) { return lineInLevel(n, n); }
bool lineInLevel(uint8_t left, uint8_t right);
unsigned short lineOutLevel(uint8_t n);
unsigned short lineOutLevel(uint8_t left, uint8_t right);
unsigned short dacVolume(float n);
unsigned short dacVolume(float left, float right);
unsigned short adcHighPassFilterEnable(void);
unsigned short adcHighPassFilterFreeze(void);
unsigned short adcHighPassFilterDisable(void);
unsigned short audioPreProcessorEnable(void);
unsigned short audioPostProcessorEnable(void);
unsigned short audioProcessorDisable(void);
unsigned short eqFilterCount(uint8_t n);
unsigned short eqSelect(uint8_t n);
unsigned short eqBand(uint8_t bandNum, float n);
void eqBands(float bass, float mid_bass, float midrange, float mid_treble, float treble);
void eqBands(float bass, float treble);
void eqFilter(uint8_t filterNum, int *filterParameters);
unsigned short autoVolumeControl(uint8_t maxGain, uint8_t lbiResponse, uint8_t hardLimit, float threshold, float attack, float decay);
unsigned short autoVolumeEnable(void);
unsigned short autoVolumeDisable(void);
unsigned short enhanceBass(float lr_lev, float bass_lev);
unsigned short enhanceBass(float lr_lev, float bass_lev, uint8_t hpf_bypass, uint8_t cutoff);
unsigned short enhanceBassEnable(void);
unsigned short enhanceBassDisable(void);
unsigned short surroundSound(uint8_t width);
unsigned short surroundSound(uint8_t width, uint8_t select);
unsigned short surroundSoundEnable(void);
unsigned short surroundSoundDisable(void);
void killAutomation(void) { semi_automated=false; }

protected:
bool muted;
bool volumeInteger(unsigned int n); // range: 0x00 to 0x80
uint16_t ana_ctrl;
unsigned char calcVol(float n, unsigned char range);
unsigned int read(unsigned int reg);
bool write(unsigned int reg, unsigned int val);
unsigned int modify(unsigned int reg, unsigned int val, unsigned int iMask);
unsigned short dap_audio_eq_band(uint8_t bandNum, float n);
private:
bool semi_automated;
void automate(uint8_t dap, uint8_t eq);
void automate(uint8_t dap, uint8_t eq, uint8_t filterCount);
};

//For Filter Type: 0 = LPF, 1 = HPF, 2 = BPF, 3 = NOTCH, 4 = PeakingEQ, 5 = LowShelf, 6 = HighShelf
#define FILTER_LOPASS 0
#define FILTER_HIPASS 1
#define FILTER_BANDPASS 2
#define FILTER_NOTCH 3
#define FILTER_PARAEQ 4
#define FILTER_LOSHELF 5
#define FILTER_HISHELF 6
//For frequency adjustment
#define FLAT_FREQUENCY 0
#define PARAMETRIC_EQUALIZER 1
#define TONE_CONTROLS 2
#define GRAPHIC_EQUALIZER 3


void calcBiquad(uint8_t filtertype, float fC, float dB_Gain, float Q, uint32_t quantization_unit, uint32_t fS, int *coef);

#endif

+ 136
- 0
control_wm8731.cpp 查看文件

@@ -0,0 +1,136 @@
/* 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.
*/

#include "control_wm8731.h"
#include "Wire.h"

#define WM8731_I2C_ADDR 0x1A
//#define WM8731_I2C_ADDR 0x1B

#define WM8731_REG_LLINEIN 0
#define WM8731_REG_RLINEIN 1
#define WM8731_REG_LHEADOUT 2
#define WM8731_REG_RHEADOUT 3
#define WM8731_REG_ANALOG 4
#define WM8731_REG_DIGITAL 5
#define WM8731_REG_POWERDOWN 6
#define WM8731_REG_INTERFACE 7
#define WM8731_REG_SAMPLING 8
#define WM8731_REG_ACTIVE 9
#define WM8731_REG_RESET 15

bool AudioControlWM8731::enable(void)
{
Wire.begin();
delay(5);
//write(WM8731_REG_RESET, 0);

write(WM8731_REG_INTERFACE, 0x02); // I2S, 16 bit, MCLK slave
write(WM8731_REG_SAMPLING, 0x20); // 256*Fs, 44.1 kHz, MCLK/1

// In order to prevent pops, the DAC should first be soft-muted (DACMU),
// the output should then be de-selected from the line and headphone output
// (DACSEL), then the DAC powered down (DACPD).

write(WM8731_REG_DIGITAL, 0x08); // DAC soft mute
write(WM8731_REG_ANALOG, 0x00); // disable all

write(WM8731_REG_POWERDOWN, 0x00); // codec powerdown

write(WM8731_REG_LHEADOUT, 0x80); // volume off
write(WM8731_REG_RHEADOUT, 0x80);

delay(100); // how long to power up?

write(WM8731_REG_ACTIVE, 1);
delay(5);
write(WM8731_REG_DIGITAL, 0x00); // DAC unmuted
write(WM8731_REG_ANALOG, 0x10); // DAC selected

return true;
}


bool AudioControlWM8731::write(unsigned int reg, unsigned int val)
{
Wire.beginTransmission(WM8731_I2C_ADDR);
Wire.write((reg << 1) | ((val >> 8) & 1));
Wire.write(val & 0xFF);
Wire.endTransmission();
return true;
}

bool AudioControlWM8731::volumeInteger(unsigned int n)
{
// n = 127 for max volume (+6 dB)
// n = 48 for min volume (-73 dB)
// n = 0 to 47 for mute
if (n > 127) n = 127;
//Serial.print("volumeInteger, n = ");
//Serial.println(n);
write(WM8731_REG_LHEADOUT, n | 0x180);
write(WM8731_REG_RHEADOUT, n | 0x80);
return true;
}



/******************************************************************/


bool AudioControlWM8731master::enable(void)
{
Wire.begin();
delay(5);
//write(WM8731_REG_RESET, 0);

write(WM8731_REG_INTERFACE, 0x42); // I2S, 16 bit, MCLK master
write(WM8731_REG_SAMPLING, 0x20); // 256*Fs, 44.1 kHz, MCLK/1

// In order to prevent pops, the DAC should first be soft-muted (DACMU),
// the output should then be de-selected from the line and headphone output
// (DACSEL), then the DAC powered down (DACPD).

write(WM8731_REG_DIGITAL, 0x08); // DAC soft mute
write(WM8731_REG_ANALOG, 0x00); // disable all
write(WM8731_REG_POWERDOWN, 0x00); // codec powerdown

write(WM8731_REG_LHEADOUT, 0x80); // volume off
write(WM8731_REG_RHEADOUT, 0x80);

delay(100); // how long to power up?

write(WM8731_REG_ACTIVE, 1);
delay(5);
write(WM8731_REG_DIGITAL, 0x00); // DAC unmuted
write(WM8731_REG_ANALOG, 0x10); // DAC selected

return true;
}




+ 51
- 0
control_wm8731.h 查看文件

@@ -0,0 +1,51 @@
/* 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 control_wm8731_h_
#define control_wm8731_h_

#include "AudioControl.h"

class AudioControlWM8731 : public AudioControl
{
public:
bool enable(void);
bool disable(void) { return false; }
bool volume(float n) { return volumeInteger(n * 80.0 + 47.499); }
bool inputLevel(float n) { return false; }
bool inputSelect(int n) { return false; }
protected:
bool write(unsigned int reg, unsigned int val);
bool volumeInteger(unsigned int n); // range: 0x2F to 0x7F
};

class AudioControlWM8731master : public AudioControlWM8731
{
public:
bool enable(void);
};

#endif

ulaw.c → data_ulaw.c 查看文件

@@ -1,5 +1,30 @@
#include <stdint.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.
*/

#include <stdint.h>

const int16_t ulaw_decode_table[256] = {
4, 12, 20, 28, 36, 44, 52, 60, 68, 76,

+ 123
- 0
data_waveforms.c 查看文件

@@ -0,0 +1,123 @@
/* 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.
*/

#include <stdint.h>

// These audio waveforms have a period of 256 points, plus a 257th
// point that is a duplicate of the first point. This duplicate
// is needed because the waveform generator uses linear interpolation
// between each point and the next point in the waveform.

const int16_t AudioWaveformSine[257] = {
0, 804, 1608, 2410, 3212, 4011, 4808, 5602, 6393, 7179,
7962, 8739, 9512, 10278, 11039, 11793, 12539, 13279, 14010, 14732,
15446, 16151, 16846, 17530, 18204, 18868, 19519, 20159, 20787, 21403,
22005, 22594, 23170, 23731, 24279, 24811, 25329, 25832, 26319, 26790,
27245, 27683, 28105, 28510, 28898, 29268, 29621, 29956, 30273, 30571,
30852, 31113, 31356, 31580, 31785, 31971, 32137, 32285, 32412, 32521,
32609, 32678, 32728, 32757, 32767, 32757, 32728, 32678, 32609, 32521,
32412, 32285, 32137, 31971, 31785, 31580, 31356, 31113, 30852, 30571,
30273, 29956, 29621, 29268, 28898, 28510, 28105, 27683, 27245, 26790,
26319, 25832, 25329, 24811, 24279, 23731, 23170, 22594, 22005, 21403,
20787, 20159, 19519, 18868, 18204, 17530, 16846, 16151, 15446, 14732,
14010, 13279, 12539, 11793, 11039, 10278, 9512, 8739, 7962, 7179,
6393, 5602, 4808, 4011, 3212, 2410, 1608, 804, 0, -804,
-1608, -2410, -3212, -4011, -4808, -5602, -6393, -7179, -7962, -8739,
-9512,-10278,-11039,-11793,-12539,-13279,-14010,-14732,-15446,-16151,
-16846,-17530,-18204,-18868,-19519,-20159,-20787,-21403,-22005,-22594,
-23170,-23731,-24279,-24811,-25329,-25832,-26319,-26790,-27245,-27683,
-28105,-28510,-28898,-29268,-29621,-29956,-30273,-30571,-30852,-31113,
-31356,-31580,-31785,-31971,-32137,-32285,-32412,-32521,-32609,-32678,
-32728,-32757,-32767,-32757,-32728,-32678,-32609,-32521,-32412,-32285,
-32137,-31971,-31785,-31580,-31356,-31113,-30852,-30571,-30273,-29956,
-29621,-29268,-28898,-28510,-28105,-27683,-27245,-26790,-26319,-25832,
-25329,-24811,-24279,-23731,-23170,-22594,-22005,-21403,-20787,-20159,
-19519,-18868,-18204,-17530,-16846,-16151,-15446,-14732,-14010,-13279,
-12539,-11793,-11039,-10278, -9512, -8739, -7962, -7179, -6393, -5602,
-4808, -4011, -3212, -2410, -1608, -804, 0
};

#if 0
#! /usr/bin/perl
use Math::Trig ':pi';
$len = 256;
print "const int16_t AudioWaveformSine[257] = {\n";
for ($i=0; $i <= $len; $i++) {
$f = sin($i / $len * 2 * pi);
$d = sprintf "%.0f", $f * 32767.0;
#print $d;
printf "%6d", $d + 0;
print "," if ($i < $len);
print "\n" if ($i % 10) == 9;
}
print "\n" unless ($len % 10) == 9;
print "};\n";
#endif


const int16_t fader_table[257] = {
0, 1, 4, 11, 19, 30, 44, 60, 78, 99,
123, 149, 177, 208, 241, 276, 314, 355, 398, 443,
490, 541, 593, 648, 705, 764, 826, 891, 957, 1026,
1097, 1171, 1247, 1325, 1405, 1488, 1572, 1660, 1749, 1840,
1934, 2030, 2128, 2228, 2330, 2435, 2541, 2650, 2761, 2873,
2988, 3105, 3224, 3344, 3467, 3592, 3718, 3847, 3977, 4109,
4243, 4379, 4517, 4657, 4798, 4941, 5086, 5232, 5380, 5530,
5682, 5835, 5989, 6145, 6303, 6462, 6623, 6785, 6949, 7114,
7281, 7448, 7618, 7788, 7960, 8133, 8307, 8483, 8660, 8838,
9017, 9197, 9378, 9560, 9743, 9928,10113,10299,10486,10674,
10863,11053,11244,11435,11627,11820,12013,12207,12402,12597,
12793,12989,13186,13384,13582,13780,13979,14178,14377,14577,
14777,14977,15177,15378,15579,15780,15981,16182,16383,16584,
16785,16986,17187,17387,17588,17788,17989,18188,18388,18588,
18787,18985,19184,19382,19579,19776,19972,20168,20364,20558,
20752,20946,21139,21331,21522,21712,21902,22091,22279,22466,
22652,22838,23022,23205,23388,23569,23749,23928,24106,24283,
24458,24633,24806,24977,25148,25317,25485,25651,25817,25980,
26142,26303,26463,26620,26776,26931,27084,27236,27385,27534,
27680,27825,27968,28109,28249,28386,28522,28656,28789,28919,
29048,29174,29299,29422,29542,29661,29778,29893,30006,30116,
30225,30331,30436,30538,30638,30736,30832,30926,31017,31107,
31194,31279,31361,31442,31520,31596,31669,31740,31809,31876,
31940,32002,32062,32119,32174,32226,32276,32324,32369,32412,
32452,32490,32526,32559,32590,32618,32644,32667,32688,32707,
32723,32737,32748,32756,32763,32766,32767
};
#if 0
#! /usr/bin/perl
print "const int16_t fader_table[257] = {\n";
$len = 256;
for ($i=0; $i < $len+1; $i++) {
$a = cos(3.14149 * $i / $len);
$in = (1 - $a) / 2;
$d = $in * 32768;
$d = 32767 if $d >= 32767.5;
printf "%5d", $d;
print "," if ($i < $len);
print "\n" if ($i % 10) == 9;
}
print "\n};\n";
#endif

+ 1618
- 0
data_windows.c
文件差異過大導致無法顯示
查看文件


+ 96
- 0
effect_bitcrusher.cpp 查看文件

@@ -0,0 +1,96 @@
/* Audio Library for Teensy 3.X
* Copyright (c) 2014, Jonathan Payne (jon@jonnypayne.com)
* Based on Effect_Fade by Paul Stoffregen
* Also samplerate reduction based on Pete Brown's bitcrusher here:
* http://10rem.net/blog/2013/01/13/a-simple-bitcrusher-and-sample-rate-reducer-in-cplusplus-for-a-windows-store-app
*
* 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.
*/

#include "effect_bitcrusher.h"

void AudioEffectBitcrusher::update(void)
{
audio_block_t *block;
uint32_t i;
uint32_t sampleSquidge, sampleSqueeze; //squidge is bitdepth, squeeze is for samplerate
if (crushBits == 16 && sampleStep <= 1) {
// nothing to do. Output is sent through clean, then exit the function
block = receiveReadOnly();
if (!block) return;
transmit(block);
release(block);
return;
}
// start of processing functions. Could be more elegant based on external
// functions but left like this to enable code optimisation later.
block = receiveWritable();
if (!block) return;

if (sampleStep <= 1) { //no sample rate mods, just crush the bitdepth.
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
// shift bits right to cut off fine detail sampleSquidge is a
// uint32 so sign extension will not occur, fills with zeroes.
sampleSquidge = block->data[i] >> (16-crushBits);
// shift bits left again to regain the volume level.
// fills with zeroes.
block->data[i] = sampleSquidge << (16-crushBits);
}
} else if (crushBits == 16) { //bitcrusher not being used, samplerate mods only.
i=0;
while (i < AUDIO_BLOCK_SAMPLES) {
// save the root sample. this will pick up a root
// sample every _sampleStep_ samples.
sampleSqueeze = block->data[i];
for (int j = 0; j < sampleStep && i < AUDIO_BLOCK_SAMPLES; j++) {
// for each repeated sample, paste in the current
// root sample, then move onto the next step.
block->data[i] = sampleSqueeze;
i++;
}
}
} else { //both being used. crush those bits and mash those samples.
i=0;
while (i < AUDIO_BLOCK_SAMPLES) {
// save the root sample. this will pick up a root sample
// every _sampleStep_ samples.
sampleSqueeze = block->data[i];
for (int j = 0; j < sampleStep && i < AUDIO_BLOCK_SAMPLES; j++) {
// shift bits right to cut off fine detail sampleSquidge
// is a uint32 so sign extension will not occur, fills
// with zeroes.
sampleSquidge = sampleSqueeze >> (16-crushBits);
// shift bits left again to regain the volume level.
// fills with zeroes. paste into buffer sample +
// sampleStep offset.
block->data[i] = sampleSquidge << (16-crushBits);
i++;
}
}
}
transmit(block);
release(block);
}



+ 57
- 0
effect_bitcrusher.h 查看文件

@@ -0,0 +1,57 @@
/* Audio Library for Teensy 3.X
* Copyright (c) 2014, Jonathan Payne (jon@jonnypayne.com)
* Based on Effect_Fade by Paul Stoffregen

* 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 effect_bitcrusher_h_
#define effect_bitcrusher_h_

#include "AudioStream.h"

class AudioEffectBitcrusher : public AudioStream
{
public:
AudioEffectBitcrusher(void)
: AudioStream(1, inputQueueArray) {}
void bits(uint8_t b) {
if (b > 16) b = 16;
else if (b == 0) b = 1;
crushBits = b;
}
void sampleRate(float hz) {
int n = (AUDIO_SAMPLE_RATE_EXACT / hz) + 0.5;
if (n < 1) n = 1;
else if (n > 64) n = 64;
sampleStep = n;
}
virtual void update(void);
private:
uint8_t crushBits; // 16 = off
uint8_t sampleStep; // the number of samples to double up. This simple technique only allows a few stepped positions.
audio_block_t *inputQueueArray[1];
};

#endif

+ 126
- 0
effect_chorus.cpp 查看文件

@@ -0,0 +1,126 @@
/* Audio Library for Teensy 3.X
* Copyright (c) 2014, Pete (El Supremo)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include "effect_chorus.h"

/******************************************************************/

// A u d i o E f f e c t C h o r u s
// Written by Pete (El Supremo) Jan 2014
// 140529 - change to handle mono stream - change modify() to voices()
// 140219 - correct storage class (not static)

boolean AudioEffectChorus::begin(short *delayline,int d_length,int n_chorus)
{
Serial.print("AudioEffectChorus.begin(Chorus delay line length = ");
Serial.print(d_length);
Serial.print(", n_chorus = ");
Serial.print(n_chorus);
Serial.println(")");

l_delayline = NULL;
delay_length = 0;
l_circ_idx = 0;

if(delayline == NULL) {
return(false);
}
if(d_length < 10) {
return(false);
}
if(n_chorus < 1) {
return(false);
}
l_delayline = delayline;
delay_length = d_length/2;
num_chorus = n_chorus;
return(true);
}

void AudioEffectChorus::voices(int n_chorus)
{
num_chorus = n_chorus;
}

//int last_idx = 0;
void AudioEffectChorus::update(void)
{
audio_block_t *block;
short *bp;
int sum;
int c_idx;

if(l_delayline == NULL)return;
// do passthru
// It stores the unmodified data in the delay line so that
// it isn't as likely to click
if(num_chorus < 1) {
// Just passthrough
block = receiveWritable(0);
if(block) {
bp = block->data;
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
l_circ_idx++;
if(l_circ_idx >= delay_length) {
l_circ_idx = 0;
}
l_delayline[l_circ_idx] = *bp++;
}
transmit(block,0);
release(block);
}
}

// L E F T C H A N N E L

block = receiveWritable(0);
if(block) {
bp = block->data;
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
l_circ_idx++;
if(l_circ_idx >= delay_length) {
l_circ_idx = 0;
}
l_delayline[l_circ_idx] = *bp;
sum = 0;
c_idx = l_circ_idx;
for(int k = 0; k < num_chorus; k++) {
sum += l_delayline[c_idx];
if(num_chorus > 1)c_idx -= delay_length/(num_chorus - 1) - 1;
if(c_idx < 0) {
c_idx += delay_length;
}
}
*bp++ = sum/num_chorus;
}

// transmit the block
transmit(block,0);
release(block);
}
}




+ 56
- 0
effect_chorus.h 查看文件

@@ -0,0 +1,56 @@
/* Audio Library for Teensy 3.X
* Copyright (c) 2014, Pete (El Supremo)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION 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 effect_chorus_h_
#define effect_chorus_h_

#include "AudioStream.h"

/******************************************************************/

// A u d i o E f f e c t C h o r u s
// Written by Pete (El Supremo) Jan 2014
// 140219 - correct storage class (not static)

#define CHORUS_DELAY_PASSTHRU -1

class AudioEffectChorus :
public AudioStream
{
public:
AudioEffectChorus(void):
AudioStream(1,inputQueueArray), num_chorus(2)
{ }

boolean begin(short *delayline,int delay_length,int n_chorus);
virtual void update(void);
void voices(int n_chorus);
private:
audio_block_t *inputQueueArray[1];
short *l_delayline;
short l_circ_idx;
int num_chorus;
int delay_length;
};

#endif

+ 135
- 0
effect_delay.cpp 查看文件

@@ -0,0 +1,135 @@
/* 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.
*/

#include "effect_delay.h"

void AudioEffectDelay::update(void)
{
audio_block_t *output;
uint32_t head, tail, count, channel, index, prev, offset;
const int16_t *src, *end;
int16_t *dst;

// grab incoming data and put it into the queue
head = headindex;
tail = tailindex;
if (++head >= DELAY_QUEUE_SIZE) head = 0;
if (head == tail) {
release(queue[tail]);
if (++tail >= DELAY_QUEUE_SIZE) tail = 0;
}
queue[head] = receiveReadOnly();
headindex = head;

// testing only.... don't allow null pointers into the queue
// instead, fill the empty times with blocks of zeros
//if (queue[head] == NULL) {
// queue[head] = allocate();
// if (queue[head]) {
// dst = queue[head]->data;
// end = dst + AUDIO_BLOCK_SAMPLES;
// do {
// *dst++ = 0;
// } while (dst < end);
// } else {
// digitalWriteFast(2, HIGH);
// delayMicroseconds(5);
// digitalWriteFast(2, LOW);
// }
//}

// discard unneeded blocks from the queue
if (head >= tail) {
count = head - tail;
} else {
count = DELAY_QUEUE_SIZE + head - tail;
}
if (count > maxblocks) {
count -= maxblocks;
do {
release(queue[tail]);
queue[tail] = NULL;
if (++tail >= DELAY_QUEUE_SIZE) tail = 0;
} while (--count > 0);
}
tailindex = tail;

// transmit the delayed outputs using queue data
for (channel = 0; channel < 8; channel++) {
if (!(activemask & (1<<channel))) continue;
index = position[channel] / AUDIO_BLOCK_SAMPLES;
offset = position[channel] % AUDIO_BLOCK_SAMPLES;
if (head >= index) {
index = head - index;
} else {
index = DELAY_QUEUE_SIZE + head - index;
}
if (offset == 0) {
// delay falls on the block boundary
if (queue[index]) {
transmit(queue[index], channel);
}
} else {
// delay requires grabbing data from 2 blocks
output = allocate();
if (!output) continue;
dst = output->data;
if (index > 0) {
prev = index - 1;
} else {
prev = DELAY_QUEUE_SIZE-1;
}
if (queue[prev]) {
end = queue[prev]->data + AUDIO_BLOCK_SAMPLES;
src = end - offset;
while (src < end) {
*dst++ = *src++; // TODO: optimize
}
} else {
end = dst + offset;
while (dst < end) {
*dst++ = 0;
}
}
end = output->data + AUDIO_BLOCK_SAMPLES;
if (queue[index]) {
src = queue[index]->data;
while (dst < end) {
*dst++ = *src++; // TODO: optimize
}
} else {
while (dst < end) {
*dst++ = 0;
}
}
transmit(output, channel);
release(output);
}
}

}



+ 98
- 0
effect_delay.h 查看文件

@@ -0,0 +1,98 @@
/* 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 effect_delay_h_
#define effect_delay_h_
#include "AudioStream.h"
#include "utility/dspinst.h"

#define DELAY_QUEUE_SIZE 117

class AudioEffectDelay : public AudioStream
{
public:
AudioEffectDelay() : AudioStream(1, inputQueueArray) {
activemask = 0;
headindex = 0;
tailindex = 0;
maxblocks = 0;
memset(queue, 0, sizeof(queue));
}
void delay(uint8_t channel, float milliseconds) {
if (channel >= 8) return;
if (milliseconds < 0.0) milliseconds = 0.0;
uint32_t n = (milliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0))+0.5;
uint32_t nmax = AUDIO_BLOCK_SAMPLES * (DELAY_QUEUE_SIZE-1);
if (n > nmax) n = nmax;
uint32_t blks = (n + (AUDIO_BLOCK_SAMPLES-1)) / AUDIO_BLOCK_SAMPLES + 1;
if (!(activemask & (1<<channel))) {
// enabling a previously disabled channel
position[channel] = n;
if (blks > maxblocks) maxblocks = blks;
activemask |= (1<<channel);
} else {
if (n > position[channel]) {
// new delay is greater than previous setting
if (blks > maxblocks) maxblocks = blks;
position[channel] = n;
} else {
// new delay is less than previous setting
position[channel] = n;
recompute_maxblocks();
}
}
}
void disable(uint8_t channel) {
if (channel >= 8) return;
// diable this channel
activemask &= ~(1<<channel);
// recompute maxblocks for remaining enabled channels
recompute_maxblocks();
}
virtual void update(void);
private:
void recompute_maxblocks(void) {
uint32_t max=0;
uint32_t channel = 0;
do {
if (activemask & (1<<channel)) {
uint32_t n = position[channel];
n = (n + (AUDIO_BLOCK_SAMPLES-1)) / AUDIO_BLOCK_SAMPLES + 1;
if (n > max) max = n;
}
} while(++channel < 8);
maxblocks = max;
}
uint8_t activemask; // which output channels are active
uint8_t headindex; // head index (incoming) data in quueu
uint8_t tailindex; // tail index (outgoing) data from queue
uint8_t maxblocks; // number of blocks needed in queue
uint16_t position[8]; // # of sample delay for each channel
audio_block_t *queue[DELAY_QUEUE_SIZE];
audio_block_t *inputQueueArray[1];
};

#endif

+ 255
- 0
effect_delay_ext.cpp 查看文件

@@ -0,0 +1,255 @@
/* 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.
*/

#include "effect_delay_ext.h"

//#define INTERNAL_TEST

// Use these with the audio adaptor board (should be adjustable by the user...)
#define SPIRAM_MOSI_PIN 7
#define SPIRAM_MISO_PIN 12
#define SPIRAM_SCK_PIN 14

#define SPIRAM_CS_PIN 6

#define MEMBOARD_CS0_PIN 2
#define MEMBOARD_CS1_PIN 3
#define MEMBOARD_CS2_PIN 4

void AudioEffectDelayExternal::update(void)
{
audio_block_t *block;
uint32_t n, channel, read_offset;

// grab incoming data and put it into the memory
block = receiveReadOnly();
if (memory_type >= AUDIO_MEMORY_UNDEFINED) {
// ignore input and do nothing if undefined memory type
release(block);
return;
}
if (block) {
if (head_offset + AUDIO_BLOCK_SAMPLES <= memory_length) {
// a single write is enough
write(head_offset, AUDIO_BLOCK_SAMPLES, block->data);
head_offset += AUDIO_BLOCK_SAMPLES;
} else {
// write wraps across end-of-memory
n = memory_length - head_offset;
write(head_offset, n, block->data);
head_offset = AUDIO_BLOCK_SAMPLES - n;
write(0, head_offset, block->data + n);
}
release(block);
} else {
// if no input, store zeros, so later playback will
// not be random garbage previously stored in memory
if (head_offset + AUDIO_BLOCK_SAMPLES <= memory_length) {
zero(head_offset, AUDIO_BLOCK_SAMPLES);
head_offset += AUDIO_BLOCK_SAMPLES;
} else {
n = memory_length - head_offset;
zero(head_offset, n);
head_offset = AUDIO_BLOCK_SAMPLES - n;
zero(0, head_offset);
}
}

// transmit the delayed outputs
for (channel = 0; channel < 8; channel++) {
if (!(activemask & (1<<channel))) continue;
block = allocate();
if (!block) continue;
// compute the delayed location where we read
if (delay_length[channel] <= head_offset) {
read_offset = head_offset - delay_length[channel];
} else {
read_offset = memory_length + head_offset - delay_length[channel];
}
if (read_offset + AUDIO_BLOCK_SAMPLES <= memory_length) {
// a single read will do it
read(read_offset, AUDIO_BLOCK_SAMPLES, block->data);
} else {
// read wraps across end-of-memory
n = memory_length - read_offset;
read(read_offset, n, block->data);
read(0, AUDIO_BLOCK_SAMPLES - n, block->data + n);
}
transmit(block, channel);
release(block);
}
}

uint32_t AudioEffectDelayExternal::allocated[2] = {0, 0};

void AudioEffectDelayExternal::initialize(AudioEffectDelayMemoryType_t type, uint32_t samples)
{
uint32_t memsize, avail;

activemask = 0;
head_offset = 0;
memory_type = type;
if (type == AUDIO_MEMORY_23LC1024) {
#ifdef INTERNAL_TEST
memsize = 8000;
#else
memsize = 65536;
#endif
pinMode(SPIRAM_CS_PIN, OUTPUT);
digitalWriteFast(SPIRAM_CS_PIN, HIGH);
} else if (type == AUDIO_MEMORY_MEMORYBOARD) {
memsize = 393216;
pinMode(MEMBOARD_CS0_PIN, OUTPUT);
pinMode(MEMBOARD_CS1_PIN, OUTPUT);
pinMode(MEMBOARD_CS2_PIN, OUTPUT);
digitalWriteFast(MEMBOARD_CS0_PIN, LOW);
digitalWriteFast(MEMBOARD_CS1_PIN, LOW);
digitalWriteFast(MEMBOARD_CS2_PIN, LOW);
} else {
return;
}
avail = memsize - allocated[type];
if (avail < AUDIO_BLOCK_SAMPLES*2+1) {
memory_type = AUDIO_MEMORY_UNDEFINED;
return;
}
if (samples > avail) samples = avail;
memory_begin = allocated[type];
allocated[type] += samples;
memory_length = samples;

SPI.setMOSI(SPIRAM_MOSI_PIN);
SPI.setMISO(SPIRAM_MISO_PIN);
SPI.setSCK(SPIRAM_SCK_PIN);

SPI.begin();
zero(0, memory_length);
}


#ifdef INTERNAL_TEST
static int16_t testmem[8000]; // testing only
#endif


#define SPISETTING SPISettings(20000000, MSBFIRST, SPI_MODE0)

void AudioEffectDelayExternal::read(uint32_t offset, uint32_t count, int16_t *data)
{
uint32_t addr = memory_begin + offset;

#ifdef INTERNAL_TEST
while (count) { *data++ = testmem[addr++]; count--; } // testing only
#else
if (memory_type == AUDIO_MEMORY_23LC1024) {
addr *= 2;
SPI.beginTransaction(SPISETTING);
digitalWriteFast(SPIRAM_CS_PIN, LOW);
SPI.transfer16((0x03 << 8) | (addr >> 16));
SPI.transfer16(addr & 0xFFFF);
while (count) {
*data++ = (int16_t)(SPI.transfer16(0));
count--;
}
digitalWriteFast(SPIRAM_CS_PIN, HIGH);
SPI.endTransaction();
} else if (memory_type == AUDIO_MEMORY_MEMORYBOARD) {
SPI.beginTransaction(SPISETTING);
while (count) {
uint32_t chip = (addr >> 16) + 1;
digitalWriteFast(MEMBOARD_CS0_PIN, chip & 1);
digitalWriteFast(MEMBOARD_CS1_PIN, chip & 2);
digitalWriteFast(MEMBOARD_CS2_PIN, chip & 4);
uint32_t chipaddr = (addr & 0xFFFF) << 1;
SPI.transfer16((0x03 << 8) | (chipaddr >> 16));
SPI.transfer16(chipaddr & 0xFFFF);
uint32_t num = 0x10000 - (addr & 0xFFFF);
if (num > count) num = count;
count -= num;
addr += num;
do {
*data++ = (int16_t)(SPI.transfer16(0));
} while (--num > 0);
}
digitalWriteFast(MEMBOARD_CS0_PIN, LOW);
digitalWriteFast(MEMBOARD_CS1_PIN, LOW);
digitalWriteFast(MEMBOARD_CS2_PIN, LOW);
SPI.endTransaction();
}
#endif
}

void AudioEffectDelayExternal::write(uint32_t offset, uint32_t count, const int16_t *data)
{
uint32_t addr = memory_begin + offset;

#ifdef INTERNAL_TEST
while (count) { testmem[addr++] = *data++; count--; } // testing only
#else
if (memory_type == AUDIO_MEMORY_23LC1024) {
addr *= 2;
SPI.beginTransaction(SPISETTING);
digitalWriteFast(SPIRAM_CS_PIN, LOW);
SPI.transfer16((0x02 << 8) | (addr >> 16));
SPI.transfer16(addr & 0xFFFF);
while (count) {
int16_t w = 0;
if (data) w = *data++;
SPI.transfer16(w);
count--;
}
digitalWriteFast(SPIRAM_CS_PIN, HIGH);
SPI.endTransaction();
} else if (memory_type == AUDIO_MEMORY_MEMORYBOARD) {
SPI.beginTransaction(SPISETTING);
while (count) {
uint32_t chip = (addr >> 16) + 1;
digitalWriteFast(MEMBOARD_CS0_PIN, chip & 1);
digitalWriteFast(MEMBOARD_CS1_PIN, chip & 2);
digitalWriteFast(MEMBOARD_CS2_PIN, chip & 4);
uint32_t chipaddr = (addr & 0xFFFF) << 1;
SPI.transfer16((0x02 << 8) | (chipaddr >> 16));
SPI.transfer16(chipaddr & 0xFFFF);
uint32_t num = 0x10000 - (addr & 0xFFFF);
if (num > count) num = count;
count -= num;
addr += num;
do {
int16_t w = 0;
if (data) w = *data++;
SPI.transfer16(w);
} while (--num > 0);
}
digitalWriteFast(MEMBOARD_CS0_PIN, LOW);
digitalWriteFast(MEMBOARD_CS1_PIN, LOW);
digitalWriteFast(MEMBOARD_CS2_PIN, LOW);
SPI.endTransaction();
}
#endif
}




+ 86
- 0
effect_delay_ext.h 查看文件

@@ -0,0 +1,86 @@
/* 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 effect_delay_ext_h_
#define effect_delay_ext_h_
#include "AudioStream.h"
#include "spi_interrupt.h"

enum AudioEffectDelayMemoryType_t {
AUDIO_MEMORY_23LC1024 = 0,
AUDIO_MEMORY_MEMORYBOARD = 1,
AUDIO_MEMORY_UNDEFINED = 2
};

class AudioEffectDelayExternal : public AudioStream
{
public:
AudioEffectDelayExternal() : AudioStream(1, inputQueueArray) {
initialize(AUDIO_MEMORY_23LC1024, 65536);
}
AudioEffectDelayExternal(AudioEffectDelayMemoryType_t type, float milliseconds=1e6)
: AudioStream(1, inputQueueArray) {
uint32_t n = (milliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f;
initialize(type, n);
}

void delay(uint8_t channel, float milliseconds) {
if (channel >= 8 || memory_type >= AUDIO_MEMORY_UNDEFINED) return;
if (milliseconds < 0.0) milliseconds = 0.0;
uint32_t n = (milliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f;
n += AUDIO_BLOCK_SAMPLES;
if (n > memory_length - AUDIO_BLOCK_SAMPLES)
n = memory_length - AUDIO_BLOCK_SAMPLES;
delay_length[channel] = n;
uint8_t mask = activemask;
if (activemask == 0) AudioStartUsingSPI();
activemask = mask | (1<<channel);
}
void disable(uint8_t channel) {
if (channel >= 8) return;
uint8_t mask = activemask & ~(1<<channel);
activemask = mask;
if (mask == 0) AudioStopUsingSPI();
}
virtual void update(void);
private:
void initialize(AudioEffectDelayMemoryType_t type, uint32_t samples);
void read(uint32_t address, uint32_t count, int16_t *data);
void write(uint32_t address, uint32_t count, const int16_t *data);
void zero(uint32_t address, uint32_t count) {
write(address, count, NULL);
}
uint32_t memory_begin; // the first address in the memory we're using
uint32_t memory_length; // the amount of memory we're using
uint32_t head_offset; // head index (incoming) data into external memory
uint32_t delay_length[8]; // # of sample delay for each channel (128 = no delay)
uint8_t activemask; // which output channels are active
uint8_t memory_type; // 0=23LC1024, 1=Frank's Memoryboard
static uint32_t allocated[2];
audio_block_t *inputQueueArray[1];
};

#endif

+ 156
- 0
effect_envelope.cpp 查看文件

@@ -0,0 +1,156 @@
/* 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.
*/

#include "effect_envelope.h"

#define STATE_IDLE 0
#define STATE_DELAY 1
#define STATE_ATTACK 2
#define STATE_HOLD 3
#define STATE_DECAY 4
#define STATE_SUSTAIN 5
#define STATE_RELEASE 6

void AudioEffectEnvelope::noteOn(void)
{
__disable_irq();
mult = 0;
count = delay_count;
if (count > 0) {
state = STATE_DELAY;
inc = 0;
} else {
state = STATE_ATTACK;
count = attack_count;
inc = (0x10000 / count) >> 3;
}
__enable_irq();
}

void AudioEffectEnvelope::noteOff(void)
{
__disable_irq();
state = STATE_RELEASE;
count = release_count;
mult = sustain_mult;
inc = (-mult / ((int32_t)count << 3));
__enable_irq();
}

void AudioEffectEnvelope::update(void)
{
audio_block_t *block;
uint32_t *p, *end;
uint32_t sample12, sample34, sample56, sample78, tmp1, tmp2;

block = receiveWritable();
if (!block) return;
if (state == STATE_IDLE) {
release(block);
return;
}
p = (uint32_t *)(block->data);
end = p + AUDIO_BLOCK_SAMPLES/2;

while (p < end) {
// we only care about the state when completing a region
if (count == 0) {
if (state == STATE_ATTACK) {
count = hold_count;
if (count > 0) {
state = STATE_HOLD;
mult = 0x10000;
inc = 0;
} else {
count = decay_count;
state = STATE_DECAY;
inc = ((sustain_mult - 0x10000) / ((int32_t)count << 3));
}
continue;
} else if (state == STATE_HOLD) {
state = STATE_DECAY;
count = decay_count;
inc = ((sustain_mult - 0x10000) / (int32_t)count) >> 3;
continue;
} else if (state == STATE_DECAY) {
state = STATE_SUSTAIN;
count = 0xFFFF;
mult = sustain_mult;
inc = 0;
} else if (state == STATE_SUSTAIN) {
count = 0xFFFF;
} else if (state == STATE_RELEASE) {
state = STATE_IDLE;
while (p < end) {
*p++ = 0;
*p++ = 0;
*p++ = 0;
*p++ = 0;
}
break;
} else if (state == STATE_DELAY) {
state = STATE_ATTACK;
count = attack_count;
inc = (0x10000 / count) >> 3;
continue;
}
}
// process 8 samples, using only mult and inc
sample12 = *p++;
sample34 = *p++;
sample56 = *p++;
sample78 = *p++;
p -= 4;
mult += inc;
tmp1 = signed_multiply_32x16b(mult, sample12);
mult += inc;
tmp2 = signed_multiply_32x16t(mult, sample12);
sample12 = pack_16b_16b(tmp2, tmp1);
mult += inc;
tmp1 = signed_multiply_32x16b(mult, sample34);
mult += inc;
tmp2 = signed_multiply_32x16t(mult, sample34);
sample34 = pack_16b_16b(tmp2, tmp1);
mult += inc;
tmp1 = signed_multiply_32x16b(mult, sample56);
mult += inc;
tmp2 = signed_multiply_32x16t(mult, sample56);
sample56 = pack_16b_16b(tmp2, tmp1);
mult += inc;
tmp1 = signed_multiply_32x16b(mult, sample78);
mult += inc;
tmp2 = signed_multiply_32x16t(mult, sample78);
sample78 = pack_16b_16b(tmp2, tmp1);
*p++ = sample12;
*p++ = sample34;
*p++ = sample56;
*p++ = sample78;
count--;
}
transmit(block);
release(block);
}


+ 94
- 0
effect_envelope.h 查看文件

@@ -0,0 +1,94 @@
/* 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 effect_envelope_h_
#define effect_envelope_h_
#include "AudioStream.h"
#include "utility/dspinst.h"

#define SAMPLES_PER_MSEC (AUDIO_SAMPLE_RATE_EXACT/1000.0)

class AudioEffectEnvelope : public AudioStream
{
public:
AudioEffectEnvelope() : AudioStream(1, inputQueueArray) {
state = 0;
delay(0.0); // default values...
attack(1.5);
hold(0.5);
decay(15.0);
sustain(0.667);
release(30.0);
}
void noteOn();
void noteOff();
void delay(float milliseconds) {
delay_count = milliseconds2count(milliseconds);
}
void attack(float milliseconds) {
attack_count = milliseconds2count(milliseconds);
}
void hold(float milliseconds) {
hold_count = milliseconds2count(milliseconds);
}
void decay(float milliseconds) {
decay_count = milliseconds2count(milliseconds);
}
void sustain(float level) {
if (level < 0.0) level = 0;
else if (level > 1.0) level = 1.0;
sustain_mult = level * 65536.0;
}
void release(float milliseconds) {
release_count = milliseconds2count(milliseconds);
}
using AudioStream::release;
virtual void update(void);
private:
uint16_t milliseconds2count(float milliseconds) {
if (milliseconds < 0.0) milliseconds = 0.0;
uint32_t c = ((uint32_t)(milliseconds*SAMPLES_PER_MSEC)+7)>>3;
if (c > 1103) return 1103; // allow up to 200 ms
return c;
}
audio_block_t *inputQueueArray[1];
// state
uint8_t state; // idle, delay, attack, hold, decay, sustain, release
uint16_t count; // how much time remains in this state, in 8 sample units
int32_t mult; // attenuation, 0=off, 0x10000=unity gain
int32_t inc; // amount to change mult on each sample
// settings
uint16_t delay_count;
uint16_t attack_count;
uint16_t hold_count;
uint16_t decay_count;
int32_t sustain_mult;
uint16_t release_count;

};

#undef SAMPLES_PER_MSEC
#endif

+ 97
- 0
effect_fade.cpp 查看文件

@@ -0,0 +1,97 @@
/* 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.
*/

#include "effect_fade.h"
#include "utility/dspinst.h"

extern "C" {
extern const int16_t fader_table[256];
};

void AudioEffectFade::update(void)
{
audio_block_t *block;
uint32_t i, pos, inc, index, scale;
int32_t val1, val2, val, sample;
uint8_t dir;

pos = position;
if (pos == 0) {
// output is silent
block = receiveReadOnly();
if (block) release(block);
return;
} else if (pos == 0xFFFFFFFF) {
// output is 100%
block = receiveReadOnly();
if (!block) return;
transmit(block);
release(block);
return;
}
block = receiveWritable();
if (!block) return;
inc = rate;
dir = direction;
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
index = pos >> 24;
val1 = fader_table[index];
val2 = fader_table[index+1];
scale = (pos >> 8) & 0xFFFF;
val2 *= scale;
val1 *= 0x10000 - scale;
val = (val1 + val2) >> 16;
sample = block->data[i];
sample = (sample * val) >> 15;
block->data[i] = sample;
if (dir > 0) {
// output is increasing
if (inc < 0xFFFFFFFF - pos) pos += inc;
else pos = 0xFFFFFFFF;
} else {
// output is decreasing
if (inc < pos) pos -= inc;
else pos = 0;
}
}
position = pos;
transmit(block);
release(block);
}

void AudioEffectFade::fadeBegin(uint32_t newrate, uint8_t dir)
{
__disable_irq();
uint32_t pos = position;
if (pos == 0) position = 1;
else if (pos == 0xFFFFFFFF) position = 0xFFFFFFFE;
rate = newrate;
direction = dir;
__enable_irq();
}




+ 56
- 0
effect_fade.h 查看文件

@@ -0,0 +1,56 @@
/* 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 effect_fade_h_
#define effect_fade_h_

#include "AudioStream.h"

class AudioEffectFade : public AudioStream
{
public:
AudioEffectFade(void)
: AudioStream(1, inputQueueArray), position(0xFFFFFFFF) {}
void fadeIn(uint32_t milliseconds) {
uint32_t samples = (uint32_t)(milliseconds * 441u + 5u) / 10u;
//Serial.printf("fadeIn, %u samples\n", samples);
fadeBegin(0xFFFFFFFFu / samples, 1);
}
void fadeOut(uint32_t milliseconds) {
uint32_t samples = (uint32_t)(milliseconds * 441u + 5u) / 10u;
//Serial.printf("fadeOut, %u samples\n", samples);
fadeBegin(0xFFFFFFFFu / samples, 0);
}
virtual void update(void);
private:
void fadeBegin(uint32_t newrate, uint8_t dir);
uint32_t position; // 0 = off, 0xFFFFFFFF = on
uint32_t rate;
uint8_t direction; // 0 = fading out, 1 = fading in
audio_block_t *inputQueueArray[1];
};

#endif

+ 219
- 0
effect_flange.cpp 查看文件

@@ -0,0 +1,219 @@
/* Audio Library for Teensy 3.X
* Copyright (c) 2014, Pete (El Supremo)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include "effect_flange.h"
#include "arm_math.h"

/******************************************************************/
// A u d i o E f f e c t F l a n g e
// Written by Pete (El Supremo) Jan 2014
// 140529 - change to handle mono stream and change modify() to voices()
// 140207 - fix calculation of delay_rate_incr which is expressed as
// a fraction of 2*PI
// 140207 - cosmetic fix to begin()
// 140219 - correct the calculation of "frac"

// circular addressing indices for left and right channels
//short AudioEffectFlange::l_circ_idx;
//short AudioEffectFlange::r_circ_idx;

//short * AudioEffectFlange::l_delayline = NULL;
//short * AudioEffectFlange::r_delayline = NULL;

// User-supplied offset for the delayed sample
// but start with passthru
//int AudioEffectFlange::delay_offset_idx = FLANGE_DELAY_PASSTHRU;
//int AudioEffectFlange::delay_length;

//int AudioEffectFlange::delay_depth;
//int AudioEffectFlange::delay_rate_incr;
//unsigned int AudioEffectFlange::l_delay_rate_index;
//unsigned int AudioEffectFlange::r_delay_rate_index;
// fails if the user provides unreasonable values but will
// coerce them and go ahead anyway. e.g. if the delay offset
// is >= CHORUS_DELAY_LENGTH, the code will force it to
// CHORUS_DELAY_LENGTH-1 and return false.
// delay_rate is the rate (in Hz) of the sine wave modulation
// delay_depth is the maximum variation around delay_offset
// i.e. the total offset is delay_offset + delay_depth * sin(delay_rate)
boolean AudioEffectFlange::begin(short *delayline,int d_length,int delay_offset,int d_depth,float delay_rate)
{
boolean all_ok = true;

if(0) {
Serial.print("AudioEffectFlange.begin(offset = ");
Serial.print(delay_offset);
Serial.print(", depth = ");
Serial.print(d_depth);
Serial.print(", rate = ");
Serial.print(delay_rate,3);
Serial.println(")");
Serial.print(" FLANGE_DELAY_LENGTH = ");
Serial.println(d_length);
}
delay_length = d_length/2;
l_delayline = delayline;
delay_depth = d_depth;
// initial index
l_delay_rate_index = 0;
l_circ_idx = 0;
delay_rate_incr = delay_rate/44100.*2147483648.;
//Serial.println(delay_rate_incr,HEX);

delay_offset_idx = delay_offset;
// Allow the passthru code to go through
if(delay_offset_idx < -1) {
delay_offset_idx = 0;
all_ok = false;
}
if(delay_offset_idx >= delay_length) {
delay_offset_idx = delay_length - 1;
all_ok = false;
}
return(all_ok);
}


boolean AudioEffectFlange::voices(int delay_offset,int d_depth,float delay_rate)
{
boolean all_ok = true;
delay_depth = d_depth;

delay_rate_incr = delay_rate/44100.*2147483648.;
delay_offset_idx = delay_offset;
// Allow the passthru code to go through
if(delay_offset_idx < -1) {
delay_offset_idx = 0;
all_ok = false;
}
if(delay_offset_idx >= delay_length) {
delay_offset_idx = delay_length - 1;
all_ok = false;
}
l_delay_rate_index = 0;
l_circ_idx = 0;
return(all_ok);
}

void AudioEffectFlange::update(void)
{
audio_block_t *block;
int idx;
short *bp;
short frac;
int idx1;

if(l_delayline == NULL)return;

// do passthru
if(delay_offset_idx == FLANGE_DELAY_PASSTHRU) {
// Just passthrough
block = receiveWritable(0);
if(block) {
bp = block->data;
// fill the delay line
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
l_circ_idx++;
if(l_circ_idx >= delay_length) {
l_circ_idx = 0;
}
l_delayline[l_circ_idx] = *bp++;
}
// transmit the unmodified block
transmit(block,0);
release(block);
}
return;
}

// L E F T C H A N N E L

block = receiveWritable(0);
if(block) {
bp = block->data;
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
// increment the index into the circular delay line buffer
l_circ_idx++;
// wrap the index around if necessary
if(l_circ_idx >= delay_length) {
l_circ_idx = 0;
}
// store the current sample in the delay line
l_delayline[l_circ_idx] = *bp;
// The argument to the arm_sin_q15 function is NOT in radians. It is
// actually, in effect, the fraction remaining after the division
// of radians/(2*PI) which is then expressed as a positive Q15
// fraction in the interval [0 , +1) - this is l_delay_rate_index.
// l_delay_rate_index should probably be called l_delay_rate_phase
// (sorry about that!)
// It is a Q31 positive number of which the high order 16 bits are
// used when calculating the sine. idx will have a value in the
// interval [-1 , +1)
frac = arm_sin_q15( (q15_t)((l_delay_rate_index >> 16) & 0x7fff));
// multiply the sin by the delay depth
idx = (frac * delay_depth) >> 15;
//Serial.println(idx);
// Calculate the offset into the buffer
idx = l_circ_idx - (delay_offset_idx + idx);
// and adjust idx to point into the circular buffer
if(idx < 0) {
idx += delay_length;
}
if(idx >= delay_length) {
idx -= delay_length;
}

// Here we interpolate between two indices but if the sine was negative
// then we interpolate between idx and idx-1, otherwise the
// interpolation is between idx and idx+1
if(frac < 0)
idx1 = idx - 1;
else
idx1 = idx + 1;
// adjust idx1 in the circular buffer
if(idx1 < 0) {
idx1 += delay_length;
}
if(idx1 >= delay_length) {
idx1 -= delay_length;
}
// Do the interpolation
frac = (l_delay_rate_index >> 1) &0x7fff;
frac = (( (int)(l_delayline[idx1] - l_delayline[idx])*frac) >> 15);
*bp++ = (l_delayline[l_circ_idx]+ l_delayline[idx] + frac)/2;

l_delay_rate_index += delay_rate_incr;
if(l_delay_rate_index & 0x80000000) {
l_delay_rate_index &= 0x7fffffff;
}
}
// send the effect output to the left channel
transmit(block,0);
release(block);
}
}




+ 58
- 0
effect_flange.h 查看文件

@@ -0,0 +1,58 @@
/* Audio Library for Teensy 3.X
* Copyright (c) 2014, Pete (El Supremo)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION 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 effect_flange_h_
#define effect_flange_h_

#include "AudioStream.h"

/******************************************************************/
// A u d i o E f f e c t F l a n g e
// Written by Pete (El Supremo) Jan 2014
// 140529 - change to handle mono stream and change modify() to voices()

#define FLANGE_DELAY_PASSTHRU 0

class AudioEffectFlange :
public AudioStream
{
public:
AudioEffectFlange(void):
AudioStream(1,inputQueueArray) {
}

boolean begin(short *delayline,int d_length,int delay_offset,int d_depth,float delay_rate);
boolean voices(int delay_offset,int d_depth,float delay_rate);
virtual void update(void);
private:
audio_block_t *inputQueueArray[1];
short *l_delayline;
int delay_length;
short l_circ_idx;
int delay_depth;
int delay_offset_idx;
int delay_rate_incr;
unsigned int l_delay_rate_index;
};

#endif

+ 89
- 0
effect_multiply.cpp 查看文件

@@ -0,0 +1,89 @@
/* 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.
*/

#include "effect_multiply.h"

void AudioEffectMultiply::update(void)
{
#if defined(KINETISK)
audio_block_t *blocka, *blockb;
uint32_t *pa, *pb, *end;
uint32_t a12, a34; //, a56, a78;
uint32_t b12, b34; //, b56, b78;

blocka = receiveWritable(0);
blockb = receiveReadOnly(1);
if (!blocka) {
if (blockb) release(blockb);
return;
}
if (!blockb) {
release(blocka);
return;
}
pa = (uint32_t *)(blocka->data);
pb = (uint32_t *)(blockb->data);
end = pa + AUDIO_BLOCK_SAMPLES/2;
while (pa < end) {
a12 = *pa;
a34 = *(pa+1);
//a56 = *(pa+2); // 8 samples/loop should work, but crashes.
//a78 = *(pa+3); // why?! maybe a compiler bug??
b12 = *pb++;
b34 = *pb++;
//b56 = *pb++;
//b78 = *pb++;
a12 = pack_16b_16b(
signed_saturate_rshift(multiply_16tx16t(a12, b12), 16, 15),
signed_saturate_rshift(multiply_16bx16b(a12, b12), 16, 15));
a34 = pack_16b_16b(
signed_saturate_rshift(multiply_16tx16t(a34, b34), 16, 15),
signed_saturate_rshift(multiply_16bx16b(a34, b34), 16, 15));
//a56 = pack_16b_16b(
// signed_saturate_rshift(multiply_16tx16t(a56, b56), 16, 15),
// signed_saturate_rshift(multiply_16bx16b(a56, b56), 16, 15));
//a78 = pack_16b_16b(
// signed_saturate_rshift(multiply_16tx16t(a78, b78), 16, 15),
// signed_saturate_rshift(multiply_16bx16b(a78, b78), 16, 15));
*pa++ = a12;
*pa++ = a34;
//*pa++ = a56;
//*pa++ = a78;
}
transmit(blocka);
release(blocka);
release(blockb);

#elif defined(KINETISL)
audio_block_t *block;

block = receiveReadOnly(0);
if (block) release(block);
block = receiveReadOnly(1);
if (block) release(block);
#endif
}


+ 41
- 0
effect_multiply.h 查看文件

@@ -0,0 +1,41 @@
/* 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 effect_multiply_h_
#define effect_multiply_h_
#include "AudioStream.h"
#include "utility/dspinst.h"

class AudioEffectMultiply : public AudioStream
{
public:
AudioEffectMultiply() : AudioStream(2, inputQueueArray) { }
virtual void update(void);
private:
audio_block_t *inputQueueArray[2];
};

#endif

+ 256
- 0
examples/Analysis/DialTone_7segment/DialTone_7segment.ino 查看文件

@@ -0,0 +1,256 @@
// Dial Tone (DTMF) decoding example.
//
// The audio with dial tones is connected to analog input A2,
// without using the audio shield. See the "DialTone_DTMF"
// example for using the audio shield.
//
// This example code is in the public domain.

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//
AudioInputAnalog audioIn;
AudioAnalyzeToneDetect row1; // 7 tone detectors are needed
AudioAnalyzeToneDetect row2; // to receive DTMF dial tones
AudioAnalyzeToneDetect row3;
AudioAnalyzeToneDetect row4;
AudioAnalyzeToneDetect column1;
AudioAnalyzeToneDetect column2;
AudioAnalyzeToneDetect column3;

// Create Audio connections between the components
//
AudioConnection patchCord1(audioIn, 0, row1, 0);
AudioConnection patchCord2(audioIn, 0, row2, 0);
AudioConnection patchCord3(audioIn, 0, row3, 0);
AudioConnection patchCord4(audioIn, 0, row4, 0);
AudioConnection patchCord5(audioIn, 0, column1, 0);
AudioConnection patchCord6(audioIn, 0, column2, 0);
AudioConnection patchCord7(audioIn, 0, column3, 0);

// pins where the 7 segment LEDs are connected
const int sevenseg_a = 17; // aaa
const int sevenseg_b = 9; // f b
const int sevenseg_c = 11; // f b
const int sevenseg_d = 12; // ggg
const int sevenseg_e = 14; // e c
const int sevenseg_f = 15; // e c
const int sevenseg_g = 10; // ddd


void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(3);
//while (!Serial) ;
//delay(100);
// Configure the tone detectors with the frequency and number
// of cycles to match. These numbers were picked for match
// times of approx 30 ms. Longer times are more precise.
row1.frequency(697, 21);
row2.frequency(770, 23);
row3.frequency(852, 25);
row4.frequency(941, 28);
column1.frequency(1209, 36);
column2.frequency(1336, 40);
column3.frequency(1477, 44);
// The 7 segment display is "common anode), where the
// common pin connects to +3.3V. LOW turns the LED on
// and HIGH turns the LED off. If you use a common
// cathode display, you will need to change all the HIGH
// to LOW and LOW to HIGH.
pinMode(sevenseg_a, OUTPUT);
pinMode(sevenseg_b, OUTPUT);
pinMode(sevenseg_c, OUTPUT);
pinMode(sevenseg_d, OUTPUT);
pinMode(sevenseg_e, OUTPUT);
pinMode(sevenseg_f, OUTPUT);
pinMode(sevenseg_g, OUTPUT);
digitalWrite(sevenseg_a, HIGH);
digitalWrite(sevenseg_b, HIGH);
digitalWrite(sevenseg_c, HIGH);
digitalWrite(sevenseg_d, HIGH);
digitalWrite(sevenseg_e, HIGH);
digitalWrite(sevenseg_f, HIGH);
digitalWrite(sevenseg_g, HIGH);
}

const float row_threshold = 0.2;
const float column_threshold = 0.2;

void loop() {
float r1, r2, r3, r4, c1, c2, c3;
char digit=0;

// read all seven tone detectors
r1 = row1.read();
r2 = row2.read();
r3 = row3.read();
r4 = row4.read();
c1 = column1.read();
c2 = column2.read();
c3 = column3.read();

// print the raw data, for troubleshooting
Serial.print("tones: ");
Serial.print(r1);
Serial.print(", ");
Serial.print(r2);
Serial.print(", ");
Serial.print(r3);
Serial.print(", ");
Serial.print(r4);
Serial.print(", ");
Serial.print(c1);
Serial.print(", ");
Serial.print(c2);
Serial.print(", ");
Serial.print(c3);

// check all 12 combinations for key press
if (r1 >= row_threshold) {
if (c1 > column_threshold) {
digit = '1';
digitalWrite(sevenseg_a, HIGH);
digitalWrite(sevenseg_b, LOW);
digitalWrite(sevenseg_c, LOW);
digitalWrite(sevenseg_d, HIGH);
digitalWrite(sevenseg_e, HIGH);
digitalWrite(sevenseg_f, HIGH);
digitalWrite(sevenseg_g, HIGH);
} else if (c2 > column_threshold) {
digit = '2';
digitalWrite(sevenseg_a, LOW);
digitalWrite(sevenseg_b, LOW);
digitalWrite(sevenseg_c, HIGH);
digitalWrite(sevenseg_d, LOW);
digitalWrite(sevenseg_e, LOW);
digitalWrite(sevenseg_f, HIGH);
digitalWrite(sevenseg_g, LOW);
} else if (c3 > column_threshold) {
digit = '3';
digitalWrite(sevenseg_a, LOW);
digitalWrite(sevenseg_b, LOW);
digitalWrite(sevenseg_c, LOW);
digitalWrite(sevenseg_d, LOW);
digitalWrite(sevenseg_e, HIGH);
digitalWrite(sevenseg_f, HIGH);
digitalWrite(sevenseg_g, LOW);
}
} else if (r2 >= row_threshold) {
if (c1 > column_threshold) {
digit = '4';
digitalWrite(sevenseg_a, HIGH);
digitalWrite(sevenseg_b, LOW);
digitalWrite(sevenseg_c, LOW);
digitalWrite(sevenseg_d, HIGH);
digitalWrite(sevenseg_e, HIGH);
digitalWrite(sevenseg_f, LOW);
digitalWrite(sevenseg_g, LOW);
} else if (c2 > column_threshold) {
digit = '5';
digitalWrite(sevenseg_a, LOW);
digitalWrite(sevenseg_b, HIGH);
digitalWrite(sevenseg_c, LOW);
digitalWrite(sevenseg_d, LOW);
digitalWrite(sevenseg_e, HIGH);
digitalWrite(sevenseg_f, LOW);
digitalWrite(sevenseg_g, LOW);
} else if (c3 > column_threshold) {
digit = '6';
digitalWrite(sevenseg_a, LOW);
digitalWrite(sevenseg_b, HIGH);
digitalWrite(sevenseg_c, LOW);
digitalWrite(sevenseg_d, LOW);
digitalWrite(sevenseg_e, LOW);
digitalWrite(sevenseg_f, LOW);
digitalWrite(sevenseg_g, LOW);
}
} else if (r3 >= row_threshold) {
if (c1 > column_threshold) {
digit = '7';
digitalWrite(sevenseg_a, LOW);
digitalWrite(sevenseg_b, LOW);
digitalWrite(sevenseg_c, LOW);
digitalWrite(sevenseg_d, HIGH);
digitalWrite(sevenseg_e, HIGH);
digitalWrite(sevenseg_f, HIGH);
digitalWrite(sevenseg_g, HIGH);
} else if (c2 > column_threshold) {
digit = '8';
digitalWrite(sevenseg_a, LOW);
digitalWrite(sevenseg_b, LOW);
digitalWrite(sevenseg_c, LOW);
digitalWrite(sevenseg_d, LOW);
digitalWrite(sevenseg_e, LOW);
digitalWrite(sevenseg_f, LOW);
digitalWrite(sevenseg_g, LOW);
} else if (c3 > column_threshold) {
digit = '9';
digitalWrite(sevenseg_a, LOW);
digitalWrite(sevenseg_b, LOW);
digitalWrite(sevenseg_c, LOW);
digitalWrite(sevenseg_d, LOW);
digitalWrite(sevenseg_e, HIGH);
digitalWrite(sevenseg_f, LOW);
digitalWrite(sevenseg_g, LOW);
}
} else if (r4 >= row_threshold) {
if (c1 > column_threshold) {
digit = '*';
digitalWrite(sevenseg_a, HIGH);
digitalWrite(sevenseg_b, HIGH);
digitalWrite(sevenseg_c, HIGH);
digitalWrite(sevenseg_d, HIGH);
digitalWrite(sevenseg_e, HIGH);
digitalWrite(sevenseg_f, HIGH);
digitalWrite(sevenseg_g, LOW);
} else if (c2 > column_threshold) {
digit = '0';
digitalWrite(sevenseg_a, LOW);
digitalWrite(sevenseg_b, LOW);
digitalWrite(sevenseg_c, LOW);
digitalWrite(sevenseg_d, LOW);
digitalWrite(sevenseg_e, LOW);
digitalWrite(sevenseg_f, LOW);
digitalWrite(sevenseg_g, HIGH);
} else if (c3 > column_threshold) {
digit = '#';
digitalWrite(sevenseg_a, HIGH);
digitalWrite(sevenseg_b, LOW);
digitalWrite(sevenseg_c, LOW);
digitalWrite(sevenseg_d, HIGH);
digitalWrite(sevenseg_e, LOW);
digitalWrite(sevenseg_f, LOW);
digitalWrite(sevenseg_g, LOW);
}
}

// print the key, if any found
if (digit > 0) {
Serial.print(" --> Key: ");
Serial.print(digit);
}
Serial.println();

// uncomment these lines to see how much CPU time
// the tone detectors and audio library are using
//Serial.print("CPU=");
//Serial.print(AudioProcessorUsage());
//Serial.print("%, max=");
//Serial.print(AudioProcessorUsageMax());
//Serial.print("% ");

delay(25);
}



+ 230
- 0
examples/Analysis/DialTone_Serial/DialTone_Serial.ino 查看文件

@@ -0,0 +1,230 @@
// Dial Tone (DTMF) decoding example.
//
// The audio with dial tones is connected to audio shield
// Left Line-In pin. Dial tone output is produced on the
// Line-Out and headphones.
//
// Use the Arduino Serial Monitor to watch for incoming
// dial tones, and to send digits to be played as dial tones.
//
// This example code is in the public domain.


#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//
AudioInputI2S audioIn;
AudioAnalyzeToneDetect row1; // 7 tone detectors are needed
AudioAnalyzeToneDetect row2; // to receive DTMF dial tones
AudioAnalyzeToneDetect row3;
AudioAnalyzeToneDetect row4;
AudioAnalyzeToneDetect column1;
AudioAnalyzeToneDetect column2;
AudioAnalyzeToneDetect column3;
AudioSynthWaveformSine sine1; // 2 sine wave
AudioSynthWaveformSine sine2; // to create DTMF
AudioMixer4 mixer;
AudioOutputI2S audioOut;

// Create Audio connections between the components
//
AudioConnection patchCord01(audioIn, 0, row1, 0);
AudioConnection patchCord02(audioIn, 0, row2, 0);
AudioConnection patchCord03(audioIn, 0, row3, 0);
AudioConnection patchCord04(audioIn, 0, row4, 0);
AudioConnection patchCord05(audioIn, 0, column1, 0);
AudioConnection patchCord06(audioIn, 0, column2, 0);
AudioConnection patchCord07(audioIn, 0, column3, 0);
AudioConnection patchCord10(sine1, 0, mixer, 0);
AudioConnection patchCord11(sine2, 0, mixer, 1);
AudioConnection patchCord12(mixer, 0, audioOut, 0);
AudioConnection patchCord13(mixer, 0, audioOut, 1);

// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;


void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(12);

// Enable the audio shield and set the output volume.
audioShield.enable();
audioShield.volume(0.5);
while (!Serial) ;
delay(100);
// Configure the tone detectors with the frequency and number
// of cycles to match. These numbers were picked for match
// times of approx 30 ms. Longer times are more precise.
row1.frequency(697, 21);
row2.frequency(770, 23);
row3.frequency(852, 25);
row4.frequency(941, 28);
column1.frequency(1209, 36);
column2.frequency(1336, 40);
column3.frequency(1477, 44);
}

const float row_threshold = 0.2;
const float column_threshold = 0.2;

void loop() {
float r1, r2, r3, r4, c1, c2, c3;
char digit=0;

// read all seven tone detectors
r1 = row1.read();
r2 = row2.read();
r3 = row3.read();
r4 = row4.read();
c1 = column1.read();
c2 = column2.read();
c3 = column3.read();

// print the raw data, for troubleshooting
Serial.print("tones: ");
Serial.print(r1);
Serial.print(", ");
Serial.print(r2);
Serial.print(", ");
Serial.print(r3);
Serial.print(", ");
Serial.print(r4);
Serial.print(", ");
Serial.print(c1);
Serial.print(", ");
Serial.print(c2);
Serial.print(", ");
Serial.print(c3);

// check all 12 combinations for key press
if (r1 >= row_threshold) {
if (c1 > column_threshold) {
digit = '1';
} else if (c2 > column_threshold) {
digit = '2';
} else if (c3 > column_threshold) {
digit = '3';
}
} else if (r2 >= row_threshold) {
if (c1 > column_threshold) {
digit = '4';
} else if (c2 > column_threshold) {
digit = '5';
} else if (c3 > column_threshold) {
digit = '6';
}
} else if (r3 >= row_threshold) {
if (c1 > column_threshold) {
digit = '7';
} else if (c2 > column_threshold) {
digit = '8';
} else if (c3 > column_threshold) {
digit = '9';
}
} else if (r4 >= row_threshold) {
if (c1 > column_threshold) {
digit = '*';
} else if (c2 > column_threshold) {
digit = '0';
} else if (c3 > column_threshold) {
digit = '#';
}
}

// print the key, if any found
if (digit > 0) {
Serial.print(" --> Key: ");
Serial.print(digit);
}
Serial.println();

// uncomment these lines to see how much CPU time
// the tone detectors and audio library are using
//Serial.print("CPU=");
//Serial.print(AudioProcessorUsage());
//Serial.print("%, max=");
//Serial.print(AudioProcessorUsageMax());
//Serial.print("% ");

// check if any data has arrived from the serial monitor
if (Serial.available()) {
char key = Serial.read();
int low=0;
int high=0;
if (key == '1') {
low = 697;
high = 1209;
} else if (key == '2') {
low = 697;
high = 1336;
} else if (key == '3') {
low = 697;
high = 1477;
} else if (key == '4') {
low = 770;
high = 1209;
} else if (key == '5') {
low = 770;
high = 1336;
} else if (key == '6') {
low = 770;
high = 1477;
} else if (key == '7') {
low = 852;
high = 1209;
} else if (key == '8') {
low = 852;
high = 1336;
} else if (key == '9') {
low = 852;
high = 1477;
} else if (key == '*') {
low = 941;
high = 1209;
} else if (key == '0') {
low = 941;
high = 1336;
} else if (key == '#') {
low = 941;
high = 1477;
}

// play the DTMF tones, if characters send from the Arduino Serial Monitor
if (low > 0 && high > 0) {
Serial.print("Output sound for key ");
Serial.print(key);
Serial.print(", low freq=");
Serial.print(low);
Serial.print(", high freq=");
Serial.print(high);
Serial.println();
AudioNoInterrupts(); // disable audio library momentarily
sine1.frequency(low);
sine1.amplitude(0.4);
sine2.frequency(high);
sine2.amplitude(0.45);
AudioInterrupts(); // enable, both tones will start together
delay(100); // let the sound play for 0.1 second
AudioNoInterrupts();
sine1.amplitude(0);
sine2.amplitude(0);
AudioInterrupts();
delay(50); // make sure we have 0.05 second silence after
}
}

delay(25);
}



+ 78
- 0
examples/Analysis/FFT/FFT.ino 查看文件

@@ -0,0 +1,78 @@
// FFT Test
//
// Compute a 1024 point Fast Fourier Transform (spectrum analysis)
// on audio connected to the Left Line-In pin. By changing code,
// a synthetic sine wave can be input instead.
//
// The first 40 (of 512) frequency analysis bins are printed to
// the Arduino Serial Monitor. Viewing the raw data can help you
// understand how the FFT works and what results to expect when
// using the data to control LEDs, motors, or other fun things!
//
// This example code is in the public domain.

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

const int myInput = AUDIO_INPUT_LINEIN;
//const int myInput = AUDIO_INPUT_MIC;

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//
AudioInputI2S audioInput; // audio shield: mic or line-in
AudioSynthWaveformSine sinewave;
AudioAnalyzeFFT1024 myFFT;
AudioOutputI2S audioOutput; // audio shield: headphones & line-out

// Connect either the live input or synthesized sine wave
AudioConnection patchCord1(audioInput, 0, myFFT, 0);
//AudioConnection patchCord1(sinewave, 0, myFFT, 0);

AudioControlSGTL5000 audioShield;

void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(12);

// Enable the audio shield and set the output volume.
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(0.5);

// Configure the window algorithm to use
myFFT.windowFunction(AudioWindowHanning1024);
//myFFT.windowFunction(NULL);

// Create a synthetic sine wave, for testing
// To use this, edit the connections above
sinewave.amplitude(0.8);
sinewave.frequency(1034.007);
}

void loop() {
float n;
int i;

if (myFFT.available()) {
// each time new FFT data is available
// print it all to the Arduino Serial Monitor
Serial.print("FFT: ");
for (i=0; i<40; i++) {
n = myFFT.read(i);
if (n >= 0.01) {
Serial.print(n);
Serial.print(" ");
} else {
Serial.print(" - "); // don't print "0.00"
}
}
Serial.println();
}
}



+ 46
- 0
examples/Analysis/PeakMeterMono/PeakMeterMono.ino 查看文件

@@ -0,0 +1,46 @@
/* Mono Peak Meter

Scrolling peak audio level meter in the Arduino Serial Monitor

Audio input needs to connect to pin 16 (A2). The signal range is 0 to 1.2V.
See the documentation in the Audio System Design Tool for the recommended
circuit to connect an analog signal.

This example code is in the public domain
*/

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputAnalog adc1; //xy=164,95
AudioAnalyzePeak peak1; //xy=317,123
AudioConnection patchCord1(adc1, peak1);
// GUItool: end automatically generated code


void setup() {
AudioMemory(4);
Serial.begin(9600);
}

// for best effect make your terminal/monitor a minimum of 31 chars wide and as high as you can.

elapsedMillis fps;

void loop() {
if (fps > 24) {
if (peak1.available()) {
fps = 0;
int monoPeak = peak1.read() * 30.0;
Serial.print("|");
for (int cnt=0; cnt<monoPeak; cnt++) {
Serial.print(">");
}
Serial.println();
}
}
}

+ 64
- 0
examples/Analysis/PeakMeterStereo/PeakMeterStereo.ino 查看文件

@@ -0,0 +1,64 @@
/* Stereo peak meter example, assumes Audio adapter but just uses terminal so no more parts required.

This example code is in the public domain
*/

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

const int myInput = AUDIO_INPUT_LINEIN;
// const int myInput = AUDIO_INPUT_MIC;

AudioInputI2S audioInput; // audio shield: mic or line-in
AudioAnalyzePeak peak_L;
AudioAnalyzePeak peak_R;
AudioOutputI2S audioOutput; // audio shield: headphones & line-out

AudioConnection c1(audioInput,0,peak_L,0);
AudioConnection c2(audioInput,1,peak_R,0);
AudioConnection c3(audioInput,0,audioOutput,0);
AudioConnection c4(audioInput,1,audioOutput,1);

AudioControlSGTL5000 audioShield;


void setup() {
AudioMemory(6);
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(0.5);
Serial.begin(9600);
}

// for best effect make your terminal/monitor a minimum of 62 chars wide and as high as you can.

elapsedMillis fps;
uint8_t cnt=0;

void loop() {
if(fps > 24) {
if (peak_L.available() && peak_R.available()) {
fps=0;
uint8_t leftPeak=peak_L.read() * 30.0;
uint8_t rightPeak=peak_R.read() * 30.0;

for(cnt=0;cnt<30-leftPeak;cnt++) {
Serial.print(" ");
}
while(cnt++<30) {
Serial.print("<");
}
Serial.print("||");
for(cnt=0;cnt<rightPeak;cnt++) {
Serial.print(">");
}
while(cnt++<30) {
Serial.print(" ");
}
Serial.println();
}
}
}

+ 143
- 0
examples/Analysis/SpectrumAnalyzerBasic/SpectrumAnalyzerBasic.ino 查看文件

@@ -0,0 +1,143 @@
#include <LiquidCrystal.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S i2s1; //xy=139,91
AudioMixer4 mixer1; //xy=312,134
AudioOutputI2S i2s2; //xy=392,32
AudioAnalyzeFFT1024 fft1024; //xy=467,147
AudioConnection patchCord1(i2s1, 0, mixer1, 0);
AudioConnection patchCord2(i2s1, 0, i2s2, 0);
AudioConnection patchCord3(i2s1, 1, mixer1, 1);
AudioConnection patchCord4(i2s1, 1, i2s2, 1);
AudioConnection patchCord5(mixer1, fft1024);
AudioControlSGTL5000 audioShield; //xy=366,225
// GUItool: end automatically generated code


const int myInput = AUDIO_INPUT_LINEIN;
//const int myInput = AUDIO_INPUT_MIC;


// The scale sets how much sound is needed in each frequency range to
// show all 8 bars. Higher numbers are more sensitive.
float scale = 60.0;

// An array to hold the 16 frequency bands
float level[16];

// This array holds the on-screen levels. When the signal drops quickly,
// these are used to lower the on-screen level 1 bar per update, which
// looks more pleasing to corresponds to human sound perception.
int shown[16];



// Use the LiquidCrystal library to display the spectrum
//
LiquidCrystal lcd(0, 1, 2, 3, 4, 5);
byte bar1[8] = {0,0,0,0,0,0,0,255};
byte bar2[8] = {0,0,0,0,0,0,255,255}; // 8 bar graph
byte bar3[8] = {0,0,0,0,0,255,255,255}; // custom
byte bar4[8] = {0,0,0,0,255,255,255,255}; // characters
byte bar5[8] = {0,0,0,255,255,255,255,255};
byte bar6[8] = {0,0,255,255,255,255,255,255};
byte bar7[8] = {0,255,255,255,255,255,255,255};
byte bar8[8] = {255,255,255,255,255,255,255,255};


void setup() {
// Audio requires memory to work.
AudioMemory(12);

// Enable the audio shield and set the output volume.
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(0.5);

// turn on the LCD and define the custom characters
lcd.begin(16, 2);
lcd.print("Audio Spectrum");
lcd.createChar(0, bar1);
lcd.createChar(1, bar2);
lcd.createChar(2, bar3);
lcd.createChar(3, bar4);
lcd.createChar(4, bar5);
lcd.createChar(5, bar6);
lcd.createChar(6, bar7);
lcd.createChar(7, bar8);

// configure the mixer to equally add left & right
mixer1.gain(0, 0.5);
mixer1.gain(1, 0.5);

// pin 21 will select rapid vs animated display
pinMode(21, INPUT_PULLUP);
}


void loop() {
if (fft1024.available()) {
// read the 512 FFT frequencies into 16 levels
// music is heard in octaves, but the FFT data
// is linear, so for the higher octaves, read
// many FFT bins together.
level[0] = fft1024.read(0);
level[1] = fft1024.read(1);
level[2] = fft1024.read(2, 3);
level[3] = fft1024.read(4, 6);
level[4] = fft1024.read(7, 10);
level[5] = fft1024.read(11, 15);
level[6] = fft1024.read(16, 22);
level[7] = fft1024.read(23, 32);
level[8] = fft1024.read(33, 46);
level[9] = fft1024.read(47, 66);
level[10] = fft1024.read(67, 93);
level[11] = fft1024.read(94, 131);
level[12] = fft1024.read(132, 184);
level[13] = fft1024.read(185, 257);
level[14] = fft1024.read(258, 359);
level[15] = fft1024.read(360, 511);

// if you have the volume pot soldered to your audio shield
// uncomment this line to make it adjust the full scale signal
//scale = 8.0 + analogRead(A1) / 5.0;

// begin drawing at the first character on the 2nd row
lcd.setCursor(0, 1);
for (int i=0; i<16; i++) {
Serial.print(level[i]);

// TODO: conversion from FFT data to display bars should be
// exponentially scaled. But how keep it a simple example?
int val = level[i] * scale;
if (val > 8) val = 8;

if (val >= shown[i]) {
shown[i] = val;
} else {
if (shown[i] > 0) shown[i] = shown[i] - 1;
val = shown[i];
}

//Serial.print(shown[i]);
Serial.print(" ");

// print each custom digit
if (shown[i] == 0) {
lcd.write(' ');
} else {
lcd.write(shown[i] - 1);
}
}
Serial.print(" cpu:");
Serial.println(AudioProcessorUsageMax());
}
}



+ 202
- 0
examples/Effects/Bitcrusher/Bitcrusher.ino 查看文件

@@ -0,0 +1,202 @@
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>

// Bitcrusher example by Jonathan Payne (Pensive) jon@jonnypayne.com
// No rights reserved. Do what you like with it.

// Create the Audio components.
AudioPlaySdWav playWav1; //this will play a looping demo file
AudioOutputI2S headphones; // and it will come out of the headphone socket.

//Audio Effect BitCrusher defs here
AudioEffectBitcrusher left_BitCrusher;
AudioEffectBitcrusher right_BitCrusher;

// Create Audio connections between the components
AudioConnection patchCord1(playWav1, 0, left_BitCrusher, 0);
AudioConnection patchCord2(playWav1, 1, right_BitCrusher, 0);
AudioConnection patchCord3(left_BitCrusher, 0, headphones, 0);
AudioConnection patchCord4(right_BitCrusher, 0, headphones, 1);

// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;

// Bounce objects to read six pushbuttons (pins 0-5)
//
Bounce button0 = Bounce(0, 5); // cycles the bitcrusher through all bitdepths
Bounce button1 = Bounce(1, 5); //cycles the bitcrusher through some key samplerates
Bounce button2 = Bounce(2, 5); // turns on the compressor (or "Automatic Volume Leveling")

unsigned long SerialMillisecondCounter;

//BitCrusher
int current_CrushBits = 16; //this defaults to passthrough.
int current_SampleRate = 44100; // this defaults to passthrough.

//Compressor
boolean compressorOn = false; // default this to off.

void setup() {
// Configure the pushbutton pins for pullups.
// Each button should connect from the pin to GND.
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
Serial.begin(38400); // open the serial

// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(40); //this is WAY more tha nwe need

// turn on the output
audioShield.enable();
audioShield.volume(0.7);

// by default the Teensy 3.1 DAC uses 3.3Vp-p output
// if your 3.3V power has noise, switching to the
// internal 1.2V reference can give you a clean signal
//dac.analogReference(INTERNAL);

// reduce the gain on mixer channels, so more than 1
// sound can play simultaneously without clipping

//SDCard Initialise
SPI.setMOSI(7);
SPI.setSCK(14);
if (!(SD.begin(10))) {
// stop here, but print a message repetitively
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}
// Bitcrusher
left_BitCrusher.bits(current_CrushBits); //set the crusher to defaults. This will passthrough clean at 16,44100
left_BitCrusher.sampleRate(current_SampleRate); //set the crusher to defaults. This will passthrough clean at 16,44100
right_BitCrusher.bits(current_CrushBits); //set the crusher to defaults. This will passthrough clean at 16,44100
right_BitCrusher.sampleRate(current_SampleRate); //set the crusher to defaults. This will passthrough clean at 16,44100
//Bitcrusher


/* Valid values for dap_avc parameters

maxGain; Maximum gain that can be applied
0 - 0 dB
1 - 6.0 dB
2 - 12 dB
lbiResponse; Integrator Response
0 - 0 mS
1 - 25 mS
2 - 50 mS
3 - 100 mS
hardLimit
0 - Hard limit disabled. AVC Compressor/Expander enabled.
1 - Hard limit enabled. The signal is limited to the programmed threshold (signal saturates at the threshold)
threshold
floating point in range 0 to -96 dB
attack
floating point figure is dB/s rate at which gain is increased
decay
floating point figure is dB/s rate at which gain is reduced
*/
// Initialise the AutoVolumeLeveller
audioShield.autoVolumeControl(1, 1, 0, -6, 40, 20); // **BUG** with a max gain of 0, turning the AVC off leaves a hung AVC problem where the attack seems to hang in a loop. with it set 1 or 2, this does not occur.
audioShield.autoVolumeDisable();
audioShield.audioPostProcessorEnable();

SerialMillisecondCounter = millis();
}

int val; //temporary variable for memory usage reporting.

void loop() {

if (millis() - SerialMillisecondCounter >= 5000) {
Serial.print("Proc = ");
Serial.print(AudioProcessorUsage());
Serial.print(" (");
Serial.print(AudioProcessorUsageMax());
Serial.print("), Mem = ");
Serial.print(AudioMemoryUsage());
Serial.print(" (");
Serial.print(AudioMemoryUsageMax());
Serial.println(")");
SerialMillisecondCounter = millis();
AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset();
}


// Update all the button objects
button0.update();
button1.update();
button2.update();

// Start test sound if it is not playing. This will loop infinitely.
if (! (playWav1.isPlaying())){
playWav1.play("SDTEST1.WAV"); // http://www.pjrc.com/teensy/td_libs_AudioDataFiles.html
}

if (button0.fallingEdge()) {
//Bitcrusher BitDepth
if (current_CrushBits >= 2) { //eachtime you press it, deduct 1 bit from the settings.
current_CrushBits--;
} else {
current_CrushBits = 16; // if you get down to 1 go back to the top.
}

left_BitCrusher.bits(current_CrushBits);
left_BitCrusher.sampleRate(current_SampleRate);
right_BitCrusher.bits(current_CrushBits);
right_BitCrusher.sampleRate(current_SampleRate);
Serial.print("Bitcrusher set to ");
Serial.print(current_CrushBits);
Serial.print(" Bit, Samplerate at ");
Serial.print(current_SampleRate);
Serial.println("Hz");
}

if (button1.fallingEdge()) {
//Bitcrusher SampleRate // the lowest sensible setting is 345. There is a 128 sample buffer, and this will copy sample 1, to each of the other 127 samples.
if (current_SampleRate >= 690) { // 345 * 2, so we can do one more divide
current_SampleRate = current_SampleRate / 2; // half the sample rate each time
} else {
current_SampleRate=44100; // if you get down to the minimum then go back to the top and start over.
}

left_BitCrusher.bits(current_CrushBits);
left_BitCrusher.sampleRate(current_SampleRate);
right_BitCrusher.bits(current_CrushBits);
right_BitCrusher.sampleRate(current_SampleRate);
Serial.print("Bitcrusher set to ");
Serial.print(current_CrushBits);
Serial.print(" Bit, Samplerate at ");
Serial.print(current_SampleRate);
Serial.println("Hz");
}

if (button2.fallingEdge()) {
if (compressorOn) {
//turn off compressor
audioShield.autoVolumeDisable();
compressorOn = false;
} else {
//turn on compressor
audioShield.autoVolumeEnable();
compressorOn = true;
}
Serial.print("Compressor: ");
Serial.println(compressorOn);
}
}


+ 186
- 0
examples/Effects/Chorus/Chorus.ino 查看文件

@@ -0,0 +1,186 @@
/*
VERSION 2 - use modified library which has been changed to handle
one channel instead of two
140529
Proc = 7 (7), Mem = 4 (4)
2a
- default at startup is to have passthru ON and the button
switches the chorus effect in.
previous performance measures were PROC/MEM 9/4

From: http://www.cs.cf.ac.uk/Dave/CM0268/PDF/10_CM0268_Audio_FX.pdf
about Comb filter effects
Effect Delay range (ms) Modulation
Resonator 0 - 20 None
Flanger 0 - 15 Sinusoidal (approx 1Hz)
Chorus 25 - 50 None
Echo >50 None

FMI:
The audio board uses the following pins.
6 - MEMCS
7 - MOSI
9 - BCLK
10 - SDCS
11 - MCLK
12 - MISO
13 - RX
14 - SCLK
15 - VOL
18 - SDA
19 - SCL
22 - TX
23 - LRCLK


AudioProcessorUsage()
AudioProcessorUsageMax()
AudioProcessorUsageMaxReset()
AudioMemoryUsage()
AudioMemoryUsageMax()
AudioMemoryUsageMaxReset()

The CPU usage is an integer from 0 to 100, and the memory is from 0 to however
many blocks you provided with AudioMemory().

*/

#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include <SerialFlash.h>
#include <Bounce.h>



// Number of samples in each delay line
#define CHORUS_DELAY_LENGTH (16*AUDIO_BLOCK_SAMPLES)
// Allocate the delay lines for left and right channels
short l_delayline[CHORUS_DELAY_LENGTH];
short r_delayline[CHORUS_DELAY_LENGTH];

// Default is to just pass the audio through. Grounding this pin
// applies the chorus effect
// Don't use any of the pins listed above
#define PASSTHRU_PIN 1

Bounce b_passthru = Bounce(PASSTHRU_PIN,15);

//const int myInput = AUDIO_INPUT_MIC;
const int myInput = AUDIO_INPUT_LINEIN;

AudioInputI2S audioInput; // audio shield: mic or line-in
AudioEffectChorus l_myEffect;
AudioEffectChorus r_myEffect;
AudioOutputI2S audioOutput; // audio shield: headphones & line-out

// Create Audio connections between the components
// Both channels of the audio input go to the chorus effect
AudioConnection c1(audioInput, 0, l_myEffect, 0);
AudioConnection c2(audioInput, 1, r_myEffect, 0);
// both channels chorus effects go to the audio output
AudioConnection c3(l_myEffect, 0, audioOutput, 0);
AudioConnection c4(r_myEffect, 0, audioOutput, 1);

AudioControlSGTL5000 audioShield;


// number of "voices" in the chorus which INCLUDES the original voice
int n_chorus = 2;

// <<<<<<<<<<<<<<>>>>>>>>>>>>>>>>
void setup() {
Serial.begin(9600);
while (!Serial) ;
delay(3000);

pinMode(PASSTHRU_PIN,INPUT_PULLUP);

// Maximum memory usage was reported as 4
// Proc = 9 (9), Mem = 4 (4)
AudioMemory(4);

audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(0.65);
// Warn that the passthru pin is grounded
if(!digitalRead(PASSTHRU_PIN)) {
Serial.print("PASSTHRU_PIN (");
Serial.print(PASSTHRU_PIN);
Serial.println(") is grounded");
}

// Initialize the effect - left channel
// address of delayline
// total number of samples in the delay line
// number of voices in the chorus INCLUDING the original voice
if(!l_myEffect.begin(l_delayline,CHORUS_DELAY_LENGTH,n_chorus)) {
Serial.println("AudioEffectChorus - left channel begin failed");
while(1);
}

// Initialize the effect - right channel
// address of delayline
// total number of samples in the delay line
// number of voices in the chorus INCLUDING the original voice
if(!r_myEffect.begin(r_delayline,CHORUS_DELAY_LENGTH,n_chorus)) {
Serial.println("AudioEffectChorus - left channel begin failed");
while(1);
}
// Initially the effect is off. It is switched on when the
// PASSTHRU button is pushed.
l_myEffect.voices(0);
r_myEffect.voices(0);

Serial.println("setup done");
AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset();
}


// audio volume
int volume = 0;

unsigned long last_time = millis();
void loop()
{
// Volume control
int n = analogRead(15);
if (n != volume) {
volume = n;
audioShield.volume((float)n / 1023);
}
if(0) {
if(millis() - last_time >= 5000) {
Serial.print("Proc = ");
Serial.print(AudioProcessorUsage());
Serial.print(" (");
Serial.print(AudioProcessorUsageMax());
Serial.print("), Mem = ");
Serial.print(AudioMemoryUsage());
Serial.print(" (");
Serial.print(AudioMemoryUsageMax());
Serial.println(")");
last_time = millis();
}
}
// update the button
b_passthru.update();
// If the passthru button is pushed, switch the chorus on
if(b_passthru.fallingEdge()) {
l_myEffect.voices(n_chorus);
r_myEffect.voices(n_chorus);
}
// If passthru button is released, turn on passthru
if(b_passthru.risingEdge()) {
l_myEffect.voices(0);
r_myEffect.voices(0);
}

}

+ 54
- 0
examples/Effects/Chorus/effects_info.h 查看文件

@@ -0,0 +1,54 @@
/*
CHORUS and FLANGE effects
Both effects use a delay line to hold previous samples. This allows
the current sample to be combined in some way with a sample that
occurred in the past. An obvious effect this would allow would be
an echo where the current sample is combined with a sample from,
say, 250 milliseconds ago. The chorus and flange effects do this
as well but they combine samples from only about 50ms (or less) ago.
CHORUS EFFECT
This combines one or more samples up to about 50ms ago. In this
library, the additional samples are evenly spread through the
supplied delay line.
E.G. If the number of voices is specified as 2 then the effect
combines the current sample and the oldest sample (the last one in
the delay line). If the number of voices is 3 then the effect
combines the most recent sample, the oldest sample and the sample
in the middle of the delay line.
For two voices the effect can be represented as:
result = (sample(0) + sample(dt))/2
where sample(0) represents the current sample and sample(dt) is
the sample in the delay line from dt milliseconds ago.

FLANGE EFFECT
This combines only one sample from the delay line but the position
of that sample varies sinusoidally.
In this case the effect can be represented as:
result = sample(0) + sample(dt + depth*sin(2*PI*Fe))
The value of the sine function is always a number from -1 to +1
and so the result of depth*(sinFe) is always a number from
-depth to +depth. Thus, the delayed sample will be selected from
the range (dt-depth) to (dt+depth). This selection will vary
at whatever rate is specified as the frequency of the effect Fe.

Try these settings:
#define FLANGE_DELAY_LENGTH (2*AUDIO_BLOCK_SAMPLES)
and
int s_idx = 2*FLANGE_DELAY_LENGTH/4;
int s_depth = FLANGE_DELAY_LENGTH/4;
double s_freq = 3;
The flange effect can also produce a chorus effect if a longer
delay line is used with a slower rate, for example try:
#define FLANGE_DELAY_LENGTH (12*AUDIO_BLOCK_SAMPLES)
and
int s_idx = 3*FLANGE_DELAY_LENGTH/4;
int s_depth = FLANGE_DELAY_LENGTH/8;
double s_freq = .0625;

When trying out these effects with recorded music as input, it is
best to use those where there is a solo voice which is clearly
"in front" of the accompaniment. Tracks which already contain
flange or chorus effects don't work well.
*/

+ 61
- 0
examples/Effects/Delay/Delay.ino 查看文件

@@ -0,0 +1,61 @@
// Delay demonstration example, Teensy Audio Library
// http://www.pjrc.com/teensy/td_libs_Audio.html
//
// Creates a chirp on the left channel, then
// three delayed copies on the right channel.
//
// Requires the audio shield:
// http://www.pjrc.com/store/teensy3_audio.html
//
// This example code is in the public domain.

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthWaveformSine sine1; //xy=158,74
AudioEffectEnvelope envelope1; //xy=232,156
AudioEffectDelay delay1; //xy=393,238
AudioMixer4 mixer1; //xy=532,205
AudioOutputI2S i2s1; //xy=611,61
AudioConnection patchCord1(sine1, envelope1);
AudioConnection patchCord2(envelope1, delay1);
AudioConnection patchCord3(envelope1, 0, i2s1, 0);
AudioConnection patchCord4(delay1, 0, mixer1, 0);
AudioConnection patchCord5(delay1, 1, mixer1, 1);
AudioConnection patchCord6(delay1, 2, mixer1, 2);
AudioConnection patchCord7(delay1, 3, mixer1, 3);
AudioConnection patchCord8(mixer1, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=195,272
// GUItool: end automatically generated code

void setup() {
// allocate enough memory for the delay
AudioMemory(120);
// enable the audio shield
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);
// configure a sine wave for the chirp
// the original is turned on/off by an envelope effect
// and output directly on the left channel
sine1.frequency(1000);
sine1.amplitude(0.5);

// create 3 delay taps, which connect through a
// mixer to the right channel output
delay1.delay(0, 110);
delay1.delay(1, 220);
delay1.delay(2, 330);
}

void loop() {
envelope1.noteOn();
delay(36);
envelope1.noteOff();
delay(4000);
}

+ 42
- 0
examples/Effects/Filter/Filter.ino 查看文件

@@ -0,0 +1,42 @@
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S i2s1; //xy=99,60
AudioFilterBiquad biquad1; //xy=257,60
AudioOutputI2S i2s2; //xy=416,60
AudioConnection patchCord1(i2s1, 0, biquad1, 0);
AudioConnection patchCord2(biquad1, 0, i2s2, 0);
AudioConnection patchCord3(biquad1, 0, i2s2, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=305,132
// GUItool: end automatically generated code


const int myInput = AUDIO_INPUT_LINEIN;
//const int myInput = AUDIO_INPUT_MIC;

void setup() {
AudioMemory(12);

sgtl5000_1.enable(); // Enable the audio shield
sgtl5000_1.inputSelect(myInput);
sgtl5000_1.volume(0.5);

// Butterworth filter, 12 db/octave
biquad1.setLowpass(0, 800, 0.707);

// Linkwitz-Riley filter, 48 dB/octave
//biquad1.setLowpass(0, 800, 0.54);
//biquad1.setLowpass(1, 800, 1.3);
//biquad1.setLowpass(2, 800, 0.54);
//biquad1.setLowpass(3, 800, 1.3);
}


void loop() {
}



+ 175
- 0
examples/Effects/Filter_FIR/Filter_FIR.ino 查看文件

@@ -0,0 +1,175 @@
/*
c
- released
b
- Use FIR filters with fast_fft option

The audio board uses the following pins.
6 - MEMCS
7 - MOSI
9 - BCLK
10 - SDCS
11 - MCLK
12 - MISO
13 - RX
14 - SCLK
15 - VOL
18 - SDA
19 - SCL
22 - TX
23 - LRCLK
*/

//#include <arm_math.h>
#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include <SerialFlash.h>
#include <Bounce.h>
#include "filters.h"

// If this pin is grounded the FIR filter is turned off
// which just passes the audio sraight through
// Don't use any of the pins listed above
#define PASSTHRU_PIN 1
// If this pin goes low the next FIR filter in the list
// is switched in.
#define FILTER_PIN 0

// debounce the passthru and filter switching pins
Bounce b_passthru = Bounce(PASSTHRU_PIN,15);
Bounce b_filter = Bounce(FILTER_PIN,15);

//const int myInput = AUDIO_INPUT_MIC;
const int myInput = AUDIO_INPUT_LINEIN;


AudioInputI2S audioInput; // audio shield: mic or line-in
AudioFilterFIR myFilterL;
AudioFilterFIR myFilterR;
AudioOutputI2S audioOutput; // audio shield: headphones & line-out

// Create Audio connections between the components
// Route audio into the left and right filters
AudioConnection c1(audioInput, 0, myFilterL, 0);
AudioConnection c2(audioInput, 1, myFilterR, 0);
// Route the output of the filters to their respective channels
AudioConnection c3(myFilterL, 0, audioOutput, 0);
AudioConnection c4(myFilterR, 0, audioOutput, 1);
AudioControlSGTL5000 audioShield;


struct fir_filter {
short *coeffs;
short num_coeffs;
};

// index of current filter. Start with the low pass.
int fir_idx = 0;
struct fir_filter fir_list[] = {
{low_pass , 100}, // low pass with cutoff at 1kHz and -60dB at 2kHz
{band_pass, 100}, // bandpass 1200Hz - 1700Hz
{NULL, 0}
};


void setup() {
Serial.begin(9600);
delay(300);

pinMode(PASSTHRU_PIN, INPUT_PULLUP);
pinMode(FILTER_PIN, INPUT_PULLUP);

// allocate memory for the audio library
AudioMemory(8);

audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(0.5);
// Warn that the passthru pin is grounded
if(!digitalRead(PASSTHRU_PIN)) {
Serial.print("PASSTHRU_PIN (");
Serial.print(PASSTHRU_PIN);
Serial.println(") is grounded");
}

// Warn that the filter pin is grounded
if(!digitalRead(FILTER_PIN)) {
Serial.print("FILTER_PIN (");
Serial.print(FILTER_PIN);
Serial.println(") is grounded");
}
// Initialize the filter
myFilterL.begin(fir_list[0].coeffs, fir_list[0].num_coeffs);
myFilterR.begin(fir_list[0].coeffs, fir_list[0].num_coeffs);
Serial.println("setup done");
}

// index of current filter when passthrough is selected
int old_idx = -1;

// audio volume
int volume = 0;
unsigned long last_time = millis();

void loop()
{
// Volume control
int n = analogRead(15);
if (n != volume) {
volume = n;
//uncomment this line if your audio shield has the volume pot
//audioShield.volume((float)n / 1023);
}
// update the two buttons
b_passthru.update();
b_filter.update();
// If the passthru button is pushed, save the current
// filter index and then switch the filter to passthru
if (b_passthru.fallingEdge()) {
old_idx = fir_idx;
myFilterL.begin(FIR_PASSTHRU, 0);
myFilterR.begin(FIR_PASSTHRU, 0);
}
// If passthru button is released, restore previous filter
if (b_passthru.risingEdge()) {
if(old_idx != -1) {
myFilterL.begin(fir_list[fir_idx].coeffs, fir_list[fir_idx].num_coeffs);
myFilterR.begin(fir_list[fir_idx].coeffs, fir_list[fir_idx].num_coeffs);
}
old_idx = -1;
}
// switch to next filter in the list
if (b_filter.fallingEdge()) {
fir_idx++;
if (fir_list[fir_idx].num_coeffs == 0) fir_idx = 0;
myFilterL.begin(fir_list[fir_idx].coeffs, fir_list[fir_idx].num_coeffs);
myFilterR.begin(fir_list[fir_idx].coeffs, fir_list[fir_idx].num_coeffs);
}

// print information about resource usage
// Proc = 18 (18), Mem = 4 (5)
if (millis() - last_time >= 2500) {
Serial.print("Proc = ");
Serial.print(AudioProcessorUsage());
Serial.print(" (");
Serial.print(AudioProcessorUsageMax());
Serial.print("), Mem = ");
Serial.print(AudioMemoryUsage());
Serial.print(" (");
Serial.print(AudioMemoryUsageMax());
Serial.println(")");
last_time = millis();
}


}




+ 108
- 0
examples/Effects/Filter_FIR/bandp_1200_1700.h 查看文件

@@ -0,0 +1,108 @@

/* .fir file parameters which generated these coefficients
100 1 3 16 32768 44100
0 500 1200 1700 2300
0.0000 1.0000 0.0000
70.0000 1.0000 70.0000
*/
(short)0xFFAA,
(short)0xFFC5,
(short)0xFFB6,
(short)0xFFA7,
(short)0xFF9B,
(short)0xFF94,
(short)0xFF93,
(short)0xFF9A,
(short)0xFFAA,
(short)0xFFC4,
(short)0xFFE9,
(short)0x0017,
(short)0x004F,
(short)0x008E,
(short)0x00D1,
(short)0x0115,
(short)0x0155,
(short)0x018F,
(short)0x01BC,
(short)0x01D9,
(short)0x01E2,
(short)0x01D3,
(short)0x01AB,
(short)0x0168,
(short)0x010A,
(short)0x0095,
(short)0x000B,
(short)0xFF72,
(short)0xFED1,
(short)0xFE2E,
(short)0xFD92,
(short)0xFD06,
(short)0xFC92,
(short)0xFC3D,
(short)0xFC0D,
(short)0xFC08,
(short)0xFC30,
(short)0xFC85,
(short)0xFD06,
(short)0xFDAF,
(short)0xFE79,
(short)0xFF5C,
(short)0x004D,
(short)0x0143,
(short)0x0231,
(short)0x030D,
(short)0x03CB,
(short)0x0463,
(short)0x04CC,
(short)0x0502,
(short)0x0502,
(short)0x04CC,
(short)0x0463,
(short)0x03CB,
(short)0x030D,
(short)0x0231,
(short)0x0143,
(short)0x004D,
(short)0xFF5C,
(short)0xFE79,
(short)0xFDAF,
(short)0xFD06,
(short)0xFC85,
(short)0xFC30,
(short)0xFC08,
(short)0xFC0D,
(short)0xFC3D,
(short)0xFC92,
(short)0xFD06,
(short)0xFD92,
(short)0xFE2E,
(short)0xFED1,
(short)0xFF72,
(short)0x000B,
(short)0x0095,
(short)0x010A,
(short)0x0168,
(short)0x01AB,
(short)0x01D3,
(short)0x01E2,
(short)0x01D9,
(short)0x01BC,
(short)0x018F,
(short)0x0155,
(short)0x0115,
(short)0x00D1,
(short)0x008E,
(short)0x004F,
(short)0x0017,
(short)0xFFE9,
(short)0xFFC4,
(short)0xFFAA,
(short)0xFF9A,
(short)0xFF93,
(short)0xFF94,
(short)0xFF9B,
(short)0xFFA7,
(short)0xFFB6,
(short)0xFFC5,
(short)0xFFAA,


+ 8
- 0
examples/Effects/Filter_FIR/filters.cpp 查看文件

@@ -0,0 +1,8 @@
#include "filters.h"
short low_pass[NUM_COEFFS] = {
#include "lopass_1000_44100.h"
};

short band_pass[NUM_COEFFS] = {
#include "bandp_1200_1700.h"
};

+ 5
- 0
examples/Effects/Filter_FIR/filters.h 查看文件

@@ -0,0 +1,5 @@
// Number of coefficients
#define NUM_COEFFS 100
extern short low_pass[];
extern short band_pass[];


+ 109
- 0
examples/Effects/Filter_FIR/lopass_1000_44100.h 查看文件

@@ -0,0 +1,109 @@

/* .fir file parameters which generated these coefficients
100 1 2 16 32768 44100
0 1000 2000
1.0000 0.0000
1.0000 70.0000
*/
(short)0x0015,
(short)0x0011,
(short)0x0017,
(short)0x001E,
(short)0x0025,
(short)0x002C,
(short)0x0032,
(short)0x0037,
(short)0x003B,
(short)0x003C,
(short)0x003B,
(short)0x0036,
(short)0x002E,
(short)0x0021,
(short)0x000F,
(short)0xFFF9,
(short)0xFFDE,
(short)0xFFBF,
(short)0xFF9C,
(short)0xFF76,
(short)0xFF4F,
(short)0xFF27,
(short)0xFF02,
(short)0xFEDF,
(short)0xFEC2,
(short)0xFEAC,
(short)0xFEA0,
(short)0xFE9F,
(short)0xFEAC,
(short)0xFEC8,
(short)0xFEF4,
(short)0xFF31,
(short)0xFF7F,
(short)0xFFDF,
(short)0x0050,
(short)0x00D0,
(short)0x015E,
(short)0x01F8,
(short)0x029A,
(short)0x0341,
(short)0x03EA,
(short)0x0491,
(short)0x0532,
(short)0x05CA,
(short)0x0653,
(short)0x06CC,
(short)0x0731,
(short)0x077F,
(short)0x07B4,
(short)0x07CF,
(short)0x07CF,
(short)0x07B4,
(short)0x077F,
(short)0x0731,
(short)0x06CC,
(short)0x0653,
(short)0x05CA,
(short)0x0532,
(short)0x0491,
(short)0x03EA,
(short)0x0341,
(short)0x029A,
(short)0x01F8,
(short)0x015E,
(short)0x00D0,
(short)0x0050,
(short)0xFFDF,
(short)0xFF7F,
(short)0xFF31,
(short)0xFEF4,
(short)0xFEC8,
(short)0xFEAC,
(short)0xFE9F,
(short)0xFEA0,
(short)0xFEAC,
(short)0xFEC2,
(short)0xFEDF,
(short)0xFF02,
(short)0xFF27,
(short)0xFF4F,
(short)0xFF76,
(short)0xFF9C,
(short)0xFFBF,
(short)0xFFDE,
(short)0xFFF9,
(short)0x000F,
(short)0x0021,
(short)0x002E,
(short)0x0036,
(short)0x003B,
(short)0x003C,
(short)0x003B,
(short)0x0037,
(short)0x0032,
(short)0x002C,
(short)0x0025,
(short)0x001E,
(short)0x0017,
(short)0x0011,
(short)0x0015,



二進制
examples/Effects/Filter_FIR/screencap_bandpass.jpg 查看文件

Before After
Width: 650  |  Height: 250  |  Size: 28KB

二進制
examples/Effects/Filter_FIR/screencap_lowpass.jpg 查看文件

Before After
Width: 651  |  Height: 248  |  Size: 30KB

+ 179
- 0
examples/Effects/Flange/Flange.ino 查看文件

@@ -0,0 +1,179 @@
/*
VERSION 2 - use modified library which has been changed to handle
one channel instead of two
Proc = 21 (22), Mem = 4 (6)
140529
2a
- default at startup is to have passthru ON and the button
switches the flange effect in.

From: http://www.cs.cf.ac.uk/Dave/CM0268/PDF/10_CM0268_Audio_FX.pdf
about Comb filter effects
Effect Delay range (ms) Modulation
Resonator 0 - 20 None
Flanger 0 - 15 Sinusoidal (approx 1Hz)
Chorus 25 - 50 None
Echo >50 None

FMI:
The audio board uses the following pins.
6 - MEMCS
7 - MOSI
9 - BCLK
10 - SDCS
11 - MCLK
12 - MISO
13 - RX
14 - SCLK
15 - VOL
18 - SDA
19 - SCL
22 - TX
23 - LRCLK


AudioProcessorUsage()
AudioProcessorUsageMax()
AudioProcessorUsageMaxReset()
AudioMemoryUsage()
AudioMemoryUsageMax()
AudioMemoryUsageMaxReset()

The CPU usage is an integer from 0 to 100, and the memory is from 0 to however
many blocks you provided with AudioMemory().


*/

#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include <SerialFlash.h>
#include <Bounce.h>

// Number of samples in each delay line
#define FLANGE_DELAY_LENGTH (6*AUDIO_BLOCK_SAMPLES)
// Allocate the delay lines for left and right channels
short l_delayline[FLANGE_DELAY_LENGTH];
short r_delayline[FLANGE_DELAY_LENGTH];

// Default is to just pass the audio through. Grounding this pin
// applies the flange effect
// Don't use any of the pins listed above
#define PASSTHRU_PIN 1

Bounce b_passthru = Bounce(PASSTHRU_PIN,15);

//const int myInput = AUDIO_INPUT_MIC;
const int myInput = AUDIO_INPUT_LINEIN;

AudioInputI2S audioInput; // audio shield: mic or line-in
AudioEffectFlange l_myEffect;
AudioEffectFlange r_myEffect;
AudioOutputI2S audioOutput; // audio shield: headphones & line-out

// Create Audio connections between the components
// Both channels of the audio input go to the flange effect
AudioConnection c1(audioInput, 0, l_myEffect, 0);
AudioConnection c2(audioInput, 1, r_myEffect, 0);
// both channels from the flange effect go to the audio output
AudioConnection c3(l_myEffect, 0, audioOutput, 0);
AudioConnection c4(r_myEffect, 0, audioOutput, 1);

AudioControlSGTL5000 audioShield;


int s_idx = FLANGE_DELAY_LENGTH/4;
int s_depth = FLANGE_DELAY_LENGTH/4;
double s_freq = .5;
void setup() {
Serial.begin(9600);
while (!Serial) ;
delay(3000);

pinMode(PASSTHRU_PIN,INPUT_PULLUP);

// It doesn't work properly with any less than 8
// but that was an earlier version. Processor and
// memory usage are now (ver j)
// Proc = 24 (24), Mem = 4 (4)
AudioMemory(8);

audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(0.5);
// Warn that the passthru pin is grounded
if(!digitalRead(PASSTHRU_PIN)) {
Serial.print("PASSTHRU_PIN (");
Serial.print(PASSTHRU_PIN);
Serial.println(") is grounded");
}

// Set up the flange effect:
// address of delayline
// total number of samples in the delay line
// Index (in samples) into the delay line for the added voice
// Depth of the flange effect
// frequency of the flange effect
l_myEffect.begin(l_delayline,FLANGE_DELAY_LENGTH,s_idx,s_depth,s_freq);
r_myEffect.begin(r_delayline,FLANGE_DELAY_LENGTH,s_idx,s_depth,s_freq);
// Initially the effect is off. It is switched on when the
// PASSTHRU button is pushed.
l_myEffect.voices(FLANGE_DELAY_PASSTHRU,0,0);
r_myEffect.voices(FLANGE_DELAY_PASSTHRU,0,0);
Serial.println("setup done");
AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset();
}


// audio volume
int volume = 0;

unsigned long last_time = millis();
void loop()
{
// Volume control
int n = analogRead(15);
if (n != volume) {
volume = n;
audioShield.volume((float)n / 10.23);
}
if(0) {
if(millis() - last_time >= 5000) {
Serial.print("Proc = ");
Serial.print(AudioProcessorUsage());
Serial.print(" (");
Serial.print(AudioProcessorUsageMax());
Serial.print("), Mem = ");
Serial.print(AudioMemoryUsage());
Serial.print(" (");
Serial.print(AudioMemoryUsageMax());
Serial.println(")");
last_time = millis();
}
}
// update the button
b_passthru.update();
// If the passthru button is pushed
// turn the flange effect on
// filter index and then switch the effect to passthru
if(b_passthru.fallingEdge()) {
l_myEffect.voices(s_idx,s_depth,s_freq);
r_myEffect.voices(s_idx,s_depth,s_freq);
}
// If passthru button is released restore passthru
if(b_passthru.risingEdge()) {
l_myEffect.voices(FLANGE_DELAY_PASSTHRU,0,0);
r_myEffect.voices(FLANGE_DELAY_PASSTHRU,0,0);
}

}

+ 54
- 0
examples/Effects/Flange/effects_info.h 查看文件

@@ -0,0 +1,54 @@
/*
CHORUS and FLANGE effects
Both effects use a delay line to hold previous samples. This allows
the current sample to be combined in some way with a sample that
occurred in the past. An obvious effect this would allow would be
an echo where the current sample is combined with a sample from,
say, 250 milliseconds ago. The chorus and flange effects do this
as well but they combine samples from only about 50ms (or less) ago.
CHORUS EFFECT
This combines one or more samples up to about 50ms ago. In this
library, the additional samples are evenly spread through the
supplied delay line.
E.G. If the number of voices is specified as 2 then the effect
combines the current sample and the oldest sample (the last one in
the delay line). If the number of voices is 3 then the effect
combines the most recent sample, the oldest sample and the sample
in the middle of the delay line.
For two voices the effect can be represented as:
result = (sample(0) + sample(dt))/2
where sample(0) represents the current sample and sample(dt) is
the sample in the delay line from dt milliseconds ago.

FLANGE EFFECT
This combines only one sample from the delay line but the position
of that sample varies sinusoidally.
In this case the effect can be represented as:
result = sample(0) + sample(dt + depth*sin(2*PI*Fe))
The value of the sine function is always a number from -1 to +1
and so the result of depth*(sinFe) is always a number from
-depth to +depth. Thus, the delayed sample will be selected from
the range (dt-depth) to (dt+depth). This selection will vary
at whatever rate is specified as the frequency of the effect Fe.

Try these settings:
#define FLANGE_DELAY_LENGTH (2*AUDIO_BLOCK_SAMPLES)
and
int s_idx = 2*FLANGE_DELAY_LENGTH/4;
int s_depth = FLANGE_DELAY_LENGTH/4;
double s_freq = 3;
The flange effect can also produce a chorus effect if a longer
delay line is used with a slower rate, for example try:
#define FLANGE_DELAY_LENGTH (12*AUDIO_BLOCK_SAMPLES)
and
int s_idx = 3*FLANGE_DELAY_LENGTH/4;
int s_depth = FLANGE_DELAY_LENGTH/8;
double s_freq = .0625;

When trying out these effects with recorded music as input, it is
best to use those where there is a solo voice which is clearly
"in front" of the accompaniment. Tracks which already contain
flange or chorus effects don't work well.
*/

+ 0
- 50
examples/FFT/FFT.ino 查看文件

@@ -1,50 +0,0 @@
#include <Audio.h>
#include <Wire.h>
#include <SD.h>

const int myInput = AUDIO_INPUT_LINEIN;
//const int myInput = AUDIO_INPUT_MIC;

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//
AudioInputI2S audioInput; // audio shield: mic or line-in
AudioAnalyzeFFT256 myFFT(20);
AudioOutputI2S audioOutput; // audio shield: headphones & line-out

// Create Audio connections between the components
//
AudioConnection c1(audioInput, 0, audioOutput, 0);
AudioConnection c2(audioInput, 0, myFFT, 0);
AudioConnection c3(audioInput, 1, audioOutput, 1);

// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;


void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(12);

// Enable the audio shield and set the output volume.
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(60);
}

void loop() {
if (myFFT.available()) {
// each time new FFT data is available
// print it all to the Arduino Serial Monitor
Serial.print("FFT: ");
for (int i=0; i<128; i++) {
Serial.print(myFFT.output[i]);
Serial.print(",");
}
Serial.println();
}
}



+ 0
- 53
examples/Filter/Filter.ino 查看文件

@@ -1,53 +0,0 @@
#include <Audio.h>
#include <Wire.h>
#include <SD.h>

const int myInput = AUDIO_INPUT_LINEIN;
//const int myInput = AUDIO_INPUT_MIC;

// each filter requires a set up parameters
int myFilterParameters[] = { // lowpass, Fc=800 Hz, Q=0.707
3224322, 6448644, 3224322, 1974735214, -913890679, 0, 0, 0};

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//
AudioInputI2S audioInput; // audio shield: mic or line-in
AudioFilterBiquad myFilter(myFilterParameters);
AudioOutputI2S audioOutput; // audio shield: headphones & line-out

// Create Audio connections between the components
//
AudioConnection c1(audioInput, 0, audioOutput, 0);
AudioConnection c2(audioInput, 0, myFilter, 0);
AudioConnection c3(myFilter, 0, audioOutput, 1);

// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;


void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(12);

// Enable the audio shield and set the output volume.
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(60);
}

elapsedMillis volmsec=0;

void loop() {
// every 50 ms, adjust the volume
if (volmsec > 50) {
float vol = analogRead(15);
vol = vol / 10.24;
audioShield.volume(vol);
volmsec = 0;
}
}



+ 34
- 0
examples/HardwareTesting/PassThroughMono/PassThroughMono.ino 查看文件

@@ -0,0 +1,34 @@
/*
* A simple hardware test which receives audio on the A2 analog pin
* and sends it to the PWM (pin 3) output and DAC (A14 pin) output.
*
* This example code is in the public domain.
*/

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputAnalog adc1; //xy=161,80
AudioOutputAnalog dac1; //xy=329,47
AudioOutputPWM pwm1; //xy=331,125
AudioConnection patchCord1(adc1, dac1);
AudioConnection patchCord2(adc1, pwm1);
// GUItool: end automatically generated code

void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(12);
}

void loop() {
// Do nothing here. The Audio flows automatically

// When AudioInputAnalog is running, analogRead() must NOT be used.
}



+ 50
- 0
examples/HardwareTesting/PassThroughStereo/PassThroughStereo.ino 查看文件

@@ -0,0 +1,50 @@
/*
* A simple hardware test which receives audio from the audio shield
* Line-In pins and send it to the Line-Out pins and headphone jack.
*
* This example code is in the public domain.
*/

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S i2s1; //xy=200,69
AudioOutputI2S i2s2; //xy=365,94
AudioConnection patchCord1(i2s1, 0, i2s2, 0);
AudioConnection patchCord2(i2s1, 1, i2s2, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=302,184
// GUItool: end automatically generated code


const int myInput = AUDIO_INPUT_LINEIN;
//const int myInput = AUDIO_INPUT_MIC;


void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(12);

// Enable the audio shield, select input, and enable output
sgtl5000_1.enable();
sgtl5000_1.inputSelect(myInput);
sgtl5000_1.volume(0.5);
}

elapsedMillis volmsec=0;

void loop() {
// every 50 ms, adjust the volume
if (volmsec > 50) {
float vol = analogRead(15);
vol = vol / 1023.0;
//audioShield.volume(vol); // <-- uncomment if you have the optional
volmsec = 0; // volume pot on your audio shield
}
}



+ 66
- 0
examples/HardwareTesting/SGTL5000/CalcBiquadToneControlDAP/CalcBiquadToneControlDAP.ino 查看文件

@@ -0,0 +1,66 @@
/* Tone example using SGTL5000 DAP PEQ filters and calcBiquad filter calculator routine.

This example code is in the public domain
*/
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

const int myInput = AUDIO_INPUT_LINEIN;
// const int myInput = AUDIO_INPUT_MIC;

int updateFilter[5];
AudioInputI2S audioInput; // audio shield: mic or line-in
AudioOutputI2S audioOutput; // audio shield: headphones & line-out

// Create Audio connections between the components
//
AudioConnection c1(audioInput, 0, audioOutput, 0); // left passing through
AudioConnection c2(audioInput, 1, audioOutput, 1); // right passing through

// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;

void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(4);
// Enable the audio shield, select the input and set the output volume.
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(0.5);
audioShield.audioPostProcessorEnable(); // enable the DAP block in SGTL5000
// audioShield.eqSelect(1); // using PEQ Biquad filters
// audioShield.eqFilterCount(2); // enable filter 0 & filter 1
calcBiquad(FILTER_PARAEQ,110,0,0.2,524288,44100,updateFilter); // automation negates the need
audioShield.eqFilter(0,updateFilter); // for the three lines commented out above.
calcBiquad(FILTER_PARAEQ,4400,0,0.167,524288,44100,updateFilter);
audioShield.eqFilter(1,updateFilter);
}

elapsedMillis chgMsec=0;
float tone1=0;

void loop() {
// every 10 ms, check for adjustment
if (chgMsec > 10) {
float tone2=analogRead(15);
tone2=floor(((tone2-512)/512)*70)/10;
if(tone2!=tone1)
{
// calcBiquad(FilterType,FrequencyC,dBgain,Q,QuantizationUnit,SampleRate,int*);
calcBiquad(FILTER_PARAEQ,110,-tone2,0.2,524288,44100,updateFilter);
audioShield.eqFilter(0,updateFilter);
calcBiquad(FILTER_PARAEQ,4400,tone2,0.167,524288,44100,updateFilter);
audioShield.eqFilter(1,updateFilter);
tone1=tone2;
}
chgMsec = 0;
}
}


+ 66
- 0
examples/HardwareTesting/SGTL5000/balanceDAC/balanceDAC.ino 查看文件

@@ -0,0 +1,66 @@
/* DAC balance example: Will influence both HP & LO outputs.

This example code is in the public domain
*/

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>


const int myInput = AUDIO_INPUT_LINEIN;
// const int myInput = AUDIO_INPUT_MIC;

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//

AudioInputI2S audioInput; // audio shield: mic or line-in
AudioOutputI2S audioOutput; // audio shield: headphones & line-out

// Create Audio connections between the components
//
AudioConnection c1(audioInput, 0, audioOutput, 0); // left passing through
AudioConnection c2(audioInput, 1, audioOutput, 1); // right passing through

// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;

void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(4);
// Enable the audio shield and set the output volume.
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(0.5);
}

elapsedMillis chgMsec=0;
float lastBal=1024;

void loop() {
// every 10 ms, check for adjustment
if (chgMsec > 10) {
float bal1=analogRead(15);
bal1=((bal1-512)/512);
bal1=(int)bal1;
if(lastBal!=bal1)
{
if(bal1<0)
{ // leaning toward left...
audioShield.dacVolume(1,1+bal1);
} else if(bal1>0) { // to the right
audioShield.dacVolume(1-bal1,1);
} else { // middle
audioShield.dacVolume(1);
}
lastBal=bal1;
}
chgMsec = 0;
}
}


+ 66
- 0
examples/HardwareTesting/SGTL5000/balanceHP/balanceHP.ino 查看文件

@@ -0,0 +1,66 @@
/* HP balance example: Will influence only HP output.

This example code is in the public domain
*/

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

const int myInput = AUDIO_INPUT_LINEIN;
// const int myInput = AUDIO_INPUT_MIC;

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//

AudioInputI2S audioInput; // audio shield: mic or line-in
AudioOutputI2S audioOutput; // audio shield: headphones & line-out

// Create Audio connections between the components

// Just connecting in to out
AudioConnection c1(audioInput, 0, audioOutput, 0); // left connection
AudioConnection c2(audioInput, 1, audioOutput, 1); // right connection

// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;

void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(4);
// Enable the audio shield and set the output volume.
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(0.5);
}

elapsedMillis chgMsec=0;

float lastBal=1024;
float vol1=0.75;

void loop() {
// every 10 ms, check for adjustment
if (chgMsec > 10) {
float bal1=analogRead(15);
bal1=((bal1-512)/512);
bal1=(int)bal1;
if(lastBal!=bal1)
{
if(bal1<0)
{
audioShield.volume(vol1,vol1*(1+bal1));
} else {
audioShield.volume(vol1*(1-bal1),vol1);
}
lastBal=bal1;
}
chgMsec = 0;
}
}


+ 63
- 0
examples/HardwareTesting/SGTL5000/dap_avc_agc/dap_avc_agc.ino 查看文件

@@ -0,0 +1,63 @@
/* DAP AVC example; AVC is SGTL5000 equiv of AGC

This example code is in the public domain
*/

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>


const int myInput = AUDIO_INPUT_LINEIN;
// const int myInput = AUDIO_INPUT_MIC;

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//

AudioInputI2S audioInput; // audio shield: mic or line-in
AudioOutputI2S audioOutput; // audio shield: headphones & line-out

// Create Audio connections between the components
//
AudioConnection c1(audioInput, 0, audioOutput, 0); // left passing through
AudioConnection c2(audioInput, 1, audioOutput, 1); // right passing through

// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;

void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(4);
// Enable the audio shield and set the output volume.
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(0.5);
audioShield.audioPreProcessorEnable();
// here are some settings for AVC that have a fairly obvious effect
audioShield.autoVolumeControl(2,1,0,-5,0.5,0.5); // see comments starting line #699 of control_sgtl5000.cpp in ./libraries/audio/
// AVC has its own enable/disable bit
// you can use audioShield.autoVolumeEnable(0); to turn off AVC
}

elapsedMillis chgMsec=0;
float lastVol=1024;

void loop() {
// every 10 ms, check for adjustment
if (chgMsec > 10) {
float vol1=analogRead(15)/1023.0;
vol1=(int)vol1;
if(lastVol!=vol1)
{
audioShield.volume(vol1);
lastVol=vol1;
}
chgMsec = 0;
}
}


+ 64
- 0
examples/HardwareTesting/SGTL5000/dap_bass_enhance/dap_bass_enhance.ino 查看文件

@@ -0,0 +1,64 @@
/* DAP Bass enhance example SGTL5000 only

This example code is in the public domain
*/

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>


const int myInput = AUDIO_INPUT_LINEIN;
// const int myInput = AUDIO_INPUT_MIC;

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//

AudioInputI2S audioInput; // audio shield: mic or line-in
AudioOutputI2S audioOutput; // audio shield: headphones & line-out

// Create Audio connections between the components
//
AudioConnection c1(audioInput, 0, audioOutput, 0); // left passing through
AudioConnection c2(audioInput, 1, audioOutput, 1); // right passing through

// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;

void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(4);
// Enable the audio shield and set the output volume.
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(0.5);
// just enable it to use default settings.
audioShield.audioPostProcessorEnable();
audioShield.enhanceBassEnable(); // all we need to do for default bass enhancement settings.
// audioShield.enhanceBass((float)lr_level,(float)bass_level);
// audioShield.enhanceBass((float)lr_level,(float)bass_level,(uint8_t)hpf_bypass,(uint8_t)cutoff);
// please see http://www.pjrc.com/teensy/SGTL5000.pdf page 50 for valid values for BYPASS_HPF and CUTOFF
}

elapsedMillis chgMsec=0;
float lastVol=1024;

void loop() {
// every 10 ms, check for adjustment
if (chgMsec > 10) { // more regular updates for actual changes seems better.
float vol1=analogRead(15)/1023.0;
vol1=(int)vol1;
if(lastVol!=vol1)
{
audioShield.volume(vol1);
lastVol=vol1;
}
chgMsec = 0;
}
}


+ 283
- 0
examples/HardwareTesting/SdCardTest/SdCardTest.ino 查看文件

@@ -0,0 +1,283 @@
// SD Card Test
//
// Check if the SD card on the Audio Shield is working,
// and perform some simple speed measurements to gauge
// its ability to play 1, 2, 3 and 4 WAV files at a time.
//
// Requires the audio shield:
// http://www.pjrc.com/store/teensy3_audio.html
//
// Data files to put on your SD card can be downloaded here:
// http://www.pjrc.com/teensy/td_libs_AudioDataFiles.html
//
// This example code is in the public domain.

#include <SD.h>
#include <SPI.h>

void setup() {
Sd2Card card;
SdVolume volume;
File f1, f2, f3, f4;
char buffer[512];
boolean status;
unsigned long usec, usecMax;
elapsedMicros usecTotal, usecSingle;
int i, type;
float size;

// wait for the Arduino Serial Monitor to open
while (!Serial) ;
delay(50);

// Configure SPI for the audio shield pins
SPI.setMOSI(7); // Audio shield has MOSI on pin 7
SPI.setSCK(14); // Audio shield has SCK on pin 14

Serial.begin(9600);
Serial.println("SD Card Test");
Serial.println("------------");

// First, detect the card
status = card.init(10); // Audio shield has SD card SD on pin 10
if (status) {
Serial.println("SD card is connected :-)");
} else {
Serial.println("SD card is not connected or unusable :-(");
return;
}

type = card.type();
if (type == SD_CARD_TYPE_SD1 || type == SD_CARD_TYPE_SD2) {
Serial.println("Card type is SD");
} else if (type == SD_CARD_TYPE_SDHC) {
Serial.println("Card type is SDHC");
} else {
Serial.println("Card is an unknown type (maybe SDXC?)");
}

// Then look at the file system and print its capacity
status = volume.init(card);
if (!status) {
Serial.println("Unable to access the filesystem on this card. :-(");
return;
}

size = volume.blocksPerCluster() * volume.clusterCount();
size = size * (512.0 / 1e6); // convert blocks to millions of bytes
Serial.print("File system space is ");
Serial.print(size);
Serial.println(" Mbytes.");

// Now open the SD card normally
status = SD.begin(10); // Audio shield has SD card CS on pin 10
if (status) {
Serial.println("SD library is able to access the filesystem");
} else {
Serial.println("SD library can not access the filesystem!");
Serial.println("Please report this problem, with the make & model of your SD card.");
Serial.println(" http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports");
}


// Open the 4 sample files. Hopefully they're on the card
f1 = SD.open("SDTEST1.WAV");
f2 = SD.open("SDTEST2.WAV");
f3 = SD.open("SDTEST3.WAV");
f4 = SD.open("SDTEST4.WAV");

// Speed test reading a single file
if (f1) {
Serial.println();
Serial.println("Reading SDTEST1.WAV:");
if (f1.size() >= 514048) {
usecMax = 0;
usecTotal = 0;
for (i=0; i < 1000; i++) {
usecSingle = 0;
f1.read(buffer, 512);
usec = usecSingle;
if (usec > usecMax) usecMax = usec;
}
reportSpeed(1, 1000, usecTotal, usecMax);
} else {
Serial.println("SDTEST1.WAV is too small for speed testing");
}
} else {
Serial.println("Unable to find SDTEST1.WAV on this card");
return;
}

// Speed test reading two files
if (f2) {
Serial.println();
Serial.println("Reading SDTEST1.WAV & SDTEST2.WAV:");
if (f2.size() >= 514048) {
f1.seek(0);
usecMax = 0;
usecTotal = 0;
for (i=0; i < 1000; i++) {
usecSingle = 0;
f1.read(buffer, 512);
f2.read(buffer, 512);
usec = usecSingle;
if (usec > usecMax) usecMax = usec;
}
reportSpeed(2, 1000, usecTotal, usecMax);

Serial.println();
Serial.println("Reading SDTEST1.WAV & SDTEST2.WAV staggered:");
f1.seek(0);
f2.seek(0);
f1.read(buffer, 512);
usecMax = 0;
usecTotal = 0;
for (i=0; i < 1000; i++) {
usecSingle = 0;
f1.read(buffer, 512);
f2.read(buffer, 512);
usec = usecSingle;
if (usec > usecMax) usecMax = usec;
}
reportSpeed(2, 1000, usecTotal, usecMax);
} else {
Serial.println("SDTEST2.WAV is too small for speed testing");
}
} else {
Serial.println("Unable to find SDTEST2.WAV on this card");
return;
}


// Speed test reading three files
if (f3) {
Serial.println();
Serial.println("Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV:");
if (f3.size() >= 514048) {
f1.seek(0);
f2.seek(0);
usecMax = 0;
usecTotal = 0;
for (i=0; i < 1000; i++) {
usecSingle = 0;
f1.read(buffer, 512);
f2.read(buffer, 512);
f3.read(buffer, 512);
usec = usecSingle;
if (usec > usecMax) usecMax = usec;
}
reportSpeed(3, 1000, usecTotal, usecMax);

Serial.println();
Serial.println("Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV staggered:");
f1.seek(0);
f2.seek(0);
f3.seek(0);
f1.read(buffer, 512);
f1.read(buffer, 512);
f2.read(buffer, 512);
usecMax = 0;
usecTotal = 0;
for (i=0; i < 1000; i++) {
usecSingle = 0;
f1.read(buffer, 512);
f2.read(buffer, 512);
f3.read(buffer, 512);
usec = usecSingle;
if (usec > usecMax) usecMax = usec;
}
reportSpeed(3, 1000, usecTotal, usecMax);
} else {
Serial.println("SDTEST3.WAV is too small for speed testing");
}
} else {
Serial.println("Unable to find SDTEST3.WAV on this card");
return;
}


// Speed test reading four files
if (f4) {
Serial.println();
Serial.println("Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV, SDTEST4.WAV:");
if (f4.size() >= 514048) {
f1.seek(0);
f2.seek(0);
f3.seek(0);
usecMax = 0;
usecTotal = 0;
for (i=0; i < 1000; i++) {
usecSingle = 0;
f1.read(buffer, 512);
f2.read(buffer, 512);
f3.read(buffer, 512);
f4.read(buffer, 512);
usec = usecSingle;
if (usec > usecMax) usecMax = usec;
}
reportSpeed(4, 1000, usecTotal, usecMax);

Serial.println();
Serial.println("Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV, SDTEST4.WAV staggered:");
f1.seek(0);
f2.seek(0);
f3.seek(0);
f4.seek(0);
f1.read(buffer, 512);
f1.read(buffer, 512);
f1.read(buffer, 512);
f2.read(buffer, 512);
f2.read(buffer, 512);
f3.read(buffer, 512);
usecMax = 0;
usecTotal = 0;
for (i=0; i < 1000; i++) {
usecSingle = 0;
f1.read(buffer, 512);
f2.read(buffer, 512);
f3.read(buffer, 512);
f4.read(buffer, 512);
usec = usecSingle;
if (usec > usecMax) usecMax = usec;
}
reportSpeed(4, 1000, usecTotal, usecMax);
} else {
Serial.println("SDTEST4.WAV is too small for speed testing");
}
} else {
Serial.println("Unable to find SDTEST4.WAV on this card");
return;
}

}


unsigned long maximum(unsigned long a, unsigned long b,
unsigned long c, unsigned long d)
{
if (b > a) a = b;
if (c > a) a = c;
if (d > a) a = d;
return a;
}


void reportSpeed(unsigned int numFiles, unsigned long blockCount,
unsigned long usecTotal, unsigned long usecMax)
{
float bytesPerSecond = (float)(blockCount * 512 * numFiles) / usecTotal;
Serial.print(" Overall speed = ");
Serial.print(bytesPerSecond);
Serial.println(" Mbyte/sec");
Serial.print(" Worst block time = ");
Serial.print((float)usecMax / 1000.0);
Serial.println(" ms");
Serial.print(" ");
Serial.print( (float)usecMax / 29.01333);
Serial.println("% of audio frame time");
}


void loop(void) {
// do nothing after the test
}

+ 84
- 0
examples/HardwareTesting/ToneSweep/ToneSweep.ino 查看文件

@@ -0,0 +1,84 @@
/*
Demo of the audio sweep function.
The user specifies the amplitude,
start and end frequencies (which can sweep up or down)
and the length of time of the sweep.
FMI:
The audio board uses the following pins.
6 - MEMCS
7 - MOSI
9 - BCLK
10 - SDCS
11 - MCLK
12 - MISO
13 - RX
14 - SCLK
15 - VOL
18 - SDA
19 - SCL
22 - TX
23 - LRCLK

*/

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>

AudioSynthToneSweep myEffect;
AudioOutputI2S audioOutput; // audio shield: headphones & line-out

// The tone sweep goes to left and right channels
AudioConnection c1(myEffect, 0, audioOutput, 0);
AudioConnection c2(myEffect, 0, audioOutput, 1);

AudioControlSGTL5000 audioShield;


float t_ampx = 0.8;
int t_lox = 10;
int t_hix = 22000;
// Length of time for the sweep in seconds
float t_timex = 10;
// <<<<<<<<<<<<<<>>>>>>>>>>>>>>>>
void setup(void)
{
Serial.begin(9600);
while (!Serial) ;
delay(3000);

AudioMemory(2);

audioShield.enable();
audioShield.volume(0.5);

Serial.println("setup done");

if(!myEffect.play(t_ampx,t_lox,t_hix,t_timex)) {
Serial.println("AudioSynthToneSweep - begin failed");
while(1);
}
// wait for the sweep to end
while(myEffect.isPlaying());

// and now reverse the sweep
if(!myEffect.play(t_ampx,t_hix,t_lox,t_timex)) {
Serial.println("AudioSynthToneSweep - begin failed");
while(1);
}
// wait for the sweep to end
while(myEffect.isPlaying());
Serial.println("Done");
}

void loop(void)
{
}




+ 51
- 0
examples/HardwareTesting/WM8731MikroSine/WM8731MikroSine.ino 查看文件

@@ -0,0 +1,51 @@
// Simple sine wave test for WM8731 Audio Codec Board
//
// Requires the MikroElektronika Audio Codec board or similar hardware
// http://www.mikroe.com/add-on-boards/audio-voice/audio-codec-proto/
//
// Recommended connections:
//
// Mikroe Teensy 3.1
// ------ ----------
// SCK 9
// MISO 13
// MOSI 22
// ADCL
// DACL 23
// SDA 18
// SCL 19
// 3.3V +3.3V
// GND GND
//
// This example code is in the public domain.

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthWaveform waveform1; //xy=110,75
AudioOutputI2Sslave i2ss1; //xy=303,78
AudioConnection patchCord1(waveform1, 0, i2ss1, 0);
AudioConnection patchCord2(waveform1, 0, i2ss1, 1);
AudioControlWM8731master wm8731m1; //xy=230,154
// GUItool: end automatically generated code


void setup() {
wm8731m1.enable();

AudioMemory(15);

waveform1.begin(WAVEFORM_SINE);
waveform1.frequency(440);
waveform1.amplitude(0.9);

wm8731m1.volume(0.50);
}


void loop() {
}

+ 154
- 0
examples/MemoryAndCpuUsage/MemoryAndCpuUsage.ino 查看文件

@@ -0,0 +1,154 @@
// MemoryAndCpuUsage
//
// This example demonstrates how to monitor CPU and memory
// usage by the audio library. You can see the total memory
// used at any moment, and the maximum (worst case) used.
//
// The total CPU usage, and CPU usage for each object can
// be monitored. Reset functions clear the maximums.
//
// Use the Arduino Serial Monitor to view the usage info
// and control ('F', 'S', and 'R' keys) this program.
//
// This example code is in the public domain.


#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthWaveformSine sine1; //xy=125,221
AudioSynthNoisePink pink1; //xy=133,121
AudioEffectEnvelope envelope1; //xy=298,133
AudioEffectEnvelope envelope2; //xy=302,197
AudioAnalyzeFFT256 fft256_1; //xy=304,272
AudioMixer4 mixer1; //xy=486,163
AudioOutputI2S i2s1; //xy=640,161
AudioConnection patchCord1(sine1, envelope2);
AudioConnection patchCord2(sine1, fft256_1);
AudioConnection patchCord3(pink1, envelope1);
AudioConnection patchCord4(envelope1, 0, mixer1, 0);
AudioConnection patchCord5(envelope2, 0, mixer1, 1);
AudioConnection patchCord6(mixer1, 0, i2s1, 0);
AudioConnection patchCord7(mixer1, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=517,297
// GUItool: end automatically generated code


void setup() {
// give the audio library some memory. We'll be able
// to see how much it actually uses, which can be used
// to reduce this to the minimum necessary.
AudioMemory(20);

// enable the audio shield
sgtl5000_1.enable();
sgtl5000_1.volume(0.6);

// create a simple percussive sound using pink noise
// and an envelope to shape it.
pink1.amplitude(0.5);
envelope1.attack(1.5);
envelope1.hold(5);
envelope1.decay(20);
envelope1.sustain(0);

// create a simple bass note using a sine wave
sine1.frequency(120);
sine1.amplitude(0.6);
envelope2.attack(6.5);
envelope2.hold(25);
envelope2.decay(70);
envelope2.sustain(0);

// add both the note together, so we can hear them
mixer1.gain(0, 0.5);
mixer1.gain(1, 0.5);
}


int count = 0;
int speed = 60;


void loop() {
// a simple sequencer, count goes from 0 to 15
count = count + 1;
if (count >= 16) count = 0;

// play percussive sounds every 4th time
if (count == 0) envelope1.noteOn();
if (count == 4) envelope1.noteOn();
if (count == 8) envelope1.noteOn();
if (count == 12) envelope1.noteOn();

// play the bass tone every 8th time
if (count == 4) {
sine1.amplitude(0.6);
sine1.frequency(100);
envelope2.noteOn();
}
if (count == 12) {
sine1.amplitude(0.3);
sine1.frequency(120);
envelope2.noteOn();
}

// turn off the sine wave, which saves
// CPU power (especially since the sine goes
// to a CPU-hungry FFT analysis)
if (count == 6) {
sine1.amplitude(0);
}

// check for incoming characters from the serial monitor
if (Serial.available()) {
char c = Serial.read();
if ((c == 'r' || c == 'R')) {
pink1.processorUsageMaxReset();
fft256_1.processorUsageMaxReset();
AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset();
Serial.println("Reset all max numbers");
}
if ((c == 'f' || c == 'F') && speed > 16) {
speed = speed - 2;
}
if ((c == 's' || c == 'S') && speed < 250) {
speed = speed + 2;
}
}

// print a summary of the current & maximum usage
Serial.print("CPU: ");
Serial.print("pink=");
Serial.print(pink1.processorUsage());
Serial.print(",");
Serial.print(pink1.processorUsageMax());
Serial.print(" ");
Serial.print("fft=");
Serial.print(fft256_1.processorUsage());
Serial.print(",");
Serial.print(fft256_1.processorUsageMax());
Serial.print(" ");
Serial.print("all=");
Serial.print(AudioProcessorUsage());
Serial.print(",");
Serial.print(AudioProcessorUsageMax());
Serial.print(" ");
Serial.print("Memory: ");
Serial.print(AudioMemoryUsage());
Serial.print(",");
Serial.print(AudioMemoryUsageMax());
Serial.print(" ");
Serial.print("Send: (R)eset, (S)lower, (F)aster");
Serial.println();

// very simple timing :-)
delay(speed);

}


+ 0
- 50
examples/PassThrough/PassThrough.ino 查看文件

@@ -1,50 +0,0 @@
#include <Audio.h>
#include <Wire.h>
#include <SD.h>

const int myInput = AUDIO_INPUT_LINEIN;
//const int myInput = AUDIO_INPUT_MIC;

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//
//AudioInputAnalog analogPinInput(16); // analog A2 (pin 16)
AudioInputI2S audioInput; // audio shield: mic or line-in
AudioOutputI2S audioOutput; // audio shield: headphones & line-out
AudioOutputPWM pwmOutput; // audio output with PWM on pins 3 & 4

// Create Audio connections between the components
//
AudioConnection c1(audioInput, 0, audioOutput, 0);
AudioConnection c2(audioInput, 1, audioOutput, 1);
AudioConnection c5(audioInput, 0, pwmOutput, 0);

// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;


void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(12);

// Enable the audio shield and set the output volume.
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(60);
}

elapsedMillis volmsec=0;

void loop() {
// every 50 ms, adjust the volume
if (volmsec > 50) {
float vol = analogRead(15);
vol = vol / 10.24;
audioShield.volume(vol);
volmsec = 0;
}
}



+ 0
- 40
examples/PassThroughAnalog/PassThroughAnalog.ino 查看文件

@@ -1,40 +0,0 @@
#include <Audio.h>
#include <Wire.h>
#include <SD.h>


// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//
AudioInputAnalog analogPinInput(16); // analog A2 (pin 16)
AudioOutputI2S audioOutput; // audio shield: headphones & line-out
AudioOutputPWM pwmOutput; // audio output with PWM on pins 3 & 4

// Create Audio connections between the components
//
AudioConnection c1(analogPinInput, 0, audioOutput, 0);
AudioConnection c2(analogPinInput, 0, audioOutput, 1);
AudioConnection c3(analogPinInput, 0, pwmOutput, 0);

// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;


void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(12);

// Enable the audio shield and set the output volume.
audioShield.enable();
audioShield.volume(60);
}

void loop() {
// Do nothing here. The Audio flows automatically

// When AudioInputAnalog is running, analogRead() must NOT be used.
}



+ 0
- 94
examples/PassThroughPlusTone/PassThroughPlusTone.ino 查看文件

@@ -1,94 +0,0 @@
#include <Audio.h>
#include <Bounce.h>
#include <Wire.h>
#include <SD.h>

const int myInput = AUDIO_INPUT_LINEIN;
//const int myInput = AUDIO_INPUT_MIC;

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//
//AudioInputAnalog analogPinInput(16); // analog A2 (pin 16)
AudioInputI2S audioInput; // audio shield: mic or line-in
AudioSynthWaveform toneLow(AudioWaveformSine);
AudioSynthWaveform toneHigh(AudioWaveformTriangle);
AudioMixer4 mixerLeft;
AudioMixer4 mixerRight;
AudioOutputI2S audioOutput; // audio shield: headphones & line-out
AudioOutputPWM pwmOutput; // audio output with PWM on pins 3 & 4

// Create Audio connections between the components
//
AudioConnection c1(audioInput, 0, mixerLeft, 0);
AudioConnection c2(audioInput, 1, mixerRight, 0);
AudioConnection c3(toneHigh, 0, mixerLeft, 1);
AudioConnection c4(toneHigh, 0, mixerRight, 1);
AudioConnection c5(toneLow, 0, mixerLeft, 2);
AudioConnection c6(toneLow, 0, mixerRight, 2);
AudioConnection c7(mixerLeft, 0, audioOutput, 0);
AudioConnection c8(mixerRight, 0, audioOutput, 1);
AudioConnection c9(mixerLeft, 0, pwmOutput, 0);

// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;


// Bounce objects to read two pushbuttons (pins 0 and 1)
//
Bounce button0 = Bounce(0, 12);
Bounce button1 = Bounce(1, 12); // 12 ms debounce time


void setup() {
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);

// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(12);

// Enable the audio shield and set the output volume.
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(60);
}

elapsedMillis volmsec=0;

void loop() {
// Check each button
button0.update();
button1.update();

// fallingEdge = high (not pressed - voltage from pullup resistor)
// to low (pressed - button connects pin to ground)
if (button0.fallingEdge()) {
toneLow.frequency(256);
toneLow.amplitude(0.4);
}
if (button1.fallingEdge()) {
toneHigh.frequency(980);
toneHigh.amplitude(0.25);
}

// risingEdge = low (pressed - button connects pin to ground)
// to high (not pressed - voltage from pullup resistor)
if (button0.risingEdge()) {
toneLow.amplitude(0);
}
if (button1.risingEdge()) {
toneHigh.amplitude(0);
}

// every 50 ms, adjust the volume
if (volmsec > 50) {
float vol = analogRead(15);
vol = vol / 10.24;
audioShield.volume(vol);
volmsec = 0;
}
}



+ 0
- 110
examples/PlayMidiTones/MidiTones.ino 查看文件

@@ -1,110 +0,0 @@
#include <Audio.h>
#include <Wire.h>
//#include <WM8731.h>
#include <SD.h>
#include <SPI.h>


//AudioInputI2S adc;
//AudioInputAnalog ana(16);
AudioSynthWaveform mysine(AudioWaveformSine);
AudioSynthWaveform sine2(AudioWaveformSine);
//AudioOutputPWM myout;
//AudioPlaySDcardWAV wav;
//AudioPlaySDcardRAW wav;
//AudioMixer4 mix;
AudioOutputI2S dac;


//AudioControl_WM8731 codec;
AudioControlSGTL5000 codec;

AudioConnection c1(mysine, dac);

//AudioConnection c1(wav, dac);
//AudioConnection c2(wav, 1, dac, 1);


int volume = 0;

void setup() {
Serial1.begin(115200);
Serial1.println("***************");

while (!Serial) ;
delay(100);
codec.enable();
//while(1);
delay(200);
Serial.println("Begin AudioTest");
delay(50);

Serial1.print("B");

// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(15);


//mysine.connect(myout);
//mysine.connect(dac);
//mysine.connect(dac, 1, 0);
mysine.frequency(440);
//wav.connect(dac);
//wav.connect(dac, 1, 0);
//codec.inputLinein();
codec.volume(40);
//adc.connect(dac);
//ana.connect(dac);
//ana.connect(dac, 1, 0);
/*
SPI.setMOSI(7);
SPI.setSCK(14);
if (SD.begin(10)) {
Serial.println("SD init ok");
//wav.play("01_16M.WAV");
}
*/
Serial.println("setup done");
}




void loop() {
/*
Serial.print("cpu: ");
Serial.print(AudioProcessorUsage());
Serial.print(", max: ");
Serial.print(AudioProcessorUsageMax());
Serial.print(", memory: ");
Serial.print(AudioMemoryUsage());
Serial.print(", max: ");
Serial.print(AudioMemoryUsageMax());
Serial.println("");
*/
//int n;
//n = analogRead(15);
//Serial.println(n);
//if (n != volume) {
//volume = n;
//codec.volume((float)n / 10.23);
//}
//n = analogRead(16) / 8;
//Serial.println(n);
//mysine.frequency(200 + n * 4);
//delay(5);
}

+ 0
- 636
examples/PlayMidiTones/william_tell_overture.c 查看文件

@@ -1,636 +0,0 @@
// Playtune bytestream for file "william_tell_overture.mid" created by MIDITONES V1.6 on Sat Oct 26 02:48:13 2013
// command line: ./miditones -t10 william_tell_overture
#include "Arduino.h"
const byte PROGMEM score [] = {
0x90,72, 0x91,72, 0x92,72, 0x93,72, 0x94,72, 1,169, 0x80, 0x81, 0x82, 0x83, 0x84, 0,183, 0x90,72,
0x91,72, 0x92,72, 0x93,72, 0x94,72, 0,41, 0x80, 0x81, 0x82, 0x83, 0x84, 0,58, 0x90,72, 0x91,72,
0x92,72, 0x93,72, 0x94,72, 0,41, 0x80, 0x81, 0x82, 0x83, 0x84, 0,58, 0x90,72, 0x91,72, 0x92,72,
0x93,72, 0x94,72, 1,239, 0x80, 0x81, 0x82, 0x83, 0x84, 0,112, 0x90,72, 0x91,72, 0x92,72, 0x93,72,
0x94,72, 0,54, 0x80, 0x81, 0x82, 0x83, 0x84, 0,50, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0x94,72,
0,50, 0x80, 0x81, 0x82, 0x83, 0x84, 0,50, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0x94,72, 0,104,
0x80, 0x81, 0x82, 0x83, 0x84, 0,100, 0x90,69, 0x91,69, 0x92,69, 0x93,69, 0x94,69, 0,83, 0x80, 0x81,
0x82, 0x83, 0x84, 0,116, 0x90,65, 0x91,65, 0x92,65, 0x93,65, 0x94,65, 0,108, 0x80, 0x81, 0x82, 0x83,
0x84, 0,95, 0x90,69, 0x91,69, 0x92,69, 0x93,69, 0x94,69, 0,112, 0x80, 0x81, 0x82, 0x83, 0x84, 0,91,
0x90,72, 0x91,72, 0x92,72, 0x93,72, 0x94,72, 0,100, 0x80, 0x81, 0x82, 0x83, 0x84, 0,100, 0x90,69,
0x91,69, 0x92,69, 0x93,69, 0x94,69, 0,112, 0x80, 0x81, 0x82, 0x83, 0x84, 0,91, 0x90,72, 0x91,72,
0x92,72, 0x93,72, 0x94,72, 0,100, 0x80, 0x81, 0x82, 0x83, 0x84, 0,104, 0x90,77, 0x91,77, 0x92,77,
0x93,77, 0x94,77, 0,91, 0x80, 0x81, 0x82, 0x83, 0x84, 0,108, 0x90,72, 0x91,72, 0x92,72, 0x93,72,
0x94,72, 0,100, 0x80, 0x81, 0x82, 0x83, 0x84, 0,104, 0x90,69, 0x91,69, 0x92,69, 0x93,69, 0x94,69,
0,83, 0x80, 0x81, 0x82, 0x83, 0x84, 0,120, 0x90,65, 0x91,65, 0x92,65, 0x93,65, 0x94,65, 0,100,
0x80, 0x81, 0x82, 0x83, 0x84, 0,100, 0x90,69, 0x91,69, 0x92,69, 0x93,69, 0x94,69, 0,91, 0x80, 0x81,
0x82, 0x83, 0x84, 0,112, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0x94,72, 0,87, 0x80, 0x81, 0x82, 0x83,
0x84, 0,116, 0x90,69, 0x91,69, 0x92,69, 0x93,69, 0x94,69, 0,91, 0x80, 0x81, 0x82, 0x83, 0x84, 0,108,
0x90,72, 0x91,72, 0x92,72, 0x93,72, 0x94,72, 0,91, 0x80, 0x81, 0x82, 0x83, 0x84, 0,112, 0x90,77,
0x91,77, 0x92,77, 0x93,77, 0x94,77, 0,83, 0x80, 0x81, 0x82, 0x83, 0x84, 0,120, 0x90,72, 0x91,72,
0x92,72, 0x93,72, 0x94,72, 1,119, 0x80, 0x81, 0x82, 0x83, 0x84, 0,233, 0x90,72, 0x91,72, 0x92,72,
0x93,72, 0x94,72, 0,41, 0x80, 0x81, 0x82, 0x83, 0x84, 0,58, 0x90,72, 0x91,72, 0x92,72, 0x93,72,
0x94,72, 0,50, 0x80, 0x81, 0x82, 0x83, 0x84, 0,50, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0x94,72,
2,8, 0x80, 0x81, 0x82, 0x83, 0x84, 0,87, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0x94,72, 0,54,
0x80, 0x81, 0x82, 0x83, 0x84, 0,45, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0x94,72, 0,62, 0x80, 0x81,
0x82, 0x83, 0x84, 0,41, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0x94,72, 0,95, 0x80, 0x81, 0x82, 0x83,
0x84, 0,108, 0x90,72, 0x91,67, 0x92,64, 0x93,60, 0x94,72, 0x95,67, 0x96,72, 0x97,67, 0x98,64,
0x99,60, 0,41, 0x82, 0x88, 0,4, 0x83, 0x89, 0,4, 0x80, 0x84, 0x86, 0x81, 0x85, 0x87, 0,50, 0x90,67,
0x91,72, 0x92,64, 0x93,60, 0x94,67, 0x95,72, 0x96,67, 0x97,72, 0x98,64, 0x99,60, 0,41, 0x80,
0x84, 0x86, 0,4, 0x82, 0x88, 0x83, 0x89, 0,12, 0x81, 0x85, 0x87, 0,41, 0x90,67, 0x91,72, 0x92,64,
0x93,60, 0x94,67, 0x95,72, 0x96,67, 0x97,72, 0x98,64, 0x99,60, 0,58, 0x82, 0x88, 0x83, 0x89, 0,4,
0x80, 0x84, 0x86, 0,12, 0x81, 0x85, 0x87, 0,129, 0x90,67, 0x91,72, 0x92,60, 0x93,64, 0x94,67, 0x95,72,
0x96,67, 0x97,72, 0x98,60, 0x99,64, 0,54, 0x80, 0x84, 0x86, 0x82, 0x88, 0x83, 0x89, 0,12, 0x81, 0x85,
0x87, 0,133, 0x90,67, 0x91,48, 0x92,72, 0x93,64, 0x94,67, 0x95,72, 0x96,67, 0x97,72, 0x98,60,
0x99,64, 0,62, 0x88, 0x83, 0x89, 0,29, 0x80, 0x84, 0x86, 0x81, 0,4, 0x82, 0x85, 0x87, 0,108, 0x90,67,
0x91,72, 0x92,48, 0x93,64, 0x94,67, 0x95,72, 0x96,67, 0x97,72, 0x98,60, 0x99,64, 0,41, 0x80,
0x84, 0x86, 0,4, 0x83, 0x89, 0x88, 0,4, 0x81, 0x85, 0x87, 0,41, 0x82, 0,8, 0x90,67, 0x91,72,
0x92,48, 0x93,64, 0x94,67, 0x95,72, 0x96,67, 0x97,72, 0x98,60, 0x99,64, 0,41, 0x88, 0x80, 0x84,
0x86, 0,4, 0x81, 0x85, 0x87, 0x83, 0x89, 0,45, 0x82, 0,12, 0x90,67, 0x91,72, 0x92,48, 0x93,64,
0x94,67, 0x95,72, 0x96,67, 0x97,72, 0x98,64, 0x99,60, 0,45, 0x83, 0x88, 0x89, 0,12, 0x80, 0x84,
0x86, 0,8, 0x81, 0x85, 0x87, 0,20, 0x82, 0,112, 0x90,67, 0x91,72, 0x92,48, 0x93,64, 0x94,67,
0x95,72, 0x96,67, 0x97,72, 0x98,60, 0x99,64, 0,50, 0x80, 0x84, 0x86, 0,4, 0x88, 0x83, 0x89, 0x81,
0x85, 0x87, 0,37, 0x82, 0,112, 0x90,72, 0x91,67, 0x92,48, 0x93,64, 0x94,72, 0x95,67, 0x96,72,
0x97,67, 0x98,64, 0x99,60, 2,167, 0x80, 0x84, 0x86, 0,8, 0x81, 0x85, 0x87, 0x82, 0,120, 0x90,72,
0x91,67, 0x92,48, 0x94,72, 0x95,67, 0x96,72, 0x97,67, 0,104, 0x82, 0,100, 0x83, 0x88, 0,12,
0x80, 0x84, 0x86, 0,4, 0x89, 0x81, 0x85, 0x87, 0,87, 1,44, 0x90,60, 0x91,60, 0x92,60, 0x93,60,
0x94,60, 0,54, 0x80, 0x81, 0x82, 0x83, 0x84, 0,50, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0x94,60,
0,62, 0x80, 0x81, 0x82, 0x83, 0x84, 0,37, 0x90,41, 0x91,57, 0x92,53, 0x93,60, 0x94,60, 0x95,41,
0x96,57, 0x97,53, 0x98,60, 0x99,60, 0,70, 0x80, 0x85, 0x81, 0x86, 0,12, 0x83, 0x84, 0x88, 0x89, 0,4,
0x82, 0x87, 0,116, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,60,
0x91,60, 0x92,60, 0x93,60, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,57, 0x91,53, 0x92,41, 0x93,60,
0x94,60, 0x95,57, 0x96,53, 0x97,41, 0x98,60, 0x99,60, 0,75, 0x80, 0x85, 0x83, 0x84, 0x88, 0x89, 0,4,
0x81, 0x86, 0x82, 0x87, 0,125, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,41, 0x80, 0x81, 0x82, 0x83, 0,62,
0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,66, 0x80, 0x81, 0x82, 0x83, 0,33, 0x90,57, 0x91,41, 0x92,53,
0x93,65, 0x94,65, 0x95,57, 0x96,41, 0x97,53, 0x98,65, 0x99,65, 0,58, 0x80, 0x85, 0,8, 0x81,
0x86, 0x82, 0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,125, 0x90,53, 0x91,57, 0x92,41, 0x93,67, 0x94,67,
0x95,53, 0x96,57, 0x97,41, 0x98,67, 0x99,67, 0,58, 0x80, 0x85, 0,4, 0x81, 0x86, 0,4, 0x82,
0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,120, 0x90,57, 0x91,53, 0x92,41, 0x93,69, 0x94,69, 0x95,57,
0x96,53, 0x97,41, 0x98,69, 0x99,69, 0,54, 0x80, 0x85, 0,4, 0x81, 0x86, 0,12, 0x82, 0x87, 0x83,
0x84, 0x88, 0x89, 0,133, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,45, 0x80, 0x81, 0x82, 0x83, 0,54,
0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,54, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,53, 0x91,57, 0x92,41,
0x93,60, 0x94,60, 0x95,53, 0x96,57, 0x97,41, 0x98,60, 0x99,60, 0,54, 0x80, 0x85, 0,4, 0x81,
0x86, 0,8, 0x82, 0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,129, 0x90,60, 0x91,60, 0x92,60, 0x93,60,
0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,62, 0x80, 0x81, 0x82,
0x83, 0,41, 0x90,53, 0x91,57, 0x92,41, 0x93,65, 0x94,65, 0x95,53, 0x96,57, 0x97,41, 0x98,65,
0x99,65, 0,58, 0x80, 0x85, 0,4, 0x81, 0x86, 0,4, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,116,
0x90,69, 0x91,69, 0x92,69, 0x93,69, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,69, 0x91,69, 0x92,69,
0x93,69, 0,66, 0x80, 0x81, 0x82, 0x83, 0,37, 0x90,48, 0x91,36, 0x92,52, 0x93,55, 0x94,67, 0x95,67,
0x96,48, 0x97,36, 0x98,52, 0x99,55, 0,45, 0x80, 0x86, 0,16, 0x81, 0x87, 0x82, 0x88, 0,4, 0x83,
0x89, 0x84, 0x85, 0,137, 0x90,48, 0x91,52, 0x92,55, 0x93,36, 0x94,64, 0x95,64, 0x96,48, 0x97,52,
0x98,55, 0x99,36, 0,37, 0x80, 0x86, 0,20, 0x81, 0x87, 0x82, 0x88, 0,4, 0x83, 0x89, 0,8, 0x84,
0x85, 0,129, 0x90,48, 0x91,52, 0x92,55, 0x93,36, 0x94,60, 0x95,60, 0x96,48, 0x97,52, 0x98,55,
0x99,36, 0,50, 0x80, 0x86, 0,4, 0x81, 0x87, 0,20, 0x82, 0x88, 0x83, 0x89, 0,4, 0x84, 0x85, 0,125,
0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,45, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,60, 0x91,60, 0x92,60,
0x93,60, 0,58, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,53, 0x91,57, 0x92,41, 0x93,60, 0x94,60, 0x95,53,
0x96,57, 0x97,41, 0x98,60, 0x99,60, 0,54, 0x80, 0x85, 0,12, 0x81, 0x86, 0,8, 0x82, 0x87, 0x83,
0x84, 0x88, 0x89, 0,125, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50,
0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,58, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,53, 0x91,57, 0x92,41,
0x93,60, 0x94,60, 0x95,53, 0x96,57, 0x97,41, 0x98,60, 0x99,60, 0,54, 0x80, 0x85, 0,4, 0x83,
0x84, 0x88, 0x89, 0,4, 0x81, 0x86, 0,8, 0x82, 0x87, 0,133, 0x90,60, 0x91,60, 0x92,60, 0x93,60,
0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,41, 0x80, 0x81, 0x82,
0x83, 0,58, 0x90,53, 0x91,57, 0x92,41, 0x93,65, 0x94,65, 0x95,53, 0x96,57, 0x97,41, 0x98,65,
0x99,65, 0,54, 0x80, 0x85, 0,8, 0x81, 0x86, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,125, 0x90,53,
0x91,41, 0x92,57, 0x93,67, 0x94,67, 0x95,53, 0x96,41, 0x97,57, 0x98,67, 0x99,67, 0,45, 0x80,
0x85, 0,8, 0x81, 0x86, 0,8, 0x82, 0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,133, 0x90,53, 0x91,41,
0x92,57, 0x93,69, 0x94,69, 0x95,53, 0x96,41, 0x97,57, 0x98,69, 0x99,69, 0,54, 0x80, 0x85, 0x81,
0x86, 0,8, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,120, 0x90,65, 0x91,65, 0x92,65, 0x93,65,
0,62, 0x80, 0x81, 0x82, 0x83, 0,37, 0x90,69, 0x91,69, 0x92,69, 0x93,69, 0,62, 0x80, 0x81, 0x82,
0x83, 0,41, 0x90,36, 0x91,72, 0x92,72, 0x93,36, 0x94,72, 0x95,72, 0,104, 0x80, 0x83, 0,95,
0x90,52, 0x93,60, 0x96,58, 0x97,52, 0x98,60, 0x99,58, 0,37, 0x80, 0x87, 0,8, 0x83, 0x88, 0,8,
0x86, 0x89, 0,50, 0x90,52, 0x93,60, 0x96,58, 0x97,52, 0x98,60, 0x99,58, 0,33, 0x80, 0x87, 0,8,
0x83, 0x88, 0,8, 0x86, 0x89, 0,50, 0x90,52, 0x93,58, 0x96,60, 0x97,36, 0x98,52, 0x99,58, 0,62,
0x80, 0x88, 0,12, 0x83, 0x89, 0,4, 0x86, 0,20, 0x90,70, 0x93,70, 0x96,70, 0x98,70, 0,16,
0x87, 0,37, 0x81, 0x82, 0x84, 0x85, 0,20, 0x80, 0x83, 0x86, 0x88, 0,29, 0x90,69, 0x91,69, 0x92,69,
0x93,69, 0,91, 0x80, 0x81, 0x82, 0x83, 0,8, 0x90,67, 0x91,67, 0x92,67, 0x93,67, 0,95, 0x80,
0x81, 0x82, 0x83, 0,4, 0x90,53, 0x91,41, 0x92,57, 0x93,65, 0x94,65, 0x95,53, 0x96,41, 0x97,57,
0x98,65, 0x99,65, 0,66, 0x80, 0x85, 0,4, 0x81, 0x86, 0,8, 0x82, 0x87, 0,66, 0x83, 0x84, 0x88,
0x89, 0,58, 0x90,60, 0x91,41, 0x92,69, 0x93,69, 0x94,60, 0x95,41, 0x96,69, 0x97,69, 0,54,
0x80, 0x84, 0x82, 0x83, 0x86, 0x87, 0,16, 0x81, 0x85, 0,129, 0x90,41, 0x91,53, 0x92,57, 0x93,65, 0x94,65,
0x95,41, 0x96,53, 0x97,57, 0x98,65, 0x99,65, 0,91, 0x83, 0x84, 0x88, 0x89, 0x80, 0x85, 0x81, 0x86, 0,8,
0x82, 0x87, 0,104, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,54, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,72,
0x91,72, 0x92,72, 0x93,72, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,41, 0x91,57, 0x92,53, 0x93,72,
0x94,72, 0x95,41, 0x96,57, 0x97,53, 0x98,72, 0x99,72, 0,58, 0x80, 0x85, 0x81, 0x86, 0,8, 0x82,
0x87, 0,4, 0x83, 0x84, 0x88, 0x89, 0,129, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,50, 0x80, 0x81,
0x82, 0x83, 0,54, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,45, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,57,
0x91,53, 0x92,41, 0x93,72, 0x94,72, 0x95,57, 0x96,53, 0x97,41, 0x98,72, 0x99,72, 0,75, 0x80,
0x85, 0x83, 0x84, 0x88, 0x89, 0,4, 0x81, 0x86, 0x82, 0x87, 0,125, 0x90,72, 0x91,72, 0x92,72, 0x93,72,
0,45, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,58, 0x80, 0x81, 0x82,
0x83, 0,41, 0x90,57, 0x91,41, 0x92,53, 0x93,77, 0x94,77, 0x95,57, 0x96,41, 0x97,53, 0x98,77,
0x99,77, 0,62, 0x80, 0x85, 0,4, 0x81, 0x86, 0x82, 0x87, 0,25, 0x83, 0x84, 0x88, 0x89, 0,112, 0x90,53,
0x91,57, 0x92,41, 0x93,79, 0x94,79, 0x95,53, 0x96,57, 0x97,41, 0x98,79, 0x99,79, 0,54, 0x80,
0x85, 0,8, 0x81, 0x86, 0,4, 0x82, 0x87, 0,12, 0x83, 0x84, 0x88, 0x89, 0,125, 0x90,57, 0x91,53,
0x92,41, 0x93,81, 0x94,81, 0x95,57, 0x96,53, 0x97,41, 0x98,81, 0x99,81, 0,50, 0x80, 0x85, 0,8,
0x81, 0x86, 0,8, 0x82, 0x87, 0,41, 0x83, 0x84, 0x88, 0x89, 0,91, 0x90,72, 0x91,72, 0x92,72, 0x93,72,
0,58, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,37, 0x80, 0x81, 0x82,
0x83, 0,62, 0x90,53, 0x91,57, 0x92,41, 0x93,72, 0x94,72, 0x95,53, 0x96,57, 0x97,41, 0x98,72,
0x99,72, 0,54, 0x80, 0x85, 0,4, 0x81, 0x86, 0,8, 0x82, 0x87, 0,4, 0x83, 0x84, 0x88, 0x89, 0,133,
0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,41, 0x80, 0x81, 0x82, 0x83, 0,58, 0x90,72, 0x91,72, 0x92,72,
0x93,72, 0,62, 0x80, 0x81, 0x82, 0x83, 0,37, 0x90,53, 0x91,57, 0x92,41, 0x93,77, 0x94,77, 0x95,53,
0x96,57, 0x97,41, 0x98,77, 0x99,77, 0,62, 0x80, 0x85, 0,4, 0x81, 0x86, 0x82, 0x87, 0,12, 0x83,
0x84, 0x88, 0x89, 0,125, 0x90,81, 0x91,81, 0x92,81, 0x93,81, 0,45, 0x80, 0x81, 0x82, 0x83, 0,54,
0x90,81, 0x91,81, 0x92,81, 0x93,81, 0,70, 0x80, 0x81, 0x82, 0x83, 0,33, 0x90,48, 0x91,36, 0x92,52,
0x93,55, 0x94,79, 0x95,79, 0x96,48, 0x97,36, 0x98,52, 0x99,55, 0,45, 0x80, 0x86, 0,16, 0x81,
0x87, 0x82, 0x88, 0x83, 0x89, 0,20, 0x84, 0x85, 0,116, 0x90,48, 0x91,52, 0x92,55, 0x93,36, 0x94,76,
0x95,76, 0x96,48, 0x97,52, 0x98,55, 0x99,36, 0,41, 0x80, 0x86, 0,20, 0x81, 0x87, 0x82, 0x88, 0,4,
0x83, 0x89, 0,4, 0x84, 0x85, 0,133, 0x90,48, 0x91,52, 0x92,55, 0x93,36, 0x94,72, 0x95,72, 0x96,48,
0x97,52, 0x98,55, 0x99,36, 0,50, 0x80, 0x86, 0,4, 0x81, 0x87, 0,20, 0x82, 0x88, 0x83, 0x89, 0,12,
0x84, 0x85, 0,116, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,45, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,72,
0x91,72, 0x92,72, 0x93,72, 0,62, 0x80, 0x81, 0x82, 0x83, 0,37, 0x90,53, 0x91,57, 0x92,41, 0x93,72,
0x94,72, 0x95,53, 0x96,57, 0x97,41, 0x98,72, 0x99,72, 0,58, 0x80, 0x85, 0,12, 0x81, 0x86, 0,8,
0x82, 0x87, 0,12, 0x83, 0x84, 0x88, 0x89, 0,112, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,62, 0x80,
0x81, 0x82, 0x83, 0,37, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,62, 0x80, 0x81, 0x82, 0x83, 0,41,
0x90,53, 0x91,57, 0x92,41, 0x93,72, 0x94,72, 0x95,53, 0x96,57, 0x97,41, 0x98,72, 0x99,72, 0,50,
0x80, 0x85, 0,8, 0x81, 0x86, 0,8, 0x82, 0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,125, 0x90,72, 0x91,72,
0x92,72, 0x93,72, 0,41, 0x80, 0x81, 0x82, 0x83, 0,58, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,70,
0x80, 0x81, 0x82, 0x83, 0,33, 0x90,53, 0x91,57, 0x92,41, 0x93,77, 0x94,77, 0x95,53, 0x96,57, 0x97,41,
0x98,77, 0x99,77, 0,54, 0x80, 0x85, 0,8, 0x81, 0x86, 0x82, 0x87, 0,25, 0x83, 0x84, 0x88, 0x89, 0,116,
0x90,53, 0x91,41, 0x92,57, 0x93,79, 0x94,79, 0x95,53, 0x96,41, 0x97,57, 0x98,79, 0x99,79, 0,45,
0x80, 0x85, 0,4, 0x81, 0x86, 0,12, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,120, 0x90,53, 0x91,41,
0x92,57, 0x93,81, 0x94,81, 0x95,53, 0x96,41, 0x97,57, 0x98,81, 0x99,81, 0,58, 0x80, 0x85, 0x81,
0x86, 0,4, 0x82, 0x87, 0,4, 0x83, 0x84, 0x88, 0x89, 0,137, 0x90,77, 0x91,77, 0x92,77, 0x93,77,
0,87, 0x80, 0x81, 0x82, 0x83, 0,12, 0x90,81, 0x91,81, 0x92,81, 0x93,81, 0,75, 0x80, 0x81, 0x82,
0x83, 0,29, 0x90,36, 0x91,84, 0x92,84, 0x93,36, 0x94,84, 0x95,84, 0,104, 0x80, 0x83, 0,95,
0x90,52, 0x93,60, 0x96,58, 0x97,52, 0x98,60, 0x99,58, 0,37, 0x80, 0x87, 0,8, 0x83, 0x88, 0,8,
0x86, 0x89, 0,45, 0x90,52, 0x93,60, 0x96,58, 0x97,52, 0x98,60, 0x99,58, 0,33, 0x80, 0x87, 0,8,
0x83, 0x88, 0,8, 0x86, 0x89, 0,54, 0x90,52, 0x93,58, 0x96,60, 0x97,36, 0x98,52, 0x99,58, 0,62,
0x80, 0x88, 0,12, 0x83, 0x89, 0,4, 0x86, 0,20, 0x90,82, 0x93,82, 0x96,82, 0x98,82, 0,16,
0x87, 0,37, 0x81, 0x82, 0x84, 0x85, 0,29, 0x80, 0x83, 0x86, 0x88, 0,20, 0x90,81, 0x91,81, 0x92,81,
0x93,81, 0,100, 0x94,79, 0x95,79, 0x96,79, 0x97,79, 0,16, 0x80, 0x81, 0x82, 0x83, 0,75, 0x84,
0x85, 0x86, 0x87, 0,8, 0x90,53, 0x91,41, 0x92,57, 0x93,77, 0x94,77, 0x95,53, 0x96,41, 0x97,57,
0x98,77, 0x99,77, 0,66, 0x80, 0x85, 0x81, 0x86, 0,12, 0x82, 0x87, 0,70, 0x83, 0x84, 0x88, 0x89, 0,54,
0x90,60, 0x91,41, 0x92,81, 0x93,81, 0x94,60, 0x95,41, 0x96,81, 0x97,81, 0,50, 0x80, 0x84, 0,20,
0x81, 0x85, 0,129, 0x90,41, 0x91,53, 0x94,57, 0x95,77, 0x98,77, 0x99,41, 0,8, 0x82, 0x83, 0x86,
0x87, 0,83, 0x85, 0x88, 0x80, 0x89, 0x81, 0,8, 0x84, 0,104, 0x90,81, 0x91,77, 0x92,81, 0x93,77,
0x94,81, 0x95,77, 0x96,81, 0x97,77, 0,45, 0x80, 0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,54, 0x90,77,
0x91,81, 0x92,77, 0x93,81, 0x94,77, 0x95,81, 0x96,77, 0x97,81, 0,45, 0x80, 0x82, 0x84, 0x86, 0,4,
0x81, 0x83, 0x85, 0x87, 0,54, 0x90,62, 0x91,57, 0x92,53, 0x93,50, 0x94,38, 0x95,77, 0x96,81, 0x97,77,
0x98,81, 0x99,62, 0,66, 0x80, 0x89, 0x81, 0x82, 0x83, 0x84, 0,8, 0x85, 0x87, 0,8, 0x86, 0x88, 0,116,
0x90,81, 0x91,77, 0x92,81, 0x93,77, 0x94,81, 0x95,77, 0x96,81, 0x97,77, 0,54, 0x80, 0x82, 0x84,
0x86, 0x81, 0x83, 0x85, 0x87, 0,50, 0x90,77, 0x91,81, 0x92,77, 0x93,81, 0x94,77, 0x95,81, 0x96,77,
0x97,81, 0,41, 0x80, 0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,58, 0x90,62, 0x91,57, 0x92,53, 0x93,50,
0x94,38, 0x95,77, 0x96,81, 0x97,77, 0x98,81, 0x99,62, 0,62, 0x85, 0x87, 0,4, 0x80, 0x89, 0x81,
0x82, 0x83, 0x84, 0,8, 0x86, 0x88, 0,125, 0x90,77, 0x91,81, 0x92,77, 0x93,81, 0x94,77, 0x95,81,
0x96,77, 0x97,81, 0,41, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,58, 0x90,77, 0x91,81,
0x92,77, 0x93,81, 0x94,77, 0x95,81, 0x96,77, 0x97,81, 0,41, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81,
0x83, 0x85, 0x87, 0,54, 0x90,62, 0x91,57, 0x92,53, 0x93,50, 0x94,38, 0x95,81, 0x96,77, 0x97,81,
0x98,77, 0x99,62, 0,70, 0x80, 0x89, 0x81, 0x82, 0x83, 0x84, 0,25, 0x85, 0x87, 0,8, 0x86, 0x88, 0,100,
0x90,86, 0x91,86, 0x92,86, 0x93,86, 0,83, 0x80, 0x81, 0x82, 0x83, 0,116, 0x90,53, 0x91,62, 0x92,57,
0x93,50, 0x94,38, 0x95,77, 0x96,81, 0x97,77, 0x98,81, 0x99,53, 0,70, 0x80, 0x89, 0x81, 0x82, 0x83,
0x84, 0,12, 0x85, 0x87, 0x86, 0x88, 0,120, 0x90,86, 0x91,86, 0x92,86, 0x93,86, 0,83, 0x80, 0x81,
0x82, 0x83, 0,120, 0x90,38, 0x91,50, 0x92,57, 0x93,62, 0x94,53, 0x95,81, 0x96,77, 0x97,81, 0x98,77,
0x99,38, 0,75, 0x80, 0x89, 0x81, 0,8, 0x85, 0x87, 0,4, 0x82, 0x86, 0x88, 0,4, 0x83, 0,8,
0x84, 0,100, 0x90,86, 0x91,86, 0x92,86, 0x93,86, 0,95, 0x80, 0x81, 0x82, 0x83, 0,108, 0x90,38,
0x91,62, 0x92,50, 0x93,57, 0x94,53, 0x95,77, 0x96,81, 0x97,77, 0x98,81, 0x99,38, 0,79, 0x80,
0x89, 0,4, 0x81, 0,4, 0x85, 0x87, 0,16, 0x82, 0x83, 0,8, 0x84, 0x86, 0x88, 0,91, 0x90,79,
0x91,76, 0x92,79, 0x93,76, 0x94,79, 0x95,76, 0x96,79, 0x97,76, 0,75, 0x80, 0x82, 0x84, 0x86, 0,8,
0x81, 0x83, 0x85, 0x87, 0,116, 0x90,38, 0x91,50, 0x92,74, 0x93,77, 0x94,74, 0x95,77, 0x96,38, 0x97,50,
0x98,74, 0x99,77, 0,79, 0x82, 0x84, 0x88, 0x80, 0x86, 0,8, 0x81, 0x87, 0x83, 0x85, 0x89, 0,116, 0x90,58,
0x91,55, 0x92,73, 0x93,76, 0x94,73, 0x95,76, 0x96,58, 0x97,55, 0x98,73, 0x99,76, 0,75, 0x82,
0x84, 0x88, 0,4, 0x80, 0x86, 0,20, 0x81, 0x87, 0x83, 0x85, 0x89, 0,104, 0x90,38, 0x91,57, 0x92,53,
0x93,74, 0x94,74, 0x95,38, 0x96,57, 0x97,53, 0x98,74, 0x99,74, 0,79, 0x83, 0x84, 0x88, 0x89, 0,4,
0x80, 0x85, 0,8, 0x81, 0x86, 0,16, 0x82, 0x87, 0,91, 0x90,77, 0x91,81, 0x92,77, 0x93,81, 0x94,77,
0x95,81, 0x96,77, 0x97,81, 0,58, 0x80, 0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,45, 0x90,81, 0x91,77,
0x92,81, 0x93,77, 0x94,81, 0x95,77, 0x96,81, 0x97,77, 0,37, 0x80, 0x82, 0x84, 0x86, 0,29, 0x81,
0x83, 0x85, 0x87, 0,33, 0x90,50, 0x91,38, 0x92,57, 0x93,62, 0x94,53, 0x95,81, 0x96,77, 0x97,81,
0x98,77, 0x99,50, 0,37, 0x85, 0x87, 0,33, 0x86, 0x88, 0,4, 0x80, 0x89, 0,4, 0x81, 0,20,
0x82, 0,4, 0x83, 0,4, 0x84, 0,95, 0x90,77, 0x91,81, 0x92,77, 0x93,81, 0x94,77, 0x95,81,
0x96,77, 0x97,81, 0,45, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,50, 0x90,81, 0x91,77,
0x92,81, 0x93,77, 0x94,81, 0x95,77, 0x96,81, 0x97,77, 0,37, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81,
0x83, 0x85, 0x87, 0,58, 0x90,50, 0x91,53, 0x92,38, 0x93,57, 0x94,62, 0x95,81, 0x96,77, 0x97,81,
0x98,77, 0x99,50, 0,66, 0x85, 0x87, 0,4, 0x86, 0x88, 0,12, 0x80, 0x89, 0,4, 0x81, 0,4,
0x82, 0,8, 0x83, 0,4, 0x84, 0,100, 0x90,77, 0x91,81, 0x92,77, 0x93,81, 0x94,77, 0x95,81,
0x96,77, 0x97,81, 0,33, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,62, 0x90,81, 0x91,77,
0x92,81, 0x93,77, 0x94,81, 0x95,77, 0x96,81, 0x97,77, 0,37, 0x80, 0x82, 0x84, 0x86, 0x81, 0x83, 0x85,
0x87, 0,66, 0x90,50, 0x91,38, 0x92,53, 0x93,62, 0x94,57, 0x95,81, 0x96,77, 0x97,81, 0x98,77,
0x99,50, 0,70, 0x80, 0x89, 0x85, 0x87, 0,4, 0x81, 0,4, 0x86, 0x88, 0,12, 0x82, 0x83, 0,4,
0x84, 0,104, 0x90,86, 0x91,86, 0x92,86, 0x93,86, 0,75, 0x80, 0x81, 0x82, 0x83, 0,129, 0x90,50,
0x91,38, 0x92,57, 0x93,62, 0x94,53, 0x95,81, 0x96,77, 0x97,81, 0x98,77, 0x99,50, 0,66, 0x80,
0x89, 0x85, 0x87, 0,4, 0x86, 0x88, 0,4, 0x81, 0,8, 0x82, 0,4, 0x83, 0,8, 0x84, 0,108,
0x90,86, 0x91,86, 0x92,86, 0x93,86, 0,83, 0x80, 0x81, 0x82, 0x83, 0,116, 0x90,50, 0x91,57, 0x92,38,
0x93,53, 0x94,62, 0x95,77, 0x96,81, 0x97,77, 0x98,81, 0x99,50, 0,50, 0x80, 0x89, 0,8, 0x81,
0,20, 0x82, 0,4, 0x83, 0x85, 0x87, 0,4, 0x86, 0x88, 0,12, 0x84, 0,104, 0x90,86, 0x91,86,
0x92,86, 0x93,86, 0,95, 0x80, 0x81, 0x82, 0x83, 0,108, 0x90,55, 0x91,60, 0x92,43, 0x93,76, 0x94,84,
0x95,76, 0x96,84, 0x97,55, 0x98,60, 0x99,43, 0,58, 0x83, 0x85, 0,33, 0x84, 0x86, 0,41, 0x80,
0x87, 0,4, 0x81, 0x88, 0,62, 0x90,62, 0x91,55, 0x93,77, 0x94,83, 0x95,77, 0x96,83, 0x97,62,
0x98,55, 0,12, 0x82, 0x89, 0,41, 0x80, 0x87, 0,12, 0x81, 0x88, 0,8, 0x83, 0x85, 0,25, 0x84,
0x86, 0,104, 0x90,55, 0x91,43, 0x92,60, 0x93,76, 0x94,84, 0x95,76, 0x96,84, 0x97,55, 0x98,43,
0x99,60, 0,70, 0x83, 0x85, 0,29, 0x84, 0x86, 0,4, 0x80, 0x87, 0,20, 0x81, 0x88, 0x82, 0x89, 0,79,
0x90,55, 0x91,62, 0x92,77, 0x93,83, 0x94,77, 0x95,83, 0x96,55, 0x97,62, 0x98,77, 0x99,83, 0,66,
0x80, 0x86, 0,4, 0x82, 0x84, 0x88, 0,4, 0x81, 0x87, 0,12, 0x83, 0x85, 0x89, 0,112, 0x90,60, 0x91,55,
0x92,36, 0x93,76, 0x94,84, 0x95,76, 0x96,84, 0x97,60, 0x98,55, 0x99,36, 0,62, 0x83, 0x85, 0,29,
0x84, 0x86, 0,75, 0x80, 0x87, 0,4, 0x81, 0x88, 0,33, 0x82, 0x89, 0x90,81, 0x91,77, 0x92,81, 0x93,77,
0x94,81, 0x95,77, 0x96,81, 0x97,77, 0,41, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,54,
0x90,77, 0x91,81, 0x92,77, 0x93,81, 0x94,77, 0x95,81, 0x96,77, 0x97,81, 0,37, 0x80, 0x82, 0x84,
0x86, 0,12, 0x81, 0x83, 0x85, 0x87, 0,50, 0x90,50, 0x91,38, 0x92,57, 0x93,53, 0x94,62, 0x95,77,
0x96,81, 0x97,77, 0x98,81, 0x99,50, 0,62, 0x80, 0x89, 0x85, 0x87, 0,4, 0x86, 0x88, 0,29, 0x81,
0,12, 0x82, 0,4, 0x83, 0,8, 0x84, 0,83, 0x90,81, 0x91,77, 0x92,81, 0x93,77, 0x94,81,
0x95,77, 0x96,81, 0x97,77, 0,50, 0x80, 0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,50, 0x90,77, 0x91,81,
0x92,77, 0x93,81, 0x94,77, 0x95,81, 0x96,77, 0x97,81, 0,41, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81,
0x83, 0x85, 0x87, 0,58, 0x90,50, 0x91,38, 0x92,57, 0x93,62, 0x94,53, 0x95,77, 0x96,81, 0x97,77,
0x98,81, 0x99,50, 0,62, 0x85, 0x87, 0,8, 0x80, 0x89, 0,4, 0x86, 0x88, 0,8, 0x81, 0,20,
0x82, 0x83, 0,8, 0x84, 0,87, 0x90,77, 0x91,81, 0x92,77, 0x93,81, 0x94,77, 0x95,81, 0x96,77,
0x97,81, 0,37, 0x80, 0x82, 0x84, 0x86, 0,8, 0x81, 0x83, 0x85, 0x87, 0,58, 0x90,77, 0x91,81, 0x92,77,
0x93,81, 0x94,77, 0x95,81, 0x96,77, 0x97,81, 0,41, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85,
0x87, 0,54, 0x90,50, 0x91,38, 0x92,57, 0x93,62, 0x94,53, 0x95,81, 0x96,77, 0x97,81, 0x98,77,
0x99,50, 0,62, 0x80, 0x89, 0,16, 0x81, 0,16, 0x85, 0x87, 0,4, 0x82, 0,4, 0x83, 0x86, 0x88,
0,8, 0x84, 0,91, 0x90,86, 0x91,86, 0x92,86, 0x93,86, 0,83, 0x80, 0x81, 0x82, 0x83, 0,116,
0x90,50, 0x91,38, 0x92,57, 0x93,62, 0x94,53, 0x95,77, 0x96,81, 0x97,77, 0x98,81, 0x99,50, 0,70,
0x80, 0x89, 0,8, 0x81, 0x85, 0x87, 0x86, 0x88, 0,16, 0x82, 0,8, 0x83, 0,12, 0x84, 0,87, 0x90,86,
0x91,86, 0x92,86, 0x93,86, 0,83, 0x80, 0x81, 0x82, 0x83, 0,116, 0x90,38, 0x91,50, 0x92,57, 0x93,62,
0x94,53, 0x95,81, 0x96,77, 0x97,81, 0x98,77, 0x99,38, 0,83, 0x80, 0x89, 0x85, 0x87, 0,8, 0x81,
0x86, 0x88, 0,20, 0x82, 0,4, 0x83, 0x84, 0,87, 0x90,86, 0x91,86, 0x92,86, 0x93,86, 0,95,
0x80, 0x81, 0x82, 0x83, 0,108, 0x90,50, 0x91,38, 0x92,57, 0x93,62, 0x94,53, 0x95,77, 0x96,81, 0x97,77,
0x98,81, 0x99,50, 0,79, 0x80, 0x89, 0,8, 0x85, 0x87, 0,4, 0x81, 0,8, 0x82, 0,8, 0x86,
0x88, 0,4, 0x83, 0,16, 0x84, 0,70, 0x90,79, 0x91,76, 0x92,79, 0x93,76, 0x94,79, 0x95,76,
0x96,79, 0x97,76, 0,75, 0x80, 0x82, 0x84, 0x86, 0,12, 0x81, 0x83, 0x85, 0x87, 0,116, 0x90,50, 0x91,38,
0x92,74, 0x93,77, 0x94,74, 0x95,77, 0x96,50, 0x97,38, 0x98,74, 0x99,77, 0,79, 0x82, 0x84, 0x88,
0x80, 0x86, 0,8, 0x81, 0x87, 0x83, 0x85, 0x89, 0,116, 0x90,58, 0x91,55, 0x92,73, 0x93,76, 0x94,73,
0x95,76, 0x96,58, 0x97,55, 0x98,73, 0x99,76, 0,75, 0x82, 0x84, 0x88, 0,25, 0x83, 0x85, 0x89, 0,4,
0x80, 0x86, 0,4, 0x81, 0x87, 0,91, 0x90,53, 0x91,57, 0x92,74, 0x93,74, 0x94,53, 0x95,57, 0x96,74,
0x97,74, 0,83, 0x82, 0x83, 0x86, 0x87, 0,8, 0x80, 0x84, 0,12, 0x81, 0x85, 0,100, 0x90,77, 0x91,81,
0x92,77, 0x93,81, 0x94,77, 0x95,81, 0x96,77, 0x97,81, 0,54, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81,
0x83, 0x85, 0x87, 0,45, 0x90,81, 0x91,77, 0x92,81, 0x93,77, 0x94,81, 0x95,77, 0x96,81, 0x97,77,
0,37, 0x80, 0x82, 0x84, 0x86, 0,29, 0x81, 0x83, 0x85, 0x87, 0,33, 0x90,50, 0x91,38, 0x92,57, 0x93,53,
0x94,62, 0x95,81, 0x96,77, 0x97,81, 0x98,77, 0x99,50, 0,33, 0x85, 0x87, 0,33, 0x86, 0x88, 0,8,
0x80, 0x89, 0,8, 0x81, 0,12, 0x82, 0,16, 0x83, 0x84, 0,87, 0x90,77, 0x91,81, 0x92,77, 0x93,81,
0x94,77, 0x95,81, 0x96,77, 0x97,81, 0,50, 0x80, 0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,54, 0x90,81,
0x91,77, 0x92,81, 0x93,77, 0x94,81, 0x95,77, 0x96,81, 0x97,77, 0,37, 0x80, 0x82, 0x84, 0x86, 0,4,
0x81, 0x83, 0x85, 0x87, 0,58, 0x90,38, 0x91,50, 0x92,57, 0x93,62, 0x94,53, 0x95,81, 0x96,77, 0x97,81,
0x98,77, 0x99,38, 0,62, 0x85, 0x87, 0,8, 0x86, 0x88, 0,8, 0x80, 0x89, 0x81, 0,29, 0x82, 0,4,
0x83, 0,4, 0x84, 0,87, 0x90,77, 0x91,81, 0x92,77, 0x93,81, 0x94,77, 0x95,81, 0x96,77, 0x97,81,
0,33, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,62, 0x90,81, 0x91,77, 0x92,81, 0x93,77,
0x94,81, 0x95,77, 0x96,81, 0x97,77, 0,37, 0x80, 0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,62, 0x90,50,
0x91,38, 0x92,57, 0x93,62, 0x94,53, 0x95,81, 0x96,77, 0x97,81, 0x98,77, 0x99,50, 0,75, 0x85,
0x87, 0,4, 0x80, 0x89, 0,4, 0x81, 0x86, 0x88, 0,12, 0x82, 0,4, 0x83, 0,4, 0x84, 0,100,
0x90,86, 0x91,86, 0x92,86, 0x93,86, 0,75, 0x80, 0x81, 0x82, 0x83, 0,129, 0x90,50, 0x91,38, 0x92,62,
0x93,57, 0x94,53, 0x95,81, 0x96,77, 0x97,81, 0x98,77, 0x99,50, 0,62, 0x85, 0x87, 0,4, 0x80,
0x89, 0,4, 0x86, 0x88, 0,4, 0x81, 0,16, 0x82, 0x83, 0,8, 0x84, 0,100, 0x90,86, 0x91,86,
0x92,86, 0x93,86, 0,87, 0x80, 0x81, 0x82, 0x83, 0,116, 0x90,50, 0x91,57, 0x92,38, 0x93,53, 0x94,62,
0x95,77, 0x96,81, 0x97,77, 0x98,81, 0x99,50, 0,58, 0x80, 0x89, 0,4, 0x81, 0,8, 0x82, 0,12,
0x85, 0x87, 0x83, 0,4, 0x86, 0x88, 0,16, 0x84, 0,100, 0x90,86, 0x91,86, 0x92,86, 0x93,86, 0,91,
0x80, 0x81, 0x82, 0x83, 0,108, 0x90,55, 0x91,60, 0x92,43, 0x93,76, 0x94,84, 0x95,76, 0x96,84, 0x97,55,
0x98,60, 0x99,43, 0,58, 0x83, 0x85, 0,12, 0x80, 0x87, 0,8, 0x81, 0x88, 0,12, 0x84, 0x86, 0,29,
0x82, 0x89, 0,83, 0x90,55, 0x91,62, 0x92,77, 0x93,83, 0x94,77, 0x95,83, 0x96,55, 0x97,62, 0x98,77,
0x99,83, 0,66, 0x80, 0x86, 0,4, 0x81, 0x87, 0,4, 0x82, 0x84, 0x88, 0,20, 0x83, 0x85, 0x89, 0,108,
0x90,60, 0x91,36, 0x92,76, 0x93,84, 0x94,76, 0x95,84, 0x96,60, 0x97,36, 0x98,76, 0x99,84, 0,70,
0x82, 0x84, 0x88, 0,8, 0x80, 0x86, 0,12, 0x81, 0x87, 0,4, 0x83, 0x85, 0x89, 2,0, 0x90,67, 0x91,60,
0x92,67, 0x93,60, 0x94,67, 0x95,60, 0x96,67, 0x97,60, 0,41, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81,
0x83, 0x85, 0x87, 0,54, 0x90,60, 0x91,67, 0x92,60, 0x93,67, 0x94,60, 0x95,67, 0x96,60, 0x97,67,
0,33, 0x80, 0x82, 0x84, 0x86, 0,16, 0x81, 0x83, 0x85, 0x87, 0,50, 0x90,60, 0x91,67, 0x92,60, 0x93,67,
0x94,60, 0x95,67, 0x96,60, 0x97,67, 0,66, 0x80, 0x82, 0x84, 0x86, 0,8, 0x81, 0x83, 0x85, 0x87, 0,129,
0x90,60, 0x91,67, 0x92,60, 0x93,67, 0x94,60, 0x95,67, 0x96,60, 0x97,67, 0,50, 0x80, 0x82, 0x84,
0x86, 0x81, 0x83, 0x85, 0x87, 0,50, 0x90,60, 0x91,67, 0x92,60, 0x93,67, 0x94,60, 0x95,67, 0x96,60,
0x97,67, 0,45, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,54, 0x90,60, 0x91,67, 0x92,60,
0x93,67, 0x94,60, 0x95,67, 0x96,60, 0x97,67, 0,58, 0x80, 0x82, 0x84, 0x86, 0,12, 0x81, 0x83, 0x85,
0x87, 0,129, 0x90,69, 0x91,65, 0x92,69, 0x93,65, 0x94,69, 0x95,65, 0x96,69, 0x97,65, 0,58,
0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,141, 0x90,67, 0x91,70, 0x92,67, 0x93,70, 0x94,67,
0x95,70, 0x96,67, 0x97,70, 0,58, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,137, 0x90,48,
0x91,67, 0x92,60, 0x93,67, 0x94,60, 0x95,48, 0x96,67, 0x97,60, 0x98,67, 0x99,60, 0,45, 0x80,
0x85, 0,158, 0x90,50, 0x95,50, 0,41, 0x81, 0x83, 0x86, 0x88, 0x80, 0x85, 0,16, 0x82, 0x84, 0x87, 0x89,
0,145, 0x90,52, 0x91,67, 0x92,70, 0x93,67, 0x94,70, 0x95,52, 0x96,67, 0x97,70, 0x98,67, 0x99,70,
0,33, 0x80, 0x85, 0,37, 0x81, 0x83, 0x86, 0x88, 0x82, 0x84, 0x87, 0x89, 0,129, 0x90,53, 0x91,69, 0x92,65,
0x93,69, 0x94,65, 0x95,53, 0x96,69, 0x97,65, 0x98,69, 0x99,65, 0,45, 0x80, 0x85, 0,33, 0x81,
0x83, 0x86, 0x88, 0,4, 0x82, 0x84, 0x87, 0x89, 0,120, 0x90,55, 0x91,65, 0x92,65, 0x93,55, 0x94,65,
0x95,65, 0,54, 0x80, 0x83, 0,150, 0x90,57, 0x93,57, 0,45, 0x80, 0x83, 0,8, 0x81, 0x82, 0x84,
0x85, 0,145, 0x90,59, 0x91,69, 0x92,65, 0x93,69, 0x94,65, 0x95,59, 0x96,69, 0x97,65, 0x98,69,
0x99,65, 0,45, 0x80, 0x85, 0,16, 0x81, 0x83, 0x86, 0x88, 0,8, 0x82, 0x84, 0x87, 0x89, 0,133, 0x90,60,
0x91,64, 0x92,67, 0x93,64, 0x94,67, 0x95,60, 0x96,64, 0x97,67, 0x98,64, 0x99,67, 0,58, 0x80,
0x85, 0,8, 0x81, 0x83, 0x86, 0x88, 0x82, 0x84, 0x87, 0x89, 0,133, 0x90,48, 0x91,67, 0x92,64, 0x93,67,
0x94,64, 0x95,48, 0x96,67, 0x97,64, 0x98,67, 0x99,64, 0,41, 0x80, 0x85, 0,25, 0x81, 0x83, 0x86,
0x88, 0,4, 0x82, 0x84, 0x87, 0x89, 0,133, 0x90,60, 0x91,64, 0x92,67, 0x93,64, 0x94,67, 0x95,60,
0x96,64, 0x97,67, 0x98,64, 0x99,67, 0,45, 0x80, 0x85, 0,16, 0x81, 0x83, 0x86, 0x88, 0x82, 0x84, 0x87,
0x89, 0,141, 0x90,60, 0x91,67, 0x92,60, 0x93,67, 0x94,60, 0x95,67, 0x96,60, 0x97,67, 0,58,
0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,37, 0x90,60, 0x91,67, 0x92,60, 0x93,67, 0x94,60,
0x95,67, 0x96,60, 0x97,67, 0,37, 0x80, 0x82, 0x84, 0x86, 0,16, 0x81, 0x83, 0x85, 0x87, 0,45, 0x90,60,
0x91,67, 0x92,60, 0x93,67, 0x94,60, 0x95,67, 0x96,60, 0x97,67, 0,58, 0x80, 0x82, 0x84, 0x86, 0,16,
0x81, 0x83, 0x85, 0x87, 0,129, 0x90,60, 0x91,67, 0x92,60, 0x93,67, 0x94,60, 0x95,67, 0x96,60, 0x97,67,
0,45, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,54, 0x90,60, 0x91,67, 0x92,60, 0x93,67,
0x94,60, 0x95,67, 0x96,60, 0x97,67, 0,37, 0x80, 0x82, 0x84, 0x86, 0,12, 0x81, 0x83, 0x85, 0x87, 0,50,
0x90,60, 0x91,67, 0x92,60, 0x93,67, 0x94,60, 0x95,67, 0x96,60, 0x97,67, 0,50, 0x80, 0x82, 0x84,
0x86, 0,16, 0x81, 0x83, 0x85, 0x87, 0,133, 0x90,65, 0x91,69, 0x92,65, 0x93,69, 0x94,65, 0x95,69,
0x96,65, 0x97,69, 0,58, 0x80, 0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,145, 0x90,67, 0x91,70, 0x92,67,
0x93,70, 0x94,67, 0x95,70, 0x96,67, 0x97,70, 0,58, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85,
0x87, 0,141, 0x90,48, 0x91,67, 0x92,60, 0x93,67, 0x94,60, 0x95,48, 0x96,67, 0x97,60, 0x98,67,
0x99,60, 0,50, 0x80, 0x85, 0,150, 0x90,50, 0x95,50, 0,50, 0x80, 0x85, 0,12, 0x81, 0x83, 0x86,
0x88, 0,4, 0x82, 0x84, 0x87, 0x89, 0,137, 0x90,52, 0x91,67, 0x92,70, 0x93,67, 0x94,70, 0x95,52,
0x96,67, 0x97,70, 0x98,67, 0x99,70, 0,37, 0x80, 0x85, 0,33, 0x81, 0x83, 0x86, 0x88, 0,4, 0x82,
0x84, 0x87, 0x89, 0,129, 0x90,53, 0x91,65, 0x92,69, 0x93,65, 0x94,69, 0x95,53, 0x96,65, 0x97,69,
0x98,65, 0x99,69, 0,41, 0x80, 0x85, 0,16, 0x81, 0x83, 0x86, 0x88, 0x82, 0x84, 0x87, 0x89, 0,141, 0x90,55,
0x91,65, 0x92,65, 0x93,55, 0x94,65, 0x95,65, 0,58, 0x80, 0x83, 0,145, 0x90,57, 0x93,57, 0,20,
0x81, 0x82, 0x84, 0x85, 0,33, 0x80, 0x83, 0,150, 0x90,59, 0x91,69, 0x92,65, 0x93,69, 0x94,65, 0x95,59,
0x96,69, 0x97,65, 0x98,69, 0x99,65, 0,45, 0x80, 0x85, 0x81, 0x83, 0x86, 0x88, 0,12, 0x82, 0x84, 0x87,
0x89, 0,141, 0x90,60, 0x91,67, 0x92,64, 0x93,67, 0x94,64, 0x95,60, 0x96,67, 0x97,64, 0x98,67,
0x99,64, 0,50, 0x80, 0x85, 0,154, 0x90,48, 0x95,48, 0,37, 0x80, 0x85, 0,87, 0x81, 0x83, 0x86,
0x88, 0,4, 0x82, 0x84, 0x87, 0x89, 0,75, 0x90,60, 0x91,60, 0,41, 0x80, 0x81, 0,158, 0x90,60,
0x91,60, 0x92,60, 0x93,60, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,60, 0x91,60, 0x92,60, 0x93,60,
0,54, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,41, 0x91,57, 0x92,53, 0x93,60, 0x94,60, 0x95,41, 0x96,57,
0x97,53, 0x98,60, 0x99,60, 0,54, 0x80, 0x85, 0,8, 0x81, 0x86, 0,4, 0x82, 0x87, 0,16, 0x83,
0x84, 0x88, 0x89, 0,120, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,45, 0x80, 0x81, 0x82, 0x83, 0,54,
0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,57, 0x91,53, 0x92,41,
0x93,60, 0x94,60, 0x95,57, 0x96,53, 0x97,41, 0x98,60, 0x99,60, 0,75, 0x80, 0x85, 0x83, 0x84, 0x88,
0x89, 0x81, 0x86, 0,4, 0x82, 0x87, 0,125, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,41, 0x80, 0x81,
0x82, 0x83, 0,58, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,66, 0x80, 0x81, 0x82, 0x83, 0,37, 0x90,57,
0x91,41, 0x92,53, 0x93,65, 0x94,65, 0x95,57, 0x96,41, 0x97,53, 0x98,65, 0x99,65, 0,58, 0x80,
0x85, 0,4, 0x81, 0x86, 0x82, 0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,129, 0x90,53, 0x91,57, 0x92,41,
0x93,67, 0x94,67, 0x95,53, 0x96,57, 0x97,41, 0x98,67, 0x99,67, 0,54, 0x80, 0x85, 0,8, 0x81,
0x86, 0,4, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,120, 0x90,57, 0x91,53, 0x92,41, 0x93,69,
0x94,69, 0x95,57, 0x96,53, 0x97,41, 0x98,69, 0x99,69, 0,54, 0x80, 0x85, 0x81, 0x86, 0,16, 0x82,
0x87, 0x83, 0x84, 0x88, 0x89, 0,133, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,41, 0x80, 0x81, 0x82, 0x83,
0,58, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,53, 0x91,57,
0x92,41, 0x93,60, 0x94,60, 0x95,53, 0x96,57, 0x97,41, 0x98,60, 0x99,60, 0,54, 0x80, 0x85, 0,4,
0x81, 0x86, 0,8, 0x82, 0x87, 0,4, 0x83, 0x84, 0x88, 0x89, 0,133, 0x90,60, 0x91,60, 0x92,60, 0x93,60,
0,45, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,62, 0x80, 0x81, 0x82,
0x83, 0,37, 0x90,53, 0x91,57, 0x92,41, 0x93,65, 0x94,65, 0x95,53, 0x96,57, 0x97,41, 0x98,65,
0x99,65, 0,62, 0x80, 0x85, 0x81, 0x86, 0,8, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,116, 0x90,69,
0x91,69, 0x92,69, 0x93,69, 0,45, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,69, 0x91,69, 0x92,69, 0x93,69,
0,66, 0x80, 0x81, 0x82, 0x83, 0,37, 0x90,48, 0x91,36, 0x92,52, 0x93,55, 0x94,67, 0x95,67, 0x96,48,
0x97,36, 0x98,52, 0x99,55, 0,45, 0x80, 0x86, 0,16, 0x81, 0x87, 0x82, 0x88, 0x83, 0x89, 0,4, 0x84,
0x85, 0,133, 0x90,48, 0x91,52, 0x92,55, 0x93,36, 0x94,64, 0x95,64, 0x96,48, 0x97,52, 0x98,55,
0x99,36, 0,41, 0x80, 0x86, 0,20, 0x81, 0x87, 0x82, 0x88, 0,4, 0x83, 0x89, 0,4, 0x84, 0x85, 0,133,
0x90,48, 0x91,52, 0x92,55, 0x93,36, 0x94,60, 0x95,60, 0x96,48, 0x97,52, 0x98,55, 0x99,36, 0,50,
0x80, 0x86, 0,4, 0x81, 0x87, 0,20, 0x82, 0x88, 0x83, 0x89, 0,4, 0x84, 0x85, 0,125, 0x90,60, 0x91,60,
0x92,60, 0x93,60, 0,45, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,58,
0x80, 0x81, 0x82, 0x83, 0,41, 0x90,53, 0x91,57, 0x92,41, 0x93,60, 0x94,60, 0x95,53, 0x96,57, 0x97,41,
0x98,60, 0x99,60, 0,58, 0x80, 0x85, 0,12, 0x81, 0x86, 0,8, 0x82, 0x87, 0x83, 0x84, 0x88, 0x89, 0,125,
0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,60, 0x91,60, 0x92,60,
0x93,60, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,53, 0x91,57, 0x92,41, 0x93,60, 0x94,60, 0x95,53,
0x96,57, 0x97,41, 0x98,60, 0x99,60, 0,54, 0x80, 0x85, 0,8, 0x83, 0x84, 0x88, 0x89, 0x81, 0x86, 0,8,
0x82, 0x87, 0,133, 0x90,60, 0x91,60, 0x92,60, 0x93,60, 0,50, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,60,
0x91,60, 0x92,60, 0x93,60, 0,41, 0x80, 0x81, 0x82, 0x83, 0,58, 0x90,53, 0x91,57, 0x92,41, 0x93,65,
0x94,65, 0x95,53, 0x96,57, 0x97,41, 0x98,65, 0x99,65, 0,50, 0x80, 0x85, 0,12, 0x81, 0x86, 0x82,
0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,120, 0x90,53, 0x91,41, 0x92,57, 0x93,67, 0x94,67, 0x95,53,
0x96,41, 0x97,57, 0x98,67, 0x99,67, 0,50, 0x80, 0x85, 0,4, 0x81, 0x86, 0,12, 0x82, 0x87, 0,4,
0x83, 0x84, 0x88, 0x89, 0,133, 0x90,53, 0x91,41, 0x92,57, 0x93,69, 0x94,69, 0x95,53, 0x96,41, 0x97,57,
0x98,69, 0x99,69, 0,58, 0x80, 0x85, 0x81, 0x86, 0,4, 0x82, 0x87, 0,20, 0x83, 0x84, 0x88, 0x89, 0,120,
0x90,65, 0x91,65, 0x92,65, 0x93,65, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,69, 0x91,69, 0x92,69,
0x93,69, 0,62, 0x80, 0x81, 0x82, 0x83, 0,37, 0x90,36, 0x91,72, 0x92,72, 0x93,36, 0x94,72, 0x95,72,
0,108, 0x80, 0x83, 0,95, 0x90,52, 0x93,60, 0x96,58, 0x97,52, 0x98,60, 0x99,58, 0,37, 0x80,
0x87, 0,8, 0x83, 0x88, 0,8, 0x86, 0x89, 0,50, 0x90,52, 0x93,60, 0x96,58, 0x97,52, 0x98,60,
0x99,58, 0,33, 0x80, 0x87, 0,8, 0x83, 0x88, 0,8, 0x86, 0x89, 0,50, 0x90,52, 0x93,58, 0x96,60,
0x97,36, 0x98,52, 0x99,58, 0,58, 0x80, 0x88, 0,16, 0x83, 0x89, 0x86, 0,25, 0x90,70, 0x93,70,
0x96,70, 0x98,70, 0,16, 0x87, 0,37, 0x81, 0x82, 0x84, 0x85, 0,20, 0x80, 0x83, 0x86, 0x88, 0,25,
0x90,69, 0x91,69, 0x92,69, 0x93,69, 0,95, 0x80, 0x81, 0x82, 0x83, 0,8, 0x90,67, 0x91,67, 0x92,67,
0x93,67, 0,95, 0x80, 0x81, 0x82, 0x83, 0,4, 0x90,53, 0x91,41, 0x92,57, 0x93,65, 0x94,65, 0x95,53,
0x96,41, 0x97,57, 0x98,65, 0x99,65, 0,66, 0x80, 0x85, 0x81, 0x86, 0,12, 0x82, 0x87, 0,66, 0x83,
0x84, 0x88, 0x89, 0,58, 0x90,60, 0x91,41, 0x92,69, 0x93,69, 0x94,60, 0x95,41, 0x96,69, 0x97,69,
0,50, 0x80, 0x84, 0,4, 0x82, 0x83, 0x86, 0x87, 0,12, 0x81, 0x85, 0,133, 0x90,41, 0x91,53, 0x92,57,
0x93,65, 0x94,65, 0x95,41, 0x96,53, 0x97,57, 0x98,65, 0x99,65, 0,91, 0x83, 0x84, 0x88, 0x89, 0x80,
0x85, 0x81, 0x86, 0,8, 0x82, 0x87, 0,104, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,66, 0x80, 0x81,
0x82, 0x83, 0,33, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,70, 0x80, 0x81, 0x82, 0x83, 0,33, 0x90,41,
0x91,57, 0x92,53, 0x93,72, 0x94,72, 0x95,41, 0x96,57, 0x97,53, 0x98,72, 0x99,72, 0,54, 0x80,
0x85, 0,4, 0x81, 0x86, 0,8, 0x82, 0x87, 0x83, 0x84, 0x88, 0x89, 0,133, 0x90,72, 0x91,72, 0x92,72,
0x93,72, 0,50, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,45, 0x80,
0x81, 0x82, 0x83, 0,54, 0x90,57, 0x91,53, 0x92,41, 0x93,72, 0x94,72, 0x95,57, 0x96,53, 0x97,41,
0x98,72, 0x99,72, 0,75, 0x80, 0x85, 0x83, 0x84, 0x88, 0x89, 0x81, 0x86, 0,4, 0x82, 0x87, 0,125, 0x90,72,
0x91,72, 0x92,72, 0x93,72, 0,45, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,72, 0x91,72, 0x92,72, 0x93,72,
0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,57, 0x91,41, 0x92,53, 0x93,77, 0x94,77, 0x95,57, 0x96,41,
0x97,53, 0x98,77, 0x99,77, 0,62, 0x80, 0x85, 0,4, 0x81, 0x86, 0x82, 0x87, 0,25, 0x83, 0x84, 0x88,
0x89, 0,112, 0x90,53, 0x91,57, 0x92,41, 0x93,79, 0x94,79, 0x95,53, 0x96,57, 0x97,41, 0x98,79,
0x99,79, 0,54, 0x80, 0x85, 0,8, 0x81, 0x86, 0,4, 0x82, 0x87, 0,12, 0x83, 0x84, 0x88, 0x89, 0,125,
0x90,57, 0x91,53, 0x92,41, 0x93,81, 0x94,81, 0x95,57, 0x96,53, 0x97,41, 0x98,81, 0x99,81, 0,50,
0x80, 0x85, 0,4, 0x81, 0x86, 0,12, 0x82, 0x87, 0,41, 0x83, 0x84, 0x88, 0x89, 0,91, 0x90,72, 0x91,72,
0x92,72, 0x93,72, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,41,
0x80, 0x81, 0x82, 0x83, 0,62, 0x90,53, 0x91,57, 0x92,41, 0x93,72, 0x94,72, 0x95,53, 0x96,57, 0x97,41,
0x98,72, 0x99,72, 0,54, 0x80, 0x85, 0,4, 0x81, 0x86, 0,8, 0x82, 0x87, 0,4, 0x83, 0x84, 0x88,
0x89, 0,133, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,41, 0x80, 0x81, 0x82, 0x83, 0,58, 0x90,72,
0x91,72, 0x92,72, 0x93,72, 0,62, 0x80, 0x81, 0x82, 0x83, 0,37, 0x90,53, 0x91,57, 0x92,41, 0x93,77,
0x94,77, 0x95,53, 0x96,57, 0x97,41, 0x98,77, 0x99,77, 0,62, 0x80, 0x85, 0x81, 0x86, 0,4, 0x82,
0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,129, 0x90,81, 0x91,81, 0x92,81, 0x93,81, 0,45, 0x80, 0x81,
0x82, 0x83, 0,54, 0x90,81, 0x91,81, 0x92,81, 0x93,81, 0,70, 0x80, 0x81, 0x82, 0x83, 0,33, 0x90,48,
0x91,36, 0x92,52, 0x93,55, 0x94,79, 0x95,79, 0x96,48, 0x97,36, 0x98,52, 0x99,55, 0,41, 0x80,
0x86, 0,20, 0x81, 0x87, 0x82, 0x88, 0x83, 0x89, 0,20, 0x84, 0x85, 0,116, 0x90,48, 0x91,52, 0x92,55,
0x93,36, 0x94,76, 0x95,76, 0x96,48, 0x97,52, 0x98,55, 0x99,36, 0,41, 0x80, 0x86, 0,20, 0x81,
0x87, 0x82, 0x88, 0,4, 0x83, 0x89, 0,4, 0x84, 0x85, 0,133, 0x90,48, 0x91,52, 0x92,55, 0x93,36,
0x94,72, 0x95,72, 0x96,48, 0x97,52, 0x98,55, 0x99,36, 0,45, 0x80, 0x86, 0,8, 0x81, 0x87, 0,20,
0x82, 0x88, 0x83, 0x89, 0,12, 0x84, 0x85, 0,112, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,50, 0x80,
0x81, 0x82, 0x83, 0,54, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,62, 0x80, 0x81, 0x82, 0x83, 0,37,
0x90,53, 0x91,57, 0x92,41, 0x93,72, 0x94,72, 0x95,53, 0x96,57, 0x97,41, 0x98,72, 0x99,72, 0,58,
0x80, 0x85, 0,12, 0x81, 0x86, 0,8, 0x82, 0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,116, 0x90,72, 0x91,72,
0x92,72, 0x93,72, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,58,
0x80, 0x81, 0x82, 0x83, 0,41, 0x90,53, 0x91,57, 0x92,41, 0x93,72, 0x94,72, 0x95,53, 0x96,57, 0x97,41,
0x98,72, 0x99,72, 0,54, 0x80, 0x85, 0,8, 0x81, 0x86, 0,8, 0x82, 0x87, 0,8, 0x83, 0x84, 0x88,
0x89, 0,125, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,41, 0x80, 0x81, 0x82, 0x83, 0,58, 0x90,72,
0x91,72, 0x92,72, 0x93,72, 0,70, 0x80, 0x81, 0x82, 0x83, 0,33, 0x90,53, 0x91,57, 0x92,41, 0x93,77,
0x94,77, 0x95,53, 0x96,57, 0x97,41, 0x98,77, 0x99,77, 0,50, 0x80, 0x85, 0,12, 0x81, 0x86, 0x82,
0x87, 0,25, 0x83, 0x84, 0x88, 0x89, 0,112, 0x90,53, 0x91,41, 0x92,57, 0x93,79, 0x94,79, 0x95,53,
0x96,41, 0x97,57, 0x98,79, 0x99,79, 0,50, 0x80, 0x85, 0,4, 0x81, 0x86, 0,12, 0x82, 0x87, 0,16,
0x83, 0x84, 0x88, 0x89, 0,120, 0x90,53, 0x91,41, 0x92,57, 0x93,81, 0x94,81, 0x95,53, 0x96,41, 0x97,57,
0x98,81, 0x99,81, 0,58, 0x80, 0x85, 0x81, 0x86, 0,4, 0x82, 0x87, 0,4, 0x83, 0x84, 0x88, 0x89, 0,133,
0x90,77, 0x91,77, 0x92,77, 0x93,77, 0,91, 0x80, 0x81, 0x82, 0x83, 0,12, 0x90,81, 0x91,81, 0x92,81,
0x93,81, 0,75, 0x80, 0x81, 0x82, 0x83, 0,25, 0x90,36, 0x91,84, 0x92,84, 0x93,36, 0x94,84, 0x95,84,
0,108, 0x80, 0x83, 0,95, 0x90,52, 0x93,60, 0x96,58, 0x97,52, 0x98,60, 0x99,58, 0,33, 0x80,
0x87, 0,8, 0x83, 0x88, 0,12, 0x86, 0x89, 0,45, 0x90,52, 0x93,60, 0x96,58, 0x97,52, 0x98,60,
0x99,58, 0,33, 0x80, 0x87, 0,8, 0x83, 0x88, 0,8, 0x86, 0x89, 0,50, 0x90,52, 0x93,58, 0x96,60,
0x97,36, 0x98,52, 0x99,58, 0,62, 0x80, 0x88, 0,16, 0x83, 0x89, 0x86, 0,25, 0x90,82, 0x93,82,
0x96,82, 0x98,82, 0,12, 0x87, 0,41, 0x81, 0x82, 0x84, 0x85, 0,29, 0x80, 0x83, 0x86, 0x88, 0,16,
0x90,81, 0x91,81, 0x92,81, 0x93,81, 0,104, 0x94,79, 0x95,79, 0x96,79, 0x97,79, 0,16, 0x80,
0x81, 0x82, 0x83, 0,75, 0x84, 0x85, 0x86, 0x87, 0,8, 0x90,53, 0x91,41, 0x92,57, 0x93,77, 0x94,77,
0x95,53, 0x96,41, 0x97,57, 0x98,77, 0x99,77, 0,66, 0x80, 0x85, 0x81, 0x86, 0,8, 0x82, 0x87, 0,70,
0x83, 0x84, 0x88, 0x89, 0,54, 0x90,60, 0x91,41, 0x92,81, 0x93,81, 0x94,60, 0x95,41, 0x96,81, 0x97,81,
0,54, 0x80, 0x84, 0,16, 0x81, 0x85, 0,133, 0x90,41, 0x91,53, 0x94,57, 0x95,77, 0x98,77, 0x99,41,
0,8, 0x82, 0x83, 0x86, 0x87, 0,79, 0x85, 0x88, 0,4, 0x80, 0x89, 0x81, 0,8, 0x84, 0,104, 0x90,72,
0x91,72, 0x92,72, 0x93,72, 0,66, 0x80, 0x81, 0x82, 0x83, 0,33, 0x90,76, 0x91,76, 0x92,76, 0x93,76,
0,66, 0x80, 0x81, 0x82, 0x83, 0,33, 0x90,53, 0x91,57, 0x92,60, 0x93,41, 0x94,77, 0x95,77, 0x96,53,
0x97,57, 0x98,60, 0x99,41, 0,62, 0x80, 0x86, 0,16, 0x81, 0x87, 0,4, 0x82, 0x88, 0,12, 0x84,
0x85, 0,108, 0x90,53, 0x91,57, 0x92,60, 0x94,77, 0x95,77, 0x96,53, 0x97,57, 0x98,60, 0,50,
0x80, 0x86, 0,8, 0x84, 0x85, 0,4, 0x81, 0x87, 0x82, 0x88, 0,25, 0x83, 0x89, 0,12, 0x90,77, 0x91,77,
0x92,77, 0x93,77, 0,50, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,53, 0x91,57, 0x92,60, 0x93,41, 0x94,77,
0x95,77, 0x96,53, 0x97,57, 0x98,60, 0x99,41, 0,58, 0x80, 0x86, 0,8, 0x81, 0x87, 0,8, 0x82,
0x88, 0x84, 0x85, 0,125, 0x90,53, 0x91,60, 0x92,57, 0x94,77, 0x95,77, 0x96,53, 0x97,60, 0x98,57,
0,58, 0x84, 0x85, 0,16, 0x80, 0x86, 0,12, 0x81, 0x87, 0x83, 0x89, 0,4, 0x82, 0x88, 0,112, 0x90,53,
0x91,61, 0x92,57, 0x93,41, 0x94,81, 0x95,73, 0x96,81, 0x97,73, 0x98,53, 0x99,61, 0,87, 0x80,
0x88, 0,12, 0x81, 0x89, 0,16, 0x82, 0,87, 0x90,53, 0x91,57, 0x92,61, 0x98,53, 0x99,57, 0,45,
0x80, 0x88, 0,20, 0x81, 0x89, 0,4, 0x82, 0,8, 0x83, 0,120, 0x90,53, 0x91,57, 0x92,61, 0x93,41,
0x98,53, 0x99,57, 0,50, 0x80, 0x88, 0,20, 0x81, 0x89, 0,4, 0x82, 0,62, 0x84, 0x86, 0,66,
0x90,53, 0x91,57, 0x92,61, 0x94,79, 0x96,79, 0x98,53, 0x99,57, 0,20, 0x85, 0x87, 0,29, 0x84,
0x86, 0,4, 0x80, 0x88, 0,4, 0x83, 0,4, 0x81, 0x89, 0,8, 0x82, 0,133, 0x90,57, 0x91,53,
0x92,62, 0x93,41, 0x94,77, 0x95,69, 0x96,77, 0x97,69, 0x98,57, 0x99,53, 0x80, 0x88, 0,100, 0x81,
0x89, 0,8, 0x82, 0,91, 0x90,53, 0x91,61, 0x92,76, 0x98,76, 0x99,53, 0,37, 0x84, 0x86, 0,29,
0x80, 0x89, 0,16, 0x81, 0,8, 0x83, 0,112, 0x90,53, 0x91,62, 0x93,41, 0x94,77, 0x96,77, 0x99,53,
0,4, 0x82, 0x88, 0,58, 0x80, 0x89, 0,33, 0x81, 0,108, 0x90,53, 0x91,58, 0x92,74, 0x98,74,
0x99,53, 0,16, 0x85, 0x87, 0,37, 0x84, 0x86, 0,8, 0x82, 0x88, 0,8, 0x80, 0x89, 0,16, 0x81,
0,20, 0x83, 0,91, 0x90,53, 0x91,57, 0x92,41, 0x93,72, 0x94,72, 0x95,53, 0x96,57, 0x97,41,
0x98,72, 0x99,72, 0,45, 0x83, 0x84, 0x88, 0x89, 0,54, 0x93,74, 0x94,74, 0x98,74, 0x99,74, 0,41,
0x83, 0x84, 0x88, 0x89, 0,62, 0x93,72, 0x94,72, 0x98,72, 0x99,72, 0,16, 0x80, 0x85, 0,12, 0x81,
0x86, 0,16, 0x82, 0x87, 0x83, 0x84, 0x88, 0x89, 0,54, 0x90,74, 0x91,74, 0x92,74, 0x93,74, 0,54,
0x80, 0x81, 0x82, 0x83, 0,50, 0x90,41, 0x91,57, 0x92,53, 0x93,72, 0x94,72, 0x95,41, 0x96,57, 0x97,53,
0x98,72, 0x99,72, 0,41, 0x83, 0x84, 0x88, 0x89, 0,58, 0x93,74, 0x94,74, 0x98,74, 0x99,74, 0,50,
0x83, 0x84, 0x88, 0x89, 0,20, 0x80, 0x85, 0,29, 0x90,76, 0x93,76, 0x94,76, 0x95,76, 0,8, 0x81,
0x86, 0,4, 0x82, 0x87, 0,41, 0x80, 0x83, 0x84, 0x85, 0,45, 0x90,77, 0x91,77, 0x92,77, 0x93,77,
0,37, 0x80, 0x81, 0x82, 0x83, 0,66, 0x90,52, 0x91,55, 0x92,36, 0x93,70, 0x94,70, 0x95,52, 0x96,55,
0x97,36, 0x98,70, 0x99,70, 0,62, 0x83, 0x84, 0x88, 0x89, 0,29, 0x80, 0x85, 0,8, 0x90,72, 0x93,72,
0x94,72, 0x95,72, 0,12, 0x81, 0x86, 0,29, 0x80, 0x83, 0x84, 0x85, 0,12, 0x82, 0x87, 0,50, 0x90,70,
0x91,70, 0x92,70, 0x93,70, 0,54, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,72, 0x91,72, 0x92,72, 0x93,72,
0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,52, 0x91,36, 0x92,55, 0x93,70, 0x94,70, 0x95,52, 0x96,36,
0x97,55, 0x98,70, 0x99,70, 0,62, 0x83, 0x84, 0x88, 0x89, 0,25, 0x80, 0x85, 0,12, 0x81, 0x86, 0x82,
0x87, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,54, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,74, 0x91,74,
0x92,74, 0x93,74, 0,54, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,76, 0x91,76, 0x92,76, 0x93,76, 0,54,
0x80, 0x81, 0x82, 0x83, 0,45, 0x90,53, 0x91,57, 0x92,41, 0x93,69, 0x94,69, 0x95,53, 0x96,57, 0x97,41,
0x98,69, 0x99,69, 0,91, 0x83, 0x84, 0x88, 0x89, 0,12, 0x93,70, 0x94,70, 0x98,70, 0x99,70, 0,8,
0x80, 0x85, 0,4, 0x81, 0x86, 0,25, 0x82, 0x87, 0,62, 0x83, 0x84, 0x88, 0x89, 0x90,69, 0x91,69, 0x92,69,
0x93,69, 0,100, 0x94,70, 0x95,70, 0x96,70, 0x97,70, 0,29, 0x80, 0x81, 0x82, 0x83, 0,75, 0x90,57,
0x91,41, 0x92,53, 0x93,69, 0x98,69, 0x99,57, 0,16, 0x84, 0x85, 0x86, 0x87, 0,79, 0x80, 0x89, 0,4,
0x90,70, 0x94,70, 0x95,70, 0x96,70, 0,12, 0x81, 0,4, 0x82, 0x83, 0x88, 0,79, 0x80, 0x84, 0x85,
0x86, 0,4, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,104, 0x94,74, 0x95,74, 0x96,74, 0x97,74,
0,8, 0x80, 0x81, 0x82, 0x83, 0,58, 0x84, 0x85, 0x86, 0x87, 0,33, 0x90,55, 0x91,50, 0x92,46, 0x93,67,
0x94,67, 0x95,55, 0x96,50, 0x97,46, 0x98,67, 0x99,67, 0,100, 0,4, 0x80, 0x85, 0,12, 0x81,
0x86, 0x82, 0x87, 0,4, 0x83, 0x84, 0x88, 0x89, 0,83, 0x90,67, 0x91,67, 0x92,67, 0x93,67, 0,4,
0,91, 0x80, 0x81, 0x82, 0x83, 0,4, 0x90,69, 0x91,69, 0x92,69, 0x93,69, 0,100, 0x94,46, 0x95,50,
0x96,55, 0x97,67, 0x98,67, 0x99,46, 0,4, 0x80, 0x81, 0x82, 0x83, 0,100, 0x87, 0x88, 0x90,69, 0x91,69,
0x92,69, 0x93,69, 0,29, 0x84, 0x89, 0,8, 0x85, 0,16, 0x86, 0,45, 0x94,67, 0x95,67, 0x96,67,
0x97,67, 0,8, 0x80, 0x81, 0x82, 0x83, 0,91, 0x84, 0x85, 0x86, 0x87, 0x90,69, 0x91,69, 0x92,69, 0x93,69,
0,100, 0x80, 0x81, 0x82, 0x83, 0x90,48, 0x91,55, 0x92,52, 0x93,67, 0x94,67, 0x95,48, 0x96,55, 0x97,52,
0x98,67, 0x99,67, 0,104, 0,4, 0x83, 0x84, 0x88, 0x89, 0,25, 0x80, 0x85, 0,8, 0x81, 0x86, 0,8,
0x82, 0x87, 0,37, 0,16, 0x90,67, 0x91,67, 0x92,67, 0x93,67, 0,104, 0x94,69, 0x95,69, 0x96,69,
0x97,69, 0,8, 0x80, 0x81, 0x82, 0x83, 0,91, 0x90,67, 0x91,67, 0x92,67, 0x93,67, 0,4, 0x84,
0x85, 0x86, 0x87, 0,91, 0x80, 0x81, 0x82, 0x83, 0,4, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,91,
0x80, 0x81, 0x82, 0x83, 0,8, 0x90,74, 0x91,74, 0x92,74, 0x93,74, 0,91, 0x80, 0x81, 0x82, 0x83, 0,12,
0x90,76, 0x91,76, 0x92,76, 0x93,76, 0,75, 0x80, 0x81, 0x82, 0x83, 0,25, 0x90,53, 0x91,57, 0x92,60,
0x93,41, 0x94,77, 0x95,77, 0x96,53, 0x97,57, 0x98,60, 0x99,41, 0,58, 0x80, 0x86, 0,12, 0x84,
0x85, 0,8, 0x81, 0x87, 0x82, 0x88, 0,125, 0x90,53, 0x91,57, 0x92,60, 0x94,77, 0x95,77, 0x96,53,
0x97,57, 0x98,60, 0,50, 0x80, 0x86, 0,4, 0x84, 0x85, 0,4, 0x81, 0x87, 0,4, 0x82, 0x88, 0,25,
0x83, 0x89, 0,12, 0x90,77, 0x91,77, 0x92,77, 0x93,77, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,53,
0x91,57, 0x92,60, 0x93,41, 0x94,77, 0x95,77, 0x96,53, 0x97,57, 0x98,60, 0x99,41, 0,58, 0x80,
0x86, 0,12, 0x81, 0x87, 0x84, 0x85, 0,8, 0x82, 0x88, 0,125, 0x90,53, 0x91,60, 0x92,57, 0x94,77,
0x95,77, 0x96,53, 0x97,60, 0x98,57, 0,58, 0x84, 0x85, 0,12, 0x80, 0x86, 0,12, 0x81, 0x87, 0,4,
0x83, 0x89, 0,4, 0x82, 0x88, 0,112, 0x90,53, 0x91,61, 0x92,57, 0x93,41, 0x94,81, 0x95,73, 0x96,81,
0x97,73, 0x98,53, 0x99,61, 0,83, 0x80, 0x88, 0,16, 0x81, 0x89, 0,16, 0x82, 0,83, 0x90,53,
0x91,57, 0x92,61, 0x98,53, 0x99,57, 0,50, 0x80, 0x88, 0,20, 0x81, 0x89, 0,4, 0x82, 0,8,
0x83, 0,120, 0x90,53, 0x91,57, 0x92,61, 0x93,41, 0x98,53, 0x99,57, 0,50, 0x80, 0x88, 0,20,
0x81, 0x89, 0x82, 0,125, 0x84, 0x86, 0,8, 0x90,53, 0x91,57, 0x92,61, 0x94,79, 0x96,79, 0x98,53,
0x99,57, 0,16, 0x85, 0x87, 0,37, 0x80, 0x88, 0x83, 0,4, 0x81, 0x89, 0,8, 0x84, 0x86, 0,4,
0x82, 0,129, 0x90,57, 0x91,53, 0x92,62, 0x93,41, 0x94,77, 0x95,69, 0x96,77, 0x97,69, 0x98,57,
0x99,53, 0,4, 0x80, 0x88, 0,100, 0x81, 0x89, 0,8, 0x82, 0,91, 0x90,53, 0x91,61, 0x92,76,
0x98,76, 0x99,53, 0,8, 0x84, 0x86, 0,58, 0x80, 0x89, 0,12, 0x81, 0,12, 0x83, 0,87, 0x82,
0x88, 0,25, 0x90,53, 0x91,62, 0x92,41, 0x93,77, 0x94,77, 0x96,53, 0x98,62, 0x99,41, 0,58,
0x80, 0x86, 0,37, 0x81, 0x88, 0,95, 0x83, 0x84, 0,8, 0x90,53, 0x91,58, 0x93,74, 0x94,74, 0x96,53,
0x98,58, 0,33, 0x85, 0x87, 0,41, 0x80, 0x86, 0,16, 0x81, 0x88, 0,20, 0x82, 0x89, 0,54, 0x83,
0x84, 0,37, 0x90,53, 0x91,57, 0x92,41, 0x93,72, 0x94,72, 0x95,53, 0x96,57, 0x97,41, 0x98,72,
0x99,72, 0,54, 0x83, 0x84, 0x88, 0x89, 0,45, 0x93,74, 0x94,74, 0x98,74, 0x99,74, 0,41, 0x83,
0x84, 0x88, 0x89, 0,62, 0x93,72, 0x94,72, 0x98,72, 0x99,72, 0,16, 0x80, 0x85, 0,12, 0x81, 0x86,
0,12, 0x83, 0x84, 0x88, 0x89, 0,4, 0x82, 0x87, 0,54, 0x90,74, 0x91,74, 0x92,74, 0x93,74, 0,50,
0x80, 0x81, 0x82, 0x83, 0,50, 0x90,41, 0x91,57, 0x92,53, 0x93,72, 0x94,72, 0x95,41, 0x96,57, 0x97,53,
0x98,72, 0x99,72, 0,50, 0x83, 0x84, 0x88, 0x89, 0,50, 0x93,74, 0x94,74, 0x98,74, 0x99,74, 0,54,
0x83, 0x84, 0x88, 0x89, 0,20, 0x80, 0x85, 0,29, 0x90,76, 0x93,76, 0x94,76, 0x95,76, 0,8, 0x81,
0x86, 0,4, 0x82, 0x87, 0,41, 0x80, 0x83, 0x84, 0x85, 0,45, 0x90,77, 0x91,77, 0x92,77, 0x93,77,
0,41, 0x80, 0x81, 0x82, 0x83, 0,62, 0x90,52, 0x91,55, 0x92,36, 0x93,70, 0x94,70, 0x95,52, 0x96,55,
0x97,36, 0x98,70, 0x99,70, 0,45, 0x83, 0x84, 0x88, 0x89, 0,45, 0x80, 0x85, 0,8, 0x90,72, 0x93,72,
0x94,72, 0x95,72, 0,12, 0x81, 0x86, 0,37, 0x82, 0x87, 0,8, 0x80, 0x83, 0x84, 0x85, 0,41, 0x90,70,
0x91,70, 0x92,70, 0x93,70, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,72, 0x91,72, 0x92,72, 0x93,72,
0,58, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,52, 0x91,36, 0x92,55, 0x93,70, 0x94,70, 0x95,52, 0x96,36,
0x97,55, 0x98,70, 0x99,70, 0,62, 0x83, 0x84, 0x88, 0x89, 0,25, 0x80, 0x85, 0,8, 0x81, 0x86, 0,4,
0x82, 0x87, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,58, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,74, 0x91,74,
0x92,74, 0x93,74, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,76, 0x91,76, 0x92,76, 0x93,76, 0,58,
0x80, 0x81, 0x82, 0x83, 0,41, 0x90,53, 0x91,57, 0x92,41, 0x93,69, 0x94,69, 0x95,53, 0x96,57, 0x97,41,
0x98,69, 0x99,69, 0,62, 0x83, 0x84, 0x88, 0x89, 0,37, 0x93,70, 0x94,70, 0x98,70, 0x99,70, 0,8,
0x80, 0x85, 0,8, 0x81, 0x86, 0,25, 0x82, 0x87, 0,20, 0x83, 0x84, 0x88, 0x89, 0,41, 0x90,69, 0x91,69,
0x92,69, 0x93,69, 0,54, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,70, 0x91,70, 0x92,70, 0x93,70, 0,62,
0x80, 0x81, 0x82, 0x83, 0,41, 0x90,57, 0x91,41, 0x92,53, 0x93,69, 0x94,69, 0x95,57, 0x96,41, 0x97,53,
0x98,69, 0x99,69, 0,66, 0x83, 0x84, 0x88, 0x89, 0,25, 0x80, 0x85, 0,8, 0x90,70, 0x93,70, 0x94,70,
0x95,70, 0,12, 0x81, 0x86, 0,4, 0x82, 0x87, 0,50, 0x80, 0x83, 0x84, 0x85, 0,33, 0x90,72, 0x91,72,
0x92,72, 0x93,72, 0,62, 0x80, 0x81, 0x82, 0x83, 0,37, 0x90,74, 0x91,74, 0x92,74, 0x93,74, 0,41,
0x80, 0x81, 0x82, 0x83, 0,62, 0x90,55, 0x91,50, 0x92,46, 0x93,67, 0x94,67, 0x95,55, 0x96,50, 0x97,46,
0x98,67, 0x99,67, 0,62, 0x83, 0x84, 0x88, 0x89, 0,37, 0x93,69, 0x94,69, 0x98,69, 0x99,69, 0,4,
0x80, 0x85, 0,12, 0x81, 0x86, 0x82, 0x87, 0,41, 0x83, 0x84, 0x88, 0x89, 0,41, 0x90,67, 0x91,67, 0x92,67,
0x93,67, 0,58, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,69, 0x91,69, 0x92,69, 0x93,69, 0,58, 0x80,
0x81, 0x82, 0x83, 0,41, 0x90,48, 0x91,55, 0x92,52, 0x93,67, 0x94,67, 0x95,48, 0x96,55, 0x97,52,
0x98,67, 0x99,67, 0,62, 0x83, 0x84, 0x88, 0x89, 0,37, 0x93,70, 0x94,70, 0x98,70, 0x99,70, 0,33,
0x80, 0x85, 0,8, 0x81, 0x86, 0,4, 0x82, 0x87, 0,37, 0x83, 0x84, 0x88, 0x89, 0,20, 0x90,69, 0x91,69,
0x92,69, 0x93,69, 0,87, 0x80, 0x81, 0x82, 0x83, 0,12, 0x90,67, 0x91,67, 0x92,67, 0x93,67, 0,83,
0x80, 0x81, 0x82, 0x83, 0,16, 0x90,57, 0x91,53, 0x92,41, 0x93,65, 0x94,65, 0x95,57, 0x96,53, 0x97,41,
0x98,65, 0x99,65, 0,104, 0,29, 0x83, 0x84, 0x88, 0x89, 0,70, 0x93,65, 0x94,65, 0x98,65, 0x99,65,
0,8, 0,91, 0,8, 0x83, 0x84, 0x88, 0x89, 0,87, 0,8, 0x93,65, 0x94,65, 0x98,65, 0x99,65,
0,66, 0x83, 0x84, 0x88, 0x89, 0,133, 0x80, 0x85, 0x81, 0x86, 0x82, 0x87, 0x90,72, 0x91,72, 0x92,72, 0x93,72,
0,45, 0x80, 0x81, 0x82, 0x83, 0,58, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,37, 0x80, 0x81, 0x82,
0x83, 0,62, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,79, 0x80, 0x81, 0x82, 0x83, 0,120, 0x90,72,
0x91,72, 0x92,72, 0x93,72, 0,54, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,72, 0x91,72, 0x92,72, 0x93,72,
0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,70, 0x80, 0x81, 0x82,
0x83, 0,133, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,54, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,72,
0x91,72, 0x92,72, 0x93,72, 0,41, 0x80, 0x81, 0x82, 0x83, 0,58, 0x90,53, 0x91,65, 0x92,77, 0x93,65,
0x94,77, 0x95,53, 0x96,65, 0x97,77, 0x98,65, 0x99,77, 0,50, 0x81, 0x83, 0x86, 0x88, 0,4, 0x82,
0x84, 0x87, 0x89, 0,12, 0x80, 0x85, 0,137, 0x90,55, 0x91,67, 0x92,79, 0x93,67, 0x94,79, 0x95,55,
0x96,67, 0x97,79, 0x98,67, 0x99,79, 0,50, 0x81, 0x83, 0x86, 0x88, 0,4, 0x82, 0x84, 0x87, 0x89, 0,8,
0x80, 0x85, 0,141, 0x90,57, 0x91,81, 0x92,69, 0x93,81, 0x94,69, 0x95,57, 0x96,81, 0x97,69, 0x98,81,
0x99,69, 0,100, 0x81, 0x83, 0x86, 0x88, 0,25, 0x82, 0x84, 0x87, 0x89, 0,75, 0x91,72, 0x92,72, 0x93,72,
0x94,72, 0,4, 0x80, 0x85, 0,66, 0x81, 0x82, 0x83, 0x84, 0,33, 0x90,72, 0x91,72, 0x92,72, 0x93,72,
0,66, 0x80, 0x81, 0x82, 0x83, 0,33, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,104, 0x80, 0x81, 0x82,
0x83, 0,100, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,37, 0x80, 0x81, 0x82, 0x83, 0,62, 0x90,72,
0x91,72, 0x92,72, 0x93,72, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,72, 0x91,72, 0x92,72, 0x93,72,
0,62, 0x80, 0x81, 0x82, 0x83, 0,141, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,41, 0x80, 0x81, 0x82,
0x83, 0,58, 0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,20, 0x80, 0x81, 0x82, 0x83, 0,83, 0x90,57,
0x91,69, 0x92,81, 0x93,69, 0x94,81, 0x95,57, 0x96,69, 0x97,81, 0x98,69, 0x99,81, 0,54, 0x81,
0x83, 0x86, 0x88, 0x82, 0x84, 0x87, 0x89, 0,20, 0x80, 0x85, 0,125, 0x90,58, 0x91,70, 0x92,82, 0x93,70,
0x94,82, 0x95,58, 0x96,70, 0x97,82, 0x98,70, 0x99,82, 0,50, 0x81, 0x83, 0x86, 0x88, 0,20, 0x82,
0x84, 0x87, 0x89, 0,4, 0x80, 0x85, 0,129, 0x90,60, 0x91,72, 0x92,84, 0x93,72, 0x94,84, 0x95,60,
0x96,72, 0x97,84, 0x98,72, 0x99,84, 0,204, 0x80, 0x85, 0,4, 0x81, 0x83, 0x86, 0x88, 0,29, 0x82,
0x84, 0x87, 0x89, 0,166, 0x90,53, 0x91,77, 0x92,65, 0x93,77, 0x94,65, 0x95,53, 0x96,77, 0x97,65,
0x98,77, 0x99,65, 0,58, 0x81, 0x83, 0x86, 0x88, 0,8, 0x80, 0x85, 0,4, 0x82, 0x84, 0x87, 0x89, 0,133,
0x90,55, 0x91,67, 0x92,79, 0x93,67, 0x94,79, 0x95,55, 0x96,67, 0x97,79, 0x98,67, 0x99,79, 0,50,
0x81, 0x83, 0x86, 0x88, 0,8, 0x82, 0x84, 0x87, 0x89, 0x80, 0x85, 0,145, 0x90,57, 0x91,69, 0x92,81, 0x93,69,
0x94,81, 0x95,57, 0x96,69, 0x97,81, 0x98,69, 0x99,81, 0,216, 0x81, 0x83, 0x86, 0x88, 0,8, 0x80,
0x85, 0x82, 0x84, 0x87, 0x89, 0,179, 0x90,45, 0x91,57, 0x92,69, 0x93,57, 0x94,69, 0x95,45, 0x96,57,
0x97,69, 0x98,57, 0x99,69, 0,54, 0x81, 0x83, 0x86, 0x88, 0,12, 0x82, 0x84, 0x87, 0x89, 0,4, 0x80,
0x85, 0,133, 0x90,46, 0x91,58, 0x92,70, 0x93,58, 0x94,70, 0x95,46, 0x96,58, 0x97,70, 0x98,58,
0x99,70, 0,54, 0x81, 0x83, 0x86, 0x88, 0,12, 0x80, 0x85, 0,4, 0x82, 0x84, 0x87, 0x89, 0,129, 0x90,48,
0x91,60, 0x92,72, 0x93,60, 0x94,72, 0x95,48, 0x96,60, 0x97,72, 0x98,60, 0x99,72, 0,204, 0x80,
0x85, 0,20, 0x81, 0x83, 0x86, 0x88, 0,8, 0x82, 0x84, 0x87, 0x89, 0,175, 0x90,53, 0x91,41, 0x92,65,
0x93,77, 0x94,77, 0x95,53, 0x96,41, 0x97,65, 0x98,77, 0x99,77, 0,54, 0x83, 0x84, 0x88, 0x89, 0,16,
0x80, 0x85, 0,12, 0x81, 0x86, 0,8, 0x82, 0x87, 0,108, 0x90,53, 0x91,41, 0x92,65, 0x93,77, 0x94,77,
0x95,53, 0x96,41, 0x97,65, 0x98,77, 0x99,77, 0,45, 0x83, 0x84, 0x88, 0x89, 0,12, 0x80, 0x85, 0,4,
0x81, 0x86, 0,12, 0x82, 0x87, 0,25, 0x90,77, 0x91,77, 0x92,77, 0x93,77, 0,50, 0x80, 0x81, 0x82,
0x83, 0,54, 0x90,53, 0x91,65, 0x92,41, 0x93,77, 0x94,77, 0x95,53, 0x96,65, 0x97,41, 0x98,77,
0x99,77, 0,66, 0x80, 0x85, 0,4, 0x81, 0x86, 0,8, 0x82, 0x87, 0x83, 0x84, 0x88, 0x89, 0,125, 0x90,53,
0x91,65, 0x92,41, 0x93,77, 0x94,77, 0x95,53, 0x96,65, 0x97,41, 0x98,77, 0x99,77, 0,62, 0x83,
0x84, 0x88, 0x89, 0,8, 0x80, 0x85, 0x81, 0x86, 0,4, 0x82, 0x87, 0,125, 0x90,53, 0x91,65, 0x92,41,
0x93,77, 0x94,77, 0x95,53, 0x96,65, 0x97,41, 0x98,77, 0x99,77, 0,54, 0x80, 0x85, 0,25, 0x81,
0x86, 0x82, 0x87, 0,91, 0x83, 0x84, 0x88, 0x89, 0,33, 0x90,60, 0x91,48, 0x92,72, 0x93,72, 0x94,60,
0x95,48, 0x96,72, 0x97,72, 0,45, 0x82, 0x83, 0x86, 0x87, 0,33, 0x80, 0x84, 0,8, 0x81, 0x85, 0,12,
0x90,72, 0x91,72, 0x92,72, 0x93,72, 0,54, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,60, 0x91,48, 0x92,72,
0x93,72, 0x94,60, 0x95,48, 0x96,72, 0x97,72, 0,62, 0x82, 0x83, 0x86, 0x87, 0,16, 0x80, 0x84, 0x81,
0x85, 0,125, 0x90,48, 0x91,60, 0x92,72, 0x93,72, 0x94,48, 0x95,60, 0x96,72, 0x97,72, 0,62,
0x82, 0x83, 0x86, 0x87, 0,12, 0x80, 0x84, 0,4, 0x81, 0x85, 0,125, 0x90,53, 0x91,65, 0x92,72, 0x93,72,
0x94,53, 0x95,65, 0x96,72, 0x97,72, 0,87, 0x80, 0x84, 0,16, 0x81, 0x85, 0,95, 0x82, 0x83, 0x86,
0x87, 0x90,57, 0x91,45, 0x92,69, 0x93,69, 0x94,57, 0x95,45, 0x96,69, 0x97,69, 0,62, 0x82, 0x83,
0x86, 0x87, 0,16, 0x80, 0x84, 0x81, 0x85, 0,25, 0x90,69, 0x91,69, 0x92,69, 0x93,69, 0,41, 0x80,
0x81, 0x82, 0x83, 0,58, 0x90,45, 0x91,57, 0x92,69, 0x93,69, 0x94,45, 0x95,57, 0x96,69, 0x97,69,
0,66, 0x82, 0x83, 0x86, 0x87, 0,8, 0x80, 0x84, 0x81, 0x85, 0,129, 0x90,45, 0x91,57, 0x92,69, 0x93,69,
0x94,45, 0x95,57, 0x96,69, 0x97,69, 0,58, 0x82, 0x83, 0x86, 0x87, 0,20, 0x80, 0x84, 0,8, 0x81,
0x85, 0,112, 0x90,57, 0x91,45, 0x92,69, 0x93,69, 0x94,57, 0x95,45, 0x96,69, 0x97,69, 0,150,
0x80, 0x84, 0,4, 0x81, 0x85, 0,41, 0x82, 0x83, 0x86, 0x87, 0,8, 0x90,53, 0x91,41, 0x92,65, 0x93,65,
0x94,53, 0x95,41, 0x96,65, 0x97,65, 0,50, 0x82, 0x83, 0x86, 0x87, 0,41, 0x80, 0x84, 0,4, 0x81,
0x85, 0,4, 0x90,65, 0x91,65, 0x92,65, 0x93,65, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,53,
0x91,41, 0x92,65, 0x93,65, 0x94,53, 0x95,41, 0x96,65, 0x97,65, 0,66, 0x82, 0x83, 0x86, 0x87, 0,12,
0x80, 0x84, 0x81, 0x85, 0,125, 0x90,41, 0x91,53, 0x92,65, 0x93,65, 0x94,41, 0x95,53, 0x96,65, 0x97,65,
0,62, 0x80, 0x84, 0x82, 0x83, 0x86, 0x87, 0,8, 0x81, 0x85, 0,133, 0x90,41, 0x91,53, 0x92,65, 0x93,65,
0x94,41, 0x95,53, 0x96,65, 0x97,65, 0,62, 0x82, 0x83, 0x86, 0x87, 0,137, 0x92,60, 0x93,60, 0x96,60,
0x97,60, 0,25, 0x80, 0x84, 0,8, 0x81, 0x85, 0,33, 0x82, 0x83, 0x86, 0x87, 0,137, 0x90,41, 0x91,53,
0x92,65, 0x93,65, 0x94,41, 0x95,53, 0x96,65, 0x97,65, 0,58, 0x82, 0x83, 0x86, 0x87, 0,145, 0x92,60,
0x93,60, 0x96,60, 0x97,60, 0,29, 0x80, 0x84, 0,29, 0x82, 0x83, 0x86, 0x87, 0,16, 0x81, 0x85, 0,125,
0x90,45, 0x91,57, 0x92,69, 0x93,69, 0x94,45, 0x95,57, 0x96,69, 0x97,69, 0,62, 0x82, 0x83, 0x86,
0x87, 0,129, 0x80, 0x84, 0,12, 0x90,65, 0x92,65, 0x93,65, 0x94,65, 0,4, 0x81, 0x85, 0,58,
0x80, 0x82, 0x83, 0x84, 0,141, 0x90,48, 0x91,60, 0x92,72, 0x93,72, 0x94,48, 0x95,60, 0x96,72, 0x97,72,
0,58, 0x82, 0x83, 0x86, 0x87, 0,141, 0x92,69, 0x93,69, 0x96,69, 0x97,69, 0,4, 0x80, 0x84, 0,20,
0x81, 0x85, 0,37, 0x82, 0x83, 0x86, 0x87, 0,141, 0x90,53, 0x91,41, 0x92,77, 0x93,77, 0x94,53, 0x95,41,
0x96,77, 0x97,77, 0,50, 0x82, 0x83, 0x86, 0x87, 0,62, 0x80, 0x84, 0,91, 0x81, 0x85, 0x90,72, 0x91,72,
0x92,72, 0x93,72, 0,58, 0x80, 0x81, 0x82, 0x83, 0,141, 0x90,53, 0x91,41, 0x92,77, 0x93,77, 0x94,53,
0x95,41, 0x96,77, 0x97,77, 0,50, 0x82, 0x83, 0x86, 0x87, 0,91, 0x80, 0x84, 0,62, 0x90,72, 0x92,72,
0x93,72, 0x94,72, 0,8, 0x81, 0x85, 0,66, 0x80, 0x82, 0x83, 0x84, 0,129, 0x90,45, 0x91,57, 0x92,81,
0x93,81, 0x94,45, 0x95,57, 0x96,81, 0x97,81, 0,62, 0x82, 0x83, 0x86, 0x87, 0,83, 0x80, 0x84, 0,12,
0x81, 0x85, 0,41, 0x90,77, 0x91,77, 0x92,77, 0x93,77, 0,75, 0x80, 0x81, 0x82, 0x83, 0,129, 0x90,48,
0x91,60, 0x92,84, 0x93,84, 0x94,48, 0x95,60, 0x96,84, 0x97,84, 0,75, 0x82, 0x83, 0x86, 0x87, 0,54,
0x80, 0x84, 0,16, 0x81, 0x85, 0,58, 0x90,81, 0x91,81, 0x92,81, 0x93,81, 0,66, 0x80, 0x81, 0x82,
0x83, 0,133, 0x90,53, 0x91,41, 0x92,77, 0x93,77, 0x94,53, 0x95,41, 0x96,77, 0x97,77, 0,233,
0x80, 0x84, 0,25, 0x81, 0x85, 0,100, 0x82, 0x83, 0x86, 0x87, 0,250, 0x90,77, 0x91,77, 0x92,77, 0x93,77,
0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,77, 0x91,77, 0x92,77, 0x93,77, 0,54, 0x80, 0x81, 0x82,
0x83, 0,50, 0x90,53, 0x91,41, 0x92,77, 0x93,77, 0x94,53, 0x95,41, 0x96,77, 0x97,77, 0,58,
0x82, 0x83, 0x86, 0x87, 0,45, 0x80, 0x84, 0,4, 0x81, 0x85, 0,95, 0x90,53, 0x91,41, 0x92,77, 0x93,77,
0x94,53, 0x95,41, 0x96,77, 0x97,77, 0,54, 0x82, 0x83, 0x86, 0x87, 0,41, 0x80, 0x84, 0x81, 0x85, 0,104,
0x90,41, 0x91,53, 0x92,77, 0x93,77, 0x94,41, 0x95,53, 0x96,77, 0x97,77, 0,62, 0x82, 0x83, 0x86,
0x87, 0,29, 0x80, 0x84, 0x81, 0x85, 0,112, 0x90,41, 0x91,53, 0x92,77, 0x93,77, 0x94,41, 0x95,53,
0x96,77, 0x97,77, 0,62, 0x82, 0x83, 0x86, 0x87, 0,25, 0x80, 0x84, 0x81, 0x85, 0,116, 0x90,41, 0x91,53,
0x92,77, 0x93,77, 0x94,41, 0x95,53, 0x96,77, 0x97,77, 1,164, 0x82, 0x83, 0x86, 0x87, 0,25, 0x80,
0x84, 0x81, 0x85, 0,158, 0x90,53, 0x91,41, 0x92,77, 0x93,69, 0x94,72, 0x95,77, 0x96,69, 0x97,72,
0x98,53, 0x99,41, 0,29, 0x82, 0x85, 0x83, 0x86, 0x84, 0x87, 0,33, 0x80, 0x88, 0,4, 0x81, 0x89, 0,137,
0x90,41, 0x91,53, 0x92,77, 0x93,69, 0x94,72, 0x95,77, 0x96,69, 0x97,72, 0x98,41, 0x99,53, 1,131,
0x82, 0x85, 0,4, 0x83, 0x86, 0,8, 0x84, 0x87, 0,41, 0x80, 0x88, 0x81, 0x89, 0,166, 0x90,41, 0x91,48,
0x92,53, 0x93,65, 0x94,57, 0x95,65, 0x96,57, 0x97,41, 0x98,48, 0x99,53, 0,45, 0x80, 0x87, 0x83,
0x85, 0,4, 0x81, 0x88, 0x84, 0x86, 0x82, 0x89, 0,154, 0x90,53, 0x91,48, 0x92,41, 0x93,57, 0x94,65,
0x95,57, 0x96,65, 0x97,53, 0x98,48, 0x99,41, 4,180, 0x80, 0x87, 0,112, 0x83, 0x85, 0,33, 0x84,
0x86, 0,95, 0x81, 0x88, 0,12, 0x82, 0x89, 0xf0};
// This score contains 13513 bytes, and 10 tone generators are used.
// 421 notes had to be skipped.

+ 0
- 60
examples/PlaySineMikroe/PlaySineMikroe.ino 查看文件

@@ -1,60 +0,0 @@
#include <Audio.h>
#include <Wire.h>
#include <SD.h>

AudioSynthWaveform mysine(AudioWaveformSine);
AudioOutputI2Sslave dac;

AudioControlWM8731master codec;

AudioConnection c1(mysine,dac);

int volume = 0;

void setup() {
codec.enable();
delay(100);
while (!Serial) ;
Serial.println("Begin AudioTest");
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(15);

mysine.frequency(440);
mysine.amplitude(0.9);

codec.volume(70);

Serial.println("setup done");
}




void loop() {
/*
Serial.print("cpu: ");
Serial.print(AudioProcessorUsage());
Serial.print(", max: ");
Serial.print(AudioProcessorUsageMax());
Serial.print(", memory: ");
Serial.print(AudioMemoryUsage());
Serial.print(", max: ");
Serial.print(AudioMemoryUsageMax());
Serial.println("");
*/
//int n;
//n = analogRead(15);
//Serial.println(n);
//if (n != volume) {
//volume = n;
//codec.volume((float)n / 10.23);
//}
//n = analogRead(16) / 8;
//Serial.println(n);
//mysine.frequency(200 + n * 4);
//delay(5);
}

+ 0
- 43
examples/PlayWavFromSdCard/PlayWavFromSdCard.ino 查看文件

@@ -1,43 +0,0 @@
#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//
AudioPlaySDcardWAV wav;
AudioOutputI2S dac;

// Create Audio connections between the components
//
AudioConnection c1(wav, 0, dac, 0);
AudioConnection c2(wav, 1, dac, 1);

// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;


void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(5);

audioShield.enable();
audioShield.volume(20);

SPI.setMOSI(7);
SPI.setSCK(14);
if (SD.begin(10)) {
wav.play("01_16M.WAV");
}
}

void loop() {
float vol = analogRead(15);
vol = vol / 10.24;
audioShield.volume(vol);
delay(20);
}


+ 194
- 0
examples/Recorder/Recorder.ino 查看文件

@@ -0,0 +1,194 @@
// Record sound as raw data to a SD card, and play it back.
//
// Requires the audio shield:
// http://www.pjrc.com/store/teensy3_audio.html
//
// Three pushbuttons need to be connected:
// Record Button: pin 0 to GND
// Stop Button: pin 1 to GND
// Play Button: pin 2 to GND
//
// This example code is in the public domain.

#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S i2s2; //xy=105,63
AudioAnalyzePeak peak1; //xy=278,108
AudioRecordQueue queue1; //xy=281,63
AudioPlaySdRaw playRaw1; //xy=302,157
AudioOutputI2S i2s1; //xy=470,120
AudioConnection patchCord1(i2s2, 0, queue1, 0);
AudioConnection patchCord2(i2s2, 0, peak1, 0);
AudioConnection patchCord3(playRaw1, 0, i2s1, 0);
AudioConnection patchCord4(playRaw1, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=265,212
// GUItool: end automatically generated code

// Bounce objects to easily and reliably read the buttons
Bounce buttonRecord = Bounce(0, 8);
Bounce buttonStop = Bounce(1, 8); // 8 = 8 ms debounce time
Bounce buttonPlay = Bounce(2, 8);


// which input on the audio shield will be used?
const int myInput = AUDIO_INPUT_LINEIN;
//const int myInput = AUDIO_INPUT_MIC;

// Remember which mode we're doing
int mode = 0; // 0=stopped, 1=recording, 2=playing

// The file where data is recorded
File frec;

void setup() {
// Configure the pushbutton pins
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);

// Audio connections require memory, and the record queue
// uses this memory to buffer incoming audio.
AudioMemory(60);

// Enable the audio shield, select input, and enable output
sgtl5000_1.enable();
sgtl5000_1.inputSelect(myInput);
sgtl5000_1.volume(0.5);

// Initialize the SD card
SPI.setMOSI(7);
SPI.setSCK(14);
if (!(SD.begin(10))) {
// stop here if no SD card, but print a message
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}
}


void loop() {
// First, read the buttons
buttonRecord.update();
buttonStop.update();
buttonPlay.update();

// Respond to button presses
if (buttonRecord.fallingEdge()) {
Serial.println("Record Button Press");
if (mode == 2) stopPlaying();
if (mode == 0) startRecording();
}
if (buttonStop.fallingEdge()) {
Serial.println("Stop Button Press");
if (mode == 1) stopRecording();
if (mode == 2) stopPlaying();
}
if (buttonPlay.fallingEdge()) {
Serial.println("Play Button Press");
if (mode == 1) stopRecording();
if (mode == 0) startPlaying();
}

// If we're playing or recording, carry on...
if (mode == 1) {
continueRecording();
}
if (mode == 2) {
continuePlaying();
}

// when using a microphone, continuously adjust gain
if (myInput == AUDIO_INPUT_MIC) adjustMicLevel();
}


void startRecording() {
Serial.println("startRecording");
if (SD.exists("RECORD.RAW")) {
// The SD library writes new data to the end of the
// file, so to start a new recording, the old file
// must be deleted before new data is written.
SD.remove("RECORD.RAW");
}
frec = SD.open("RECORD.RAW", FILE_WRITE);
if (frec) {
queue1.begin();
mode = 1;
}
}

void continueRecording() {
if (queue1.available() >= 2) {
byte buffer[512];
// Fetch 2 blocks from the audio library and copy
// into a 512 byte buffer. The Arduino SD library
// is most efficient when full 512 byte sector size
// writes are used.
memcpy(buffer, queue1.readBuffer(), 256);
queue1.freeBuffer();
memcpy(buffer+256, queue1.readBuffer(), 256);
queue1.freeBuffer();
// write all 512 bytes to the SD card
elapsedMicros usec = 0;
frec.write(buffer, 512);
// Uncomment these lines to see how long SD writes
// are taking. A pair of audio blocks arrives every
// 5802 microseconds, so hopefully most of the writes
// take well under 5802 us. Some will take more, as
// the SD library also must write to the FAT tables
// and the SD card controller manages media erase and
// wear leveling. The queue1 object can buffer
// approximately 301700 us of audio, to allow time
// for occasional high SD card latency, as long as
// the average write time is under 5802 us.
//Serial.print("SD write, us=");
//Serial.println(usec);
}
}

void stopRecording() {
Serial.println("stopRecording");
queue1.end();
if (mode == 1) {
while (queue1.available() > 0) {
frec.write((byte*)queue1.readBuffer(), 256);
queue1.freeBuffer();
}
frec.close();
}
mode = 0;
}


void startPlaying() {
Serial.println("startPlaying");
playRaw1.play("RECORD.RAW");
mode = 2;
}

void continuePlaying() {
if (!playRaw1.isPlaying()) {
playRaw1.stop();
mode = 0;
}
}

void stopPlaying() {
Serial.println("stopPlaying");
if (mode == 2) playRaw1.stop();
mode = 0;
}

void adjustMicLevel() {
// TODO: read the peak1 object and adjust sgtl5000_1.micGain()
// if anyone gets this working, please submit a github pull request :-)
}


examples/PlayFromSketch/AudioSampleCashregister.cpp → examples/SamplePlayer/AudioSampleCashregister.cpp 查看文件


examples/PlayFromSketch/AudioSampleCashregister.h → examples/SamplePlayer/AudioSampleCashregister.h 查看文件


examples/PlayFromSketch/AudioSampleGong.cpp → examples/SamplePlayer/AudioSampleGong.cpp 查看文件


examples/PlayFromSketch/AudioSampleGong.h → examples/SamplePlayer/AudioSampleGong.h 查看文件


examples/PlayFromSketch/AudioSampleHihat.cpp → examples/SamplePlayer/AudioSampleHihat.cpp 查看文件


examples/PlayFromSketch/AudioSampleHihat.h → examples/SamplePlayer/AudioSampleHihat.h 查看文件


examples/PlayFromSketch/AudioSampleKick.cpp → examples/SamplePlayer/AudioSampleKick.cpp 查看文件


examples/PlayFromSketch/AudioSampleKick.h → examples/SamplePlayer/AudioSampleKick.h 查看文件


examples/PlayFromSketch/AudioSampleSnare.cpp → examples/SamplePlayer/AudioSampleSnare.cpp 查看文件


examples/PlayFromSketch/AudioSampleSnare.h → examples/SamplePlayer/AudioSampleSnare.h 查看文件


examples/PlayFromSketch/AudioSampleTomtom.cpp → examples/SamplePlayer/AudioSampleTomtom.cpp 查看文件


examples/PlayFromSketch/AudioSampleTomtom.h → examples/SamplePlayer/AudioSampleTomtom.h 查看文件


examples/PlayFromSketch/PlayFromSketch.ino → examples/SamplePlayer/SamplePlayer.ino 查看文件

@@ -1,6 +1,8 @@
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>

// WAV files converted to code by wav2sketch
@@ -68,7 +70,7 @@ void setup() {

// turn on the output
audioShield.enable();
audioShield.volume(50);
audioShield.volume(0.5);

// by default the Teensy 3.1 DAC uses 3.3Vp-p output
// if your 3.3V power has noise, switching to the

+ 0
- 126
examples/SdCardTest/SdCardTest.ino 查看文件

@@ -1,126 +0,0 @@
/*
SD card test
This example shows how use the utility libraries on which the'
SD library is based in order to get info about your SD card.
Very useful for testing a card when you're not sure whether its working or not.
The circuit:
* SD card attached to SPI bus as follows:
** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
** CS - depends on your SD card shield or module.
Pin 4 used here for consistency with other Arduino examples

created 28 Mar 2011
by Limor Fried
modified 9 Apr 2012
by Tom Igoe
*/
// include the SD library:
#include <SD.h>
#include <SPI.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// Teensy 2.0: pin 0
// Teensy++ 2.0: pin 20
// Teensy 3.0: pin 10
// Audio Shield for Teensy 3.0: pin 10
const int chipSelect = 10;

void setup()
{
SPI.setMOSI(7); // Audio shield has MOSI on pin 7
SPI.setSCK(14); // Audio shield has SCK on pin 14
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
delay(250);


Serial.print("\nInitializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
pinMode(10, OUTPUT); // change this to 53 on a mega


// we'll use the initialization code from the utility libraries
// since we're just testing if the card is working!
if (!card.init(SPI_HALF_SPEED, chipSelect)) {
Serial.println("initialization failed. Things to check:");
Serial.println("* is a card is inserted?");
Serial.println("* Is your wiring correct?");
Serial.println("* did you change the chipSelect pin to match your shield or module?");
return;
} else {
Serial.println("Wiring is correct and a card is present.");
}

// print the type of card
Serial.print("\nCard type: ");
switch(card.type()) {
case SD_CARD_TYPE_SD1:
Serial.println("SD1");
break;
case SD_CARD_TYPE_SD2:
Serial.println("SD2");
break;
case SD_CARD_TYPE_SDHC:
Serial.println("SDHC");
break;
default:
Serial.println("Unknown");
}

// Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
if (!volume.init(card)) {
Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
return;
}


// print the type and size of the first FAT-type volume
uint32_t volumesize;
Serial.print("\nVolume type is FAT");
Serial.println(volume.fatType(), DEC);
Serial.println();
volumesize = volume.blocksPerCluster(); // clusters are collections of blocks
volumesize *= volume.clusterCount(); // we'll have a lot of clusters
volumesize *= 512; // SD card blocks are always 512 bytes
Serial.print("Volume size (bytes): ");
Serial.println(volumesize);
Serial.print("Volume size (Kbytes): ");
volumesize /= 1024;
Serial.println(volumesize);
Serial.print("Volume size (Mbytes): ");
volumesize /= 1024;
Serial.println(volumesize);

Serial.println("\nFiles found on the card (name, date and size in bytes): ");
root.openRoot(volume);
// list all files in the card with date and size
root.ls(LS_R | LS_DATE | LS_SIZE);
}


void loop(void) {
}

+ 0
- 139
examples/SpectrumAnalyzer/SpectrumAnalyzer.ino 查看文件

@@ -1,139 +0,0 @@
#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <LiquidCrystal.h>

//const int myInput = AUDIO_INPUT_LINEIN;
const int myInput = AUDIO_INPUT_MIC;

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//
AudioInputI2S audioInput; // audio shield: mic or line-in
AudioAnalyzeFFT256 myFFT(11);
AudioOutputI2S audioOutput; // audio shield: headphones & line-out

// Create Audio connections between the components
//
AudioConnection c1(audioInput, 0, audioOutput, 0);
AudioConnection c2(audioInput, 0, myFFT, 0);
AudioConnection c3(audioInput, 1, audioOutput, 1);

// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;

// Use the LiquidCrystal library to display the spectrum
//
LiquidCrystal lcd(0, 1, 2, 3, 4, 5);
byte bar1[8] = {0,0,0,0,0,0,0,255};
byte bar2[8] = {0,0,0,0,0,0,255,255};
byte bar3[8] = {0,0,0,0,0,255,255,255};
byte bar4[8] = {0,0,0,0,255,255,255,255};
byte bar5[8] = {0,0,0,255,255,255,255,255};
byte bar6[8] = {0,0,255,255,255,255,255,255};
byte bar7[8] = {0,255,255,255,255,255,255,255};
byte bar8[8] = {255,255,255,255,255,255,255,255};

void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(12);

// Enable the audio shield and set the output volume.
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(60);
lcd.begin(16, 2);
lcd.print("Audio Spectrum");
lcd.createChar(0, bar1);
lcd.createChar(1, bar2);
lcd.createChar(2, bar3);
lcd.createChar(3, bar4);
lcd.createChar(4, bar5);
lcd.createChar(5, bar6);
lcd.createChar(6, bar7);
lcd.createChar(7, bar8);

// pin 21 will select rapid vs animated display
pinMode(21, INPUT_PULLUP);
}

int count=0;

const int nsum[16] = {1, 1, 2, 2, 3, 4, 5, 6, 6, 8, 12, 14, 16, 20, 28, 24};

int maximum[16];

void loop() {
if (myFFT.available()) {
// convert the 128 FFT frequency bins
// to only 16 sums, for a 16 character LCD
int sum[16];
int i;
for (i=0; i<16; i++) {
sum[i] = 0;
}
int n=0;
int count=0;
for (i=0; i<128; i++) {
sum[n] = sum[n] + myFFT.output[i];
count = count + 1;
if (count >= nsum[n]) {
Serial.print(count);
Serial.print(" ");
n = n + 1;
if (n >= 16) break;
count = 0;
}
}

// The range is set by the audio shield's
// knob, which connects to analog pin A1.
int scale;
scale = 2 + (1023 - analogRead(A1)) / 7;
Serial.print(" - ");
Serial.print(scale);
Serial.print(" ");
lcd.setCursor(0, 1);
for (int i=0; i<16; i++) {
// Reduce the range to 0-8
int val = sum[i] / scale;
if (val > 8) val = 8;

// Compute an animated maximum, where increases
// show instantly, but if the number is less that
// the last displayed value, decrease it by 1 for
// a slow decay (looks pretty)
if (val >= maximum[i]) {
maximum[i] = val;
} else {
if (maximum[i] > 0) maximum[i] = maximum[i] - 1;
}

// a switch on pin 22 select whether we show the
// slower animation or the direct/fast data
if (digitalRead(21) == HIGH) {
val = maximum[i];
}

// print each custom digit
if (val == 0) {
lcd.write(' ');
} else {
lcd.write(val - 1);
}
Serial.print(sum[i]);
Serial.print("=");
Serial.print(val);
Serial.print(",");
}
Serial.println();
count = 0;
}
}



+ 70
- 0
examples/Synthesis/PlaySynthMusic/PlaySynthMusic.h 查看文件

@@ -0,0 +1,70 @@

// Table of midi note frequencies * 2
// They are times 2 for greater accuracy, yet still fits in a word.
// Generated from Excel by =ROUND(2*440/32*(2^((x-9)/12)),0) for 0<x<128
// The lowest notes might not work, depending on the Arduino clock frequency

// This is for the Teensy Audio library which specifies
// frequencies as floating point. See make_notetab.xlsx
const float tune_frequencies2_PGM[128] =
{
8.1758, 8.6620, 9.1770, 9.7227, 10.3009, 10.9134, 11.5623, 12.2499,
12.9783, 13.7500, 14.5676, 15.4339, 16.3516, 17.3239, 18.3540, 19.4454,
20.6017, 21.8268, 23.1247, 24.4997, 25.9565, 27.5000, 29.1352, 30.8677,
32.7032, 34.6478, 36.7081, 38.8909, 41.2034, 43.6535, 46.2493, 48.9994,
51.9131, 55.0000, 58.2705, 61.7354, 65.4064, 69.2957, 73.4162, 77.7817,
82.4069, 87.3071, 92.4986, 97.9989, 103.8262, 110.0000, 116.5409, 123.4708,
130.8128, 138.5913, 146.8324, 155.5635, 164.8138, 174.6141, 184.9972, 195.9977,
207.6523, 220.0000, 233.0819, 246.9417, 261.6256, 277.1826, 293.6648, 311.1270,
329.6276, 349.2282, 369.9944, 391.9954, 415.3047, 440.0000, 466.1638, 493.8833,
523.2511, 554.3653, 587.3295, 622.2540, 659.2551, 698.4565, 739.9888, 783.9909,
830.6094, 880.0000, 932.3275, 987.7666, 1046.5023, 1108.7305, 1174.6591, 1244.5079,
1318.5102, 1396.9129, 1479.9777, 1567.9817, 1661.2188, 1760.0000, 1864.6550, 1975.5332,
2093.0045, 2217.4610, 2349.3181, 2489.0159, 2637.0205, 2793.8259, 2959.9554, 3135.9635,
3322.4376, 3520.0000, 3729.3101, 3951.0664, 4186.0090, 4434.9221, 4698.6363, 4978.0317,
5274.0409, 5587.6517, 5919.9108, 6271.9270, 6644.8752, 7040.0000, 7458.6202, 7902.1328,
8372.0181, 8869.8442, 9397.2726, 9956.0635, 10548.0818, 11175.3034, 11839.8215, 12543.8540
};

#define CMD_PLAYNOTE 0x90 /* play a note: low nibble is generator #, note is next byte */
#define CMD_STOPNOTE 0x80 /* stop a note: low nibble is generator # */
#define CMD_RESTART 0xe0 /* restart the score from the beginning */
#define CMD_STOP 0xf0 /* stop playing */

const float velocity2amplitude[127] = {
0.01778,0.01966,0.02164,0.02371,0.02588,0.02814,0.03049,0.03294,0.03549,0.03812,
0.04086,0.04369,0.04661,0.04963,0.05274,0.05594,0.05924,0.06264,0.06613,0.06972,
0.07340,0.07717,0.08104,0.08500,0.08906,0.09321,0.09746,0.10180,0.10624,0.11077,
0.11539,0.12011,0.12493,0.12984,0.13484,0.13994,0.14513,0.15042,0.15581,0.16128,
0.16685,0.17252,0.17828,0.18414,0.19009,0.19613,0.20227,0.20851,0.21484,0.22126,
0.22778,0.23439,0.24110,0.24790,0.25480,0.26179,0.26887,0.27605,0.28333,0.29070,
0.29816,0.30572,0.31337,0.32112,0.32896,0.33690,0.34493,0.35306,0.36128,0.36960,
0.37801,0.38651,0.39511,0.40381,0.41260,0.42148,0.43046,0.43953,0.44870,0.45796,
0.46732,0.47677,0.48631,0.49595,0.50569,0.51552,0.52544,0.53546,0.54557,0.55578,
0.56609,0.57648,0.58697,0.59756,0.60824,0.61902,0.62989,0.64085,0.65191,0.66307,
0.67432,0.68566,0.69710,0.70863,0.72026,0.73198,0.74380,0.75571,0.76771,0.77981,
0.79201,0.80430,0.81668,0.82916,0.84174,0.85440,0.86717,0.88003,0.89298,0.90602,
0.91917,0.93240,0.94573,0.95916,0.97268,0.98629,1.00000
};
/*
#! /usr/bin/perl
# The Interpretation of MIDI Velocity
# Roger B. Dannenberg
# School of Computer Science, Carnegie Mellon University
$dynamic_range = 35;
$r = 10 ** ($dynamic_range / 20);
$b = 127 / (126 * sqrt($r)) - 1/126;
$m = (1 - $b) / 127;
print "const float velocity2amplitude[127] = {\n";
for ($v=1; $v <= 127; $v++) {
$a = ($m * $v + $b) ** 2;
printf "%.5f", $a;
print "," if $v < 127;
print "\n" if ($v % 10) == 0;
}
print "\n};\n";
*/


// User must supply this score array
extern unsigned char score[];

+ 256
- 0
examples/Synthesis/PlaySynthMusic/PlaySynthMusic.ino 查看文件

@@ -0,0 +1,256 @@
// Implement a 16 note polyphonic midi player :-)
//
// Music data is read from memory. The "Miditones" program is used to
// convert from a MIDI file to this compact format.
//
// This example code is in the public domain.
#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include <SerialFlash.h>

#include "PlaySynthMusic.h"

unsigned char *sp = score;

#define AMPLITUDE (0.2)

// Create 16 waveforms, one for each MIDI channel
AudioSynthWaveform sine0, sine1, sine2, sine3;
AudioSynthWaveform sine4, sine5, sine6, sine7;
AudioSynthWaveform sine8, sine9, sine10, sine11;
AudioSynthWaveform sine12, sine13, sine14, sine15;
AudioSynthWaveform *waves[16] = {
&sine0, &sine1, &sine2, &sine3,
&sine4, &sine5, &sine6, &sine7,
&sine8, &sine9, &sine10, &sine11,
&sine12, &sine13, &sine14, &sine15
};

// allocate a wave type to each channel.
// The types used and their order is purely arbitrary.
short wave_type[16] = {
WAVEFORM_SINE,
WAVEFORM_SQUARE,
WAVEFORM_SAWTOOTH,
WAVEFORM_TRIANGLE,
WAVEFORM_SINE,
WAVEFORM_SQUARE,
WAVEFORM_SAWTOOTH,
WAVEFORM_TRIANGLE,
WAVEFORM_SINE,
WAVEFORM_SQUARE,
WAVEFORM_SAWTOOTH,
WAVEFORM_TRIANGLE,
WAVEFORM_SINE,
WAVEFORM_SQUARE,
WAVEFORM_SAWTOOTH,
WAVEFORM_TRIANGLE
};

// Each waveform will be shaped by an envelope
AudioEffectEnvelope env0, env1, env2, env3;
AudioEffectEnvelope env4, env5, env6, env7;
AudioEffectEnvelope env8, env9, env10, env11;
AudioEffectEnvelope env12, env13, env14, env15;
AudioEffectEnvelope *envs[16] = {
&env0, &env1, &env2, &env3,
&env4, &env5, &env6, &env7,
&env8, &env9, &env10, &env11,
&env12, &env13, &env14, &env15
};

// Route each waveform through its own envelope effect
AudioConnection patchCord01(sine0, env0);
AudioConnection patchCord02(sine1, env1);
AudioConnection patchCord03(sine2, env2);
AudioConnection patchCord04(sine3, env3);
AudioConnection patchCord05(sine4, env4);
AudioConnection patchCord06(sine5, env5);
AudioConnection patchCord07(sine6, env6);
AudioConnection patchCord08(sine7, env7);
AudioConnection patchCord09(sine8, env8);
AudioConnection patchCord10(sine9, env9);
AudioConnection patchCord11(sine10, env10);
AudioConnection patchCord12(sine11, env11);
AudioConnection patchCord13(sine12, env12);
AudioConnection patchCord14(sine13, env13);
AudioConnection patchCord15(sine14, env14);
AudioConnection patchCord16(sine15, env15);

// Four mixers are needed to handle 16 channels of music
AudioMixer4 mixer1;
AudioMixer4 mixer2;
AudioMixer4 mixer3;
AudioMixer4 mixer4;

// Mix the 16 channels down to 4 audio streams
AudioConnection patchCord17(env0, 0, mixer1, 0);
AudioConnection patchCord18(env1, 0, mixer1, 1);
AudioConnection patchCord19(env2, 0, mixer1, 2);
AudioConnection patchCord20(env3, 0, mixer1, 3);
AudioConnection patchCord21(env4, 0, mixer2, 0);
AudioConnection patchCord22(env5, 0, mixer2, 1);
AudioConnection patchCord23(env6, 0, mixer2, 2);
AudioConnection patchCord24(env7, 0, mixer2, 3);
AudioConnection patchCord25(env8, 0, mixer3, 0);
AudioConnection patchCord26(env9, 0, mixer3, 1);
AudioConnection patchCord27(env10, 0, mixer3, 2);
AudioConnection patchCord28(env11, 0, mixer3, 3);
AudioConnection patchCord29(env12, 0, mixer4, 0);
AudioConnection patchCord30(env13, 0, mixer4, 1);
AudioConnection patchCord31(env14, 0, mixer4, 2);
AudioConnection patchCord32(env15, 0, mixer4, 3);

// Now create 2 mixers for the main output
AudioMixer4 mixerLeft;
AudioMixer4 mixerRight;
AudioOutputI2S audioOut;

// Mix all channels to both the outputs
AudioConnection patchCord33(mixer1, 0, mixerLeft, 0);
AudioConnection patchCord34(mixer2, 0, mixerLeft, 1);
AudioConnection patchCord35(mixer3, 0, mixerLeft, 2);
AudioConnection patchCord36(mixer4, 0, mixerLeft, 3);
AudioConnection patchCord37(mixer1, 0, mixerRight, 0);
AudioConnection patchCord38(mixer2, 0, mixerRight, 1);
AudioConnection patchCord39(mixer3, 0, mixerRight, 2);
AudioConnection patchCord40(mixer4, 0, mixerRight, 3);
AudioConnection patchCord41(mixerLeft, 0, audioOut, 0);
AudioConnection patchCord42(mixerRight, 0, audioOut, 1);

AudioControlSGTL5000 codec;

// Initial value of the volume control
int volume = 50;

void setup()
{
Serial.begin(115200);
//while (!Serial) ; // wait for Arduino Serial Monitor
delay(200);
// http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html
Serial.print("Begin ");
Serial.println(__FILE__);
// Proc = 12 (13), Mem = 2 (8)
// Audio connections require memory to work.
// The memory usage code indicates that 10 is the maximum
// so give it 12 just to be sure.
AudioMemory(18);
codec.enable();
codec.volume(0.45);

// reduce the gain on some channels, so half of the channels
// are "positioned" to the left, half to the right, but all
// are heard at least partially on both ears
mixerLeft.gain(1, 0.36);
mixerLeft.gain(3, 0.36);
mixerRight.gain(0, 0.36);
mixerRight.gain(2, 0.36);

// set envelope parameters, for pleasing sound :-)
for (int i=0; i<16; i++) {
envs[i]->attack(9.2);
envs[i]->hold(2.1);
envs[i]->decay(31.4);
envs[i]->sustain(0.6);
envs[i]->release(84.5);
// uncomment these to hear without envelope effects
//envs[i]->attack(0.0);
//envs[i]->hold(0.0);
//envs[i]->decay(0.0);
//envs[i]->release(0.0);
}

Serial.println("setup done");
// Initialize processor and memory measurements
AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset();
}


unsigned long last_time = millis();
void loop()
{
unsigned char c,opcode,chan;
unsigned long d_time;
// Change this to if(1) for measurement output every 5 seconds
if(1) {
if(millis() - last_time >= 5000) {
Serial.print("Proc = ");
Serial.print(AudioProcessorUsage());
Serial.print(" (");
Serial.print(AudioProcessorUsageMax());
Serial.print("), Mem = ");
Serial.print(AudioMemoryUsage());
Serial.print(" (");
Serial.print(AudioMemoryUsageMax());
Serial.println(")");
last_time = millis();
}
}

// Volume control
// uncomment if you have a volume pot soldered to your audio shield
/*
int n = analogRead(15);
if (n != volume) {
volume = n;
codec.volume((float)n / 1023);
}
*/
// read the next note from the table
c = *sp++;
opcode = c & 0xF0;
chan = c & 0x0F;

if(c < 0x80) {
// Delay
d_time = (c << 8) | *sp++;
delay(d_time);
return;
}
if(*sp == CMD_STOP) {
for (chan=0; chan<10; chan++) {
envs[chan]->noteOff();
waves[chan]->amplitude(0);
}
Serial.println("DONE");
while(1);
}

// It is a command
// Stop the note on 'chan'
if(opcode == CMD_STOPNOTE) {
envs[chan]->noteOff();
return;
}
// Play the note on 'chan'
if(opcode == CMD_PLAYNOTE) {
unsigned char note = *sp++;
unsigned char velocity = *sp++;
AudioNoInterrupts();
waves[chan]->begin(AMPLITUDE * velocity2amplitude[velocity-1],
tune_frequencies2_PGM[note],
wave_type[chan]);
envs[chan]->noteOn();
AudioInterrupts();
return;
}

// replay the tune
if(opcode == CMD_RESTART) {
sp = score;
return;
}
}

+ 5
- 0
examples/Synthesis/PlaySynthMusic/miditones/Makefile 查看文件

@@ -0,0 +1,5 @@
miditones: miditonesV1.6.c
gcc -O2 -Wall -o miditones miditonesV1.6.c

clean:
rm -f miditones

+ 975
- 0
examples/Synthesis/PlaySynthMusic/miditones/miditonesV1.6.c 查看文件

@@ -0,0 +1,975 @@
/*********************************************************************************
*
* MIDITONES
*
* Convert a MIDI file into a bytestream of notes
*
*
* (C) Copyright 2011, Len Shustek
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of version 3 of the GNU General Public License as
* published by the Free Software Foundation at http://www.gnu.org/licenses,
* with Additional Permissions under term 7(b) that the original copyright
* notice and author attibution must be preserved and under term 7(c) that
* modified versions be marked as different from the original.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
***********************************************************************************/
/*
* Change log
* 19 January 2011, L.Shustek, V1.0
* -Initial release.
* 26 February 2011, L. Shustek, V1.1
* -Expand the documentation generated in the output file.
* -End the binary output file with an "end of score" command.
* -Fix bug: Some "stop note" commands were generated too early.
* 04 March 2011, L. Shustek, V1.2
* -Minor error message rewording.
* 13 June 2011, L. Shustek, V1.3
* -Add -s2 strategy to try to keep each track on its own tone generator
* for when there are separate speakers. This obviously works only when
* each track is monophonic. (Suggested by Michal Pustejovsky)
* 20 November 2011, L. Shustek, V1.4
* -Add -cn option to mask which channels (tracks) to process
* -Add -kn option to change key
* Both of these are in support of music-playing on my Tesla Coil.
* 05 December 2011, L. Shustek, V1.5
* -Fix command line parsing error for option -s1
* -Display the commandline in the C file output
* -Change to decimal instead of hex for note numbers in the C file output
* 06 August 2013, L. Shustek, V1.6
* -Changed to allow compilation and execution in 64-bit environments
* by using C99 standard intN_t and uintN_t types for MIDI structures,
* and formatting specifications like "PRId32" instead of "ld".
*/
// Sept 2014 - Add option for velocity output
#define VERSION "1.6"
/*--------------------------------------------------------------------------------
*
*
* About MIDITONES
*
*
* MIDITONES converts a MIDI music file into a much simplified stream of commands,
* so that a version of the music can be played on a synthesizer having only
* tone generators without any volume or tone controls.
*
* Volume ("velocity") and instrument specifications in the MIDI files are discarded.
* All the tracks are prcoessed and merged into a single time-ordered stream of
* "note on", "note off", and "delay" commands.
*
* This was written for the "Playtune" Arduino library, which plays polyphonic music
* using up to 6 tone generators run by the timers on the processor. See the separate
* documentation for Playtune. But MIDITONES may prove useful for other tone
* generating systems.
*
* The output can be either a C-language source code fragment that initializes an
* array with the command bytestream, or a binary file with the bytestream itself.
*
* MIDITONES is written in standard ANSI C (plus strlcpy and strlcat functions), and
* is meant to be executed from the command line. There is no GUI interface.
*
* The MIDI file format is complicated, and this has not been tested on a very
* wide variety of file types. In particular, we have tested only format type "1",
* which seems to be what most of them are. Let me know if you find MIDI files
* that it won't digest and I'll see if I can fix it.
* This has been tested only on a little-endian PC, but I think it should work on
* big-endian processors too. Note that the MIDI file format is inherently
* big-endian.
*
*
* ***** The command line *****
*
* To convert a MIDI file called "chopin.mid" into a command bytestream, execute
*
* miditones chopin
*
* It will create a file in the same directory called "chopin.c" which contains
* the C-language statement to intiialize an array called "score" with the bytestream.
*
*
* The general form for command line execution is this:
*
* miditones [-p] [-lg] [-lp] [-s1] [-tn] [-b] [-cn] [-kn] <basefilename>
*
* The <basefilename> is the base name, without an extension, for the input and
* output files. It can contain directory path information, or not.
*
* The input file is the base name with the extension ".mid". The output filename(s)
* are the base name with ".c", ".bin", and/or ".log" extensions.
*
*
* The following command-line options can be specified:
*
* -p Only parse the MIDI file; don't generate an output file.
* Tracks are processed sequentially instead of being merged into chronological order.
* This is mostly useful when generating a log to debug MIDI file parsing problems.
*
* -lp Log input file parsing information to the <basefilename>.log file
*
* -lg Log output bytestream generation information to the <basefilename>.log file
*
* -sn Use bytestream generation strategy "n".
* Two strategies are currently implemented:
* 1: favor track 1 notes instead of all tracks equally
* 2: try to keep each track to its own tone generator
*
* -tn Generate the bytestream so that at most n tone generators are used.
* The default is 6 tone generators, and the maximum is 16.
* The program will report how many notes had to be discarded because there
* weren't enough tone generators. Note that for the Arduino Playtunes
* library, it's ok to have the bytestream use more tone genreators than
* exist on your processor because any extra notes will be ignored, although
* it does make the file bigger than necessary . Of course, too many ignored
* notes will make the music sound really strange!
*
* -b Generate a binary file with the name <basefilename>.bin, instead of a
* C-language source file with the name <basefilename>.c.
*
* -cn Only process the channel numbers whose bits are on in the number "n".
* For example, -c3 means "only process channels 0 and 1"
*
* -kn Change the musical key of the output by n chromatic notes.
* -k-12 goes one octave down, -k12 goes one octave up, etc.
*
* -v Add velocity information to output
*
*
* ***** The score bytestream *****
*
* The generated bytestream is a series of commands that turn notes on and off, and
* start delays until the next note change. Here are the details, with numbers
* shown in hexadecimal.
*
* If the high-order bit of the byte is 1, then it is one of the following commands:
*
* 9t nn Start playing note nn on tone generator t. Generators are numbered
* starting with 0. The notes numbers are the MIDI numbers for the chromatic
* scale, with decimal 60 being Middle C, and decimal 69 being Middle A (440 Hz).
*
* 8t Stop playing the note on tone generator t.
*
* F0 End of score: stop playing.
*
* E0 End of score: start playing again from the beginning.
* (Shown for completeness; MIDITONES won't generate this.)
*
* If the high-order bit of the byte is 0, it is a command to delay for a while until
* the next note change.. The other 7 bits and the 8 bits of the following byte are
* interpreted as a 15-bit big-endian integer that is the number of milliseconds to
* wait before processing the next command. For example,
*
* 07 D0
*
* would cause a delay of 0x07d0 = 2000 decimal millisconds, or 2 seconds. Any tones
* that were playing before the delay command will continue to play.
*
*
* Len Shustek, 4 Feb 2011
*
*----------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <time.h>
#include <inttypes.h>
/*********** MIDI file header formats *****************/
struct midi_header {
int8_t MThd[4];
uint32_t header_size;
uint16_t format_type;
uint16_t number_of_tracks;
uint16_t time_division;
};
struct track_header {
int8_t MTrk[4];
uint32_t track_size;
};
/*********** Global variables ******************/
#define MAX_TONEGENS 16 /* max tone generators: tones we can play simultaneously */
#define DEFAULT_TONEGENS 6 /* default number of tone generators */
#define MAX_TRACKS 24 /* max number of MIDI tracks we will process */
bool loggen, logparse, parseonly, strategy1, strategy2, binaryoutput, velocityoutput;
FILE *infile, *outfile, *logfile;
uint8_t *buffer, *hdrptr;
unsigned long buflen;
int num_tracks;
int tracks_done = 0;
int outfile_itemcount = 0;
int num_tonegens = DEFAULT_TONEGENS;
int num_tonegens_used = 0;
unsigned channel_mask = 0xffff; // bit mask of channels to process
int keyshift = 0; // optional chromatic note shift for output file
long int outfile_bytecount = 0;
unsigned int ticks_per_beat = 240;
unsigned long timenow = 0;
unsigned long tempo; /* current tempo in usec/qnote */
struct tonegen_status { /* current status of a tone generator */
bool playing; /* is it playing? */
int track; /* if so, which track is the note from? */
int note; /* what note is playing? */
}
tonegen [MAX_TONEGENS] = {
{0}};
struct track_status { /* current processing point of a MIDI track */
uint8_t *trkptr; /* ptr to the next note change */
uint8_t *trkend; /* ptr past the end of the track */
unsigned long time; /* what time we're at in the score */
unsigned long tempo; /* the tempo last set, in usec/qnote */
unsigned int preferred_tonegen; /* for strategy2: try to use this generator */
unsigned char cmd; /* CMD_xxxx next to do */
unsigned char note; /* for which note */
unsigned char velocity;
unsigned char last_event; /* the last event, for MIDI's "running status" */
bool tonegens[MAX_TONEGENS];/* which tone generators our notes are playing on */
}
track[MAX_TRACKS] = {
{0}};
/* output bytestream commands, which are also stored in track_status.cmd */
#define CMD_PLAYNOTE 0x90 /* play a note: low nibble is generator #, note is next byte */
#define CMD_STOPNOTE 0x80 /* stop a note: low nibble is generator # */
#define CMD_RESTART 0xe0 /* restart the score from the beginning */
#define CMD_STOP 0xf0 /* stop playing */
/* if CMD < 0x80, then the other 7 bits and the next byte are a 15-bit number of msec to delay */
/* these other commands stored in the track_status.com */
#define CMD_TEMPO 0xFE /* tempo in usec per quarter note ("beat") */
#define CMD_TRACKDONE 0xFF /* no more data left in this track */
/************** command-line processing *******************/
void SayUsage(char *programName){
static char *usage[] = {
"Convert MIDI files to an Arduino PLAYTUNE bytestream",
"miditones [-p] [-lg] [-lp] [-s1] [-tn] <basefilename>",
" -p parse only, don't generate bytestream",
" -lp log input parsing",
" -lg log output generation",
" -s1 strategy 1: favor track 1",
" -s2 strategy 2: try to assign tracks to specific tone generators",
" -tn use at most n tone generators (default is 6, max is 16)",
" -b binary file output instead of C source text",
" -cn mask for which tracks to process, e.g. -c3 for only 0 and 1",
" -kn key shift in chromatic notes, positive or negative",
"input file: <basefilename>.mid",
"output file: <basefilename>.bin or .c",
"log file: <basefilename>.log",
"" };
int i=0;
while (usage[i][0] != '\0') fprintf(stderr, "%s\n", usage[i++]);
}
int HandleOptions(int argc,char *argv[]) {
/* returns the index of the first argument that is not an option; i.e.
does not start with a dash or a slash*/
int i,firstnonoption=0;
/* --- The following skeleton comes from C:\lcc\lib\wizard\textmode.tpl. */
for (i=1; i< argc;i++) {
if (argv[i][0] == '/' || argv[i][0] == '-') {
switch (toupper(argv[i][1])) {
case 'H':
case '?':
SayUsage(argv[0]);
exit(1);
case 'L':
if (toupper(argv[i][2]) == 'G') loggen = true;
else if (toupper(argv[i][2]) == 'P') logparse = true;
else goto opterror;
break;
case 'P':
parseonly = true;
break;
case 'B':
binaryoutput = true;
break;
case 'V':
velocityoutput = true;
break;
case 'S':
if (argv[i][2] == '1') strategy1 = true;
else if (argv[i][2] == '2') strategy2 = true;
else goto opterror;
break;
case 'T':
if (sscanf(&argv[i][2],"%d",&num_tonegens) != 1 || num_tonegens <1 || num_tonegens > MAX_TONEGENS) goto opterror;
printf("Using %d tone generators.\n", num_tonegens);
break;
case 'C':
if (sscanf(&argv[i][2],"%d",&channel_mask) != 1 || channel_mask > 0xffff) goto opterror;
printf("Channel (track) mask is %04X.\n", channel_mask);
break;
case 'K':
if (sscanf(&argv[i][2],"%d",&keyshift) != 1 || keyshift < -100 || keyshift > 100) goto opterror;
printf("Using keyshift %d.\n", keyshift);
break;
/* add more option switches here */
opterror:
default:
fprintf(stderr,"unknown option: %s\n",argv[i]);
SayUsage(argv[0]);
exit(4);
}
}
else {
firstnonoption = i;
break;
}
}
return firstnonoption;
}
void print_command_line (int argc,char *argv[]) {
int i;
fprintf(outfile, "// command line: ");
for (i=0; i< argc; i++) fprintf(outfile,"%s ",argv[i]);
fprintf(outfile, "\n");
}
/**************** utility routines **********************/
size_t strlcat (char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return (dlen + strlen(s));
while (*s != '\0') {
if (n != 1) {
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return (dlen + (s - src)); /* count does not include NUL */
}
size_t strlcpy(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0) {
while (--n != 0) {
if ((*d++ = *s++) == '\0') break;
}
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return (s - src - 1); /* count does not include NUL */
}
/* match a constant character sequence */
int charcmp (const char *buf, const char *match) {
int len, i;
len = strlen (match);
for (i=0; i<len; ++i)
if (buf[i] != match[i]) return 0;
return 1;
}
/* announce a fatal MIDI file format error */
void midi_error (char *msg, unsigned char *bufptr) {
unsigned char *ptr;
fprintf(stderr, "---> MIDI file error at position %04X (%d): %s\n", (uint16_t)(bufptr-buffer), (uint16_t)(bufptr-buffer), msg);
/* print some bytes surrounding the error */
ptr = bufptr - 16;
if (ptr < buffer) ptr = buffer;
for (; ptr <= bufptr+16 && ptr < buffer+buflen; ++ptr) fprintf (stderr, ptr==bufptr ? " [%02X] ":"%02X ", *ptr);
fprintf(stderr, "\n");
exit(8);
}
/* check that we have a specified number of bytes left in the buffer */
void chk_bufdata(unsigned char *ptr, int len) {
if (ptr + len - buffer > buflen) midi_error("data missing", ptr);
}
/* fetch big-endian numbers */
uint16_t rev_short (uint16_t val) {
return ((val&0xff)<<8) | ((val>>8)&0xff);
}
uint32_t rev_long (uint32_t val){
return (((rev_short((uint16_t)val) & 0xffff) << 16) |
(rev_short((uint16_t)(val >> 16)) & 0xffff));
}
/* account for new items in the non-binary output file
and generate a newline every so often. */
void outfile_items (int n) {
outfile_bytecount += n;
outfile_itemcount += n;
if (!binaryoutput && outfile_itemcount > 20) {
fprintf (outfile, "\n");
outfile_itemcount = 0;
}
}
/************** process the MIDI file header *****************/
void process_header (void) {
struct midi_header *hdr;
unsigned int time_division;
chk_bufdata(hdrptr, sizeof(struct midi_header));
hdr = (struct midi_header *) hdrptr;
if (!charcmp((char *)(hdr->MThd),"MThd")) midi_error("Missing 'MThd'", hdrptr);
num_tracks = rev_short(hdr->number_of_tracks);
time_division = rev_short(hdr->time_division);
if (time_division < 0x8000) ticks_per_beat = time_division;
else ticks_per_beat = ((time_division >> 8) & 0x7f) /* SMTE frames/sec */ * (time_division & 0xff); /* ticks/SMTE frame */
if (logparse) {
fprintf (logfile, "Header size %" PRId32 "\n", rev_long(hdr->header_size));
fprintf (logfile, "Format type %d\n", rev_short(hdr->format_type));
fprintf (logfile, "Number of tracks %d\n", num_tracks);
fprintf (logfile, "Time division %04X\n", time_division);
fprintf (logfile, "Ticks/beat = %d\n", ticks_per_beat);
}
hdrptr += rev_long(hdr->header_size) + 8; /* point past header to track header, presumably. */
return;
}
/**************** Process a MIDI track header *******************/
void start_track (int tracknum) {
struct track_header *hdr;
unsigned long tracklen;
chk_bufdata(hdrptr, sizeof(struct track_header));
hdr = (struct track_header *) hdrptr;
if (!charcmp((char *)(hdr->MTrk),"MTrk")) midi_error("Missing 'MTrk'", hdrptr);
tracklen = rev_long(hdr->track_size);
if (logparse) fprintf (logfile, "\nTrack %d length %ld\n", tracknum, tracklen);
hdrptr += sizeof (struct track_header); /* point past header */
chk_bufdata(hdrptr, tracklen);
track[tracknum].trkptr = hdrptr;
hdrptr += tracklen; /* point to the start of the next track */
track[tracknum].trkend = hdrptr; /* the point past the end of the track */
}
/* Get a MIDI-style variable-length integer */
unsigned long get_varlen (uint8_t **ptr) {
/* Get a 1-4 byte variable-length value and adjust the pointer past it.
These are a succession of 7-bit values with a MSB bit of zero marking the end */
unsigned long val;
int i, byte;
val = 0;
for (i=0; i<4; ++i){
byte = *(*ptr)++;
val = (val<<7) | (byte&0x7f);
if (!(byte&0x80)) return val;
}
return val;
}
/*************** Process the MIDI track data ***************************/
/* Skip in the track for the next "note on", "note off" or "set tempo" command,
then record that information in the track status block and return. */
void find_note (int tracknum) {
unsigned long int delta_time;
int event, chan;
int i;
int note, velocity; // , parm;
int meta_cmd, meta_length;
unsigned long int sysex_length;
struct track_status *t;
/* process events */
t = &track[tracknum]; /* our track status structure */
while (t->trkptr < t->trkend) {
delta_time = get_varlen(&t->trkptr);
if (logparse) {
fprintf (logfile, "trk %d ", tracknum);
fprintf (logfile, delta_time ? "delta time %4ld, " : " ", delta_time);
}
t->time += delta_time;
if (*t->trkptr < 0x80) /* "running status" */ event = t->last_event;/* means same event as before */
else { /* new "status" (event type) */
event = *t->trkptr++;
t->last_event = event;
}
if (event == 0xff) { /* meta-event */
meta_cmd = *t->trkptr++;
meta_length = *t->trkptr++;
switch (meta_cmd) {
case 0x2f:
if (logparse) fprintf(logfile, "end of track\n");
break;
case 0x00:
if (logparse) fprintf(logfile, "sequence number %d\n", rev_short(*(unsigned short *)t->trkptr));
break;
case 0x20:
if (logparse) fprintf(logfile, "channel prefix %d\n", *t->trkptr);
break;
case 0x51: /* tempo: 3 byte big-endian integer! */
t->cmd = CMD_TEMPO;
t->tempo = rev_long(*(unsigned long *)(t->trkptr-1)) & 0xffffffL;
if (logparse) fprintf(logfile, "set tempo %ld usec/qnote\n", t->tempo);
t->trkptr += meta_length;
return;
case 0x54:
if (logparse) fprintf(logfile, "SMPTE offset %08" PRIx32 "\n", rev_long(*(unsigned long *)t->trkptr));
break;
case 0x58:
if (logparse) fprintf(logfile, "time signature %08" PRIx32 "\n", rev_long(*(unsigned long *)t->trkptr));
break;
case 0x59:
if (logparse) fprintf(logfile, "key signature %04X\n", rev_short(*(unsigned short *)t->trkptr));
break;
default: /* assume it is a string */
if (logparse) {
fprintf(logfile, "meta cmd %02X, length %d, \"", meta_cmd, meta_length);
for (i=0; i<meta_length; ++i) {
int ch = t->trkptr[i];
fprintf(logfile, "%c", isprint(ch) ? ch : '?');
}
fprintf(logfile, "\"\n");
}
if (tracknum==0 && meta_cmd==0x03 && !parseonly && !binaryoutput) {
/* Incredibly, MIDI has no standard for recording the name of the piece!
Track 0's "trackname" (meta 0x03) is sometimes used for that, so
we output it to the C file as documentation. */
fprintf(outfile, "// ");
for (i=0; i<meta_length; ++i) {
int ch = t->trkptr[i];
fprintf(outfile, "%c", isprint(ch) ? ch : '?');
}
fprintf(outfile, "\n");
}
break;
}
t->trkptr += meta_length;
}
else if (event <0x80) midi_error("Unknown MIDI event type", t->trkptr);
else {
chan = event & 0xf;
switch (event>>4) {
case 0x8:
t->note = *t->trkptr++;
velocity = *t->trkptr++;
note_off:
if (logparse) fprintf (logfile, "note %02X off, chan %d, velocity %d\n", t->note, chan, velocity);
if ((1<<chan) & channel_mask) { // if we're processing this channel
t->cmd = CMD_STOPNOTE;
return; /* stop processing and return */
}
break; // else keep looking
case 0x9:
t->note = *t->trkptr++;
velocity = *t->trkptr++;
if (velocity == 0) /* some scores use note-on with zero velocity for off! */ goto note_off;
t->velocity = velocity;
if (logparse) fprintf (logfile, "note %02X on, chan %d, velocity %d\n", t->note, chan, velocity);
if ((1<<chan) & channel_mask) { // if we're processing this channel
t->cmd = CMD_PLAYNOTE;
return; /* stop processing and return */
}
break; // else keep looking
case 0xa:
note = *t->trkptr++;
velocity = *t->trkptr++;
if (logparse) fprintf (logfile, "after-touch %02X, %02X\n", note, velocity);
break;
case 0xb:
note = *t->trkptr++;
velocity = *t->trkptr++;
if (logparse) fprintf (logfile, "control change %02X, %02X\n", note, velocity);
break;
case 0xc:
note = *t->trkptr++;
if (logparse) fprintf(logfile, "program patch %02X\n", note);
break;
case 0xd:
chan = *t->trkptr++;
if (logparse) fprintf(logfile, "channel after-touch %02X\n", chan);
break;
case 0xe:
note = *t->trkptr++;
velocity = *t->trkptr++;
if (logparse) fprintf(logfile, "pitch wheel change %02X, %02X\n", note, velocity);
break;
case 0xf:
sysex_length = get_varlen(&t->trkptr);
if (logparse) fprintf(logfile, "SysEx event %02X, %ld bytes\n", event, sysex_length);
t->trkptr += sysex_length;
break;
default:
midi_error("Unknown MIDI command", t->trkptr);
}
}
}
t->cmd = CMD_TRACKDONE; /* no more notes to process */
++tracks_done;
}
/********************* main ****************************/
int main(int argc,char *argv[]) {
int argno;
char *filebasename;
#define MAXPATH 120
char filename[MAXPATH];
//int i;
int tracknum;
int earliest_tracknum;
unsigned long earliest_time;
int notes_skipped = 0;
printf("MIDITONES V%s, (C) 2011 Len Shustek\n", VERSION);
printf("See the source code for license information.\n\n");
if (argc == 1) { /* no arguments */
SayUsage(argv[0]);
return 1;
}
/* process options */
argno = HandleOptions(argc,argv);
filebasename = argv[argno];
/* Open the log file */
if (logparse || loggen) {
strlcpy(filename, filebasename, MAXPATH);
strlcat(filename, ".log", MAXPATH);
logfile = fopen(filename, "w");
if (!logfile) {
fprintf(stderr, "Unable to open log file %s", filename);
return 1;
}
}
/* Open the input file */
strlcpy(filename, filebasename, MAXPATH);
strlcat(filename, ".mid", MAXPATH);
infile = fopen(filename, "rb");
if (!infile) {
fprintf(stderr, "Unable to open input file %s", filename);
return 1;
}
/* Read the whole input file into memory */
fseek(infile, 0, SEEK_END); /* find file size */
buflen = ftell(infile);
fseek(infile, 0, SEEK_SET);
buffer = (unsigned char *) malloc (buflen+1);
if (!buffer) {
fprintf(stderr, "Unable to allocate %ld bytes for the file", buflen);
return 1;
}
fread(buffer, buflen, 1, infile);
fclose(infile);
if (logparse) fprintf(logfile, "Processing %s, %ld bytes\n", filename, buflen);
/* Create the output file */
if (!parseonly) {
strlcpy(filename, filebasename, MAXPATH);
if (binaryoutput) {
strlcat(filename, ".bin", MAXPATH);
outfile = fopen(filename, "wb");
}
else {
strlcat(filename, ".c", MAXPATH);
outfile = fopen(filename, "w");
}
if (!outfile) {
fprintf(stderr, "Unable to open output file %s", filename);
return 1;
}
if (!binaryoutput) { /* create header of C file that initializes score data */
time_t rawtime;
//struct tm *ptime;
time (&rawtime);
fprintf(outfile, "// Playtune bytestream for file \"%s.mid\" ", filebasename);
fprintf(outfile, "created by MIDITONES V%s on %s", VERSION, asctime(localtime(&rawtime)));
print_command_line(argc,argv);
if (channel_mask != 0xffff)
fprintf(outfile, "// Only the masked channels were processed: %04X\n", channel_mask);
if (keyshift != 0)
fprintf(outfile, "// Keyshift was %d chromatic notes\n", keyshift);
fprintf(outfile, "#ifdef __AVR__\n");
fprintf(outfile, "#include <avr/pgmspace.h>\n");
fprintf(outfile, "#else\n");
fprintf(outfile, "#define PROGMEM\n");
fprintf(outfile, "#endif\n");
fprintf(outfile, "const unsigned char PROGMEM score [] = {\n");
}
}
/* process the MIDI file header */
hdrptr = buffer; /* pointer to file and track headers */
process_header ();
printf (" Processing %d tracks.\n", num_tracks);
if (num_tracks > MAX_TRACKS) midi_error ("Too many tracks", buffer);
/* initialize processing of all the tracks */
for (tracknum=0; tracknum < num_tracks; ++tracknum) {
start_track (tracknum); /* process the track header */
find_note (tracknum); /* position to the first note on/off */
/* if we are in "parse only" mode, do the whole track,
so we do them one at a time instead of time-synchronized. */
if (parseonly) while (track[tracknum].cmd != CMD_TRACKDONE) find_note(tracknum);
}
/* Continue processing all tracks, in an order based on the simulated time.
This is not unlike multiway merging used for tape sorting algoritms in the 50's! */
tracknum = 0;
if (!parseonly) do { /* while there are still track notes to process */
struct track_status *trk;
struct tonegen_status *tg;
int tgnum;
int count_tracks;
unsigned long delta_time, delta_msec;
/* Find the track with the earliest event time,
and output a delay command if time has advanced.
A potential improvement: If there are multiple tracks with the same time,
first do the ones with STOPNOTE as the next command, if any. That would
help avoid running out of tone generators. In practice, though, most MIDI
files do all the STOPNOTEs first anyway, so it won't have much effect.
*/
earliest_time = 0x7fffffff;
/* Usually we start with the track after the one we did last time (tracknum),
so that if we run out of tone generators, we have been fair to all the tracks.
The alternate "strategy1" says we always start with track 0, which means
that we favor early tracks over later ones when there aren't enough tone generators.
*/
count_tracks = num_tracks;
if (strategy1) tracknum = num_tracks; /* beyond the end, so we start with track 0 */
do {
if (++tracknum >= num_tracks) tracknum=0;
trk = &track[tracknum];
if (trk->cmd != CMD_TRACKDONE && trk->time < earliest_time) {
earliest_time = trk->time;
earliest_tracknum = tracknum;
}
}
while (--count_tracks);
tracknum = earliest_tracknum; /* the track we picked */
trk = &track[tracknum];
if (loggen) fprintf (logfile, "Earliest time is trk %d, time %ld\n", tracknum, earliest_time);
if (earliest_time < timenow) midi_error ("INTERNAL: time went backwards", trk->trkptr);
/* If time has advanced, output a "delay" command */
delta_time = earliest_time - timenow;
if (delta_time) {
/* Convert ticks to milliseconds based on the current tempo */
delta_msec = ((unsigned long) delta_time * tempo) / ticks_per_beat / 1000;
if (loggen) fprintf (logfile, "->Delay %ld msec (%ld ticks)\n", delta_msec, delta_time);
if (delta_msec > 0x7fff) midi_error ("INTERNAL: time delta too big", trk->trkptr);
/* output a 15-bit delay in big-endian format */
if (binaryoutput) {
putc ((unsigned char) (delta_msec >> 8), outfile);
putc ((unsigned char) (delta_msec & 0xff), outfile);
outfile_bytecount += 2;
}
else {
fprintf (outfile, "%ld,%ld, ", delta_msec >> 8, delta_msec & 0xff);
outfile_items(2);
}
}
timenow = earliest_time;
/* If this track event is "set tempo", just change the global tempo.
That affects how we generate "delay" commands. */
if (trk->cmd == CMD_TEMPO) {
tempo = trk->tempo;
if (loggen) fprintf (logfile, "Tempo changed to %ld usec/qnote\n", tempo);
find_note (tracknum);
}
/* If this track event is "stop note", process it and all subsequent "stop notes" for this track
that are happening at the same time. Doing so frees up as many tone generators as possible. */
else if (trk->cmd == CMD_STOPNOTE) do {
// stop a note
for (tgnum=0; tgnum < num_tonegens; ++tgnum) { /* find which generator is playing it */
tg = &tonegen[tgnum];
if (tg->playing && tg->track == tracknum && tg->note == trk->note) {
if (loggen) fprintf (logfile, "->Stop note %02X, generator %d, track %d\n", tg->note, tgnum, tracknum);
if (binaryoutput) {
putc (CMD_STOPNOTE | tgnum, outfile);
outfile_bytecount += 1;
}
else {
fprintf (outfile, "0x%02X, ", CMD_STOPNOTE | tgnum);
outfile_items (1);
}
tg->playing = false;
trk->tonegens[tgnum] = false;
}
}
find_note (tracknum); // use up the note
}
while (trk->cmd == CMD_STOPNOTE && trk->time == timenow);
/* If this track event is "start note", process only it.
Don't do more than one, so we allow other tracks their chance at grabbing tone generators. */
else if (trk->cmd == CMD_PLAYNOTE) {
bool foundgen = false;
if (strategy2) { /* try to use the same tone generator this track used last time */
tg = &tonegen [trk->preferred_tonegen];
if (!tg->playing) {
tgnum = trk->preferred_tonegen;
foundgen = true;
}
}
if (!foundgen) for (tgnum=0; tgnum < num_tonegens; ++tgnum) { /* search for a free tone generator */
tg = &tonegen[tgnum];
if (!tg->playing) {
foundgen = true;
break;
}
}
if (foundgen) {
int shifted_note;
if (tgnum+1 > num_tonegens_used) num_tonegens_used = tgnum+1;
tg->playing = true;
tg->track = tracknum;
tg->note = trk->note;
trk->tonegens[tgnum] = true;
trk->preferred_tonegen = tgnum;
if (loggen) fprintf (logfile, "->Start note %02X, generator %d, track %d\n", trk->note, tgnum, tracknum);
shifted_note = trk->note + keyshift;
if (shifted_note < 0) shifted_note = 0;
if (shifted_note > 127) shifted_note = 127;
if (binaryoutput) {
putc (CMD_PLAYNOTE | tgnum, outfile);
putc (shifted_note, outfile);
outfile_bytecount += 2;
if (velocityoutput) {
putc (shifted_note, outfile);
outfile_bytecount++;
}
}
else {
if (velocityoutput == 0) {
fprintf (outfile, "0x%02X,%d, ", CMD_PLAYNOTE | tgnum, shifted_note);
outfile_items(2);
} else {
fprintf (outfile, "0x%02X,%d,%d, ", CMD_PLAYNOTE | tgnum, shifted_note, trk->velocity);
outfile_items(3);
}
}
}
else {
if (loggen) fprintf (logfile, "----> No free generator, skipping note %02X, track %d\n", trk->note, tracknum);
++notes_skipped;
}
find_note (tracknum); // use up the note
}
} /* !parseonly do */
while (tracks_done < num_tracks);
if (!parseonly) {
// generate the end-of-score command and some commentary
if(binaryoutput) putc(CMD_STOP, outfile);
else {
fprintf(outfile, "0x%02x};\n// This score contains %ld bytes, and %d tone generator%s used.\n", CMD_STOP, outfile_bytecount, num_tonegens_used, num_tonegens_used == 1 ? " is" : "s are");
if (notes_skipped) fprintf(outfile, "// %d notes had to be skipped.\n", notes_skipped);
}
printf (" %s %d tone generators were used.\n", num_tonegens_used < num_tonegens ? "Only":"All", num_tonegens_used);
if (notes_skipped) printf(" %d notes were skipped because there weren't enough tone generators.\n", notes_skipped);
printf (" %ld bytes of score data were generated.\n", outfile_bytecount);
}
printf (" Done.\n");
return 0;
}

+ 864
- 0
examples/Synthesis/PlaySynthMusic/william_tell_overture.c 查看文件

@@ -0,0 +1,864 @@
// Playtune bytestream for file "william_tell_overture.mid" created by MIDITONES V1.6 on Sat Sep 6 16:56:56 2014
// command line: ./miditones -t16 -v william_tell_overture
#ifdef __AVR__
#include <avr/pgmspace.h>
#else
#define PROGMEM
#endif
const unsigned char PROGMEM score [] = {
0x90,72,127, 0x91,72,107, 0x92,72,127, 0x93,72,127, 0x94,72,127, 1,169, 0x80, 0x81, 0x82, 0x83,
0x84, 0,183, 0x90,72,127, 0x91,72,107, 0x92,72,127, 0x93,72,127, 0x94,72,127, 0,41, 0x80,
0x81, 0x82, 0x83, 0x84, 0,58, 0x90,72,127, 0x91,72,101, 0x92,72,121, 0x93,72,121, 0x94,72,121,
0,41, 0x80, 0x81, 0x82, 0x83, 0x84, 0,58, 0x90,72,127, 0x91,72,107, 0x92,72,127, 0x93,72,127,
0x94,72,127, 1,239, 0x80, 0x81, 0x82, 0x83, 0x84, 0,112, 0x90,72,127, 0x91,72,107, 0x92,72,127,
0x93,72,127, 0x94,72,127, 0,54, 0x80, 0x81, 0x82, 0x83, 0x84, 0,50, 0x90,72,127, 0x91,72,107,
0x92,72,127, 0x93,72,127, 0x94,72,127, 0,50, 0x80, 0x81, 0x82, 0x83, 0x84, 0,50, 0x90,72,127,
0x91,72,107, 0x92,72,127, 0x93,72,127, 0x94,72,127, 0,104, 0x80, 0x81, 0x82, 0x83, 0x84, 0,100,
0x90,69,127, 0x91,69,98, 0x92,69,118, 0x93,69,118, 0x94,69,118, 0,83, 0x80, 0x81, 0x82, 0x83,
0x84, 0,116, 0x90,65,127, 0x91,65,98, 0x92,65,118, 0x93,65,118, 0x94,65,118, 0,108, 0x80,
0x81, 0x82, 0x83, 0x84, 0,95, 0x90,69,127, 0x91,69,103, 0x92,69,123, 0x93,69,123, 0x94,69,123,
0,112, 0x80, 0x81, 0x82, 0x83, 0x84, 0,91, 0x90,72,127, 0x91,72,104, 0x92,72,124, 0x93,72,124,
0x94,72,124, 0,100, 0x80, 0x81, 0x82, 0x83, 0x84, 0,100, 0x90,69,127, 0x91,69,104, 0x92,69,124,
0x93,69,124, 0x94,69,124, 0,112, 0x80, 0x81, 0x82, 0x83, 0x84, 0,91, 0x90,72,127, 0x91,72,104,
0x92,72,124, 0x93,72,124, 0x94,72,124, 0,100, 0x80, 0x81, 0x82, 0x83, 0x84, 0,104, 0x90,77,127,
0x91,77,103, 0x92,77,123, 0x93,77,123, 0x94,77,123, 0,91, 0x80, 0x81, 0x82, 0x83, 0x84, 0,108,
0x90,72,127, 0x91,72,96, 0x92,72,116, 0x93,72,116, 0x94,72,116, 0,100, 0x80, 0x81, 0x82, 0x83,
0x84, 0,104, 0x90,69,127, 0x91,69,104, 0x92,69,124, 0x93,69,124, 0x94,69,124, 0,83, 0x80,
0x81, 0x82, 0x83, 0x84, 0,120, 0x90,65,127, 0x91,65,103, 0x92,65,123, 0x93,65,123, 0x94,65,123,
0,100, 0x80, 0x81, 0x82, 0x83, 0x84, 0,100, 0x90,69,127, 0x91,69,104, 0x92,69,124, 0x93,69,124,
0x94,69,124, 0,91, 0x80, 0x81, 0x82, 0x83, 0x84, 0,112, 0x90,72,127, 0x91,72,96, 0x92,72,116,
0x93,72,116, 0x94,72,116, 0,87, 0x80, 0x81, 0x82, 0x83, 0x84, 0,116, 0x90,69,127, 0x91,69,103,
0x92,69,123, 0x93,69,123, 0x94,69,123, 0,91, 0x80, 0x81, 0x82, 0x83, 0x84, 0,108, 0x90,72,127,
0x91,72,104, 0x92,72,124, 0x93,72,124, 0x94,72,124, 0,91, 0x80, 0x81, 0x82, 0x83, 0x84, 0,112,
0x90,77,127, 0x91,77,107, 0x92,77,127, 0x93,77,127, 0x94,77,127, 0,83, 0x80, 0x81, 0x82, 0x83,
0x84, 0,120, 0x90,72,127, 0x91,72,107, 0x92,72,127, 0x93,72,127, 0x94,72,127, 1,119, 0x80,
0x81, 0x82, 0x83, 0x84, 0,233, 0x90,72,127, 0x91,72,96, 0x92,72,116, 0x93,72,116, 0x94,72,116,
0,41, 0x80, 0x81, 0x82, 0x83, 0x84, 0,58, 0x90,72,127, 0x91,72,103, 0x92,72,123, 0x93,72,123,
0x94,72,123, 0,50, 0x80, 0x81, 0x82, 0x83, 0x84, 0,50, 0x90,72,127, 0x91,72,107, 0x92,72,127,
0x93,72,127, 0x94,72,127, 2,8, 0x80, 0x81, 0x82, 0x83, 0x84, 0,87, 0x90,72,127, 0x91,72,103,
0x92,72,123, 0x93,72,123, 0x94,72,123, 0,54, 0x80, 0x81, 0x82, 0x83, 0x84, 0,45, 0x90,72,127,
0x91,72,107, 0x92,72,127, 0x93,72,127, 0x94,72,127, 0,62, 0x80, 0x81, 0x82, 0x83, 0x84, 0,41,
0x90,72,123, 0x91,72,103, 0x92,72,123, 0x93,72,123, 0x94,72,123, 0,95, 0x80, 0x81, 0x82, 0x83,
0x84, 0,108, 0x90,72,116, 0x91,67,112, 0x92,64,68, 0x93,60,93, 0x94,72,96, 0x95,67,92,
0x96,72,116, 0x97,67,112, 0x98,64,98, 0x99,60,123, 0x9A,72,116, 0x9B,67,112, 0x9C,72,116,
0x9D,67,112, 0,41, 0x82, 0x88, 0,4, 0x83, 0x89, 0,4, 0x80, 0x84, 0x86, 0x8A, 0x8C, 0x81, 0x85, 0x87,
0x8B, 0x8D, 0,50, 0x90,67,90, 0x91,72,116, 0x92,64,83, 0x93,60,88, 0x94,67,70, 0x95,72,96,
0x96,67,90, 0x97,72,116, 0x98,64,113, 0x99,60,118, 0x9A,67,90, 0x9B,72,116, 0x9C,67,90,
0x9D,72,116, 0,41, 0x80, 0x84, 0x86, 0x8A, 0x8C, 0,4, 0x82, 0x88, 0x83, 0x89, 0,12, 0x81, 0x85, 0x87,
0x8B, 0x8D, 0,41, 0x90,67,106, 0x91,72,121, 0x92,64,90, 0x93,60,91, 0x94,67,86, 0x95,72,101,
0x96,67,106, 0x97,72,121, 0x98,64,120, 0x99,60,121, 0x9A,67,106, 0x9B,72,121, 0x9C,67,106,
0x9D,72,121, 0,58, 0x82, 0x88, 0x83, 0x89, 0,4, 0x80, 0x84, 0x86, 0x8A, 0x8C, 0,12, 0x81, 0x85, 0x87,
0x8B, 0x8D, 0,129, 0x90,67,116, 0x91,72,117, 0x92,60,93, 0x93,64,90, 0x94,67,96, 0x95,72,97,
0x96,67,116, 0x97,72,117, 0x98,60,123, 0x99,64,120, 0x9A,67,116, 0x9B,72,117, 0x9C,67,116,
0x9D,72,117, 0,54, 0x80, 0x84, 0x86, 0x8A, 0x8C, 0x82, 0x88, 0x83, 0x89, 0,12, 0x81, 0x85, 0x87, 0x8B, 0x8D,
0,133, 0x90,67,117, 0x91,48,117, 0x92,72,120, 0x93,64,87, 0x94,67,97, 0x95,72,100, 0x96,67,117,
0x97,72,120, 0x98,60,124, 0x99,64,117, 0x9A,67,117, 0x9B,48,117, 0x9C,72,120, 0x9D,67,117,
0x9E,48,117, 0x9F,72,120, 0,62, 0x88, 0x83, 0x89, 0,29, 0x80, 0x84, 0x86, 0x8A, 0x8D, 0x81, 0x8B, 0x8E,
0,4, 0x82, 0x85, 0x87, 0x8C, 0x8F, 0,108, 0x90,67,112, 0x91,72,123, 0x92,48,117, 0x93,64,82,
0x94,67,92, 0x95,72,103, 0x96,67,112, 0x97,72,123, 0x98,60,120, 0x99,64,112, 0x9A,67,112,
0x9B,72,123, 0x9C,48,117, 0x9D,67,112, 0x9E,72,123, 0x9F,48,117, 0,41, 0x80, 0x84, 0x86, 0x8A,
0x8D, 0,4, 0x83, 0x89, 0x88, 0,4, 0x81, 0x85, 0x87, 0x8B, 0x8E, 0,41, 0x82, 0x8C, 0x8F, 0,8, 0x90,67,102,
0x91,72,113, 0x92,48,117, 0x93,64,83, 0x94,67,82, 0x95,72,93, 0x96,67,102, 0x97,72,113,
0x98,60,121, 0x99,64,113, 0x9A,67,102, 0x9B,72,113, 0x9C,48,117, 0x9D,67,102, 0x9E,72,113,
0x9F,48,117, 0,41, 0x88, 0x80, 0x84, 0x86, 0x8A, 0x8D, 0,4, 0x81, 0x85, 0x87, 0x8B, 0x8E, 0x83, 0x89, 0,45,
0x82, 0x8C, 0x8F, 0,12, 0x90,67,110, 0x91,72,117, 0x92,48,117, 0x93,64,92, 0x94,67,90, 0x95,72,97,
0x96,67,110, 0x97,72,117, 0x98,64,122, 0x99,60,124, 0x9A,67,110, 0x9B,72,117, 0x9C,48,117,
0x9D,67,110, 0x9E,72,117, 0x9F,48,117, 0,45, 0x83, 0x88, 0x89, 0,12, 0x80, 0x84, 0x86, 0x8A, 0x8D,
0,8, 0x81, 0x85, 0x87, 0x8B, 0x8E, 0,20, 0x82, 0x8C, 0x8F, 0,112, 0x90,67,115, 0x91,72,121, 0x92,48,117,
0x93,64,93, 0x94,67,95, 0x95,72,101, 0x96,67,115, 0x97,72,121, 0x98,60,122, 0x99,64,123,
0x9A,67,115, 0x9B,72,121, 0x9C,48,117, 0x9D,67,115, 0x9E,72,121, 0x9F,48,117, 0,50, 0x80,
0x84, 0x86, 0x8A, 0x8D, 0,4, 0x88, 0x83, 0x89, 0x81, 0x85, 0x87, 0x8B, 0x8E, 0,37, 0x82, 0x8C, 0x8F, 0,112,
0x90,72,123, 0x91,67,122, 0x92,48,122, 0x93,64,97, 0x94,72,123, 0x95,67,122, 0x96,72,123,
0x97,67,122, 0x98,64,127, 0x99,60,127, 0x9A,72,123, 0x9B,67,122, 0x9C,48,122, 0x9D,72,123,
0x9E,67,122, 0x9F,48,122, 2,167, 0x80, 0x84, 0x86, 0x8A, 0x8D, 0,8, 0x81, 0x85, 0x87, 0x8B, 0x8E, 0x82,
0x8C, 0x8F, 0,120, 0x90,72,124, 0x91,67,112, 0x92,48,122, 0x94,72,124, 0x95,67,112, 0x96,72,124,
0x97,67,112, 0x9A,48,122, 0x9B,72,124, 0x9C,67,112, 0x9D,48,122, 0x9E,72,124, 0x9F,67,112,
0,104, 0x82, 0x8A, 0x8D, 0,100, 0x83, 0x88, 0,12, 0x80, 0x84, 0x86, 0x8B, 0x8E, 0,4, 0x89, 0x81, 0x85,
0x87, 0x8C, 0x8F, 0,87, 1,44, 0x90,60,86, 0x91,60,86, 0x92,60,86, 0x93,60,86, 0x94,60,86,
0,54, 0x80, 0x81, 0x82, 0x83, 0x84, 0,50, 0x90,60,120, 0x91,60,120, 0x92,60,120, 0x93,60,120,
0x94,60,120, 0,62, 0x80, 0x81, 0x82, 0x83, 0x84, 0,37, 0x90,41,93, 0x91,57,86, 0x92,53,82,
0x93,60,116, 0x94,60,116, 0x95,41,123, 0x96,57,116, 0x97,53,112, 0x98,60,116, 0x99,60,116,
0,70, 0x80, 0x85, 0x81, 0x86, 0,12, 0x83, 0x84, 0x88, 0x89, 0,4, 0x82, 0x87, 0,116, 0x90,60,110,
0x91,60,110, 0x92,60,110, 0x93,60,110, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,60,108, 0x91,60,108,
0x92,60,108, 0x93,60,108, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,57,85, 0x91,53,75, 0x92,41,86,
0x93,60,110, 0x94,60,110, 0x95,57,115, 0x96,53,105, 0x97,41,116, 0x98,60,110, 0x99,60,110,
0,75, 0x80, 0x85, 0x83, 0x84, 0x88, 0x89, 0,4, 0x81, 0x86, 0x82, 0x87, 0,125, 0x90,60,98, 0x91,60,98,
0x92,60,98, 0x93,60,98, 0,41, 0x80, 0x81, 0x82, 0x83, 0,62, 0x90,60,101, 0x91,60,101, 0x92,60,101,
0x93,60,101, 0,66, 0x80, 0x81, 0x82, 0x83, 0,33, 0x90,57,83, 0x91,41,86, 0x92,53,72, 0x93,65,124,
0x94,65,124, 0x95,57,113, 0x96,41,116, 0x97,53,102, 0x98,65,124, 0x99,65,124, 0,58, 0x80,
0x85, 0,8, 0x81, 0x86, 0x82, 0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,125, 0x90,53,72, 0x91,57,83,
0x92,41,86, 0x93,67,127, 0x94,67,127, 0x95,53,102, 0x96,57,113, 0x97,41,116, 0x98,67,127,
0x99,67,127, 0,58, 0x80, 0x85, 0,4, 0x81, 0x86, 0,4, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88, 0x89,
0,120, 0x90,57,83, 0x91,53,76, 0x92,41,91, 0x93,69,127, 0x94,69,127, 0x95,57,113, 0x96,53,106,
0x97,41,121, 0x98,69,127, 0x99,69,127, 0,54, 0x80, 0x85, 0,4, 0x81, 0x86, 0,12, 0x82, 0x87,
0x83, 0x84, 0x88, 0x89, 0,133, 0x90,60,113, 0x91,60,113, 0x92,60,113, 0x93,60,113, 0,45, 0x80,
0x81, 0x82, 0x83, 0,54, 0x90,60,116, 0x91,60,116, 0x92,60,116, 0x93,60,116, 0,54, 0x80, 0x81,
0x82, 0x83, 0,45, 0x90,53,78, 0x91,57,88, 0x92,41,94, 0x93,60,118, 0x94,60,118, 0x95,53,108,
0x96,57,118, 0x97,41,124, 0x98,60,118, 0x99,60,118, 0,54, 0x80, 0x85, 0,4, 0x81, 0x86, 0,8,
0x82, 0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,129, 0x90,60,121, 0x91,60,121, 0x92,60,121, 0x93,60,121,
0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,60,110, 0x91,60,110, 0x92,60,110, 0x93,60,110, 0,62,
0x80, 0x81, 0x82, 0x83, 0,41, 0x90,53,82, 0x91,57,92, 0x92,41,90, 0x93,65,124, 0x94,65,124,
0x95,53,112, 0x96,57,122, 0x97,41,120, 0x98,65,124, 0x99,65,124, 0,58, 0x80, 0x85, 0,4,
0x81, 0x86, 0,4, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,116, 0x90,69,122, 0x91,69,122, 0x92,69,122,
0x93,69,122, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,69,124, 0x91,69,124, 0x92,69,124, 0x93,69,124,
0,66, 0x80, 0x81, 0x82, 0x83, 0,37, 0x90,48,82, 0x91,36,94, 0x92,52,90, 0x93,55,83, 0x94,67,127,
0x95,67,127, 0x96,48,112, 0x97,36,124, 0x98,52,120, 0x99,55,113, 0x9A,67,127, 0x9B,67,127,
0,45, 0x80, 0x86, 0,16, 0x81, 0x87, 0x82, 0x88, 0,4, 0x83, 0x89, 0x84, 0x85, 0x8A, 0x8B, 0,137, 0x90,48,78,
0x91,52,81, 0x92,55,90, 0x93,36,93, 0x94,64,124, 0x95,64,124, 0x96,48,108, 0x97,52,111,
0x98,55,120, 0x99,36,123, 0x9A,64,124, 0x9B,64,124, 0,37, 0x80, 0x86, 0,20, 0x81, 0x87, 0x82,
0x88, 0,4, 0x83, 0x89, 0,8, 0x84, 0x85, 0x8A, 0x8B, 0,129, 0x90,48,90, 0x91,52,82, 0x92,55,91,
0x93,36,90, 0x94,60,116, 0x95,60,116, 0x96,48,120, 0x97,52,112, 0x98,55,121, 0x99,36,120,
0x9A,60,116, 0x9B,60,116, 0,50, 0x80, 0x86, 0,4, 0x81, 0x87, 0,20, 0x82, 0x88, 0x83, 0x89, 0,4,
0x84, 0x85, 0x8A, 0x8B, 0,125, 0x90,60,103, 0x91,60,103, 0x92,60,103, 0x93,60,103, 0,45, 0x80,
0x81, 0x82, 0x83, 0,54, 0x90,60,110, 0x91,60,110, 0x92,60,110, 0x93,60,110, 0,58, 0x80, 0x81,
0x82, 0x83, 0,45, 0x90,53,85, 0x91,57,90, 0x92,41,92, 0x93,60,124, 0x94,60,124, 0x95,53,115,
0x96,57,120, 0x97,41,122, 0x98,60,124, 0x99,60,124, 0,54, 0x80, 0x85, 0,12, 0x81, 0x86, 0,8,
0x82, 0x87, 0x83, 0x84, 0x88, 0x89, 0,125, 0x90,60,118, 0x91,60,118, 0x92,60,118, 0x93,60,118, 0,50,
0x80, 0x81, 0x82, 0x83, 0,50, 0x90,60,118, 0x91,60,118, 0x92,60,118, 0x93,60,118, 0,58, 0x80,
0x81, 0x82, 0x83, 0,45, 0x90,53,92, 0x91,57,94, 0x92,41,88, 0x93,60,111, 0x94,60,111, 0x95,53,122,
0x96,57,124, 0x97,41,118, 0x98,60,111, 0x99,60,111, 0,54, 0x80, 0x85, 0,4, 0x83, 0x84, 0x88,
0x89, 0,4, 0x81, 0x86, 0,8, 0x82, 0x87, 0,133, 0x90,60,112, 0x91,60,112, 0x92,60,112, 0x93,60,112,
0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,60,88, 0x91,60,88, 0x92,60,88, 0x93,60,88, 0,41,
0x80, 0x81, 0x82, 0x83, 0,58, 0x90,53,90, 0x91,57,90, 0x92,41,91, 0x93,65,127, 0x94,65,127,
0x95,53,120, 0x96,57,120, 0x97,41,121, 0x98,65,127, 0x99,65,127, 0,54, 0x80, 0x85, 0,8,
0x81, 0x86, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,125, 0x90,53,83, 0x91,41,94, 0x92,57,86,
0x93,67,124, 0x94,67,124, 0x95,53,113, 0x96,41,124, 0x97,57,116, 0x98,67,124, 0x99,67,124,
0,45, 0x80, 0x85, 0,8, 0x81, 0x86, 0,8, 0x82, 0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,133, 0x90,53,93,
0x91,41,91, 0x92,57,92, 0x93,69,122, 0x94,69,122, 0x95,53,123, 0x96,41,121, 0x97,57,122,
0x98,69,122, 0x99,69,122, 0,54, 0x80, 0x85, 0x81, 0x86, 0,8, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88,
0x89, 0,120, 0x90,65,124, 0x91,65,124, 0x92,65,124, 0x93,65,124, 0,62, 0x80, 0x81, 0x82, 0x83,
0,37, 0x90,69,124, 0x91,69,124, 0x92,69,124, 0x93,69,124, 0,62, 0x80, 0x81, 0x82, 0x83, 0,41,
0x90,36,97, 0x91,72,127, 0x92,72,127, 0x93,36,127, 0x94,72,127, 0x95,72,127, 0,104, 0x80,
0x83, 0,95, 0x90,52,80, 0x93,60,91, 0x96,58,83, 0x97,52,110, 0x98,60,121, 0x99,58,113,
0,37, 0x80, 0x87, 0,8, 0x83, 0x88, 0,8, 0x86, 0x89, 0,50, 0x90,52,82, 0x93,60,90, 0x96,58,77,
0x97,52,112, 0x98,60,120, 0x99,58,107, 0,33, 0x80, 0x87, 0,8, 0x83, 0x88, 0,8, 0x86, 0x89,
0,50, 0x90,52,91, 0x93,58,73, 0x96,60,83, 0x97,36,97, 0x98,52,121, 0x99,58,103, 0x9A,60,113,
0x9B,36,127, 0,62, 0x80, 0x88, 0,12, 0x83, 0x89, 0,4, 0x86, 0x8A, 0,20, 0x90,70,127, 0x93,70,127,
0x96,70,127, 0x98,70,127, 0,16, 0x87, 0x8B, 0,37, 0x81, 0x82, 0x84, 0x85, 0,20, 0x80, 0x83, 0x86,
0x88, 0,29, 0x90,69,105, 0x91,69,105, 0x92,69,105, 0x93,69,105, 0,91, 0x80, 0x81, 0x82, 0x83,
0,8, 0x90,67,123, 0x91,67,123, 0x92,67,123, 0x93,67,123, 0,95, 0x80, 0x81, 0x82, 0x83, 0,4,
0x90,53,86, 0x91,41,78, 0x92,57,92, 0x93,65,123, 0x94,65,123, 0x95,53,116, 0x96,41,108,
0x97,57,122, 0x98,65,123, 0x99,65,123, 0,66, 0x80, 0x85, 0,4, 0x81, 0x86, 0,8, 0x82, 0x87,
0,66, 0x83, 0x84, 0x88, 0x89, 0,58, 0x90,60,92, 0x91,41,92, 0x92,69,127, 0x93,69,127, 0x94,60,122,
0x95,41,122, 0x96,69,127, 0x97,69,127, 0,54, 0x80, 0x84, 0x82, 0x83, 0x86, 0x87, 0,16, 0x81, 0x85,
0,129, 0x90,41,97, 0x91,53,91, 0x92,57,94, 0x93,65,124, 0x94,65,124, 0x95,41,127, 0x96,53,121,
0x97,57,124, 0x98,65,124, 0x99,65,124, 0,91, 0x83, 0x84, 0x88, 0x89, 0x80, 0x85, 0x81, 0x86, 0,8,
0x82, 0x87, 0,104, 0x90,72,105, 0x91,72,105, 0x92,72,105, 0x93,72,105, 0,54, 0x80, 0x81, 0x82,
0x83, 0,50, 0x90,72,113, 0x91,72,113, 0x92,72,113, 0x93,72,113, 0,50, 0x80, 0x81, 0x82, 0x83,
0,50, 0x90,41,93, 0x91,57,86, 0x92,53,82, 0x93,72,118, 0x94,72,118, 0x95,41,123, 0x96,57,116,
0x97,53,112, 0x98,72,118, 0x99,72,118, 0,58, 0x80, 0x85, 0x81, 0x86, 0,8, 0x82, 0x87, 0,4,
0x83, 0x84, 0x88, 0x89, 0,129, 0x90,72,112, 0x91,72,112, 0x92,72,112, 0x93,72,112, 0,50, 0x80,
0x81, 0x82, 0x83, 0,54, 0x90,72,113, 0x91,72,113, 0x92,72,113, 0x93,72,113, 0,45, 0x80, 0x81,
0x82, 0x83, 0,54, 0x90,57,85, 0x91,53,75, 0x92,41,86, 0x93,72,113, 0x94,72,113, 0x95,57,115,
0x96,53,105, 0x97,41,116, 0x98,72,113, 0x99,72,113, 0,75, 0x80, 0x85, 0x83, 0x84, 0x88, 0x89, 0,4,
0x81, 0x86, 0x82, 0x87, 0,125, 0x90,72,122, 0x91,72,122, 0x92,72,122, 0x93,72,122, 0,45, 0x80,
0x81, 0x82, 0x83, 0,54, 0x90,72,116, 0x91,72,116, 0x92,72,116, 0x93,72,116, 0,58, 0x80, 0x81,
0x82, 0x83, 0,41, 0x90,57,83, 0x91,41,86, 0x92,53,72, 0x93,77,124, 0x94,77,124, 0x95,57,113,
0x96,41,116, 0x97,53,102, 0x98,77,124, 0x99,77,124, 0,62, 0x80, 0x85, 0,4, 0x81, 0x86, 0x82,
0x87, 0,25, 0x83, 0x84, 0x88, 0x89, 0,112, 0x90,53,72, 0x91,57,83, 0x92,41,86, 0x93,79,127,
0x94,79,127, 0x95,53,102, 0x96,57,113, 0x97,41,116, 0x98,79,127, 0x99,79,127, 0,54, 0x80,
0x85, 0,8, 0x81, 0x86, 0,4, 0x82, 0x87, 0,12, 0x83, 0x84, 0x88, 0x89, 0,125, 0x90,57,83, 0x91,53,76,
0x92,41,91, 0x93,81,127, 0x94,81,127, 0x95,57,113, 0x96,53,106, 0x97,41,121, 0x98,81,127,
0x99,81,127, 0,50, 0x80, 0x85, 0,8, 0x81, 0x86, 0,8, 0x82, 0x87, 0,41, 0x83, 0x84, 0x88, 0x89,
0,91, 0x90,72,122, 0x91,72,122, 0x92,72,122, 0x93,72,122, 0,58, 0x80, 0x81, 0x82, 0x83, 0,45,
0x90,72,105, 0x91,72,105, 0x92,72,105, 0x93,72,105, 0,37, 0x80, 0x81, 0x82, 0x83, 0,62, 0x90,53,78,
0x91,57,88, 0x92,41,94, 0x93,72,112, 0x94,72,112, 0x95,53,108, 0x96,57,118, 0x97,41,124,
0x98,72,112, 0x99,72,112, 0,54, 0x80, 0x85, 0,4, 0x81, 0x86, 0,8, 0x82, 0x87, 0,4, 0x83,
0x84, 0x88, 0x89, 0,133, 0x90,72,112, 0x91,72,112, 0x92,72,112, 0x93,72,112, 0,41, 0x80, 0x81,
0x82, 0x83, 0,58, 0x90,72,113, 0x91,72,113, 0x92,72,113, 0x93,72,113, 0,62, 0x80, 0x81, 0x82,
0x83, 0,37, 0x90,53,82, 0x91,57,92, 0x92,41,90, 0x93,77,123, 0x94,77,123, 0x95,53,112,
0x96,57,122, 0x97,41,120, 0x98,77,123, 0x99,77,123, 0,62, 0x80, 0x85, 0,4, 0x81, 0x86, 0x82,
0x87, 0,12, 0x83, 0x84, 0x88, 0x89, 0,125, 0x90,81,118, 0x91,81,118, 0x92,81,118, 0x93,81,118,
0,45, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,81,121, 0x91,81,121, 0x92,81,121, 0x93,81,121, 0,70,
0x80, 0x81, 0x82, 0x83, 0,33, 0x90,48,82, 0x91,36,94, 0x92,52,90, 0x93,55,83, 0x94,79,118,
0x95,79,118, 0x96,48,112, 0x97,36,124, 0x98,52,120, 0x99,55,113, 0x9A,79,118, 0x9B,79,118,
0,45, 0x80, 0x86, 0,16, 0x81, 0x87, 0x82, 0x88, 0x83, 0x89, 0,20, 0x84, 0x85, 0x8A, 0x8B, 0,116, 0x90,48,78,
0x91,52,81, 0x92,55,90, 0x93,36,93, 0x94,76,118, 0x95,76,118, 0x96,48,108, 0x97,52,111,
0x98,55,120, 0x99,36,123, 0x9A,76,118, 0x9B,76,118, 0,41, 0x80, 0x86, 0,20, 0x81, 0x87, 0x82,
0x88, 0,4, 0x83, 0x89, 0,4, 0x84, 0x85, 0x8A, 0x8B, 0,133, 0x90,48,90, 0x91,52,82, 0x92,55,91,
0x93,36,90, 0x94,72,122, 0x95,72,122, 0x96,48,120, 0x97,52,112, 0x98,55,121, 0x99,36,120,
0x9A,72,122, 0x9B,72,122, 0,50, 0x80, 0x86, 0,4, 0x81, 0x87, 0,20, 0x82, 0x88, 0x83, 0x89, 0,12,
0x84, 0x85, 0x8A, 0x8B, 0,116, 0x90,72,113, 0x91,72,113, 0x92,72,113, 0x93,72,113, 0,45, 0x80,
0x81, 0x82, 0x83, 0,54, 0x90,72,110, 0x91,72,110, 0x92,72,110, 0x93,72,110, 0,62, 0x80, 0x81,
0x82, 0x83, 0,37, 0x90,53,85, 0x91,57,90, 0x92,41,92, 0x93,72,121, 0x94,72,121, 0x95,53,115,
0x96,57,120, 0x97,41,122, 0x98,72,121, 0x99,72,121, 0,58, 0x80, 0x85, 0,12, 0x81, 0x86, 0,8,
0x82, 0x87, 0,12, 0x83, 0x84, 0x88, 0x89, 0,112, 0x90,72,121, 0x91,72,121, 0x92,72,121, 0x93,72,121,
0,62, 0x80, 0x81, 0x82, 0x83, 0,37, 0x90,72,116, 0x91,72,116, 0x92,72,116, 0x93,72,116, 0,62,
0x80, 0x81, 0x82, 0x83, 0,41, 0x90,53,92, 0x91,57,94, 0x92,41,88, 0x93,72,121, 0x94,72,121,
0x95,53,122, 0x96,57,124, 0x97,41,118, 0x98,72,121, 0x99,72,121, 0,50, 0x80, 0x85, 0,8,
0x81, 0x86, 0,8, 0x82, 0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,125, 0x90,72,116, 0x91,72,116, 0x92,72,116,
0x93,72,116, 0,41, 0x80, 0x81, 0x82, 0x83, 0,58, 0x90,72,112, 0x91,72,112, 0x92,72,112, 0x93,72,112,
0,70, 0x80, 0x81, 0x82, 0x83, 0,33, 0x90,53,90, 0x91,57,90, 0x92,41,91, 0x93,77,123, 0x94,77,123,
0x95,53,120, 0x96,57,120, 0x97,41,121, 0x98,77,123, 0x99,77,123, 0,54, 0x80, 0x85, 0,8,
0x81, 0x86, 0x82, 0x87, 0,25, 0x83, 0x84, 0x88, 0x89, 0,116, 0x90,53,83, 0x91,41,94, 0x92,57,86,
0x93,79,115, 0x94,79,115, 0x95,53,113, 0x96,41,124, 0x97,57,116, 0x98,79,115, 0x99,79,115,
0,45, 0x80, 0x85, 0,4, 0x81, 0x86, 0,12, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,120, 0x90,53,93,
0x91,41,91, 0x92,57,92, 0x93,81,122, 0x94,81,122, 0x95,53,123, 0x96,41,121, 0x97,57,122,
0x98,81,122, 0x99,81,122, 0,58, 0x80, 0x85, 0x81, 0x86, 0,4, 0x82, 0x87, 0,4, 0x83, 0x84, 0x88,
0x89, 0,137, 0x90,77,105, 0x91,77,105, 0x92,77,105, 0x93,77,105, 0,87, 0x80, 0x81, 0x82, 0x83,
0,12, 0x90,81,121, 0x91,81,121, 0x92,81,121, 0x93,81,121, 0,75, 0x80, 0x81, 0x82, 0x83, 0,29,
0x90,36,97, 0x91,84,105, 0x92,84,105, 0x93,36,127, 0x94,84,105, 0x95,84,105, 0,104, 0x80,
0x83, 0,95, 0x90,52,80, 0x93,60,91, 0x96,58,83, 0x97,52,110, 0x98,60,121, 0x99,58,113,
0,37, 0x80, 0x87, 0,8, 0x83, 0x88, 0,8, 0x86, 0x89, 0,45, 0x90,52,82, 0x93,60,90, 0x96,58,77,
0x97,52,112, 0x98,60,120, 0x99,58,107, 0,33, 0x80, 0x87, 0,8, 0x83, 0x88, 0,8, 0x86, 0x89,
0,54, 0x90,52,91, 0x93,58,73, 0x96,60,83, 0x97,36,97, 0x98,52,121, 0x99,58,103, 0x9A,60,113,
0x9B,36,127, 0,62, 0x80, 0x88, 0,12, 0x83, 0x89, 0,4, 0x86, 0x8A, 0,20, 0x90,82,105, 0x93,82,105,
0x96,82,105, 0x98,82,105, 0,16, 0x87, 0x8B, 0,37, 0x81, 0x82, 0x84, 0x85, 0,29, 0x80, 0x83, 0x86,
0x88, 0,20, 0x90,81,107, 0x91,81,107, 0x92,81,107, 0x93,81,107, 0,100, 0x94,79,118, 0x95,79,118,
0x96,79,118, 0x97,79,118, 0,16, 0x80, 0x81, 0x82, 0x83, 0,75, 0x84, 0x85, 0x86, 0x87, 0,8, 0x90,53,86,
0x91,41,78, 0x92,57,92, 0x93,77,116, 0x94,77,116, 0x95,53,116, 0x96,41,108, 0x97,57,122,
0x98,77,116, 0x99,77,116, 0,66, 0x80, 0x85, 0x81, 0x86, 0,12, 0x82, 0x87, 0,70, 0x83, 0x84, 0x88,
0x89, 0,54, 0x90,60,92, 0x91,41,92, 0x92,81,124, 0x93,81,124, 0x94,60,122, 0x95,41,122,
0x96,81,124, 0x97,81,124, 0,50, 0x80, 0x84, 0,20, 0x81, 0x85, 0,129, 0x90,41,97, 0x91,53,91,
0x94,57,94, 0x95,77,113, 0x98,77,113, 0x99,41,127, 0x9A,53,121, 0x9B,57,124, 0x9C,77,113,
0x9D,77,113, 0,8, 0x82, 0x83, 0x86, 0x87, 0,83, 0x85, 0x88, 0x8C, 0x8D, 0x80, 0x89, 0x81, 0x8A, 0,8,
0x84, 0x8B, 0,104, 0x90,81,115, 0x91,77,105, 0x92,81,115, 0x93,77,105, 0x94,81,115, 0x95,77,105,
0x96,81,115, 0x97,77,105, 0,45, 0x80, 0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,54, 0x90,77,102,
0x91,81,113, 0x92,77,102, 0x93,81,113, 0x94,77,102, 0x95,81,113, 0x96,77,102, 0x97,81,113,
0,45, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,54, 0x90,62,94, 0x91,57,94, 0x92,53,94,
0x93,50,94, 0x94,38,94, 0x95,77,111, 0x96,81,122, 0x97,77,111, 0x98,81,122, 0x99,62,124,
0x9A,57,124, 0x9B,53,124, 0x9C,50,124, 0x9D,38,124, 0x9E,77,111, 0x9F,81,122, 0,66, 0x80,
0x89, 0x81, 0x8A, 0x82, 0x8B, 0x83, 0x8C, 0x84, 0x8D, 0,8, 0x85, 0x87, 0x8E, 0,8, 0x86, 0x88, 0x8F, 0,116,
0x90,81,116, 0x91,77,113, 0x92,81,116, 0x93,77,113, 0x94,81,116, 0x95,77,113, 0x96,81,116,
0x97,77,113, 0,54, 0x80, 0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,50, 0x90,77,103, 0x91,81,113,
0x92,77,103, 0x93,81,113, 0x94,77,103, 0x95,81,113, 0x96,77,103, 0x97,81,113, 0,41, 0x80,
0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,58, 0x90,62,94, 0x91,57,94, 0x92,53,94, 0x93,50,94,
0x94,38,94, 0x95,77,113, 0x96,81,117, 0x97,77,113, 0x98,81,117, 0x99,62,124, 0x9A,57,124,
0x9B,53,124, 0x9C,50,124, 0x9D,38,124, 0x9E,77,113, 0x9F,81,117, 0,62, 0x85, 0x87, 0x8E, 0,4,
0x80, 0x89, 0x81, 0x8A, 0x82, 0x8B, 0x83, 0x8C, 0x84, 0x8D, 0,8, 0x86, 0x88, 0x8F, 0,125, 0x90,77,102, 0x91,81,116,
0x92,77,102, 0x93,81,116, 0x94,77,102, 0x95,81,116, 0x96,77,102, 0x97,81,116, 0,41, 0x80,
0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,58, 0x90,77,98, 0x91,81,120, 0x92,77,98, 0x93,81,120,
0x94,77,98, 0x95,81,120, 0x96,77,98, 0x97,81,120, 0,41, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81,
0x83, 0x85, 0x87, 0,54, 0x90,62,94, 0x91,57,94, 0x92,53,94, 0x93,50,94, 0x94,38,94, 0x95,81,126,
0x96,77,101, 0x97,81,126, 0x98,77,101, 0x99,62,124, 0x9A,57,124, 0x9B,53,124, 0x9C,50,124,
0x9D,38,124, 0x9E,81,126, 0x9F,77,101, 0,70, 0x80, 0x89, 0x81, 0x8A, 0x82, 0x8B, 0x83, 0x8C, 0x84, 0x8D,
0,25, 0x85, 0x87, 0x8E, 0,8, 0x86, 0x88, 0x8F, 0,100, 0x90,86,121, 0x91,86,121, 0x92,86,121,
0x93,86,121, 0,83, 0x80, 0x81, 0x82, 0x83, 0,116, 0x90,53,94, 0x91,62,94, 0x92,57,94, 0x93,50,94,
0x94,38,94, 0x95,77,115, 0x96,81,117, 0x97,77,115, 0x98,81,117, 0x99,53,124, 0x9A,62,124,
0x9B,57,124, 0x9C,50,124, 0x9D,38,124, 0x9E,77,115, 0x9F,81,117, 0,70, 0x80, 0x89, 0x81, 0x8A,
0x82, 0x8B, 0x83, 0x8C, 0x84, 0x8D, 0,12, 0x85, 0x87, 0x8E, 0x86, 0x88, 0x8F, 0,120, 0x90,86,121, 0x91,86,121,
0x92,86,121, 0x93,86,121, 0,83, 0x80, 0x81, 0x82, 0x83, 0,120, 0x90,38,94, 0x91,50,75, 0x92,57,86,
0x93,62,85, 0x94,53,88, 0x95,81,124, 0x96,77,116, 0x97,81,124, 0x98,77,116, 0x99,38,124,
0x9A,50,105, 0x9B,57,116, 0x9C,62,115, 0x9D,53,118, 0x9E,81,124, 0x9F,77,116, 0,75, 0x80,
0x89, 0x81, 0x8A, 0,8, 0x85, 0x87, 0x8E, 0,4, 0x82, 0x8B, 0x86, 0x88, 0x8F, 0,4, 0x83, 0x8C, 0,8,
0x84, 0x8D, 0,100, 0x90,86,122, 0x91,86,122, 0x92,86,122, 0x93,86,122, 0,95, 0x80, 0x81, 0x82,
0x83, 0,108, 0x90,38,91, 0x91,62,83, 0x92,50,82, 0x93,57,88, 0x94,53,91, 0x95,77,113,
0x96,81,122, 0x97,77,113, 0x98,81,122, 0x99,38,121, 0x9A,62,113, 0x9B,50,112, 0x9C,57,118,
0x9D,53,121, 0x9E,77,113, 0x9F,81,122, 0,79, 0x80, 0x89, 0,4, 0x81, 0x8A, 0,4, 0x85, 0x87,
0x8E, 0,16, 0x82, 0x8B, 0x83, 0x8C, 0,8, 0x84, 0x8D, 0x86, 0x88, 0x8F, 0,91, 0x90,79,123, 0x91,76,111,
0x92,79,123, 0x93,76,111, 0x94,79,123, 0x95,76,111, 0x96,79,123, 0x97,76,111, 0,75, 0x80,
0x82, 0x84, 0x86, 0,8, 0x81, 0x83, 0x85, 0x87, 0,116, 0x90,38,92, 0x91,50,93, 0x92,74,105, 0x93,77,123,
0x94,74,105, 0x95,77,123, 0x96,38,122, 0x97,50,123, 0x98,74,105, 0x99,77,123, 0x9A,74,105,
0x9B,77,123, 0,79, 0x82, 0x84, 0x88, 0x8A, 0x80, 0x86, 0,8, 0x81, 0x87, 0x83, 0x85, 0x89, 0x8B, 0,116,
0x90,58,94, 0x91,55,83, 0x92,73,98, 0x93,76,106, 0x94,73,98, 0x95,76,106, 0x96,58,124,
0x97,55,113, 0x98,73,98, 0x99,76,106, 0x9A,73,98, 0x9B,76,106, 0,75, 0x82, 0x84, 0x88, 0x8A,
0,4, 0x80, 0x86, 0,20, 0x81, 0x87, 0x83, 0x85, 0x89, 0x8B, 0,104, 0x90,38,93, 0x91,57,97, 0x92,53,91,
0x93,74,107, 0x94,74,107, 0x95,38,123, 0x96,57,127, 0x97,53,121, 0x98,74,107, 0x99,74,107,
0,79, 0x83, 0x84, 0x88, 0x89, 0,4, 0x80, 0x85, 0,8, 0x81, 0x86, 0,16, 0x82, 0x87, 0,91, 0x90,77,115,
0x91,81,111, 0x92,77,115, 0x93,81,111, 0x94,77,115, 0x95,81,111, 0x96,77,115, 0x97,81,111,
0,58, 0x80, 0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,45, 0x90,81,120, 0x91,77,124, 0x92,81,120,
0x93,77,124, 0x94,81,120, 0x95,77,124, 0x96,81,120, 0x97,77,124, 0,37, 0x80, 0x82, 0x84, 0x86,
0,29, 0x81, 0x83, 0x85, 0x87, 0,33, 0x90,50,77, 0x91,38,92, 0x92,57,82, 0x93,62,88, 0x94,53,62,
0x95,81,85, 0x96,77,124, 0x97,81,85, 0x98,77,124, 0x99,50,107, 0x9A,38,122, 0x9B,57,112,
0x9C,62,118, 0x9D,53,92, 0x9E,81,85, 0x9F,77,124, 0,37, 0x85, 0x87, 0x8E, 0,33, 0x86, 0x88,
0x8F, 0,4, 0x80, 0x89, 0,4, 0x81, 0x8A, 0,20, 0x82, 0x8B, 0,4, 0x83, 0x8C, 0,4, 0x84, 0x8D,
0,95, 0x90,77,108, 0x91,81,121, 0x92,77,108, 0x93,81,121, 0x94,77,108, 0x95,81,121, 0x96,77,108,
0x97,81,121, 0,45, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,50, 0x90,81,113, 0x91,77,102,
0x92,81,113, 0x93,77,102, 0x94,81,113, 0x95,77,102, 0x96,81,113, 0x97,77,102, 0,37, 0x80,
0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,58, 0x90,50,76, 0x91,53,91, 0x92,38,91, 0x93,57,88,
0x94,62,87, 0x95,81,122, 0x96,77,113, 0x97,81,122, 0x98,77,113, 0x99,50,106, 0x9A,53,121,
0x9B,38,121, 0x9C,57,118, 0x9D,62,117, 0x9E,81,122, 0x9F,77,113, 0,66, 0x85, 0x87, 0x8E, 0,4,
0x86, 0x88, 0x8F, 0,12, 0x80, 0x89, 0,4, 0x81, 0x8A, 0,4, 0x82, 0x8B, 0,8, 0x83, 0x8C, 0,4,
0x84, 0x8D, 0,100, 0x90,77,100, 0x91,81,110, 0x92,77,100, 0x93,81,110, 0x94,77,100, 0x95,81,110,
0x96,77,100, 0x97,81,110, 0,33, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,62, 0x90,81,112,
0x91,77,98, 0x92,81,112, 0x93,77,98, 0x94,81,112, 0x95,77,98, 0x96,81,112, 0x97,77,98,
0,37, 0x80, 0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,66, 0x90,50,76, 0x91,38,90, 0x92,53,94,
0x93,62,87, 0x94,57,83, 0x95,81,122, 0x96,77,108, 0x97,81,122, 0x98,77,108, 0x99,50,106,
0x9A,38,120, 0x9B,53,124, 0x9C,62,117, 0x9D,57,113, 0x9E,81,122, 0x9F,77,108, 0,70, 0x80,
0x89, 0x85, 0x87, 0x8E, 0,4, 0x81, 0x8A, 0,4, 0x86, 0x88, 0x8F, 0,12, 0x82, 0x8B, 0x83, 0x8C, 0,4,
0x84, 0x8D, 0,104, 0x90,86,121, 0x91,86,121, 0x92,86,121, 0x93,86,121, 0,75, 0x80, 0x81, 0x82,
0x83, 0,129, 0x90,50,81, 0x91,38,93, 0x92,57,87, 0x93,62,82, 0x94,53,91, 0x95,81,117,
0x96,77,115, 0x97,81,117, 0x98,77,115, 0x99,50,111, 0x9A,38,123, 0x9B,57,117, 0x9C,62,112,
0x9D,53,121, 0x9E,81,117, 0x9F,77,115, 0,66, 0x80, 0x89, 0x85, 0x87, 0x8E, 0,4, 0x86, 0x88, 0x8F,
0,4, 0x81, 0x8A, 0,8, 0x82, 0x8B, 0,4, 0x83, 0x8C, 0,8, 0x84, 0x8D, 0,108, 0x90,86,122,
0x91,86,122, 0x92,86,122, 0x93,86,122, 0,83, 0x80, 0x81, 0x82, 0x83, 0,116, 0x90,50,71, 0x91,57,83,
0x92,38,93, 0x93,53,92, 0x94,62,90, 0x95,77,115, 0x96,81,121, 0x97,77,115, 0x98,81,121,
0x99,50,101, 0x9A,57,113, 0x9B,38,123, 0x9C,53,122, 0x9D,62,120, 0x9E,77,115, 0x9F,81,121,
0,50, 0x80, 0x89, 0,8, 0x81, 0x8A, 0,20, 0x82, 0x8B, 0,4, 0x83, 0x8C, 0x85, 0x87, 0x8E, 0,4,
0x86, 0x88, 0x8F, 0,12, 0x84, 0x8D, 0,104, 0x90,86,116, 0x91,86,116, 0x92,86,116, 0x93,86,116,
0,95, 0x80, 0x81, 0x82, 0x83, 0,108, 0x90,55,86, 0x91,60,92, 0x92,43,94, 0x93,76,101, 0x94,84,116,
0x95,76,101, 0x96,84,116, 0x97,55,116, 0x98,60,122, 0x99,43,124, 0x9A,76,101, 0x9B,84,116,
0x9C,76,101, 0x9D,84,116, 0,58, 0x83, 0x85, 0x8A, 0x8C, 0,33, 0x84, 0x86, 0x8B, 0x8D, 0,41, 0x80,
0x87, 0,4, 0x81, 0x88, 0,62, 0x90,62,97, 0x91,55,94, 0x93,77,113, 0x94,83,122, 0x95,77,113,
0x96,83,122, 0x97,62,127, 0x98,55,124, 0x9A,77,113, 0x9B,83,122, 0x9C,77,113, 0x9D,83,122,
0,12, 0x82, 0x89, 0,41, 0x80, 0x87, 0,12, 0x81, 0x88, 0,8, 0x83, 0x85, 0x8A, 0x8C, 0,25, 0x84,
0x86, 0x8B, 0x8D, 0,104, 0x90,55,91, 0x91,43,94, 0x92,60,93, 0x93,76,111, 0x94,84,122, 0x95,76,111,
0x96,84,122, 0x97,55,121, 0x98,43,124, 0x99,60,123, 0x9A,76,111, 0x9B,84,122, 0x9C,76,111,
0x9D,84,122, 0,70, 0x83, 0x85, 0x8A, 0x8C, 0,29, 0x84, 0x86, 0x8B, 0x8D, 0,4, 0x80, 0x87, 0,20,
0x81, 0x88, 0x82, 0x89, 0,79, 0x90,55,94, 0x91,62,94, 0x92,77,116, 0x93,83,126, 0x94,77,116,
0x95,83,126, 0x96,55,124, 0x97,62,124, 0x98,77,116, 0x99,83,126, 0x9A,77,116, 0x9B,83,126,
0,66, 0x80, 0x86, 0,4, 0x82, 0x84, 0x88, 0x8A, 0,4, 0x81, 0x87, 0,12, 0x83, 0x85, 0x89, 0x8B, 0,112,
0x90,60,94, 0x91,55,90, 0x92,36,83, 0x93,76,113, 0x94,84,115, 0x95,76,113, 0x96,84,115,
0x97,60,124, 0x98,55,120, 0x99,36,113, 0x9A,76,113, 0x9B,84,115, 0x9C,76,113, 0x9D,84,115,
0,62, 0x83, 0x85, 0x8A, 0x8C, 0,29, 0x84, 0x86, 0x8B, 0x8D, 0,75, 0x80, 0x87, 0,4, 0x81, 0x88, 0,33,
0x82, 0x89, 0x90,81,120, 0x91,77,112, 0x92,81,120, 0x93,77,112, 0x94,81,120, 0x95,77,112, 0x96,81,120,
0x97,77,112, 0,41, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,54, 0x90,77,96, 0x91,81,117,
0x92,77,96, 0x93,81,117, 0x94,77,96, 0x95,81,117, 0x96,77,96, 0x97,81,117, 0,37, 0x80,
0x82, 0x84, 0x86, 0,12, 0x81, 0x83, 0x85, 0x87, 0,50, 0x90,50,88, 0x91,38,88, 0x92,57,80, 0x93,53,91,
0x94,62,73, 0x95,77,111, 0x96,81,122, 0x97,77,111, 0x98,81,122, 0x99,50,118, 0x9A,38,118,
0x9B,57,110, 0x9C,53,121, 0x9D,62,103, 0x9E,77,111, 0x9F,81,122, 0,62, 0x80, 0x89, 0x85, 0x87,
0x8E, 0,4, 0x86, 0x88, 0x8F, 0,29, 0x81, 0x8A, 0,12, 0x82, 0x8B, 0,4, 0x83, 0x8C, 0,8, 0x84,
0x8D, 0,83, 0x90,81,116, 0x91,77,113, 0x92,81,116, 0x93,77,113, 0x94,81,116, 0x95,77,113,
0x96,81,116, 0x97,77,113, 0,50, 0x80, 0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,50, 0x90,77,103,
0x91,81,113, 0x92,77,103, 0x93,81,113, 0x94,77,103, 0x95,81,113, 0x96,77,103, 0x97,81,113,
0,41, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,58, 0x90,50,75, 0x91,38,97, 0x92,57,86,
0x93,62,82, 0x94,53,90, 0x95,77,113, 0x96,81,117, 0x97,77,113, 0x98,81,117, 0x99,50,105,
0x9A,38,127, 0x9B,57,116, 0x9C,62,112, 0x9D,53,120, 0x9E,77,113, 0x9F,81,117, 0,62, 0x85,
0x87, 0x8E, 0,8, 0x80, 0x89, 0,4, 0x86, 0x88, 0x8F, 0,8, 0x81, 0x8A, 0,20, 0x82, 0x8B, 0x83, 0x8C,
0,8, 0x84, 0x8D, 0,87, 0x90,77,102, 0x91,81,116, 0x92,77,102, 0x93,81,116, 0x94,77,102,
0x95,81,116, 0x96,77,102, 0x97,81,116, 0,37, 0x80, 0x82, 0x84, 0x86, 0,8, 0x81, 0x83, 0x85, 0x87,
0,58, 0x90,77,98, 0x91,81,120, 0x92,77,98, 0x93,81,120, 0x94,77,98, 0x95,81,120, 0x96,77,98,
0x97,81,120, 0,41, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,54, 0x90,50,75, 0x91,38,97,
0x92,57,80, 0x93,62,93, 0x94,53,85, 0x95,81,126, 0x96,77,101, 0x97,81,126, 0x98,77,101,
0x99,50,105, 0x9A,38,127, 0x9B,57,110, 0x9C,62,123, 0x9D,53,115, 0x9E,81,126, 0x9F,77,101,
0,62, 0x80, 0x89, 0,16, 0x81, 0x8A, 0,16, 0x85, 0x87, 0x8E, 0,4, 0x82, 0x8B, 0,4, 0x83, 0x8C,
0x86, 0x88, 0x8F, 0,8, 0x84, 0x8D, 0,91, 0x90,86,121, 0x91,86,121, 0x92,86,121, 0x93,86,121,
0,83, 0x80, 0x81, 0x82, 0x83, 0,116, 0x90,50,61, 0x91,38,87, 0x92,57,80, 0x93,62,83, 0x94,53,90,
0x95,77,115, 0x96,81,117, 0x97,77,115, 0x98,81,117, 0x99,50,91, 0x9A,38,117, 0x9B,57,110,
0x9C,62,113, 0x9D,53,120, 0x9E,77,115, 0x9F,81,117, 0,70, 0x80, 0x89, 0,8, 0x81, 0x8A, 0x85,
0x87, 0x8E, 0x86, 0x88, 0x8F, 0,16, 0x82, 0x8B, 0,8, 0x83, 0x8C, 0,12, 0x84, 0x8D, 0,87, 0x90,86,121,
0x91,86,121, 0x92,86,121, 0x93,86,121, 0,83, 0x80, 0x81, 0x82, 0x83, 0,116, 0x90,38,96, 0x91,50,81,
0x92,57,82, 0x93,62,87, 0x94,53,93, 0x95,81,124, 0x96,77,116, 0x97,81,124, 0x98,77,116,
0x99,38,126, 0x9A,50,111, 0x9B,57,112, 0x9C,62,117, 0x9D,53,123, 0x9E,81,124, 0x9F,77,116,
0,83, 0x80, 0x89, 0x85, 0x87, 0x8E, 0,8, 0x81, 0x8A, 0x86, 0x88, 0x8F, 0,20, 0x82, 0x8B, 0,4, 0x83,
0x8C, 0x84, 0x8D, 0,87, 0x90,86,122, 0x91,86,122, 0x92,86,122, 0x93,86,122, 0,95, 0x80, 0x81,
0x82, 0x83, 0,108, 0x90,50,81, 0x91,38,81, 0x92,57,87, 0x93,62,80, 0x94,53,94, 0x95,77,113,
0x96,81,122, 0x97,77,113, 0x98,81,122, 0x99,50,111, 0x9A,38,111, 0x9B,57,117, 0x9C,62,110,
0x9D,53,124, 0x9E,77,113, 0x9F,81,122, 0,79, 0x80, 0x89, 0,8, 0x85, 0x87, 0x8E, 0,4, 0x81,
0x8A, 0,8, 0x82, 0x8B, 0,8, 0x86, 0x88, 0x8F, 0,4, 0x83, 0x8C, 0,16, 0x84, 0x8D, 0,70, 0x90,79,123,
0x91,76,111, 0x92,79,123, 0x93,76,111, 0x94,79,123, 0x95,76,111, 0x96,79,123, 0x97,76,111,
0,75, 0x80, 0x82, 0x84, 0x86, 0,12, 0x81, 0x83, 0x85, 0x87, 0,116, 0x90,50,76, 0x91,38,91, 0x92,74,105,
0x93,77,123, 0x94,74,105, 0x95,77,123, 0x96,50,106, 0x97,38,121, 0x98,74,105, 0x99,77,123,
0x9A,74,105, 0x9B,77,123, 0,79, 0x82, 0x84, 0x88, 0x8A, 0x80, 0x86, 0,8, 0x81, 0x87, 0x83, 0x85, 0x89,
0x8B, 0,116, 0x90,58,92, 0x91,55,97, 0x92,73,98, 0x93,76,106, 0x94,73,98, 0x95,76,106,
0x96,58,122, 0x97,55,127, 0x98,73,98, 0x99,76,106, 0x9A,73,98, 0x9B,76,106, 0,75, 0x82,
0x84, 0x88, 0x8A, 0,25, 0x83, 0x85, 0x89, 0x8B, 0,4, 0x80, 0x86, 0,4, 0x81, 0x87, 0,91, 0x90,53,94,
0x91,57,97, 0x92,74,107, 0x93,74,107, 0x94,53,124, 0x95,57,127, 0x96,74,107, 0x97,74,107,
0,83, 0x82, 0x83, 0x86, 0x87, 0,8, 0x80, 0x84, 0,12, 0x81, 0x85, 0,100, 0x90,77,115, 0x91,81,111,
0x92,77,115, 0x93,81,111, 0x94,77,115, 0x95,81,111, 0x96,77,115, 0x97,81,111, 0,54, 0x80,
0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,45, 0x90,81,120, 0x91,77,124, 0x92,81,120, 0x93,77,124,
0x94,81,120, 0x95,77,124, 0x96,81,120, 0x97,77,124, 0,37, 0x80, 0x82, 0x84, 0x86, 0,29, 0x81,
0x83, 0x85, 0x87, 0,33, 0x90,50,68, 0x91,38,94, 0x92,57,85, 0x93,53,81, 0x94,62,83, 0x95,81,85,
0x96,77,124, 0x97,81,85, 0x98,77,124, 0x99,50,98, 0x9A,38,124, 0x9B,57,115, 0x9C,53,111,
0x9D,62,113, 0x9E,81,85, 0x9F,77,124, 0,33, 0x85, 0x87, 0x8E, 0,33, 0x86, 0x88, 0x8F, 0,8,
0x80, 0x89, 0,8, 0x81, 0x8A, 0,12, 0x82, 0x8B, 0,16, 0x83, 0x8C, 0x84, 0x8D, 0,87, 0x90,77,108,
0x91,81,121, 0x92,77,108, 0x93,81,121, 0x94,77,108, 0x95,81,121, 0x96,77,108, 0x97,81,121,
0,50, 0x80, 0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,54, 0x90,81,113, 0x91,77,102, 0x92,81,113,
0x93,77,102, 0x94,81,113, 0x95,77,102, 0x96,81,113, 0x97,77,102, 0,37, 0x80, 0x82, 0x84, 0x86,
0,4, 0x81, 0x83, 0x85, 0x87, 0,58, 0x90,38,94, 0x91,50,81, 0x92,57,83, 0x93,62,90, 0x94,53,83,
0x95,81,122, 0x96,77,113, 0x97,81,122, 0x98,77,113, 0x99,38,124, 0x9A,50,111, 0x9B,57,113,
0x9C,62,120, 0x9D,53,113, 0x9E,81,122, 0x9F,77,113, 0,62, 0x85, 0x87, 0x8E, 0,8, 0x86, 0x88,
0x8F, 0,8, 0x80, 0x89, 0x81, 0x8A, 0,29, 0x82, 0x8B, 0,4, 0x83, 0x8C, 0,4, 0x84, 0x8D, 0,87,
0x90,77,100, 0x91,81,110, 0x92,77,100, 0x93,81,110, 0x94,77,100, 0x95,81,110, 0x96,77,100,
0x97,81,110, 0,33, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,62, 0x90,81,112, 0x91,77,98,
0x92,81,112, 0x93,77,98, 0x94,81,112, 0x95,77,98, 0x96,81,112, 0x97,77,98, 0,37, 0x80,
0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,62, 0x90,50,80, 0x91,38,94, 0x92,57,83, 0x93,62,73,
0x94,53,91, 0x95,81,122, 0x96,77,108, 0x97,81,122, 0x98,77,108, 0x99,50,110, 0x9A,38,124,
0x9B,57,113, 0x9C,62,103, 0x9D,53,121, 0x9E,81,122, 0x9F,77,108, 0,75, 0x85, 0x87, 0x8E, 0,4,
0x80, 0x89, 0,4, 0x81, 0x8A, 0x86, 0x88, 0x8F, 0,12, 0x82, 0x8B, 0,4, 0x83, 0x8C, 0,4, 0x84, 0x8D,
0,100, 0x90,86,121, 0x91,86,121, 0x92,86,121, 0x93,86,121, 0,75, 0x80, 0x81, 0x82, 0x83, 0,129,
0x90,50,78, 0x91,38,94, 0x92,62,85, 0x93,57,86, 0x94,53,88, 0x95,81,117, 0x96,77,115,
0x97,81,117, 0x98,77,115, 0x99,50,108, 0x9A,38,124, 0x9B,62,115, 0x9C,57,116, 0x9D,53,118,
0x9E,81,117, 0x9F,77,115, 0,62, 0x85, 0x87, 0x8E, 0,4, 0x80, 0x89, 0,4, 0x86, 0x88, 0x8F, 0,4,
0x81, 0x8A, 0,16, 0x82, 0x8B, 0x83, 0x8C, 0,8, 0x84, 0x8D, 0,100, 0x90,86,122, 0x91,86,122, 0x92,86,122,
0x93,86,122, 0,87, 0x80, 0x81, 0x82, 0x83, 0,116, 0x90,50,78, 0x91,57,83, 0x92,38,92, 0x93,53,92,
0x94,62,83, 0x95,77,115, 0x96,81,121, 0x97,77,115, 0x98,81,121, 0x99,50,108, 0x9A,57,113,
0x9B,38,122, 0x9C,53,122, 0x9D,62,113, 0x9E,77,115, 0x9F,81,121, 0,58, 0x80, 0x89, 0,4,
0x81, 0x8A, 0,8, 0x82, 0x8B, 0,12, 0x85, 0x87, 0x8E, 0x83, 0x8C, 0,4, 0x86, 0x88, 0x8F, 0,16, 0x84,
0x8D, 0,100, 0x90,86,116, 0x91,86,116, 0x92,86,116, 0x93,86,116, 0,91, 0x80, 0x81, 0x82, 0x83,
0,108, 0x90,55,93, 0x91,60,97, 0x92,43,90, 0x93,76,101, 0x94,84,116, 0x95,76,101, 0x96,84,116,
0x97,55,123, 0x98,60,127, 0x99,43,120, 0x9A,76,101, 0x9B,84,116, 0x9C,76,101, 0x9D,84,116,
0,58, 0x83, 0x85, 0x8A, 0x8C, 0,12, 0x80, 0x87, 0,8, 0x81, 0x88, 0,12, 0x84, 0x86, 0x8B, 0x8D, 0,29,
0x82, 0x89, 0,83, 0x90,55,94, 0x91,62,97, 0x92,77,113, 0x93,83,122, 0x94,77,113, 0x95,83,122,
0x96,55,124, 0x97,62,127, 0x98,77,113, 0x99,83,122, 0x9A,77,113, 0x9B,83,122, 0,66, 0x80,
0x86, 0,4, 0x81, 0x87, 0,4, 0x82, 0x84, 0x88, 0x8A, 0,20, 0x83, 0x85, 0x89, 0x8B, 0,108, 0x90,60,93,
0x91,36,92, 0x92,76,111, 0x93,84,122, 0x94,76,111, 0x95,84,122, 0x96,60,123, 0x97,36,122,
0x98,76,111, 0x99,84,122, 0x9A,76,111, 0x9B,84,122, 0,70, 0x82, 0x84, 0x88, 0x8A, 0,8, 0x80,
0x86, 0,12, 0x81, 0x87, 0,4, 0x83, 0x85, 0x89, 0x8B, 2,0, 0x90,67,120, 0x91,60,112, 0x92,67,120,
0x93,60,112, 0x94,67,120, 0x95,60,112, 0x96,67,120, 0x97,60,112, 0,41, 0x80, 0x82, 0x84, 0x86,
0,4, 0x81, 0x83, 0x85, 0x87, 0,54, 0x90,60,96, 0x91,67,117, 0x92,60,96, 0x93,67,117, 0x94,60,96,
0x95,67,117, 0x96,60,96, 0x97,67,117, 0,33, 0x80, 0x82, 0x84, 0x86, 0,16, 0x81, 0x83, 0x85, 0x87,
0,50, 0x90,60,117, 0x91,67,124, 0x92,60,117, 0x93,67,124, 0x94,60,117, 0x95,67,124, 0x96,60,117,
0x97,67,124, 0,66, 0x80, 0x82, 0x84, 0x86, 0,8, 0x81, 0x83, 0x85, 0x87, 0,129, 0x90,60,110, 0x91,67,117,
0x92,60,110, 0x93,67,117, 0x94,60,110, 0x95,67,117, 0x96,60,110, 0x97,67,117, 0,50, 0x80,
0x82, 0x84, 0x86, 0x81, 0x83, 0x85, 0x87, 0,50, 0x90,60,112, 0x91,67,117, 0x92,60,112, 0x93,67,117,
0x94,60,112, 0x95,67,117, 0x96,60,112, 0x97,67,117, 0,45, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81,
0x83, 0x85, 0x87, 0,54, 0x90,60,111, 0x91,67,122, 0x92,60,111, 0x93,67,122, 0x94,60,111, 0x95,67,122,
0x96,60,111, 0x97,67,122, 0,58, 0x80, 0x82, 0x84, 0x86, 0,12, 0x81, 0x83, 0x85, 0x87, 0,129, 0x90,69,118,
0x91,65,116, 0x92,69,118, 0x93,65,116, 0x94,69,118, 0x95,65,116, 0x96,69,118, 0x97,65,116,
0,58, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87, 0,141, 0x90,67,113, 0x91,70,112, 0x92,67,113,
0x93,70,112, 0x94,67,113, 0x95,70,112, 0x96,67,113, 0x97,70,112, 0,58, 0x80, 0x82, 0x84, 0x86,
0,4, 0x81, 0x83, 0x85, 0x87, 0,137, 0x90,48,97, 0x91,67,113, 0x92,60,94, 0x93,67,113, 0x94,60,94,
0x95,48,127, 0x96,67,113, 0x97,60,94, 0x98,67,113, 0x99,60,94, 0,45, 0x80, 0x85, 0,158,
0x90,50,83, 0x95,50,113, 0,41, 0x81, 0x83, 0x86, 0x88, 0x80, 0x85, 0,16, 0x82, 0x84, 0x87, 0x89, 0,145,
0x90,52,68, 0x91,67,110, 0x92,70,97, 0x93,67,110, 0x94,70,97, 0x95,52,98, 0x96,67,110,
0x97,70,97, 0x98,67,110, 0x99,70,97, 0,33, 0x80, 0x85, 0,37, 0x81, 0x83, 0x86, 0x88, 0x82, 0x84,
0x87, 0x89, 0,129, 0x90,53,97, 0x91,69,112, 0x92,65,91, 0x93,69,112, 0x94,65,91, 0x95,53,127,
0x96,69,112, 0x97,65,91, 0x98,69,112, 0x99,65,91, 0,45, 0x80, 0x85, 0,33, 0x81, 0x83, 0x86,
0x88, 0,4, 0x82, 0x84, 0x87, 0x89, 0,120, 0x90,55,94, 0x91,65,123, 0x92,65,123, 0x93,55,124,
0x94,65,123, 0x95,65,123, 0,54, 0x80, 0x83, 0,150, 0x90,57,92, 0x93,57,122, 0,45, 0x80,
0x83, 0,8, 0x81, 0x82, 0x84, 0x85, 0,145, 0x90,59,97, 0x91,69,116, 0x92,65,112, 0x93,69,116,
0x94,65,112, 0x95,59,127, 0x96,69,116, 0x97,65,112, 0x98,69,116, 0x99,65,112, 0,45, 0x80,
0x85, 0,16, 0x81, 0x83, 0x86, 0x88, 0,8, 0x82, 0x84, 0x87, 0x89, 0,133, 0x90,60,88, 0x91,64,110,
0x92,67,110, 0x93,64,110, 0x94,67,110, 0x95,60,118, 0x96,64,110, 0x97,67,110, 0x98,64,110,
0x99,67,110, 0,58, 0x80, 0x85, 0,8, 0x81, 0x83, 0x86, 0x88, 0x82, 0x84, 0x87, 0x89, 0,133, 0x90,48,88,
0x91,67,108, 0x92,64,108, 0x93,67,108, 0x94,64,108, 0x95,48,118, 0x96,67,108, 0x97,64,108,
0x98,67,108, 0x99,64,108, 0,41, 0x80, 0x85, 0,25, 0x81, 0x83, 0x86, 0x88, 0,4, 0x82, 0x84, 0x87,
0x89, 0,133, 0x90,60,88, 0x91,64,110, 0x92,67,116, 0x93,64,110, 0x94,67,116, 0x95,60,118,
0x96,64,110, 0x97,67,116, 0x98,64,110, 0x99,67,116, 0,45, 0x80, 0x85, 0,16, 0x81, 0x83, 0x86,
0x88, 0x82, 0x84, 0x87, 0x89, 0,141, 0x90,60,100, 0x91,67,112, 0x92,60,100, 0x93,67,112, 0x94,60,100,
0x95,67,112, 0x96,60,100, 0x97,67,112, 0,58, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87,
0,37, 0x90,60,103, 0x91,67,117, 0x92,60,103, 0x93,67,117, 0x94,60,103, 0x95,67,117, 0x96,60,103,
0x97,67,117, 0,37, 0x80, 0x82, 0x84, 0x86, 0,16, 0x81, 0x83, 0x85, 0x87, 0,45, 0x90,60,102, 0x91,67,115,
0x92,60,102, 0x93,67,115, 0x94,60,102, 0x95,67,115, 0x96,60,102, 0x97,67,115, 0,58, 0x80,
0x82, 0x84, 0x86, 0,16, 0x81, 0x83, 0x85, 0x87, 0,129, 0x90,60,111, 0x91,67,113, 0x92,60,111, 0x93,67,113,
0x94,60,111, 0x95,67,113, 0x96,60,111, 0x97,67,113, 0,45, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81,
0x83, 0x85, 0x87, 0,54, 0x90,60,100, 0x91,67,112, 0x92,60,100, 0x93,67,112, 0x94,60,100, 0x95,67,112,
0x96,60,100, 0x97,67,112, 0,37, 0x80, 0x82, 0x84, 0x86, 0,12, 0x81, 0x83, 0x85, 0x87, 0,50, 0x90,60,97,
0x91,67,112, 0x92,60,97, 0x93,67,112, 0x94,60,97, 0x95,67,112, 0x96,60,97, 0x97,67,112,
0,50, 0x80, 0x82, 0x84, 0x86, 0,16, 0x81, 0x83, 0x85, 0x87, 0,133, 0x90,65,115, 0x91,69,116, 0x92,65,115,
0x93,69,116, 0x94,65,115, 0x95,69,116, 0x96,65,115, 0x97,69,116, 0,58, 0x80, 0x82, 0x84, 0x86,
0x81, 0x83, 0x85, 0x87, 0,145, 0x90,67,112, 0x91,70,108, 0x92,67,112, 0x93,70,108, 0x94,67,112,
0x95,70,108, 0x96,67,112, 0x97,70,108, 0,58, 0x80, 0x82, 0x84, 0x86, 0,4, 0x81, 0x83, 0x85, 0x87,
0,141, 0x90,48,93, 0x91,67,117, 0x92,60,112, 0x93,67,117, 0x94,60,112, 0x95,48,123, 0x96,67,117,
0x97,60,112, 0x98,67,117, 0x99,60,112, 0,50, 0x80, 0x85, 0,150, 0x90,50,83, 0x95,50,113,
0,50, 0x80, 0x85, 0,12, 0x81, 0x83, 0x86, 0x88, 0,4, 0x82, 0x84, 0x87, 0x89, 0,137, 0x90,52,64,
0x91,67,113, 0x92,70,107, 0x93,67,113, 0x94,70,107, 0x95,52,94, 0x96,67,113, 0x97,70,107,
0x98,67,113, 0x99,70,107, 0,37, 0x80, 0x85, 0,33, 0x81, 0x83, 0x86, 0x88, 0,4, 0x82, 0x84, 0x87,
0x89, 0,129, 0x90,53,86, 0x91,65,117, 0x92,69,115, 0x93,65,117, 0x94,69,115, 0x95,53,116,
0x96,65,117, 0x97,69,115, 0x98,65,117, 0x99,69,115, 0,41, 0x80, 0x85, 0,16, 0x81, 0x83, 0x86,
0x88, 0x82, 0x84, 0x87, 0x89, 0,141, 0x90,55,88, 0x91,65,123, 0x92,65,123, 0x93,55,118, 0x94,65,123,
0x95,65,123, 0,58, 0x80, 0x83, 0,145, 0x90,57,97, 0x93,57,127, 0,20, 0x81, 0x82, 0x84, 0x85,
0,33, 0x80, 0x83, 0,150, 0x90,59,97, 0x91,69,107, 0x92,65,115, 0x93,69,107, 0x94,65,115,
0x95,59,127, 0x96,69,107, 0x97,65,115, 0x98,69,107, 0x99,65,115, 0,45, 0x80, 0x85, 0x81, 0x83,
0x86, 0x88, 0,12, 0x82, 0x84, 0x87, 0x89, 0,141, 0x90,60,80, 0x91,67,123, 0x92,64,111, 0x93,67,123,
0x94,64,111, 0x95,60,110, 0x96,67,123, 0x97,64,111, 0x98,67,123, 0x99,64,111, 0,50, 0x80,
0x85, 0,154, 0x90,48,88, 0x95,48,118, 0,37, 0x80, 0x85, 0,87, 0x81, 0x83, 0x86, 0x88, 0,4,
0x82, 0x84, 0x87, 0x89, 0,75, 0x90,60,92, 0x91,60,122, 0,41, 0x80, 0x81, 0,158, 0x90,60,116,
0x91,60,116, 0x92,60,116, 0x93,60,116, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,60,122, 0x91,60,122,
0x92,60,122, 0x93,60,122, 0,54, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,41,93, 0x91,57,86, 0x92,53,82,
0x93,60,116, 0x94,60,116, 0x95,41,123, 0x96,57,116, 0x97,53,112, 0x98,60,116, 0x99,60,116,
0,54, 0x80, 0x85, 0,8, 0x81, 0x86, 0,4, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,120, 0x90,60,110,
0x91,60,110, 0x92,60,110, 0x93,60,110, 0,45, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,60,108, 0x91,60,108,
0x92,60,108, 0x93,60,108, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,57,85, 0x91,53,75, 0x92,41,86,
0x93,60,110, 0x94,60,110, 0x95,57,115, 0x96,53,105, 0x97,41,116, 0x98,60,110, 0x99,60,110,
0,75, 0x80, 0x85, 0x83, 0x84, 0x88, 0x89, 0x81, 0x86, 0,4, 0x82, 0x87, 0,125, 0x90,60,98, 0x91,60,98,
0x92,60,98, 0x93,60,98, 0,41, 0x80, 0x81, 0x82, 0x83, 0,58, 0x90,60,101, 0x91,60,101, 0x92,60,101,
0x93,60,101, 0,66, 0x80, 0x81, 0x82, 0x83, 0,37, 0x90,57,83, 0x91,41,86, 0x92,53,72, 0x93,65,124,
0x94,65,124, 0x95,57,113, 0x96,41,116, 0x97,53,102, 0x98,65,124, 0x99,65,124, 0,58, 0x80,
0x85, 0,4, 0x81, 0x86, 0x82, 0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,129, 0x90,53,72, 0x91,57,83,
0x92,41,86, 0x93,67,127, 0x94,67,127, 0x95,53,102, 0x96,57,113, 0x97,41,116, 0x98,67,127,
0x99,67,127, 0,54, 0x80, 0x85, 0,8, 0x81, 0x86, 0,4, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88, 0x89,
0,120, 0x90,57,83, 0x91,53,76, 0x92,41,91, 0x93,69,127, 0x94,69,127, 0x95,57,113, 0x96,53,106,
0x97,41,121, 0x98,69,127, 0x99,69,127, 0,54, 0x80, 0x85, 0x81, 0x86, 0,16, 0x82, 0x87, 0x83, 0x84,
0x88, 0x89, 0,133, 0x90,60,113, 0x91,60,113, 0x92,60,113, 0x93,60,113, 0,41, 0x80, 0x81, 0x82,
0x83, 0,58, 0x90,60,116, 0x91,60,116, 0x92,60,116, 0x93,60,116, 0,50, 0x80, 0x81, 0x82, 0x83,
0,50, 0x90,53,78, 0x91,57,88, 0x92,41,94, 0x93,60,118, 0x94,60,118, 0x95,53,108, 0x96,57,118,
0x97,41,124, 0x98,60,118, 0x99,60,118, 0,54, 0x80, 0x85, 0,4, 0x81, 0x86, 0,8, 0x82, 0x87,
0,4, 0x83, 0x84, 0x88, 0x89, 0,133, 0x90,60,121, 0x91,60,121, 0x92,60,121, 0x93,60,121, 0,45,
0x80, 0x81, 0x82, 0x83, 0,54, 0x90,60,110, 0x91,60,110, 0x92,60,110, 0x93,60,110, 0,62, 0x80,
0x81, 0x82, 0x83, 0,37, 0x90,53,82, 0x91,57,92, 0x92,41,90, 0x93,65,124, 0x94,65,124, 0x95,53,112,
0x96,57,122, 0x97,41,120, 0x98,65,124, 0x99,65,124, 0,62, 0x80, 0x85, 0x81, 0x86, 0,8, 0x82,
0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,116, 0x90,69,122, 0x91,69,122, 0x92,69,122, 0x93,69,122,
0,45, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,69,124, 0x91,69,124, 0x92,69,124, 0x93,69,124, 0,66,
0x80, 0x81, 0x82, 0x83, 0,37, 0x90,48,82, 0x91,36,94, 0x92,52,90, 0x93,55,83, 0x94,67,127,
0x95,67,127, 0x96,48,112, 0x97,36,124, 0x98,52,120, 0x99,55,113, 0x9A,67,127, 0x9B,67,127,
0,45, 0x80, 0x86, 0,16, 0x81, 0x87, 0x82, 0x88, 0x83, 0x89, 0,4, 0x84, 0x85, 0x8A, 0x8B, 0,133, 0x90,48,78,
0x91,52,81, 0x92,55,90, 0x93,36,93, 0x94,64,124, 0x95,64,124, 0x96,48,108, 0x97,52,111,
0x98,55,120, 0x99,36,123, 0x9A,64,124, 0x9B,64,124, 0,41, 0x80, 0x86, 0,20, 0x81, 0x87, 0x82,
0x88, 0,4, 0x83, 0x89, 0,4, 0x84, 0x85, 0x8A, 0x8B, 0,133, 0x90,48,90, 0x91,52,82, 0x92,55,91,
0x93,36,90, 0x94,60,116, 0x95,60,116, 0x96,48,120, 0x97,52,112, 0x98,55,121, 0x99,36,120,
0x9A,60,116, 0x9B,60,116, 0,50, 0x80, 0x86, 0,4, 0x81, 0x87, 0,20, 0x82, 0x88, 0x83, 0x89, 0,4,
0x84, 0x85, 0x8A, 0x8B, 0,125, 0x90,60,103, 0x91,60,103, 0x92,60,103, 0x93,60,103, 0,45, 0x80,
0x81, 0x82, 0x83, 0,54, 0x90,60,110, 0x91,60,110, 0x92,60,110, 0x93,60,110, 0,58, 0x80, 0x81,
0x82, 0x83, 0,41, 0x90,53,85, 0x91,57,90, 0x92,41,92, 0x93,60,124, 0x94,60,124, 0x95,53,115,
0x96,57,120, 0x97,41,122, 0x98,60,124, 0x99,60,124, 0,58, 0x80, 0x85, 0,12, 0x81, 0x86, 0,8,
0x82, 0x87, 0x83, 0x84, 0x88, 0x89, 0,125, 0x90,60,118, 0x91,60,118, 0x92,60,118, 0x93,60,118, 0,50,
0x80, 0x81, 0x82, 0x83, 0,50, 0x90,60,118, 0x91,60,118, 0x92,60,118, 0x93,60,118, 0,58, 0x80,
0x81, 0x82, 0x83, 0,41, 0x90,53,92, 0x91,57,94, 0x92,41,88, 0x93,60,111, 0x94,60,111, 0x95,53,122,
0x96,57,124, 0x97,41,118, 0x98,60,111, 0x99,60,111, 0,54, 0x80, 0x85, 0,8, 0x83, 0x84, 0x88,
0x89, 0x81, 0x86, 0,8, 0x82, 0x87, 0,133, 0x90,60,112, 0x91,60,112, 0x92,60,112, 0x93,60,112,
0,50, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,60,88, 0x91,60,88, 0x92,60,88, 0x93,60,88, 0,41,
0x80, 0x81, 0x82, 0x83, 0,58, 0x90,53,90, 0x91,57,90, 0x92,41,91, 0x93,65,127, 0x94,65,127,
0x95,53,120, 0x96,57,120, 0x97,41,121, 0x98,65,127, 0x99,65,127, 0,50, 0x80, 0x85, 0,12,
0x81, 0x86, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,120, 0x90,53,83, 0x91,41,94, 0x92,57,86,
0x93,67,124, 0x94,67,124, 0x95,53,113, 0x96,41,124, 0x97,57,116, 0x98,67,124, 0x99,67,124,
0,50, 0x80, 0x85, 0,4, 0x81, 0x86, 0,12, 0x82, 0x87, 0,4, 0x83, 0x84, 0x88, 0x89, 0,133, 0x90,53,93,
0x91,41,91, 0x92,57,92, 0x93,69,122, 0x94,69,122, 0x95,53,123, 0x96,41,121, 0x97,57,122,
0x98,69,122, 0x99,69,122, 0,58, 0x80, 0x85, 0x81, 0x86, 0,4, 0x82, 0x87, 0,20, 0x83, 0x84, 0x88,
0x89, 0,120, 0x90,65,124, 0x91,65,124, 0x92,65,124, 0x93,65,124, 0,58, 0x80, 0x81, 0x82, 0x83,
0,41, 0x90,69,124, 0x91,69,124, 0x92,69,124, 0x93,69,124, 0,62, 0x80, 0x81, 0x82, 0x83, 0,37,
0x90,36,97, 0x91,72,127, 0x92,72,127, 0x93,36,127, 0x94,72,127, 0x95,72,127, 0,108, 0x80,
0x83, 0,95, 0x90,52,80, 0x93,60,91, 0x96,58,83, 0x97,52,110, 0x98,60,121, 0x99,58,113,
0,37, 0x80, 0x87, 0,8, 0x83, 0x88, 0,8, 0x86, 0x89, 0,50, 0x90,52,82, 0x93,60,90, 0x96,58,77,
0x97,52,112, 0x98,60,120, 0x99,58,107, 0,33, 0x80, 0x87, 0,8, 0x83, 0x88, 0,8, 0x86, 0x89,
0,50, 0x90,52,91, 0x93,58,73, 0x96,60,83, 0x97,36,97, 0x98,52,121, 0x99,58,103, 0x9A,60,113,
0x9B,36,127, 0,58, 0x80, 0x88, 0,16, 0x83, 0x89, 0x86, 0x8A, 0,25, 0x90,70,127, 0x93,70,127,
0x96,70,127, 0x98,70,127, 0,16, 0x87, 0x8B, 0,37, 0x81, 0x82, 0x84, 0x85, 0,20, 0x80, 0x83, 0x86,
0x88, 0,25, 0x90,69,105, 0x91,69,105, 0x92,69,105, 0x93,69,105, 0,95, 0x80, 0x81, 0x82, 0x83,
0,8, 0x90,67,123, 0x91,67,123, 0x92,67,123, 0x93,67,123, 0,95, 0x80, 0x81, 0x82, 0x83, 0,4,
0x90,53,86, 0x91,41,78, 0x92,57,92, 0x93,65,123, 0x94,65,123, 0x95,53,116, 0x96,41,108,
0x97,57,122, 0x98,65,123, 0x99,65,123, 0,66, 0x80, 0x85, 0x81, 0x86, 0,12, 0x82, 0x87, 0,66,
0x83, 0x84, 0x88, 0x89, 0,58, 0x90,60,92, 0x91,41,92, 0x92,69,127, 0x93,69,127, 0x94,60,122,
0x95,41,122, 0x96,69,127, 0x97,69,127, 0,50, 0x80, 0x84, 0,4, 0x82, 0x83, 0x86, 0x87, 0,12,
0x81, 0x85, 0,133, 0x90,41,97, 0x91,53,91, 0x92,57,94, 0x93,65,124, 0x94,65,124, 0x95,41,127,
0x96,53,121, 0x97,57,124, 0x98,65,124, 0x99,65,124, 0,91, 0x83, 0x84, 0x88, 0x89, 0x80, 0x85, 0x81,
0x86, 0,8, 0x82, 0x87, 0,104, 0x90,72,124, 0x91,72,124, 0x92,72,124, 0x93,72,124, 0,66,
0x80, 0x81, 0x82, 0x83, 0,33, 0x90,72,124, 0x91,72,124, 0x92,72,124, 0x93,72,124, 0,70, 0x80,
0x81, 0x82, 0x83, 0,33, 0x90,41,93, 0x91,57,86, 0x92,53,82, 0x93,72,118, 0x94,72,118, 0x95,41,123,
0x96,57,116, 0x97,53,112, 0x98,72,118, 0x99,72,118, 0,54, 0x80, 0x85, 0,4, 0x81, 0x86, 0,8,
0x82, 0x87, 0x83, 0x84, 0x88, 0x89, 0,133, 0x90,72,112, 0x91,72,112, 0x92,72,112, 0x93,72,112, 0,50,
0x80, 0x81, 0x82, 0x83, 0,54, 0x90,72,113, 0x91,72,113, 0x92,72,113, 0x93,72,113, 0,45, 0x80,
0x81, 0x82, 0x83, 0,54, 0x90,57,85, 0x91,53,75, 0x92,41,86, 0x93,72,113, 0x94,72,113, 0x95,57,115,
0x96,53,105, 0x97,41,116, 0x98,72,113, 0x99,72,113, 0,75, 0x80, 0x85, 0x83, 0x84, 0x88, 0x89, 0x81,
0x86, 0,4, 0x82, 0x87, 0,125, 0x90,72,122, 0x91,72,122, 0x92,72,122, 0x93,72,122, 0,45,
0x80, 0x81, 0x82, 0x83, 0,54, 0x90,72,116, 0x91,72,116, 0x92,72,116, 0x93,72,116, 0,58, 0x80,
0x81, 0x82, 0x83, 0,41, 0x90,57,83, 0x91,41,86, 0x92,53,72, 0x93,77,124, 0x94,77,124, 0x95,57,113,
0x96,41,116, 0x97,53,102, 0x98,77,124, 0x99,77,124, 0,62, 0x80, 0x85, 0,4, 0x81, 0x86, 0x82,
0x87, 0,25, 0x83, 0x84, 0x88, 0x89, 0,112, 0x90,53,72, 0x91,57,83, 0x92,41,86, 0x93,79,127,
0x94,79,127, 0x95,53,102, 0x96,57,113, 0x97,41,116, 0x98,79,127, 0x99,79,127, 0,54, 0x80,
0x85, 0,8, 0x81, 0x86, 0,4, 0x82, 0x87, 0,12, 0x83, 0x84, 0x88, 0x89, 0,125, 0x90,57,83, 0x91,53,76,
0x92,41,91, 0x93,81,127, 0x94,81,127, 0x95,57,113, 0x96,53,106, 0x97,41,121, 0x98,81,127,
0x99,81,127, 0,50, 0x80, 0x85, 0,4, 0x81, 0x86, 0,12, 0x82, 0x87, 0,41, 0x83, 0x84, 0x88, 0x89,
0,91, 0x90,72,122, 0x91,72,122, 0x92,72,122, 0x93,72,122, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41,
0x90,72,105, 0x91,72,105, 0x92,72,105, 0x93,72,105, 0,41, 0x80, 0x81, 0x82, 0x83, 0,62, 0x90,53,78,
0x91,57,88, 0x92,41,94, 0x93,72,112, 0x94,72,112, 0x95,53,108, 0x96,57,118, 0x97,41,124,
0x98,72,112, 0x99,72,112, 0,54, 0x80, 0x85, 0,4, 0x81, 0x86, 0,8, 0x82, 0x87, 0,4, 0x83,
0x84, 0x88, 0x89, 0,133, 0x90,72,112, 0x91,72,112, 0x92,72,112, 0x93,72,112, 0,41, 0x80, 0x81,
0x82, 0x83, 0,58, 0x90,72,113, 0x91,72,113, 0x92,72,113, 0x93,72,113, 0,62, 0x80, 0x81, 0x82,
0x83, 0,37, 0x90,53,82, 0x91,57,92, 0x92,41,90, 0x93,77,123, 0x94,77,123, 0x95,53,112,
0x96,57,122, 0x97,41,120, 0x98,77,123, 0x99,77,123, 0,62, 0x80, 0x85, 0x81, 0x86, 0,4, 0x82,
0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,129, 0x90,81,118, 0x91,81,118, 0x92,81,118, 0x93,81,118,
0,45, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,81,121, 0x91,81,121, 0x92,81,121, 0x93,81,121, 0,70,
0x80, 0x81, 0x82, 0x83, 0,33, 0x90,48,82, 0x91,36,94, 0x92,52,90, 0x93,55,83, 0x94,79,118,
0x95,79,118, 0x96,48,112, 0x97,36,124, 0x98,52,120, 0x99,55,113, 0x9A,79,118, 0x9B,79,118,
0,41, 0x80, 0x86, 0,20, 0x81, 0x87, 0x82, 0x88, 0x83, 0x89, 0,20, 0x84, 0x85, 0x8A, 0x8B, 0,116, 0x90,48,78,
0x91,52,81, 0x92,55,90, 0x93,36,93, 0x94,76,118, 0x95,76,118, 0x96,48,108, 0x97,52,111,
0x98,55,120, 0x99,36,123, 0x9A,76,118, 0x9B,76,118, 0,41, 0x80, 0x86, 0,20, 0x81, 0x87, 0x82,
0x88, 0,4, 0x83, 0x89, 0,4, 0x84, 0x85, 0x8A, 0x8B, 0,133, 0x90,48,90, 0x91,52,82, 0x92,55,91,
0x93,36,90, 0x94,72,122, 0x95,72,122, 0x96,48,120, 0x97,52,112, 0x98,55,121, 0x99,36,120,
0x9A,72,122, 0x9B,72,122, 0,45, 0x80, 0x86, 0,8, 0x81, 0x87, 0,20, 0x82, 0x88, 0x83, 0x89, 0,12,
0x84, 0x85, 0x8A, 0x8B, 0,112, 0x90,72,113, 0x91,72,113, 0x92,72,113, 0x93,72,113, 0,50, 0x80,
0x81, 0x82, 0x83, 0,54, 0x90,72,110, 0x91,72,110, 0x92,72,110, 0x93,72,110, 0,62, 0x80, 0x81,
0x82, 0x83, 0,37, 0x90,53,85, 0x91,57,90, 0x92,41,92, 0x93,72,121, 0x94,72,121, 0x95,53,115,
0x96,57,120, 0x97,41,122, 0x98,72,121, 0x99,72,121, 0,58, 0x80, 0x85, 0,12, 0x81, 0x86, 0,8,
0x82, 0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,116, 0x90,72,121, 0x91,72,121, 0x92,72,121, 0x93,72,121,
0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,72,116, 0x91,72,116, 0x92,72,116, 0x93,72,116, 0,58,
0x80, 0x81, 0x82, 0x83, 0,41, 0x90,53,92, 0x91,57,94, 0x92,41,88, 0x93,72,121, 0x94,72,121,
0x95,53,122, 0x96,57,124, 0x97,41,118, 0x98,72,121, 0x99,72,121, 0,54, 0x80, 0x85, 0,8,
0x81, 0x86, 0,8, 0x82, 0x87, 0,8, 0x83, 0x84, 0x88, 0x89, 0,125, 0x90,72,116, 0x91,72,116, 0x92,72,116,
0x93,72,116, 0,41, 0x80, 0x81, 0x82, 0x83, 0,58, 0x90,72,112, 0x91,72,112, 0x92,72,112, 0x93,72,112,
0,70, 0x80, 0x81, 0x82, 0x83, 0,33, 0x90,53,90, 0x91,57,90, 0x92,41,91, 0x93,77,123, 0x94,77,123,
0x95,53,120, 0x96,57,120, 0x97,41,121, 0x98,77,123, 0x99,77,123, 0,50, 0x80, 0x85, 0,12,
0x81, 0x86, 0x82, 0x87, 0,25, 0x83, 0x84, 0x88, 0x89, 0,112, 0x90,53,83, 0x91,41,94, 0x92,57,86,
0x93,79,115, 0x94,79,115, 0x95,53,113, 0x96,41,124, 0x97,57,116, 0x98,79,115, 0x99,79,115,
0,50, 0x80, 0x85, 0,4, 0x81, 0x86, 0,12, 0x82, 0x87, 0,16, 0x83, 0x84, 0x88, 0x89, 0,120, 0x90,53,93,
0x91,41,91, 0x92,57,92, 0x93,81,122, 0x94,81,122, 0x95,53,123, 0x96,41,121, 0x97,57,122,
0x98,81,122, 0x99,81,122, 0,58, 0x80, 0x85, 0x81, 0x86, 0,4, 0x82, 0x87, 0,4, 0x83, 0x84, 0x88,
0x89, 0,133, 0x90,77,105, 0x91,77,105, 0x92,77,105, 0x93,77,105, 0,91, 0x80, 0x81, 0x82, 0x83,
0,12, 0x90,81,121, 0x91,81,121, 0x92,81,121, 0x93,81,121, 0,75, 0x80, 0x81, 0x82, 0x83, 0,25,
0x90,36,97, 0x91,84,105, 0x92,84,105, 0x93,36,127, 0x94,84,105, 0x95,84,105, 0,108, 0x80,
0x83, 0,95, 0x90,52,80, 0x93,60,91, 0x96,58,83, 0x97,52,110, 0x98,60,121, 0x99,58,113,
0,33, 0x80, 0x87, 0,8, 0x83, 0x88, 0,12, 0x86, 0x89, 0,45, 0x90,52,82, 0x93,60,90, 0x96,58,77,
0x97,52,112, 0x98,60,120, 0x99,58,107, 0,33, 0x80, 0x87, 0,8, 0x83, 0x88, 0,8, 0x86, 0x89,
0,50, 0x90,52,91, 0x93,58,73, 0x96,60,83, 0x97,36,97, 0x98,52,121, 0x99,58,103, 0x9A,60,113,
0x9B,36,127, 0,62, 0x80, 0x88, 0,16, 0x83, 0x89, 0x86, 0x8A, 0,25, 0x90,82,105, 0x93,82,105,
0x96,82,105, 0x98,82,105, 0,12, 0x87, 0x8B, 0,41, 0x81, 0x82, 0x84, 0x85, 0,29, 0x80, 0x83, 0x86,
0x88, 0,16, 0x90,81,107, 0x91,81,107, 0x92,81,107, 0x93,81,107, 0,104, 0x94,79,118, 0x95,79,118,
0x96,79,118, 0x97,79,118, 0,16, 0x80, 0x81, 0x82, 0x83, 0,75, 0x84, 0x85, 0x86, 0x87, 0,8, 0x90,53,86,
0x91,41,78, 0x92,57,92, 0x93,77,116, 0x94,77,116, 0x95,53,116, 0x96,41,108, 0x97,57,122,
0x98,77,116, 0x99,77,116, 0,66, 0x80, 0x85, 0x81, 0x86, 0,8, 0x82, 0x87, 0,70, 0x83, 0x84, 0x88,
0x89, 0,54, 0x90,60,92, 0x91,41,92, 0x92,81,124, 0x93,81,124, 0x94,60,122, 0x95,41,122,
0x96,81,124, 0x97,81,124, 0,54, 0x80, 0x84, 0,16, 0x81, 0x85, 0,133, 0x90,41,97, 0x91,53,91,
0x94,57,94, 0x95,77,113, 0x98,77,113, 0x99,41,127, 0x9A,53,121, 0x9B,57,124, 0x9C,77,113,
0x9D,77,113, 0,8, 0x82, 0x83, 0x86, 0x87, 0,79, 0x85, 0x88, 0x8C, 0x8D, 0,4, 0x80, 0x89, 0x81, 0x8A,
0,8, 0x84, 0x8B, 0,104, 0x90,72,124, 0x91,72,124, 0x92,72,124, 0x93,72,124, 0,66, 0x80,
0x81, 0x82, 0x83, 0,33, 0x90,76,124, 0x91,76,124, 0x92,76,124, 0x93,76,124, 0,66, 0x80, 0x81,
0x82, 0x83, 0,33, 0x90,53,93, 0x91,57,92, 0x92,60,92, 0x93,41,94, 0x94,77,127, 0x95,77,127,
0x96,53,123, 0x97,57,122, 0x98,60,122, 0x99,41,124, 0x9A,77,127, 0x9B,77,127, 0,62, 0x80,
0x86, 0,16, 0x81, 0x87, 0,4, 0x82, 0x88, 0,12, 0x84, 0x85, 0x8A, 0x8B, 0,108, 0x90,53,85, 0x91,57,91,
0x92,60,68, 0x94,77,123, 0x95,77,123, 0x96,53,115, 0x97,57,121, 0x98,60,98, 0x9A,77,123,
0x9B,77,123, 0,50, 0x80, 0x86, 0,8, 0x84, 0x85, 0x8A, 0x8B, 0,4, 0x81, 0x87, 0x82, 0x88, 0,25,
0x83, 0x89, 0,12, 0x90,77,124, 0x91,77,124, 0x92,77,124, 0x93,77,124, 0,50, 0x80, 0x81, 0x82,
0x83, 0,54, 0x90,53,78, 0x91,57,86, 0x92,60,80, 0x93,41,92, 0x94,77,127, 0x95,77,127,
0x96,53,108, 0x97,57,116, 0x98,60,110, 0x99,41,122, 0x9A,77,127, 0x9B,77,127, 0,58, 0x80,
0x86, 0,8, 0x81, 0x87, 0,8, 0x82, 0x88, 0x84, 0x85, 0x8A, 0x8B, 0,125, 0x90,53,97, 0x91,60,93,
0x92,57,90, 0x94,77,127, 0x95,77,127, 0x96,53,127, 0x97,60,123, 0x98,57,120, 0x9A,77,127,
0x9B,77,127, 0,58, 0x84, 0x85, 0x8A, 0x8B, 0,16, 0x80, 0x86, 0,12, 0x81, 0x87, 0x83, 0x89, 0,4,
0x82, 0x88, 0,112, 0x90,53,97, 0x91,61,92, 0x92,57,93, 0x93,41,94, 0x94,81,124, 0x95,73,118,
0x96,81,124, 0x97,73,118, 0x98,53,127, 0x99,61,122, 0x9A,57,123, 0x9B,41,124, 0x9C,81,124,
0x9D,73,118, 0x9E,81,124, 0x9F,73,118, 0,87, 0x80, 0x88, 0,12, 0x81, 0x89, 0,16, 0x82, 0x8A,
0,87, 0x90,53,87, 0x91,57,92, 0x92,61,85, 0x98,53,117, 0x99,57,122, 0x9A,61,115, 0,45,
0x80, 0x88, 0,20, 0x81, 0x89, 0,4, 0x82, 0x8A, 0,8, 0x83, 0x8B, 0,120, 0x90,53,92, 0x91,57,93,
0x92,61,90, 0x93,41,94, 0x98,53,122, 0x99,57,123, 0x9A,61,120, 0x9B,41,124, 0,50, 0x80,
0x88, 0,20, 0x81, 0x89, 0,4, 0x82, 0x8A, 0,62, 0x84, 0x86, 0x8C, 0x8E, 0,66, 0x90,53,93, 0x91,57,97,
0x92,61,92, 0x94,79,118, 0x96,79,118, 0x98,53,123, 0x99,57,127, 0x9A,61,122, 0x9C,79,118,
0x9E,79,118, 0,20, 0x85, 0x87, 0x8D, 0x8F, 0,29, 0x84, 0x86, 0x8C, 0x8E, 0,4, 0x80, 0x88, 0,4,
0x83, 0x8B, 0,4, 0x81, 0x89, 0,8, 0x82, 0x8A, 0,133, 0x90,57,97, 0x91,53,97, 0x92,62,96,
0x93,41,97, 0x94,77,124, 0x95,69,105, 0x96,77,124, 0x97,69,105, 0x98,57,127, 0x99,53,127,
0x9A,62,126, 0x9B,41,127, 0x9C,77,124, 0x9D,69,105, 0x9E,77,124, 0x9F,69,105, 0x80, 0x88, 0,100,
0x81, 0x89, 0,8, 0x82, 0x8A, 0,91, 0x90,53,94, 0x91,61,92, 0x92,76,122, 0x98,76,122, 0x99,53,124,
0x9A,61,122, 0,37, 0x84, 0x86, 0x8C, 0x8E, 0,29, 0x80, 0x89, 0,16, 0x81, 0x8A, 0,8, 0x83, 0x8B,
0,112, 0x90,53,91, 0x91,62,97, 0x93,41,97, 0x94,77,121, 0x96,77,121, 0x99,53,121, 0x9A,62,127,
0x9B,41,127, 0x9C,77,121, 0x9E,77,121, 0,4, 0x82, 0x88, 0,58, 0x80, 0x89, 0,33, 0x81, 0x8A,
0,108, 0x90,53,87, 0x91,58,86, 0x92,74,123, 0x98,74,123, 0x99,53,117, 0x9A,58,116, 0,16,
0x85, 0x87, 0x8D, 0x8F, 0,37, 0x84, 0x86, 0x8C, 0x8E, 0,8, 0x82, 0x88, 0,8, 0x80, 0x89, 0,16, 0x81,
0x8A, 0,20, 0x83, 0x8B, 0,91, 0x90,53,96, 0x91,57,97, 0x92,41,97, 0x93,72,118, 0x94,72,118,
0x95,53,126, 0x96,57,127, 0x97,41,127, 0x98,72,118, 0x99,72,118, 0,45, 0x83, 0x84, 0x88, 0x89,
0,54, 0x93,74,118, 0x94,74,118, 0x98,74,118, 0x99,74,118, 0,41, 0x83, 0x84, 0x88, 0x89, 0,62,
0x93,72,116, 0x94,72,116, 0x98,72,116, 0x99,72,116, 0,16, 0x80, 0x85, 0,12, 0x81, 0x86, 0,16,
0x82, 0x87, 0x83, 0x84, 0x88, 0x89, 0,54, 0x90,74,121, 0x91,74,121, 0x92,74,121, 0x93,74,121, 0,54,
0x80, 0x81, 0x82, 0x83, 0,50, 0x90,41,97, 0x91,57,97, 0x92,53,91, 0x93,72,113, 0x94,72,113,
0x95,41,127, 0x96,57,127, 0x97,53,121, 0x98,72,113, 0x99,72,113, 0,41, 0x83, 0x84, 0x88, 0x89,
0,58, 0x93,74,110, 0x94,74,110, 0x98,74,110, 0x99,74,110, 0,50, 0x83, 0x84, 0x88, 0x89, 0,20,
0x80, 0x85, 0,29, 0x90,76,124, 0x93,76,124, 0x94,76,124, 0x95,76,124, 0,8, 0x81, 0x86, 0,4,
0x82, 0x87, 0,41, 0x80, 0x83, 0x84, 0x85, 0,45, 0x90,77,118, 0x91,77,118, 0x92,77,118, 0x93,77,118,
0,37, 0x80, 0x81, 0x82, 0x83, 0,66, 0x90,52,91, 0x91,55,97, 0x92,36,92, 0x93,70,127, 0x94,70,127,
0x95,52,121, 0x96,55,127, 0x97,36,122, 0x98,70,127, 0x99,70,127, 0,62, 0x83, 0x84, 0x88, 0x89,
0,29, 0x80, 0x85, 0,8, 0x90,72,110, 0x93,72,110, 0x94,72,110, 0x95,72,110, 0,12, 0x81,
0x86, 0,29, 0x80, 0x83, 0x84, 0x85, 0,12, 0x82, 0x87, 0,50, 0x90,70,113, 0x91,70,113, 0x92,70,113,
0x93,70,113, 0,54, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,72,118, 0x91,72,118, 0x92,72,118, 0x93,72,118,
0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,52,96, 0x91,36,97, 0x92,55,97, 0x93,70,122, 0x94,70,122,
0x95,52,126, 0x96,36,127, 0x97,55,127, 0x98,70,122, 0x99,70,122, 0,62, 0x83, 0x84, 0x88, 0x89,
0,25, 0x80, 0x85, 0,12, 0x81, 0x86, 0x82, 0x87, 0x90,72,124, 0x91,72,124, 0x92,72,124, 0x93,72,124,
0,54, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,74,122, 0x91,74,122, 0x92,74,122, 0x93,74,122, 0,54,
0x80, 0x81, 0x82, 0x83, 0,45, 0x90,76,124, 0x91,76,124, 0x92,76,124, 0x93,76,124, 0,54, 0x80,
0x81, 0x82, 0x83, 0,45, 0x90,53,92, 0x91,57,96, 0x92,41,92, 0x93,69,116, 0x94,69,116, 0x95,53,122,
0x96,57,126, 0x97,41,122, 0x98,69,116, 0x99,69,116, 0,91, 0x83, 0x84, 0x88, 0x89, 0,12, 0x93,70,107,
0x94,70,107, 0x98,70,107, 0x99,70,107, 0,8, 0x80, 0x85, 0,4, 0x81, 0x86, 0,25, 0x82, 0x87,
0,62, 0x83, 0x84, 0x88, 0x89, 0x90,69,116, 0x91,69,116, 0x92,69,116, 0x93,69,116, 0,100, 0x94,70,113,
0x95,70,113, 0x96,70,113, 0x97,70,113, 0,29, 0x80, 0x81, 0x82, 0x83, 0,75, 0x90,57,94, 0x91,41,97,
0x92,53,75, 0x93,69,116, 0x98,69,116, 0x99,57,124, 0x9A,41,127, 0x9B,53,105, 0x9C,69,116,
0x9D,69,116, 0,16, 0x84, 0x85, 0x86, 0x87, 0,79, 0x80, 0x89, 0,4, 0x90,70,121, 0x94,70,121,
0x95,70,121, 0x96,70,121, 0,12, 0x81, 0x8A, 0,4, 0x82, 0x8B, 0x83, 0x88, 0x8C, 0x8D, 0,79, 0x80,
0x84, 0x85, 0x86, 0,4, 0x90,72,113, 0x91,72,113, 0x92,72,113, 0x93,72,113, 0,104, 0x94,74,118,
0x95,74,118, 0x96,74,118, 0x97,74,118, 0,8, 0x80, 0x81, 0x82, 0x83, 0,58, 0x84, 0x85, 0x86, 0x87,
0,33, 0x90,55,97, 0x91,50,93, 0x92,46,92, 0x93,67,121, 0x94,67,121, 0x95,55,127, 0x96,50,123,
0x97,46,122, 0x98,67,121, 0x99,67,121, 0,100, 0x9A,69,124, 0x9B,69,124, 0x9C,69,124, 0x9D,69,124,
0,4, 0x80, 0x85, 0,12, 0x81, 0x86, 0x82, 0x87, 0,4, 0x83, 0x84, 0x88, 0x89, 0,83, 0x90,67,112,
0x91,67,112, 0x92,67,112, 0x93,67,112, 0,4, 0x8A, 0x8B, 0x8C, 0x8D, 0,91, 0x80, 0x81, 0x82, 0x83,
0,4, 0x90,69,124, 0x91,69,124, 0x92,69,124, 0x93,69,124, 0,100, 0x94,46,96, 0x95,50,97,
0x96,55,97, 0x97,67,113, 0x98,67,113, 0x99,46,126, 0x9A,50,127, 0x9B,55,127, 0x9C,67,113,
0x9D,67,113, 0,4, 0x80, 0x81, 0x82, 0x83, 0,100, 0x87, 0x88, 0x8C, 0x8D, 0x90,69,121, 0x91,69,121,
0x92,69,121, 0x93,69,121, 0,29, 0x84, 0x89, 0,8, 0x85, 0x8A, 0,16, 0x86, 0x8B, 0,45, 0x94,67,112,
0x95,67,112, 0x96,67,112, 0x97,67,112, 0,8, 0x80, 0x81, 0x82, 0x83, 0,91, 0x84, 0x85, 0x86, 0x87,
0x90,69,116, 0x91,69,116, 0x92,69,116, 0x93,69,116, 0,100, 0x80, 0x81, 0x82, 0x83, 0x90,48,90,
0x91,55,93, 0x92,52,92, 0x93,67,110, 0x94,67,110, 0x95,48,120, 0x96,55,123, 0x97,52,122,
0x98,67,110, 0x99,67,110, 0,104, 0x9A,69,122, 0x9B,69,122, 0x9C,69,122, 0x9D,69,122, 0,4,
0x83, 0x84, 0x88, 0x89, 0,25, 0x80, 0x85, 0,8, 0x81, 0x86, 0,8, 0x82, 0x87, 0,37, 0x8A, 0x8B, 0x8C,
0x8D, 0,16, 0x90,67,102, 0x91,67,102, 0x92,67,102, 0x93,67,102, 0,104, 0x94,69,120, 0x95,69,120,
0x96,69,120, 0x97,69,120, 0,8, 0x80, 0x81, 0x82, 0x83, 0,91, 0x90,67,116, 0x91,67,116, 0x92,67,116,
0x93,67,116, 0,4, 0x84, 0x85, 0x86, 0x87, 0,91, 0x80, 0x81, 0x82, 0x83, 0,4, 0x90,72,121, 0x91,72,121,
0x92,72,121, 0x93,72,121, 0,91, 0x80, 0x81, 0x82, 0x83, 0,8, 0x90,74,112, 0x91,74,112, 0x92,74,112,
0x93,74,112, 0,91, 0x80, 0x81, 0x82, 0x83, 0,12, 0x90,76,120, 0x91,76,120, 0x92,76,120, 0x93,76,120,
0,75, 0x80, 0x81, 0x82, 0x83, 0,25, 0x90,53,93, 0x91,57,92, 0x92,60,92, 0x93,41,94, 0x94,77,127,
0x95,77,127, 0x96,53,123, 0x97,57,122, 0x98,60,122, 0x99,41,124, 0x9A,77,127, 0x9B,77,127,
0,58, 0x80, 0x86, 0,12, 0x84, 0x85, 0x8A, 0x8B, 0,8, 0x81, 0x87, 0x82, 0x88, 0,125, 0x90,53,85,
0x91,57,91, 0x92,60,68, 0x94,77,121, 0x95,77,121, 0x96,53,115, 0x97,57,121, 0x98,60,98,
0x9A,77,121, 0x9B,77,121, 0,50, 0x80, 0x86, 0,4, 0x84, 0x85, 0x8A, 0x8B, 0,4, 0x81, 0x87, 0,4,
0x82, 0x88, 0,25, 0x83, 0x89, 0,12, 0x90,77,124, 0x91,77,124, 0x92,77,124, 0x93,77,124, 0,50,
0x80, 0x81, 0x82, 0x83, 0,50, 0x90,53,78, 0x91,57,86, 0x92,60,80, 0x93,41,92, 0x94,77,124,
0x95,77,124, 0x96,53,108, 0x97,57,116, 0x98,60,110, 0x99,41,122, 0x9A,77,124, 0x9B,77,124,
0,58, 0x80, 0x86, 0,12, 0x81, 0x87, 0x84, 0x85, 0x8A, 0x8B, 0,8, 0x82, 0x88, 0,125, 0x90,53,97,
0x91,60,93, 0x92,57,90, 0x94,77,127, 0x95,77,127, 0x96,53,127, 0x97,60,123, 0x98,57,120,
0x9A,77,127, 0x9B,77,127, 0,58, 0x84, 0x85, 0x8A, 0x8B, 0,12, 0x80, 0x86, 0,12, 0x81, 0x87, 0,4,
0x83, 0x89, 0,4, 0x82, 0x88, 0,112, 0x90,53,97, 0x91,61,92, 0x92,57,93, 0x93,41,94, 0x94,81,127,
0x95,73,112, 0x96,81,127, 0x97,73,112, 0x98,53,127, 0x99,61,122, 0x9A,57,123, 0x9B,41,124,
0x9C,81,127, 0x9D,73,112, 0x9E,81,127, 0x9F,73,112, 0,83, 0x80, 0x88, 0,16, 0x81, 0x89, 0,16,
0x82, 0x8A, 0,83, 0x90,53,87, 0x91,57,92, 0x92,61,85, 0x98,53,117, 0x99,57,122, 0x9A,61,115,
0,50, 0x80, 0x88, 0,20, 0x81, 0x89, 0,4, 0x82, 0x8A, 0,8, 0x83, 0x8B, 0,120, 0x90,53,92,
0x91,57,93, 0x92,61,90, 0x93,41,94, 0x98,53,122, 0x99,57,123, 0x9A,61,120, 0x9B,41,124,
0,50, 0x80, 0x88, 0,20, 0x81, 0x89, 0x82, 0x8A, 0,125, 0x84, 0x86, 0x8C, 0x8E, 0,8, 0x90,53,93,
0x91,57,97, 0x92,61,92, 0x94,79,91, 0x96,79,91, 0x98,53,123, 0x99,57,127, 0x9A,61,122,
0x9C,79,91, 0x9E,79,91, 0,16, 0x85, 0x87, 0x8D, 0x8F, 0,37, 0x80, 0x88, 0x83, 0x8B, 0,4, 0x81,
0x89, 0,8, 0x84, 0x86, 0x8C, 0x8E, 0,4, 0x82, 0x8A, 0,129, 0x90,57,97, 0x91,53,97, 0x92,62,96,
0x93,41,97, 0x94,77,124, 0x95,69,116, 0x96,77,124, 0x97,69,116, 0x98,57,127, 0x99,53,127,
0x9A,62,126, 0x9B,41,127, 0x9C,77,124, 0x9D,69,116, 0x9E,77,124, 0x9F,69,116, 0,4, 0x80,
0x88, 0,100, 0x81, 0x89, 0,8, 0x82, 0x8A, 0,91, 0x90,53,94, 0x91,61,92, 0x92,76,116, 0x98,76,116,
0x99,53,124, 0x9A,61,122, 0,8, 0x84, 0x86, 0x8C, 0x8E, 0,58, 0x80, 0x89, 0,12, 0x81, 0x8A, 0,12,
0x83, 0x8B, 0,87, 0x82, 0x88, 0,25, 0x90,53,91, 0x91,62,97, 0x92,41,97, 0x93,77,115, 0x94,77,115,
0x96,53,121, 0x98,62,127, 0x99,41,127, 0x9A,77,115, 0x9B,77,115, 0,58, 0x80, 0x86, 0,37,
0x81, 0x88, 0,95, 0x83, 0x84, 0x8A, 0x8B, 0,8, 0x90,53,87, 0x91,58,86, 0x93,74,116, 0x94,74,116,
0x96,53,117, 0x98,58,116, 0x9A,74,116, 0x9B,74,116, 0,33, 0x85, 0x87, 0x8D, 0x8F, 0,41, 0x80,
0x86, 0,16, 0x81, 0x88, 0,20, 0x82, 0x89, 0,54, 0x83, 0x84, 0x8A, 0x8B, 0,37, 0x90,53,96, 0x91,57,97,
0x92,41,97, 0x93,72,118, 0x94,72,118, 0x95,53,126, 0x96,57,127, 0x97,41,127, 0x98,72,118,
0x99,72,118, 0,54, 0x83, 0x84, 0x88, 0x89, 0,45, 0x93,74,124, 0x94,74,124, 0x98,74,124, 0x99,74,124,
0,41, 0x83, 0x84, 0x88, 0x89, 0,62, 0x93,72,113, 0x94,72,113, 0x98,72,113, 0x99,72,113, 0,16,
0x80, 0x85, 0,12, 0x81, 0x86, 0,12, 0x83, 0x84, 0x88, 0x89, 0,4, 0x82, 0x87, 0,54, 0x90,74,112,
0x91,74,112, 0x92,74,112, 0x93,74,112, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,41,97, 0x91,57,97,
0x92,53,91, 0x93,72,115, 0x94,72,115, 0x95,41,127, 0x96,57,127, 0x97,53,121, 0x98,72,115,
0x99,72,115, 0,50, 0x83, 0x84, 0x88, 0x89, 0,50, 0x93,74,121, 0x94,74,121, 0x98,74,121, 0x99,74,121,
0,54, 0x83, 0x84, 0x88, 0x89, 0,20, 0x80, 0x85, 0,29, 0x90,76,122, 0x93,76,122, 0x94,76,122,
0x95,76,122, 0,8, 0x81, 0x86, 0,4, 0x82, 0x87, 0,41, 0x80, 0x83, 0x84, 0x85, 0,45, 0x90,77,124,
0x91,77,124, 0x92,77,124, 0x93,77,124, 0,41, 0x80, 0x81, 0x82, 0x83, 0,62, 0x90,52,91, 0x91,55,97,
0x92,36,92, 0x93,70,113, 0x94,70,113, 0x95,52,121, 0x96,55,127, 0x97,36,122, 0x98,70,113,
0x99,70,113, 0,45, 0x83, 0x84, 0x88, 0x89, 0,45, 0x80, 0x85, 0,8, 0x90,72,116, 0x93,72,116,
0x94,72,116, 0x95,72,116, 0,12, 0x81, 0x86, 0,37, 0x82, 0x87, 0,8, 0x80, 0x83, 0x84, 0x85, 0,41,
0x90,70,111, 0x91,70,111, 0x92,70,111, 0x93,70,111, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,72,124,
0x91,72,124, 0x92,72,124, 0x93,72,124, 0,58, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,52,96, 0x91,36,97,
0x92,55,97, 0x93,70,111, 0x94,70,111, 0x95,52,126, 0x96,36,127, 0x97,55,127, 0x98,70,111,
0x99,70,111, 0,62, 0x83, 0x84, 0x88, 0x89, 0,25, 0x80, 0x85, 0,8, 0x81, 0x86, 0,4, 0x82, 0x87,
0x90,72,121, 0x91,72,121, 0x92,72,121, 0x93,72,121, 0,58, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,74,110,
0x91,74,110, 0x92,74,110, 0x93,74,110, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,76,116, 0x91,76,116,
0x92,76,116, 0x93,76,116, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,53,92, 0x91,57,96, 0x92,41,92,
0x93,69,107, 0x94,69,107, 0x95,53,122, 0x96,57,126, 0x97,41,122, 0x98,69,107, 0x99,69,107,
0,62, 0x83, 0x84, 0x88, 0x89, 0,37, 0x93,70,112, 0x94,70,112, 0x98,70,112, 0x99,70,112, 0,8,
0x80, 0x85, 0,8, 0x81, 0x86, 0,25, 0x82, 0x87, 0,20, 0x83, 0x84, 0x88, 0x89, 0,41, 0x90,69,110,
0x91,69,110, 0x92,69,110, 0x93,69,110, 0,54, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,70,107, 0x91,70,107,
0x92,70,107, 0x93,70,107, 0,62, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,57,94, 0x91,41,97, 0x92,53,75,
0x93,69,110, 0x94,69,110, 0x95,57,124, 0x96,41,127, 0x97,53,105, 0x98,69,110, 0x99,69,110,
0,66, 0x83, 0x84, 0x88, 0x89, 0,25, 0x80, 0x85, 0,8, 0x90,70,110, 0x93,70,110, 0x94,70,110,
0x95,70,110, 0,12, 0x81, 0x86, 0,4, 0x82, 0x87, 0,50, 0x80, 0x83, 0x84, 0x85, 0,33, 0x90,72,116,
0x91,72,116, 0x92,72,116, 0x93,72,116, 0,62, 0x80, 0x81, 0x82, 0x83, 0,37, 0x90,74,113, 0x91,74,113,
0x92,74,113, 0x93,74,113, 0,41, 0x80, 0x81, 0x82, 0x83, 0,62, 0x90,55,97, 0x91,50,93, 0x92,46,92,
0x93,67,113, 0x94,67,113, 0x95,55,127, 0x96,50,123, 0x97,46,122, 0x98,67,113, 0x99,67,113,
0,62, 0x83, 0x84, 0x88, 0x89, 0,37, 0x93,69,116, 0x94,69,116, 0x98,69,116, 0x99,69,116, 0,4,
0x80, 0x85, 0,12, 0x81, 0x86, 0x82, 0x87, 0,41, 0x83, 0x84, 0x88, 0x89, 0,41, 0x90,67,110, 0x91,67,110,
0x92,67,110, 0x93,67,110, 0,58, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,69,113, 0x91,69,113, 0x92,69,113,
0x93,69,113, 0,58, 0x80, 0x81, 0x82, 0x83, 0,41, 0x90,48,90, 0x91,55,93, 0x92,52,92, 0x93,67,113,
0x94,67,113, 0x95,48,120, 0x96,55,123, 0x97,52,122, 0x98,67,113, 0x99,67,113, 0,62, 0x83,
0x84, 0x88, 0x89, 0,37, 0x93,70,118, 0x94,70,118, 0x98,70,118, 0x99,70,118, 0,33, 0x80, 0x85,
0,8, 0x81, 0x86, 0,4, 0x82, 0x87, 0,37, 0x83, 0x84, 0x88, 0x89, 0,20, 0x90,69,103, 0x91,69,103,
0x92,69,103, 0x93,69,103, 0,87, 0x80, 0x81, 0x82, 0x83, 0,12, 0x90,67,118, 0x91,67,118, 0x92,67,118,
0x93,67,118, 0,83, 0x80, 0x81, 0x82, 0x83, 0,16, 0x90,57,94, 0x91,53,94, 0x92,41,94, 0x93,65,113,
0x94,65,113, 0x95,57,124, 0x96,53,124, 0x97,41,124, 0x98,65,113, 0x99,65,113, 0,104, 0x9A,64,118,
0x9B,64,118, 0x9C,64,118, 0x9D,64,118, 0,29, 0x83, 0x84, 0x88, 0x89, 0,70, 0x93,65,123, 0x94,65,123,
0x98,65,123, 0x99,65,123, 0,8, 0x8A, 0x8B, 0x8C, 0x8D, 0,91, 0x9A,64,123, 0x9B,64,123, 0x9C,64,123,
0x9D,64,123, 0,8, 0x83, 0x84, 0x88, 0x89, 0,87, 0x8A, 0x8B, 0x8C, 0x8D, 0,8, 0x93,65,127, 0x94,65,127,
0x98,65,127, 0x99,65,127, 0,66, 0x83, 0x84, 0x88, 0x89, 0,133, 0x80, 0x85, 0x81, 0x86, 0x82, 0x87, 0x90,72,113,
0x91,72,113, 0x92,72,113, 0x93,72,113, 0,45, 0x80, 0x81, 0x82, 0x83, 0,58, 0x90,72,115, 0x91,72,115,
0x92,72,115, 0x93,72,115, 0,37, 0x80, 0x81, 0x82, 0x83, 0,62, 0x90,72,123, 0x91,72,123, 0x92,72,123,
0x93,72,123, 0,79, 0x80, 0x81, 0x82, 0x83, 0,120, 0x90,72,122, 0x91,72,122, 0x92,72,122, 0x93,72,122,
0,54, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,72,118, 0x91,72,118, 0x92,72,118, 0x93,72,118, 0,58,
0x80, 0x81, 0x82, 0x83, 0,41, 0x90,72,121, 0x91,72,121, 0x92,72,121, 0x93,72,121, 0,70, 0x80,
0x81, 0x82, 0x83, 0,133, 0x90,72,118, 0x91,72,118, 0x92,72,118, 0x93,72,118, 0,54, 0x80, 0x81,
0x82, 0x83, 0,45, 0x90,72,122, 0x91,72,122, 0x92,72,122, 0x93,72,122, 0,41, 0x80, 0x81, 0x82,
0x83, 0,58, 0x90,53,94, 0x91,65,116, 0x92,77,120, 0x93,65,116, 0x94,77,120, 0x95,53,124,
0x96,65,116, 0x97,77,120, 0x98,65,116, 0x99,77,120, 0,50, 0x81, 0x83, 0x86, 0x88, 0,4, 0x82,
0x84, 0x87, 0x89, 0,12, 0x80, 0x85, 0,137, 0x90,55,97, 0x91,67,122, 0x92,79,126, 0x93,67,122,
0x94,79,126, 0x95,55,127, 0x96,67,122, 0x97,79,126, 0x98,67,122, 0x99,79,126, 0,50, 0x81,
0x83, 0x86, 0x88, 0,4, 0x82, 0x84, 0x87, 0x89, 0,8, 0x80, 0x85, 0,141, 0x90,57,97, 0x91,81,126,
0x92,69,124, 0x93,81,126, 0x94,69,124, 0x95,57,127, 0x96,81,126, 0x97,69,124, 0x98,81,126,
0x99,69,124, 0,100, 0x81, 0x83, 0x86, 0x88, 0,25, 0x82, 0x84, 0x87, 0x89, 0,75, 0x91,72,124, 0x92,72,124,
0x93,72,124, 0x94,72,124, 0,4, 0x80, 0x85, 0,66, 0x81, 0x82, 0x83, 0x84, 0,33, 0x90,72,124,
0x91,72,124, 0x92,72,124, 0x93,72,124, 0,66, 0x80, 0x81, 0x82, 0x83, 0,33, 0x90,72,124, 0x91,72,124,
0x92,72,124, 0x93,72,124, 0,104, 0x80, 0x81, 0x82, 0x83, 0,100, 0x90,72,116, 0x91,72,116, 0x92,72,116,
0x93,72,116, 0,37, 0x80, 0x81, 0x82, 0x83, 0,62, 0x90,72,103, 0x91,72,103, 0x92,72,103, 0x93,72,103,
0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,72,123, 0x91,72,123, 0x92,72,123, 0x93,72,123, 0,62,
0x80, 0x81, 0x82, 0x83, 0,141, 0x90,72,116, 0x91,72,116, 0x92,72,116, 0x93,72,116, 0,41, 0x80,
0x81, 0x82, 0x83, 0,58, 0x90,72,78, 0x91,72,78, 0x92,72,78, 0x93,72,78, 0,20, 0x80, 0x81,
0x82, 0x83, 0,83, 0x90,57,97, 0x91,69,127, 0x92,81,122, 0x93,69,127, 0x94,81,122, 0x95,57,127,
0x96,69,127, 0x97,81,122, 0x98,69,127, 0x99,81,122, 0,54, 0x81, 0x83, 0x86, 0x88, 0x82, 0x84, 0x87,
0x89, 0,20, 0x80, 0x85, 0,125, 0x90,58,97, 0x91,70,118, 0x92,82,124, 0x93,70,118, 0x94,82,124,
0x95,58,127, 0x96,70,118, 0x97,82,124, 0x98,70,118, 0x99,82,124, 0,50, 0x81, 0x83, 0x86, 0x88,
0,20, 0x82, 0x84, 0x87, 0x89, 0,4, 0x80, 0x85, 0,129, 0x90,60,97, 0x91,72,127, 0x92,84,127,
0x93,72,127, 0x94,84,127, 0x95,60,127, 0x96,72,127, 0x97,84,127, 0x98,72,127, 0x99,84,127,
0,204, 0x80, 0x85, 0,4, 0x81, 0x83, 0x86, 0x88, 0,29, 0x82, 0x84, 0x87, 0x89, 0,166, 0x90,53,97,
0x91,77,122, 0x92,65,127, 0x93,77,122, 0x94,65,127, 0x95,53,127, 0x96,77,122, 0x97,65,127,
0x98,77,122, 0x99,65,127, 0,58, 0x81, 0x83, 0x86, 0x88, 0,8, 0x80, 0x85, 0,4, 0x82, 0x84, 0x87,
0x89, 0,133, 0x90,55,97, 0x91,67,127, 0x92,79,127, 0x93,67,127, 0x94,79,127, 0x95,55,127,
0x96,67,127, 0x97,79,127, 0x98,67,127, 0x99,79,127, 0,50, 0x81, 0x83, 0x86, 0x88, 0,8, 0x82,
0x84, 0x87, 0x89, 0x80, 0x85, 0,145, 0x90,57,97, 0x91,69,127, 0x92,81,127, 0x93,69,127, 0x94,81,127,
0x95,57,127, 0x96,69,127, 0x97,81,127, 0x98,69,127, 0x99,81,127, 0,216, 0x81, 0x83, 0x86, 0x88,
0,8, 0x80, 0x85, 0x82, 0x84, 0x87, 0x89, 0,179, 0x90,45,97, 0x91,57,124, 0x92,69,127, 0x93,57,124,
0x94,69,127, 0x95,45,127, 0x96,57,124, 0x97,69,127, 0x98,57,124, 0x99,69,127, 0,54, 0x81,
0x83, 0x86, 0x88, 0,12, 0x82, 0x84, 0x87, 0x89, 0,4, 0x80, 0x85, 0,133, 0x90,46,97, 0x91,58,124,
0x92,70,127, 0x93,58,124, 0x94,70,127, 0x95,46,127, 0x96,58,124, 0x97,70,127, 0x98,58,124,
0x99,70,127, 0,54, 0x81, 0x83, 0x86, 0x88, 0,12, 0x80, 0x85, 0,4, 0x82, 0x84, 0x87, 0x89, 0,129,
0x90,48,94, 0x91,60,127, 0x92,72,127, 0x93,60,127, 0x94,72,127, 0x95,48,124, 0x96,60,127,
0x97,72,127, 0x98,60,127, 0x99,72,127, 0,204, 0x80, 0x85, 0,20, 0x81, 0x83, 0x86, 0x88, 0,8,
0x82, 0x84, 0x87, 0x89, 0,175, 0x90,53,68, 0x91,41,86, 0x92,65,93, 0x93,77,127, 0x94,77,127,
0x95,53,98, 0x96,41,116, 0x97,65,123, 0x98,77,127, 0x99,77,127, 0,54, 0x83, 0x84, 0x88, 0x89,
0,16, 0x80, 0x85, 0,12, 0x81, 0x86, 0,8, 0x82, 0x87, 0,108, 0x90,53,71, 0x91,41,86, 0x92,65,97,
0x93,77,121, 0x94,77,121, 0x95,53,101, 0x96,41,116, 0x97,65,127, 0x98,77,121, 0x99,77,121,
0,45, 0x83, 0x84, 0x88, 0x89, 0,12, 0x80, 0x85, 0,4, 0x81, 0x86, 0,12, 0x82, 0x87, 0,25, 0x90,77,124,
0x91,77,124, 0x92,77,124, 0x93,77,124, 0,50, 0x80, 0x81, 0x82, 0x83, 0,54, 0x90,53,85, 0x91,65,97,
0x92,41,93, 0x93,77,123, 0x94,77,123, 0x95,53,115, 0x96,65,127, 0x97,41,123, 0x98,77,123,
0x99,77,123, 0,66, 0x80, 0x85, 0,4, 0x81, 0x86, 0,8, 0x82, 0x87, 0x83, 0x84, 0x88, 0x89, 0,125,
0x90,53,77, 0x91,65,94, 0x92,41,90, 0x93,77,127, 0x94,77,127, 0x95,53,107, 0x96,65,124,
0x97,41,120, 0x98,77,127, 0x99,77,127, 0,62, 0x83, 0x84, 0x88, 0x89, 0,8, 0x80, 0x85, 0x81, 0x86,
0,4, 0x82, 0x87, 0,125, 0x90,53,83, 0x91,65,93, 0x92,41,88, 0x93,77,127, 0x94,77,127,
0x95,53,113, 0x96,65,123, 0x97,41,118, 0x98,77,127, 0x99,77,127, 0,54, 0x80, 0x85, 0,25,
0x81, 0x86, 0x82, 0x87, 0,91, 0x83, 0x84, 0x88, 0x89, 0,33, 0x90,60,96, 0x91,48,97, 0x92,72,118,
0x93,72,118, 0x94,60,126, 0x95,48,127, 0x96,72,118, 0x97,72,118, 0,45, 0x82, 0x83, 0x86, 0x87,
0,33, 0x80, 0x84, 0,8, 0x81, 0x85, 0,12, 0x90,72,112, 0x91,72,112, 0x92,72,112, 0x93,72,112,
0,54, 0x80, 0x81, 0x82, 0x83, 0,45, 0x90,60,97, 0x91,48,77, 0x92,72,112, 0x93,72,112, 0x94,60,127,
0x95,48,107, 0x96,72,112, 0x97,72,112, 0,62, 0x82, 0x83, 0x86, 0x87, 0,16, 0x80, 0x84, 0x81, 0x85,
0,125, 0x90,48,97, 0x91,60,97, 0x92,72,127, 0x93,72,127, 0x94,48,127, 0x95,60,127, 0x96,72,127,
0x97,72,127, 0,62, 0x82, 0x83, 0x86, 0x87, 0,12, 0x80, 0x84, 0,4, 0x81, 0x85, 0,125, 0x90,53,88,
0x91,65,97, 0x92,72,127, 0x93,72,127, 0x94,53,118, 0x95,65,127, 0x96,72,127, 0x97,72,127,
0,87, 0x80, 0x84, 0,16, 0x81, 0x85, 0,95, 0x82, 0x83, 0x86, 0x87, 0x90,57,94, 0x91,45,94, 0x92,69,98,
0x93,69,98, 0x94,57,124, 0x95,45,124, 0x96,69,98, 0x97,69,98, 0,62, 0x82, 0x83, 0x86, 0x87,
0,16, 0x80, 0x84, 0x81, 0x85, 0,25, 0x90,69,121, 0x91,69,121, 0x92,69,121, 0x93,69,121, 0,41,
0x80, 0x81, 0x82, 0x83, 0,58, 0x90,45,96, 0x91,57,94, 0x92,69,121, 0x93,69,121, 0x94,45,126,
0x95,57,124, 0x96,69,121, 0x97,69,121, 0,66, 0x82, 0x83, 0x86, 0x87, 0,8, 0x80, 0x84, 0x81, 0x85,
0,129, 0x90,45,90, 0x91,57,97, 0x92,69,127, 0x93,69,127, 0x94,45,120, 0x95,57,127, 0x96,69,127,
0x97,69,127, 0,58, 0x82, 0x83, 0x86, 0x87, 0,20, 0x80, 0x84, 0,8, 0x81, 0x85, 0,112, 0x90,57,97,
0x91,45,91, 0x92,69,127, 0x93,69,127, 0x94,57,127, 0x95,45,121, 0x96,69,127, 0x97,69,127,
0,150, 0x80, 0x84, 0,4, 0x81, 0x85, 0,41, 0x82, 0x83, 0x86, 0x87, 0,8, 0x90,53,90, 0x91,41,92,
0x92,65,120, 0x93,65,120, 0x94,53,120, 0x95,41,122, 0x96,65,120, 0x97,65,120, 0,50, 0x82,
0x83, 0x86, 0x87, 0,41, 0x80, 0x84, 0,4, 0x81, 0x85, 0,4, 0x90,65,122, 0x91,65,122, 0x92,65,122,
0x93,65,122, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,53,97, 0x91,41,97, 0x92,65,122, 0x93,65,122,
0x94,53,127, 0x95,41,127, 0x96,65,122, 0x97,65,122, 0,66, 0x82, 0x83, 0x86, 0x87, 0,12, 0x80,
0x84, 0x81, 0x85, 0,125, 0x90,41,97, 0x91,53,96, 0x92,65,121, 0x93,65,121, 0x94,41,127, 0x95,53,126,
0x96,65,121, 0x97,65,121, 0,62, 0x80, 0x84, 0x82, 0x83, 0x86, 0x87, 0,8, 0x81, 0x85, 0,133, 0x90,41,97,
0x91,53,97, 0x92,65,123, 0x93,65,123, 0x94,41,127, 0x95,53,127, 0x96,65,123, 0x97,65,123,
0,62, 0x82, 0x83, 0x86, 0x87, 0,137, 0x92,60,113, 0x93,60,113, 0x96,60,113, 0x97,60,113, 0,25,
0x80, 0x84, 0,8, 0x81, 0x85, 0,33, 0x82, 0x83, 0x86, 0x87, 0,137, 0x90,41,93, 0x91,53,97, 0x92,65,118,
0x93,65,118, 0x94,41,123, 0x95,53,127, 0x96,65,118, 0x97,65,118, 0,58, 0x82, 0x83, 0x86, 0x87,
0,145, 0x92,60,107, 0x93,60,107, 0x96,60,107, 0x97,60,107, 0,29, 0x80, 0x84, 0,29, 0x82,
0x83, 0x86, 0x87, 0,16, 0x81, 0x85, 0,125, 0x90,45,96, 0x91,57,97, 0x92,69,118, 0x93,69,118,
0x94,45,126, 0x95,57,127, 0x96,69,118, 0x97,69,118, 0,62, 0x82, 0x83, 0x86, 0x87, 0,129, 0x80,
0x84, 0,12, 0x90,65,116, 0x92,65,116, 0x93,65,116, 0x94,65,116, 0,4, 0x81, 0x85, 0,58,
0x80, 0x82, 0x83, 0x84, 0,141, 0x90,48,94, 0x91,60,97, 0x92,72,121, 0x93,72,121, 0x94,48,124,
0x95,60,127, 0x96,72,121, 0x97,72,121, 0,58, 0x82, 0x83, 0x86, 0x87, 0,141, 0x92,69,111, 0x93,69,111,
0x96,69,111, 0x97,69,111, 0,4, 0x80, 0x84, 0,20, 0x81, 0x85, 0,37, 0x82, 0x83, 0x86, 0x87, 0,141,
0x90,53,88, 0x91,41,97, 0x92,77,118, 0x93,77,118, 0x94,53,118, 0x95,41,127, 0x96,77,118,
0x97,77,118, 0,50, 0x82, 0x83, 0x86, 0x87, 0,62, 0x80, 0x84, 0,91, 0x81, 0x85, 0x90,72,96, 0x91,72,96,
0x92,72,96, 0x93,72,96, 0,58, 0x80, 0x81, 0x82, 0x83, 0,141, 0x90,53,97, 0x91,41,97, 0x92,77,122,
0x93,77,122, 0x94,53,127, 0x95,41,127, 0x96,77,122, 0x97,77,122, 0,50, 0x82, 0x83, 0x86, 0x87,
0,91, 0x80, 0x84, 0,62, 0x90,72,116, 0x92,72,116, 0x93,72,116, 0x94,72,116, 0,8, 0x81,
0x85, 0,66, 0x80, 0x82, 0x83, 0x84, 0,129, 0x90,45,97, 0x91,57,97, 0x92,81,110, 0x93,81,110,
0x94,45,127, 0x95,57,127, 0x96,81,110, 0x97,81,110, 0,62, 0x82, 0x83, 0x86, 0x87, 0,83, 0x80,
0x84, 0,12, 0x81, 0x85, 0,41, 0x90,77,116, 0x91,77,116, 0x92,77,116, 0x93,77,116, 0,75,
0x80, 0x81, 0x82, 0x83, 0,129, 0x90,48,97, 0x91,60,93, 0x92,84,110, 0x93,84,110, 0x94,48,127,
0x95,60,123, 0x96,84,110, 0x97,84,110, 0,75, 0x82, 0x83, 0x86, 0x87, 0,54, 0x80, 0x84, 0,16,
0x81, 0x85, 0,58, 0x90,81,116, 0x91,81,116, 0x92,81,116, 0x93,81,116, 0,66, 0x80, 0x81, 0x82,
0x83, 0,133, 0x90,53,97, 0x91,41,97, 0x92,77,127, 0x93,77,127, 0x94,53,127, 0x95,41,127,
0x96,77,127, 0x97,77,127, 0,233, 0x80, 0x84, 0,25, 0x81, 0x85, 0,100, 0x82, 0x83, 0x86, 0x87, 0,250,
0x90,77,127, 0x91,77,127, 0x92,77,127, 0x93,77,127, 0,50, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,77,121,
0x91,77,121, 0x92,77,121, 0x93,77,121, 0,54, 0x80, 0x81, 0x82, 0x83, 0,50, 0x90,53,97, 0x91,41,82,
0x92,77,124, 0x93,77,124, 0x94,53,127, 0x95,41,112, 0x96,77,124, 0x97,77,124, 0,58, 0x82,
0x83, 0x86, 0x87, 0,45, 0x80, 0x84, 0,4, 0x81, 0x85, 0,95, 0x90,53,97, 0x91,41,93, 0x92,77,127,
0x93,77,127, 0x94,53,127, 0x95,41,123, 0x96,77,127, 0x97,77,127, 0,54, 0x82, 0x83, 0x86, 0x87,
0,41, 0x80, 0x84, 0x81, 0x85, 0,104, 0x90,41,90, 0x91,53,97, 0x92,77,127, 0x93,77,127, 0x94,41,120,
0x95,53,127, 0x96,77,127, 0x97,77,127, 0,62, 0x82, 0x83, 0x86, 0x87, 0,29, 0x80, 0x84, 0x81, 0x85,
0,112, 0x90,41,97, 0x91,53,96, 0x92,77,122, 0x93,77,122, 0x94,41,127, 0x95,53,126, 0x96,77,122,
0x97,77,122, 0,62, 0x82, 0x83, 0x86, 0x87, 0,25, 0x80, 0x84, 0x81, 0x85, 0,116, 0x90,41,93, 0x91,53,97,
0x92,77,127, 0x93,77,127, 0x94,41,123, 0x95,53,127, 0x96,77,127, 0x97,77,127, 1,164, 0x82,
0x83, 0x86, 0x87, 0,25, 0x80, 0x84, 0x81, 0x85, 0,158, 0x90,53,97, 0x91,41,93, 0x92,77,102, 0x93,69,91,
0x94,72,97, 0x95,77,102, 0x96,69,91, 0x97,72,97, 0x98,53,127, 0x99,41,123, 0x9A,77,102,
0x9B,69,91, 0x9C,72,97, 0x9D,77,102, 0x9E,69,91, 0x9F,72,97, 0,29, 0x82, 0x85, 0x8A, 0x8D,
0x83, 0x86, 0x8B, 0x8E, 0x84, 0x87, 0x8C, 0x8F, 0,33, 0x80, 0x88, 0,4, 0x81, 0x89, 0,137, 0x90,41,97,
0x91,53,97, 0x92,77,121, 0x93,69,124, 0x94,72,122, 0x95,77,121, 0x96,69,124, 0x97,72,122,
0x98,41,127, 0x99,53,127, 0x9A,77,121, 0x9B,69,124, 0x9C,72,122, 0x9D,77,121, 0x9E,69,124,
0x9F,72,122, 1,131, 0x82, 0x85, 0x8A, 0x8D, 0,4, 0x83, 0x86, 0x8B, 0x8E, 0,8, 0x84, 0x87, 0x8C, 0x8F,
0,41, 0x80, 0x88, 0x81, 0x89, 0,166, 0x90,41,73, 0x91,48,97, 0x92,53,88, 0x93,65,110, 0x94,57,102,
0x95,65,110, 0x96,57,102, 0x97,41,103, 0x98,48,127, 0x99,53,118, 0x9A,65,110, 0x9B,57,102,
0x9C,65,110, 0x9D,57,102, 0,45, 0x80, 0x87, 0x83, 0x85, 0x8A, 0x8C, 0,4, 0x81, 0x88, 0x84, 0x86, 0x8B,
0x8D, 0x82, 0x89, 0,154, 0x90,53,97, 0x91,48,97, 0x92,41,97, 0x93,57,127, 0x94,65,127, 0x95,57,127,
0x96,65,127, 0x97,53,127, 0x98,48,127, 0x99,41,127, 0x9A,57,127, 0x9B,65,127, 0x9C,57,127,
0x9D,65,127, 4,180, 0x80, 0x87, 0,112, 0x83, 0x85, 0x8A, 0x8C, 0,33, 0x84, 0x86, 0x8B, 0x8D, 0,95,
0x81, 0x88, 0,12, 0x82, 0x89, 0xf0};
// This score contains 18424 bytes, and 16 tone generators are used.
// 50 notes had to be skipped.

+ 0
- 0
examples/Synthesis/pulseWidth/pulseWidth.ino 查看文件


部分文件因文件數量過多而無法顯示

Loading…
取消
儲存