Matlab音乐播放代码故障排查:逐频生成播放信号问题求助
问题排查与代码修正
我帮你梳理下这段Octave/Matlab代码里的几个关键问题,这些应该就是导致你没法正常播放音乐的核心原因:
核心问题分析
FrTm数组遍历逻辑错误:FrTm是每行存「键位编号, 时长」的二维数组,但你用
for i = 1:length(FrTm)循环时,length(FrTm)返回的是数组最大维度的长度,而FrTm(i)会按列优先取元素,导致你把时长值当成键位编号来用,完全打乱了频率和时长的对应关系。正确做法是按行遍历,每次取出一行的键位和时长。M数组的逻辑混乱:你先基于十二平均律计算了M(I)对应钢琴键的频率(这部分是对的),但循环里又用
M(i) = FrTm(i)覆盖了之前的频率值,等于直接废掉了原本的频率计算逻辑。应该用FrTm里的键位编号去索引M数组,拿到对应的实际频率。时间序列t的固定化错误:你定义了固定长度的
t = 0:1/18:5,但每个音符的时长应该由FrTm里的第二个值决定,每个音符需要生成对应时长的时间序列,而不是用统一的t。信号拼接方向错误:你用
Signal = [data; Signal];把新音符堆叠到现有信号上方,这会生成多通道信号(每行是一个通道),但你需要的是单声道连续音频,应该按横向拼接(把新音符接在现有信号后面)。另外这种拼接顺序还会让音乐倒放,因为你每次把新音符放在了前面。stem绘图的错误:如果Signal是多行数组,stem会绘制多个序列,而实际你应该绘制拼接后的一维信号。
修正后的代码
function Music3 () Fs = 44100; % 采样率 T = 1 / Fs; note_unit = 1/18; % 每个时长单位对应的秒数,对应你原本的时间步长逻辑 % 生成钢琴键对应的频率(7到88号键) M = zeros(1, 88); for I = 7:88 M(I) = round(36.8 * (2^(1/12))^(I - 6)); endfor Signal = []; % FrTm是[N,2]数组:每行[键位编号, 时长单位数] FrTm = [50, 3; 50, 3; 52, 3; 54, 3; 50, 3; 54, 3; 52, 3; 45, 3; 50, 3; 50, 3; 52, 3; 54, 3; 50, 6; 49, 3; 1, 3; 50, 3; 50, 3; 52, 3; 54, 3; 55, 3; 54, 3; 52, 3; 50, 3; 49, 3; 45, 3; 47, 3; 49, 3; 50, 6; 50, 3; 1, 3; 47, 5; 49, 1; 47, 3; 45, 3; 47, 3; 49, 3; 50, 3; 1, 3; 45, 5; 47, 1; 45, 3; 43, 3; 42, 6; 45, 3; 1, 3; 47, 5; 49, 1; 47, 3; 45, 3; 47, 3; 49, 3; 50, 3; 47, 3; 45, 3; 50, 3; 49, 3; 52, 3; 50, 6; 50, 6]; % 按行遍历FrTm的每一个音符 for i = 1:size(FrTm, 1) key_num = FrTm(i, 1); duration_units = FrTm(i, 2); % 获取对应频率,键位1设为静音(0频率) if key_num == 1 freq = 0; else freq = M(key_num); end % 生成当前音符的时间序列:时长为 duration_units * note_unit t_note = 0:T:(duration_units * note_unit - T); % 生成正弦信号,静音时输出0 if freq == 0 data = zeros(size(t_note)); else data = sin(2 * pi * freq * t_note); end % 把当前音符拼接到信号末尾(保持播放顺序) Signal = [Signal, data]; endfor % 绘制单声道信号的时域图 plot(Signal); % 播放音频 sound(Signal, Fs); end
修正点说明
- 改用
size(FrTm, 1)获取FrTm的行数,确保按行遍历每个音符,正确取出键位和时长。 - 保留了M数组的频率计算逻辑,用FrTm的键位编号去索引M拿到对应频率;同时处理了键位1的静音逻辑(输出0信号)。
- 为每个音符生成对应时长的时间序列
t_note,时长由duration_units * note_unit决定,符合你原本的1/18秒单位设计。 - 横向拼接信号
Signal = [Signal, data],保证音符按顺序播放,且生成单声道信号。 - 把
stem改成plot,更适合展示连续的音频信号;同时处理了静音情况,避免播放杂音。
内容的提问来源于stack exchange,提问作者Inam




