ここでは、音階データから簡単な音楽を流します。
1オクターブ分の周期の計算 |
---|
#include <stdio.h> #include <math.h> main() { int i, x; int m=1191; int n=0x10000-m; // 65536-m for(i=0; i<=12; i++) { x = (int)round(n/pow(2.0, i/12.)); if(i%12==0) printf("\n"); printf("%d,", x); } } |
計算結果
| 64345,60734,57325,54107,51071,48204,45499,42945,40535,38260,36112,34086, 32173, |
タイマーにセットする値を求める |
---|
#include <stdio.h> #include <math.h> main() { int i, x; int m=1191; for(i=0; i<=12; i++) { x = (int)round(m/pow(2.0, i/12.)); if(i%12==0) printf("\n"); printf("%d,", x); } } |
計算結果
| 1191,1124,1061,1002,945,892,842,795,750,708,668,631, 596, |
差分の計算 |
---|
#include <stdio.h> #include <math.h> main() { int i, x, y; int m=1191; y=m; for(i=0; i<=12; i++) { x = (int)round(m/pow(2.0, i/12.)); if(i%12==0) printf("\n"); printf("%d,", y-x); y=x; } } |
計算結果
| 0,67,63,59,57,53,50,47,45,42,40,37, 35, |
元のタイマーの値に戻す |
---|
#include <stdio.h> #include <math.h> #define FirstPeriod 64345 unsigned char diff[]={ 67,63,59,57,53,50,47,45,42,40,37,35}; main() { unsigned peri, term; int j, tone; for(tone=0; tone=12; tone++) { peri = FirstPeriod; for(j=0; j<tone; j++) peri += diff[j]; term = 0xffff-peri+1; printf("%d, ", term); } } |
計算結果
| 1191,1124,1061,1002,945,892,842,795,750,708,668,631, 596, |
単音を出す |
---|
// ファイル名 tone.c // 単音を出す #include <htc.h> __CONFIG(PWRTEN&HS&WDTDIS&UNPROTECT&MCLRDIS&BORDIS&IESODIS&FCMDIS); #define _XTAL_FREQ 20000000 #define FirstPeriod 64345 typedef unsigned char byte; void SoundPlay(byte tone, byte dulation); void Delay500(); main() { OPTION = 3; // FOSC/4 プリスケーラ1/16 T1CON = 0x31; // Timer1 settings TMR1IF = 0; // clear TMR1IF TMR1H = 0xf8; // Initialize Timer1 register TMR1L = 0x00; TRISB = 0x00; // スピーカー PORTB = 0; while(1) { Delay500(); SoundPlay(51, 2); } } byte diff[]={ 67,63,59,57,53,50,47,45,42,40,37,35, 34,31,30,28,27,25,24,22,21,20,19,17, 17,16,15,14,13,12,12,11,11,10, 9, 9, 8, 8, 8, 7, 6, 7, 6, 5, 5, 5, 5, 5, 4, 4, 3, 4}; void SoundPlay(byte tone, byte dulation) { unsigned i, peri, n; byte j, k=0; byte H, L; unsigned term; unsigned all = 1191;//0xffff-FirstPeriod+1; peri = FirstPeriod; if(tone == 255) { // 255 は休符 tone = 0; k = 1; } for(j=0; j<tone; j++) peri += diff[j]; term = 0xffff-peri+1; n = 4*dulation*all/term*10; H = peri >> 8; L = peri & 0xff; for(i=0; i<n; ) { if(TMR1IF) { if(!k) PORTB = ~PORTB; TMR1H = H; // Initialize Timer1 register TMR1L = L; TMR1IF = 0; i++; } } } void Delay500() // 500m秒ディレイ { int i; for(i=0; i<50; i++) __delay_ms(10); } |
void SoundPlay(byte tone, byte dulation)
| 音程toneの音をdulationの間発生させる。 |
音階を奏でる |
---|
// 音階を奏でる #include <htc.h> __CONFIG(PWRTEN&HS&WDTDIS&UNPROTECT&MCLRDIS&BORDIS&IESODIS&FCMDIS); #define _XTAL_FREQ 20000000 #define FirstPeriod 64345 typedef unsigned char byte; void SoundPlay(unsigned tone, byte dulation); main() { unsigned int i; unsigned int value; byte tone[]={ 3, 5, 7, 8,10,12,14, 15,17,19,20,22,24,26, 27,29,31,32,34,36,38, 39,41,43,44,46,48,50,51}; OPTION = 3; // FOSC/4 プリスケーラ1/16 T1CON = 0x31; // Timer1 settings TMR1IF = 0; // clear TMR1IF TMR1H = 0xf8; // Initialize Timer1 register TMR1L = 0x00; TRISB = 0x00; // スピーカー PORTB = 0; while(1) { for(i=0; i<29; i++) SoundPlay(tone[i], 5); } } byte diff[]={ 67,63,59,57,53,50,47,45,42,40,37,35, 34,31,30,28,27,25,24,22,21,20,19,17, 17,16,15,14,13,12,12,11,11,10, 9, 9, 8, 8, 8, 7, 6, 7, 6, 5, 5, 5, 5, 5, 4, 4, 3, 4}; void SoundPlay(unsigned tone, byte dulation) { unsigned i, peri, n; byte j, k=0; byte H, L; unsigned term; unsigned all = 1191;//0xffff-FirstPeriod+1; peri = FirstPeriod; if(tone == 255) { // 255 は休符 tone = 0; k = 1; } for(j=0; j<tone; j++) peri += diff[j]; term = 0xffff-peri+1; n = 4*dulation*all/term*10; H = peri >> 8; L = peri & 0xff; for(i=0; i<n; ) { if(TMR1IF) { if(!k) PORTB = ~PORTB; TMR1H = H; // Initialize Timer1 register TMR1L = L; TMR1IF = 0; i++; } } } |
0 1 2 3 4 5 6 7 8 9 10 11 A A# B C C# D D# E F F# G G# 12 13 14 15 16 17 18 19 20 21 22 23 A A# B C C# D D# E F F# G G# 24 25 26 27 28 29 30 31 32 33 34 35 A A# B C C# D D# E F F# G G# 36 37 38 39 40 41 42 43 44 45 46 47 A A# B C C# D D# E F F# G G# 48 49 50 51 52 53 54 55 56 57 58 59
CdSに手をかざすとスピーカーから「猫踏んじゃった」 |
---|
// CdSに手をかざすとスピーカーから「猫踏んじゃった」が流れる #include <htc.h> __CONFIG(PWRTEN&HS&WDTDIS&UNPROTECT&MCLRDIS&BORDIS&IESODIS&FCMDIS); #define _XTAL_FREQ 20000000 #define ANS4 0x10 #define FirstPeriod 64345 typedef unsigned char byte; void SoundPlay(unsigned tone, byte dulation); void musicPlay(byte tones[], byte speed); main() { unsigned int i; unsigned int value; byte tone[]={8,14,12, 5, 5,17,255,17,255}; PORTA = 0; // PORTAを0にする TRISA = 0; // PORTAを出力に設定する ANSEL = ANS4; // アナログ入力をAN4をON ADCON0 = 0x11; // ADFM=0(左詰) AN4 adOn OPTION = 3; // FOSC/4 プリスケーラ1/16 T1CON = 0x31; // Timer1 settings TMR1IF = 0; // clear TMR1IF TMR1H = 0xf8; // Initialize Timer1 register TMR1L = 0x00; TRISB = 0x00; // スピーカー PORTB = 0; while(1) { GODONE = 1; // A/D 変換開始 while(GODONE); // 変換完了 value = ADRESH; if(value < 30) { musicPlay(tone, 3); musicPlay(tone, 3); } } } byte diff[]={ 67,63,59,57,53,50,47,45,42,40,37,35, 34,31,30,28,27,25,24,22,21,20,19,17, 17,16,15,14,13,12,12,11,11,10, 9, 9, 8, 8, 8, 7, 6, 7, 6, 5, 5, 5, 5, 5, 4, 4, 3, 4}; void SoundPlay(unsigned tone, byte dulation) { unsigned i, peri, n; byte j, k=0; byte H, L; unsigned term; unsigned all = 1191;//0xffff-FirstPeriod+1; peri = FirstPeriod; if(tone == 255) { // 255 は休符 tone = 0; k = 1; } for(j=0; j<tone; j++) peri += diff[j]; term = 0xffff-peri+1; n = 4*dulation*all/term*10; H = peri >> 8; L = peri & 0xff; for(i=0; i<n; ) { if(TMR1IF) { if(!k) PORTB = ~PORTB; TMR1H = H; // Initialize Timer1 register TMR1L = L; TMR1IF = 0; i++; } } } void musicPlay(byte tones[], byte speed) { byte m, j; unsigned int i; m = tones[0]; for(i=1; i<=m; i++) SoundPlay(tones[i], speed); } |
void musicPlay(byte tones[], byte speed)
| tones配列で示された楽譜をspeedの速さで奏でる。 |