
[PWMDAC_Synth - PWM DAC synthesizer library for Arduino]

ver.20200418

https://osdn.jp/users/kamide/pf/PWMDAC_Synth/wiki/FrontPage


́ACAmiDion

  http://www.yk.rim.or.jp/~kamide/music/chordhelper/hardware/

̂Q@ȍ~ŎCuƂēƗA
Arduino݊@pPWMVZTCUCułB


ArduinoŊy낤ƂāAȖɂԂƂ͂܂񂩁H

EoȂ tone() 葁ǁAaoȂc

EanalogWrite()  PWM o͂ĂApXg̎g490Hz
  Ⴗ邩A1kHzỎȂď悹ȂAǂ悤c

ȖAAVR̃vXP[ij̐ݒς
pXg̎gőɂΈCɉB

̃CúAKő̎Ŕ^C}[荞݂ŁA
̏uԂ̔g̍ɉAPWM̃pX𖈉񃊃A^CɑfXV
ƂɂA`głȂAFXȔg`̉o͂܂B

̃{CXgdZɂPWM̃pXvZĂ̂ŁA
ȁo͂\łB

O`bvȂ Arduino {̂̂̂ɃVZTCỦ
ƂɊpĂB


CXg[

	WJ PWMDAC_Synth tH_AWindows 

		}ChLg\Arduino\libraries\

	ɒuŃCXg[ł܂B

	uAArduino IDE ̃j[ [t@C]  [XPb`̗] 
	PWMDAC_Synth 邱ƂmFĂB


g

	{IȎgLɎ܂BȂAm[gIAm[gItȂǁȀoɂĂ
	Arduino IDE ̃j[炽ǂuXPb`̗vQlɂĂB

	yTvR[hz
	//
	// KvɉAPWMDAC_Synth.h CN[hO #define ŉLwł܂B
	//
	#define PWMDAC_OUTPUT_PIN  3 // PWMo̓sԍiȗFLuo̓s(PWM)vQƁj
	#define PWMDAC_POLYPHONY   6 // iȗFLuvQƁj
	#define PWMDAC_NOTE_A_FREQUENCY 440  // Ã`[jOgiȗFftHg440Hzj
	#define PWMDAC_CHANNEL_PRIORITY_SUPPORT // `l̗Dxグ@\LigȂꍇ͏ȗj
	#include <PWMDAC_Synth.h>
	//
	// g`e[uAKvȕ`܂B
	//
	PWMDAC_CREATE_WAVETABLE(squareWavetable, PWMDAC_SQUARE_WAVE);      // `g
	PWMDAC_CREATE_WAVETABLE(triangleWavetable, PWMDAC_TRIANGLE_WAVE);  // Opg
	PWMDAC_CREATE_WAVETABLE(sineWavetable, PWMDAC_SINE_WAVE);          // g
	PWMDAC_CREATE_WAVETABLE(shepardToneSineWavetable, PWMDAC_SHEPARD_TONE);  // VFp[hg[iKj
	PWMDAC_CREATE_WAVETABLE(sawtoothWavetable, PWMDAC_SAWTOOTH_WAVE);  // ̂g
	//
	// g`ƃGx[vp[^iADSRj Instrument \̂ɑ˂
	// vÖɉFf[^𐶐܂B
	//  {} ɂADSR̒ltŎw肵܂il͈̔͂ɂĂ͌q́uFύXvQƁjB
	//
	PROGMEM const Instrument instrument = {sawtoothWavetable, {9, 0, 11, 4}};
	//
	// Fw肵PWMDAC_Synth̎́iCX^Xj𐶐܂B
	// MIDI`l1`16ׂẲFɏ܂B
	//
	PWMDAC_CREATE_INSTANCE(&instrument);

	setup() {
		PWMDACSynth::setup(); // iK{j
#if defined(PWMDAC_CHANNEL_PRIORITY_SUPPORT)
	// KvɉāAfBp[gĂMIDI`l̗Dx܂
	//iڍׂɂĂ͌q́u`lDxwvQƁjB
	PWMDACSynth::getChannel(1)->setPriority(0xC0);
#endif
	}

	loop() {
		PWMDACSynth::update(); // ԍXViK{j
		//  ́AȂǂADSRGx[v`݈̌ʒui߂A
		// W[Vɂĕω鎞ԂƂ̎gXV邽߂̊֐łB
		// Ăяopx͎ŃJE^pӂȂǂ̕@ŃRg[ĂB
	}


i{CXj

	ftHg6dałB
	PWMDAC_POLYPHONY ɐlݒ肵ăRpCƂő\łB

	 𑝂₵ĂƁA̕
	ISR() (Interrupt Service Routine: 荞݃T[rX[`)ɂ
	[v񐔂AZɂȂĂ܂B܂ɑZ߂ loop() s
	ɂȂȂƁAs\Ɋׂ܂BȂ鐡OA̎̏łB

	 ISR() Ȃǂœ쑬xv邽߁APWMDAC_Synth.h ɂ
	#pragma GCC optimize ("-O3")
	w肳Ă܂BRpC̍œKÃCuxDɂ邽߂łB

	MIDI`lɑ΂{CXATC̗Dxグ邱Ƃł܂B
	q́u`lDxwvQƁB


o̓s(PWM)

	PWMo͗pƂĎwłsԍ 3,9,10,11 ̂ꂩłB
	ftHg̃sԍ 3 łB

	3,11 Iꍇ TIMER2A9,10 Iꍇ TIMER1 g܂B

	ȂAsԍ 5,6  PWM [qłAw肵ĂRpCG[ɂȂA
	pł܂B TIMER0 p ISR() AArduino  millis() ֐
	邽߂łɎgĂāAĒ`łȂ߂łB

	PWM o̓śÂ܂ PC  LINE IN ȂǂɂȂłꉞ͕܂A
	[pXtB^ŉgʂ悤ɂƁA蕷₷Ȃ܂B


MIDI`l

	PWMDACSynth::getChannel() 

		MIDI`lԍ(1`16)  MIDI`lւ̃|C^

	𑊌ݕϊł܂BMIDI`lւ̃|C^āA
	`lPʂɎp[^𑀍ł܂B
	i@ɂĂ PWMDAC_Synth.h QƁj

	ȂAm[gIAm[gItAsb`xhȂǁAoĂ鉹
	iATCĂ{CXjɑɔfɂ́APWMDACSynth ̂ق
	pӂĂ郁o֐ĂяoA`lƃ{CX𓯎ɍXVKv܂B


MIDI֐

	PWMDACSynth Œ`ꂽ static IuWFNǵA
	MIDICu MIDI.setHandleXxxx() ɒڎwł`ɂȂĂ܂B

	AڑMIDIfoCXɂẮANOTE OFF ̑
	velocity=0  NOTE ON 𑗂Ă邱Ƃ̂ŁȀꍇ
	NOTE OFF ĂяoƂHvKvɂȂ܂B

	MIDI`lԍ́AMIDICuɍ킹 1`16 ͈̔͂
	w肷悤ɍĂ܂B


FύX

	g`e[uADSRGx[vp[^Aꂼ MidiChannel NX
	wavetable  envelope[] Ɏw肷邱ƂŁAFύXł܂B

	܂AInstrument \̒萔vÖɍA
	programChange() Ɏw肷邾ŁAg`ƃGx[vxɐݒł܂B
	MIDĨvO`FWƂɕ֗łB

	yg`z wavetable
	g`e[úAvf256byte^PROGMEMzƂĐ܂B
	 wavetable Ɏw肷邱ƂŁAg`؂ւ邱Ƃł܂B
	g`֐̃}N PWMDAC_CREATE_WAVETABLE() }NɎw肷邩A
	܂͂ɂȂĎŔz`邱ƂŁACӂ̔g`𐶐邱Ƃ\łB

	 ǵi255FftHg6dâƂ42j𒴂Ȃ悤ɂĂB
	ςɖ炵Ƃɍő剹255𒴂ăI[o[t[AmCY
	鋰ꂪ܂B

	yADSRGx[vz envelope[]
	  ADSR_ATTACK_VALUE - A^bNԁi0`15A傫قǃm[gI̗オ肪j
	  ADSR_DECAY_VALUE - fBPCԁi0`15A傫قǃm[gǏj
	  ADSR_SUSTAIN_VALUE - TXeBxi0`255A~܂ƈێ鉹ʁj
	  ADSR_RELEASE_VALUE - [Xԁi0`15A傫قǃm[gIťj
	Ԃ loop()  update() Ăяopxɂĕς܂B


`lDxw

	̋@\́AMIDI`liFfBp[gj̉MIDI`l̉
	錻ۂڗꍇɁAMIDI`lɑ΂{CXATC̗Dx
	邽߂̋@\łB

	̋@\gɂ PWMDAC_CHANNEL_PRIORITY_SUPPORT  #define Kv܂B

		#define PWMDAC_CHANNEL_PRIORITY_SUPPORT

		PWMDACSynth::getChannel(`lԍ)->setPriority(`lDx);

	`lDxɂ 0x00i0AŒFftHgj` 0xFFi255Aōjwł܂B

	{IȍlƂāAADSRGx[vŕϓʂ̍ł{CX珇ɁA
	MIDI`lɏ邱ƂƂĂ܂B

	̂ŁA`lDx̃rbg]li1̕␔ju臒lvƂA
	𒴂鉹ʂ̃{CXÃ`lDIɐL悤ɂĂ܂B

	Dx܂荂ƁA\ʂɂ炸{CXLĂ܂A
	da邱Ƃ܂̂ŁAKXĂB



ҁF悵 - Akiyoshi Kamide
	http://www.yk.rim.or.jp/~kamide/

