当前位置:   article > 正文

linux c语言播放midi,C语言实现--计算MIDI音符的频率

输入音频输出音乐频率怎么代码实现

MIDI音符数据

MIDI音符数据的值是无符号 seven-bit 整数,每个整数的取值范围是[0,127]。MIDI音符数据包含的信息有:key numbers(调式标记,例如B小调), various controllers (控制器输入变化,如踩踏板、弯音), Key Velocity and Pressure, and so on.

中央C(Middle C,C5)的MIDI音符编号被定义为60,中央C低一个八度的C编号为60-12=48。编号的取值范围是[0,127]。MIDI最低音是C0,比中央C低5个八度,编号为0。

(ps: 在88键钢琴上中央C是第四个C,所以在乐理中,中央C标记为C4,和在MIDI中是不一样的。)

(pss: 这个编号不要和字母的ASCII编码搞混了,不是一码事哈。'C'的ASCII码是67)

音高与频率的关系

中央C上的A音符(Concert A,A5)发出的频率为440Hz(表示成"A=440Hz",或是"A440"),通常被当作“标准音高”。其编号是69。

音符编号 p 与其基频 f 的关系满足以下公式:

math?formula=p%3D69%2B12%20%5Ctimes%20%5Clog%20_%7B2%7D%5Cleft(%5Cfrac%7Bf%7D%7B440%7D%5Cright)

math?formula=f%3D440%20%5Ctimes%202%5E%7B(p-69)%20%2F%2012%7D

以此计算得知中央C的频率约为261.6Hz。

semitone_ratio

音符每升高1个八度,其频率就变为之前的2倍。也就是说,音符每升高一个半音,其频率就乘上

math?formula=%5Csqrt%5B12%5D%7B2%7D%3D1.0594631 乘12次1.0594631就相当于升高1个八度(12个半音),其频率翻倍。1.0594631也叫做semitone_ratio。

代码

midi2freq

输入MIDI编号,输出其频率。(思路:先计算C0的频率,然后乘semitone_ratio的midinote次方。)

#include

#include

#include

int main()

{

double semitone_ratio;

double c0; /* for frequency of MIDI Note 0 */

double c5; /* for frequency of Middle C */

double frequency; /* . . . which we want to find, */

int midinote; /* . . . given this note. */

/* calculate required numbers */

semitone_ratio = pow(2, 1/12.0); /* approx. 1.0594631 */

/* find Middle C, three semitones above low A = 220 */

c5 = 220.0 * pow(semitone_ratio, 3);

/* MIDI Note 0 is C, 5 octaves below Middle C */

c0 = c5 * pow(0.5, 5);

/* calculate a frequency for a given MIDI Note Number */

printf("Input MIDI Note: ");

scanf("%d",&midinote);

// midinote = 73; /* C# above A = 440 */

frequency = c0 * pow(semitone_ratio, midinote);

printf("MIDI Note %d has frequency %f\n",midinote,frequency);

return 0;

}

freq2midi

输入频率,输出频率最接近的MIDI编号以及偏离的pitchbend百分比。(思路:假设频率是最低音的x个2倍,那么编号就是12个半音乘以x。)

#include

#include

#include

int main()

{

double semitone_ratio;

double c0; /* for frequency of MIDI Note 0 */

double c5; /* for frequency of Middle C */

double frequency; /* . . . which we want to find, */

double midinote; /* . . . given this note. */

double diff;

/* calculate required numbers */

semitone_ratio = pow(2, 1/12.0); /* approx. 1.0594631 */

/* find Middle C, three semitones above low A = 220 */

c5 = 220.0 * pow(semitone_ratio, 3);

/* MIDI Note 0 is C, 5 octaves below Middle C */

c0 = c5 * pow(0.5, 5);

printf("Input MIDI frequency: ");

scanf("%lf",&frequency);

midinote = log2(frequency/c0)*12;

diff = midinote-(int)midinote;

if (diff<0.5){ // 如果“四舍”

printf("The nearest MIDI Note is %d, and the pitchbend is +%lf%%\n",(int)midinote,diff*100);

}

else{ // 如果“五入”

printf("The nearest MIDI Note is %d, and the pitchbend is %lf%%\n",(int)midinote+1,(diff-1)*100);

}

return 0;

}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/248491
推荐阅读
相关标签
  

闽ICP备14008679号