Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
シンセサイザー入門
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Fadis
May 09, 2015
Programming
0
580
シンセサイザー入門
mbedのDAコンバータを使って色んな方式のシンセサイザーの仕組みを解説します
Fadis
May 09, 2015
Tweet
Share
More Decks by Fadis
See All by Fadis
ゲームの物理 剛体編
fadis
1
510
ゲームの物理
fadis
5
2k
バイラテラルアップサンプリング
fadis
4
990
Kernel/VM探検隊@関西 11回目 大阪駅から会場までの道のりマップ
fadis
0
290
C++でシェーダを書く
fadis
6
5.2k
ライトたくさんReSTIRを実装しよう
fadis
3
1.6k
コンピュータグラフィクスの空
fadis
8
2.8k
NNEFを読めるようになろう
fadis
0
1.2k
低レイヤーから始める GUI
fadis
18
12k
Other Decks in Programming
See All in Programming
Swift ConcurrencyでよりSwiftyに
yuukiw00w
0
260
Ruby and LLM Ecosystem 2nd
koic
1
550
「やめとこ」がなくなった — 1月にZennを始めて22本書いた AI共創開発のリアル
atani14
0
370
grapheme_strrev関数が採択されました(あと雑感)
youkidearitai
PRO
1
210
20260228_JAWS_Beginner_Kansai
takuyay0ne
5
490
Cyrius ーLinux非依存にコンテナをネイティブ実行する専用OSー
n4mlz
0
130
ふつうの Rubyist、ちいさなデバイス、大きな一年
bash0c7
0
830
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
510
モジュラモノリスにおける境界をGoのinternalパッケージで守る
magavel
0
3.5k
Unity6.3 AudioUpdate
cova8bitdots
0
120
ロボットのための工場に灯りは要らない
watany
10
2.6k
Go 1.26でのsliceのメモリアロケーション最適化 / Go 1.26 リリースパーティ #go126party
mazrean
1
380
Featured
See All Featured
The browser strikes back
jonoalderson
0
780
YesSQL, Process and Tooling at Scale
rocio
174
15k
Prompt Engineering for Job Search
mfonobong
0
180
The Language of Interfaces
destraynor
162
26k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
9.9k
sira's awesome portfolio website redesign presentation
elsirapls
0
190
Being A Developer After 40
akosma
91
590k
Into the Great Unknown - MozCon
thekraken
40
2.3k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.2k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
0
450
We Are The Robots
honzajavorek
0
190
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
190
Transcript
γϯηαΠβʔೖ
দྛঘཧ !GBEJT@ 5XJUUFS ࣗݾհ
দྛঘཧ IUUQTHJUIVCDPN'BEJT HJUIVC͡Ί·ͨ͠ ࠓճհ͢Δίʔυ ͜͜Ͱެ։த ࣗݾհ
ݹͷੲ ୈҰճΧʔωϧ7.୳ݕୂ!ؔ CFFQԻͰԿ͕ग़དྷΔ͔
ࠓճΦʔσΟΦωλ CFFQԻͳΜͯένष͍͜ͱݴΘͣ ΨνͰγϯηαΠβʔΛ࡞Δ
ԻͷपʹΑͬͯԻ֊͕มΘΔ ͜͜ ͜͜
ؚ·Ε͍ͯΔपʹΑͬͯԻ৭͕มΘΔ ͜͜ͱ͔
γϯηαΠβʔͷجຊ ҙਤͨ͠Ի֊ʹରԠ͢ΔपΛ ओͱ͢ΔΛ࡞Δ
ྲྀߦͷϚΠίϯNCFE͞Μ AnalogOut
#include "mbed.h" AnalogOut audio_out(p18); const float freq_table[ 8 ] =
{ 523.25113f, 587.32953f, 659.25511f, 698.45646f, 783.99087f, 880.00000f, 987.76660f, 1046.5022f, }; int main() { while(1) { for( int note = 0; note != 8; ++note ) for( float time = 0.0f; time < 1.0f; time += 1.0f/16000.0f ) { Timer used_time; used_time.start(); audio_out = sinf( time * freq_table[ note ] * 3.141592f * 2.0f ) * 0.5f + 0.5f; used_time.stop(); wait(1.0f/16000.0f-used_time.read()); } } }
αΠζͷ߹ͰಈըΧοτʜ
ͬͱෳࡶͳԻΛग़͍ͨ͠ ϑΝϛίϯۣܗͱࡾ֯ͷ छྨͷܗ͔͑͠ͳ͍ͷʹ ଟ࠼ͳԻ৭ΛͰΔ͜ͱ͕ग़དྷΔͷԿނ͔ ۣܗ ࡾ֯
Τϯϕϩʔϓ ͬͱෳࡶͳԻΛग़͍ͨ͠ ԻྔΛܦա࣌ؒʹԠͯ͡มԽͤ͞Δ ͜͜Ͱ໐Β͢ͷΛΊͨ ͜͜Ͱ໐Β͠͡Ίͨ
ΞλοΫ ϐΞϊ όΠΦϦϯ ໐Γ͡Ίͷ Իྔ͕࠷େ͖͍ ໐Γ͡Ί͔ͯΒ ঃʑʹԻྔ͕େ͖͘ͳΔ ͜ͷ෦ͷ͞Λม͑Δ͜ͱͰରԠ
σΟέΠ γϩϑΥϯ Ϊλʔ ໐Β͠͡Ίͯ࠷େԻྔʹୡͨ͠ޙ ͙͢ʹԻྔ͕Լ͕Δ ໐Β͠͡Ίͯ࠷େԻྔʹୡͨ͠ޙ Ώͬ͘ΓԻྔ͕Լ͕Δ ͜ͷ෦ͷ͞Λม͑Δ͜ͱͰରԠ
αεςΠϯ ϐΞϊ ΦϧΨϯ ݤ൫Λԡ͍ͯ͠Δ࣌ؒʹؔΘΒͣ ͋Δఔͷ࣌ؒͰԻ͕ফ͑Δ ݤ൫Λԡ͍ͯ͠ΔݶΓࡍݶͳ͘ Ի͕໐Γଓ͚Δ ͜ͷ෦ͷେ͖͞Λม͑Δ͜ͱͰରԠ
ϦϦʔε ΦϧΨϯ ενʔϧυϥϜ ͘ͷΛΊΔͱ ൺֱత࣌ؒͰԻ͕ফ͑Δ ͜ͷ෦ͷ͖Λม͑Δ͜ͱͰରԠ ͘ͷΛΊͯԻ͕ ফ͑Δ·Ͱʹ͋Δఔͷ࣌ؒΛཁ͢
Τϯϕϩʔϓ º
#include "mbed.h" AnalogOut audio_out(p18); DigitalIn button(p19); class Envelope { bool
note_stat; float prev; public: Envelope() : note_stat( true ), prev( 0.0f ) {} void off() { note_stat = false; } float operator()( float _time ) { if( note_stat ) { if( _time < 0.2f ) prev = _time / 0.2f; else if( _time < 0.7f ) prev = 1.0f - ( _time - 0.2f ); else prev = 0.5f; return prev; } else return ( prev - _time < 0.0f ) ? 0.0f : prev - _time; } }; int main() { while(1) { Envelope envelope; float time, note_off_time; for( time = 0.0f; button; time += 1.0f/16000.0f ) { Timer used_time; used_time.start(); audio_out = envelope( time ) * sinf( time * 880.0f * 3.141592f * 2.0f ) * 0.4f + 0.5f; used_time.stop(); wait(1.0f/16000.0f-used_time.read()); } envelope.off(); for( note_off_time = time; !button; time += 1.0f/16000.0f ) { Timer used_time; used_time.start(); audio_out = envelope( time - note_off_time ) * sinf( time * 880.0f * 3.141592f * 2.0f ) * 0.4f + 0.5f; used_time.stop(); wait(1.0f/16000.0f-used_time.read()); } } }
αΠζͷ߹ͰಈըΧοτʜ
ϋϞϯυΦϧΨϯ αΠϯͱ͔ۣܗͱ͔Ͱͳ͘ ͬͱෳࡶͳܗΛ͏͜ͱͰ ଟ࠼ͳԻ৭ΛͰ͍ͨ ෳͷαΠϯΛॏͶ߹ΘͤΔ ࡞ઓ
ϋϞϯυΦϧΨϯ ഒ ഒ ഒ ഒ ̏ഒ ̐ഒ ഒ ̒ഒ ഒ
جԻ ͜ΕΒͷഒԻΛҙͷԻྔͰॏͶ߹ΘͤΔ
ϋϞϯυΦϧΨϯ ຊͷϋϞϯυΦϧΨϯ αΠϯͷࠁ·Εͨຕͷԁ൫Λ ߴճసͤ͞Δ͜ͱͰ֤पͷΛ࡞͍ͬͯͨ ϚΠίϯͰ؆୯ʹαΠϯΛ࡞ΕΔ࣌Ͱ ຊʹྑ͔ͬͨ
... template< typename Traits > class Hammond { public: Hammond(){}
fixed32< 16 > operator()( fixed32< 16 > _time ) { static const fixed32< 16 > scale_16 = 220.0f; static const fixed32< 16 > scale_8 = 440.0f; static const fixed32< 16 > scale_513 = 659.3f; static const fixed32< 16 > scale_4 = 880.0f; static const fixed32< 16 > scale_223 = 1318.5f; static const fixed32< 16 > scale_2 = 1760.0f; static const fixed32< 16 > scale_135 = 2217.0f; static const fixed32< 16 > scale_113 = 2637.0f; static const fixed32< 16 > scale_1 = 3520.0f; fixed32< 16 > sum = 0.0f; sum += sint( _time * scale_16 ) * Traits::level_16; sum += sint( _time * scale_8 ) * Traits::level_8; sum += sint( _time * scale_513 ) * Traits::level_513; sum += sint( _time * scale_4 ) * Traits::level_4; sum += sint( _time * scale_223 ) * Traits::level_223; sum += sint( _time * scale_2 ) * Traits::level_2; sum += sint( _time * scale_135 ) * Traits::level_135; sum += sint( _time * scale_113 ) * Traits::level_113; sum += sint( _time * scale_1) * Traits::level_1; fixed32< 16 > max = 0.0f; max += Traits::level_16; max += Traits::level_8; max += Traits::level_513; max += Traits::level_4; max += Traits::level_223; max += Traits::level_2; max += Traits::level_135; max += Traits::level_113; max += Traits::level_1; sum /= max; return sum; } private: }; ...
αΠζͷ߹ͰಈըΧοτʜ
ϋϞϯυΦϧΨϯ ϑʔϦΤڃΑΓ ͋ΒΏΔܗαΠϯͷॏͶ߹ΘͤͰ࡞ΕΔ͕ Ұൠʹेͳ࣭ΛಘΔҝʹཁٻ͞ΕΔ αΠϯͷඇৗʹଟ͘ ͔͔ͨͩݸఔͷαΠϯͰ େͨ͠Ի৭ͷࣗ༝ಘΒΕͳ͍
'.Իݯ αΠϯͱ͔ۣܗͱ͔Ͱͳ͘ ͬͱෳࡶͳܗΛ͏͜ͱͰ ଟ࠼ͳԻ৭ΛͰ͍ͨ '.มௐΛͬͯαΠϯΛΊΔ ࡞ઓ
ΦϖϨʔλ PVUQVUTJO DMPDL JOQVU FOWFMPQF ·ͨผͷΦϖϨʔλ ΦʔσΟΦग़ྗ·ͨผͷΦϖϨʔλ
ΦϖϨʔλྻͷ'.Իݯ ΦϖϨʔλ ΦϖϨʔλ ΦʔσΟΦग़ྗ
ΦϖϨʔλฒྻͷ'.Իݯ ΦϖϨʔλ ΦϖϨʔλ ΦʔσΟΦग़ྗ
ೖྗଆͷԻྔͰΈ۩߹͕ௐઅͰ͖Δ ΦϖϨʔλ ΦϖϨʔλ ΦϖϨʔλ ΦϖϨʔλ
ೖྗଆͷԻྔͰΈ۩߹͕ௐઅͰ͖Δ PVUQVUTJO DMPDL JOQVU FOWFMPQF ΦϖϨʔλʹ Τϯϕϩʔϓ͕͍͍ͭͯΔ ΦʔσΟΦग़ྗʹܨ͕͍ͬͯͳ͍ ΦϖϨʔλͷΤϯϕϩʔϓ
ܗͷΈΛ࣌ؒมԽͤ͞ΔͨΊʹ͑Δ
... class Const { public: fixed32< 16 > operator()( fixed32<
16 > _time ) { static const fixed32< 16 > value = 0; return value; } }; ! template< typename Source > class FM { public: FM() {} void off( fixed32< 16 > _off_time ) { envelope.off( _off_time ); } fixed32< 16 > operator()( fixed32< 16 > _time ) { fixed32< 16 > looped_time = _time - static_cast< int >( _time ); return sint( ( looped_time * 880.0f + source( _time ) / 2 ) ) * envelope( _time ); } private: Source source; Envelope envelope; }; ! int main() { while(1) { FM< FM< Const > > fm; fixed32< 16 > time, note_off_time; for( time = 0.0f; button; time += 1.0f/16000.0f ) { Timer used_time; used_time.start(); audio_out = fm( time ) * 0.4f + 0.5f; used_time.stop(); wait(1.0f/16000.0f-used_time.read()); } fm.off( time ); ...
αΠζͷ߹ͰಈըΧοτʜ
'.Իݯ '.มௐͷ݁Ռײతʹ༧͠ਏ͍ͨΊ ҙਤͨ͠Ի৭Λ࡞ΔͨΊʹࢼߦࡨޡ͕ඞཁ
ܗςʔϒϧԻݯ αΠϯͱ͔ۣܗͱ͔Ͱͳ͘ ͬͱෳࡶͳܗΛ͏͜ͱͰ ଟ࠼ͳԻ৭ΛͰ͍ͨ ࣄલʹ༻ҙͨ͠ܗσʔλΛ͏ ࡞ઓ
ܗςʔϒϧԻݯ ٕज़తʹ໘ന͘ͳ͍͚Ͳ ͦΕͳΓʹྑ͍Ի͕ग़Δํ๏ ͋Β͔͡Ίຊͷָث͔ΒԻ͖ͯͨ͠ ܗσʔλΛԻ֊ʹରԠ͢Δ͞ͰᢞΊΔ ྻ
... class Guiter { public: virtual fixed32< 16 > operator()(
fixed32< 16 > _pos ) { static const int16_t guiter_table[ 512 ] = { -32735, -32583, -32431, -32279, -32127, -31975, -31823, -31671, ... -27519, -28171, -28823, -29475, -30127, -30779, -31431, -32083, }; fixed32< 16 > result; fixed32< 16 > a4 = _pos * 220.0f; int pos = ( a4.get() >> 7 ) % 512; // pos = pos * 880 % 512; int32_t value = static_cast< int32_t >( guiter_table[ pos ] ) << 1; result.set( value ); return result * envelope( _pos ); } void off( fixed32< 16 > _off_time ) { envelope.off( _off_time ); } private: Envelope envelope; }; ...
αΠζͷ߹ͰಈըΧοτʜ
ܗςʔϒϧԻݯ ࣮ͷଘࡏ͠ͳ͍ԻΛ࡞Δͷࠔ ࣌ؒมԽ͢ΔԻ৭Λѻ͏ͷ͕ࠔ
࠷ऴతʹग़དྷ্͕ͬͨͷ ͦͷଞ৭ʑ࣮͚ͨ͠Ͳ ͦͷΜͷղઆ·ͨͷػձʹ Ψοπͷ͋Δਓ ιʔεΛݟͯΈΔͱ͍͍͔
IUUQZPVUVCFSY5RX&:#.
ษڧձ෮शࢿྉ IUUQCJUMZF2,WE& ιʔείʔυ IUUQCJUMZRJBR'
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠