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
Fadis
May 09, 2015
Programming
0
550
シンセサイザー入門
mbedのDAコンバータを使って色んな方式のシンセサイザーの仕組みを解説します
Fadis
May 09, 2015
Tweet
Share
More Decks by Fadis
See All by Fadis
C++でシェーダを書く
fadis
6
4.7k
ライトたくさんReSTIRを実装しよう
fadis
2
1.2k
コンピュータグラフィクスの空
fadis
7
2.4k
NNEFを読めるようになろう
fadis
0
990
低レイヤーから始める GUI
fadis
18
12k
いまどきのVulkan
fadis
14
7.7k
L2 WireGuard
fadis
2
4.5k
Wasserstein逆FM音源
fadis
3
3.6k
HSEとは何か
fadis
15
3.4k
Other Decks in Programming
See All in Programming
一休.com のログイン体験を支える技術 〜Web Components x Vue.js 活用事例と最適化について〜
atsumim
0
920
パスキーのすべて ── 導入・UX設計・実装の紹介 / 20250213 パスキー開発者の集い
kuralab
3
880
Go 1.24でジェネリックになった型エイリアスの紹介
syumai
2
280
CDK開発におけるコーディング規約の運用
yamanashi_ren01
2
250
Honoをフロントエンドで使う 3つのやり方
yusukebe
7
3.5k
1年目の私に伝えたい!テストコードを怖がらなくなるためのヒント/Tips for not being afraid of test code
push_gawa
1
500
Honoのおもしろいミドルウェアをみてみよう
yusukebe
1
220
Boos Performance and Developer Productivity with Jakarta EE 11
ivargrimstad
0
250
楽しく向き合う例外対応
okutsu
0
590
自力でTTSモデルを作った話
zgock999
0
100
GoとPHPのインターフェイスの違い
shimabox
2
210
苦しいTiDBへの移行を乗り越えて快適な運用を目指す
leveragestech
0
1k
Featured
See All Featured
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
30
4.6k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
27
1.6k
Become a Pro
speakerdeck
PRO
26
5.2k
Designing Experiences People Love
moore
140
23k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.2k
How to Ace a Technical Interview
jacobian
276
23k
Product Roadmaps are Hard
iamctodd
PRO
50
11k
Unsuck your backbone
ammeep
669
57k
Gamification - CAS2011
davidbonilla
80
5.2k
Side Projects
sachag
452
42k
The Cult of Friendly URLs
andyhume
78
6.2k
Building Flexible Design Systems
yeseniaperezcruz
328
38k
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'
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠