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.6k
ライトたくさんReSTIRを実装しよう
fadis
2
1.2k
コンピュータグラフィクスの空
fadis
7
2.4k
NNEFを読めるようになろう
fadis
0
980
低レイヤーから始める 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.3k
Other Decks in Programming
See All in Programming
How mixi2 Uses TiDB for SNS Scalability and Performance
kanmo
40
15k
PHP ステートレス VS ステートフル 状態管理と並行性 / php-stateless-stateful
ytake
0
110
ファインディLT_ポケモン対戦の定量的分析
fufufukakaka
0
840
Kubernetes History Inspector(KHI)を触ってみた
bells17
0
230
GAEログのコスト削減
mot_techtalk
0
120
Amazon Q Developer Proで効率化するAPI開発入門
seike460
PRO
0
120
Spring gRPC について / About Spring gRPC
mackey0225
0
230
時計仕掛けのCompose
mkeeda
1
310
Conform を推す - Advocating for Conform
mizoguchicoji
3
700
SpringBoot3.4の構造化ログ #kanjava
irof
3
1k
CloudNativePGを布教したい
nnaka2992
0
100
Go 1.24でジェネリックになった型エイリアスの紹介
syumai
1
120
Featured
See All Featured
Visualization
eitanlees
146
15k
How to Ace a Technical Interview
jacobian
276
23k
Facilitating Awesome Meetings
lara
52
6.2k
Building an army of robots
kneath
303
45k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
Become a Pro
speakerdeck
PRO
26
5.1k
Automating Front-end Workflow
addyosmani
1368
200k
The Power of CSS Pseudo Elements
geoffreycrofte
75
5.5k
Being A Developer After 40
akosma
89
590k
RailsConf 2023
tenderlove
29
1k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
30
4.6k
Optimising Largest Contentful Paint
csswizardry
34
3.1k
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'
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠