- BPM: If not specified, the assumed BPM of 120 may differ from the track's actual tempo. With MIDI clicks at 0.1250s and assuming there are two notes played for each click, the resulting tempo is 240 BPM.
- Sampling rate: The sampling rate used in the code can be different from the original sampling rate.
How to convert MIDI file into audio file and preserve tempo?
9 次查看(过去 30 天)
显示 更早的评论
This is a bit of a musical question.
First, I generate a click track in MIDI at 1/8 = .1250 and save the data in a MAT file. I don't need the whole MIDI header etc. since I just need to use the data to create an audio file. Since I don't specify a tempo in BPM, I assume it is 120.
Next I attempt to convert the MIDI info into an audio file, using Sine waves as the clicks. When I do this, the track is not at the same tempo as the MIDI file. Why is this?
(Excuse my clumsy programming.)
Fs = 96000; % SAMPLE RATE OF AUDIO FILE
% CREATE SINE WAVE PULSE
sine1 = dsp.SineWave();
sine1.SamplesPerFrame = Fs;
sine1.Frequency = 5;
fSine = sine1();
% CREATE AN EMPTY 1-SEC WAVE FILE TO HOLD OUTPUT
zOUT = zeros(Fs*1,1); % NUMBER OF SECONDS
% LOAD MIDI FILE INFO AND PUT IT INTO SEPARATE ARRAYS
zF = load("Click Track TEST.mat"); % LOAD MIDI FILE INFO
cMALL = zF.cZ;
cMTRACK = cMALL(:,1);
cMPITCH = cMALL(:,3);
cMVEL = cMALL(:,4);
cMDb = cMALL(:,5); % BEGIN DURATION FOR EACH PULSE
cMDe = cMALL(:,6); % END DURATION
cMsiz = size(cMTRACK,1);
aa = 0;
zz = 0;
cc = 1;
for ii = 1:cMsiz
% MIDI DURATION CALCULATE
bD = cMDb(ii); % MIDI DURATION BEGIN
eD = cMDe(ii); % MIDI DURATION END
cMDz = eD - bD; % DURATION OF THE PULSE
% CONVERT MIDI DURATION TO AUDIO FRAME # DURATION
cMDFsz = round(cMDz * Fs); % CONVERT MIDI TO SAMPLE DURATION
zzend = cMDFsz;
% ALTERNATE BETWEEN SINE WAVE AND SILENCE TO HEAR PULSE
if mod(ii,2) == 1
cMP = fSine(1:cMDFsz);
else
cMP = 0;
end
zOUT(zz+1:zz+zzend,1) = cMP;
zz = zz + zzend;
end
% WRITE FILE AS WAVE AUDIO
fileOUT = ' Click Test 96K 2023.wav';
audiowrite(fileOUT,zOUT, Fs);
0 个评论
回答(2 个)
Binaya
2024-1-14
Hi Mark
I understand that you would like to know why the audio file generated from MIDI file is not playing at the same tempo as the original MIDI track.
The main reason of the tempo mismatch can be:
I hope this helps.
Regards
Binaya
0 个评论
Voss
2024-1-14
编辑:Voss
2024-1-14
zF = load('Click Track TEST.mat'); % LOAD MIDI FILE INFO
cMALL = zF.cZ;
disp(cMALL)
Assuming 120 BPM (i.e., 1 beat every 0.5 seconds), then each 4 rows is one beat.
A guess: You shouldn't be turning on the sine wave every alternate row:
if mod(ii,2) == 1
cMP = fSine(1:cMDFsz);
else
cMP = 0;
end
but every fourth row, based on where the 75's are in the third column
if cMPITCH(ii) == 75
cMP = fSine(1:cMDFsz);
else
cMP = 0;
end
Here's your code, incorporating that change (and re-written in a more concise style), including a plot that shows you get one duration-0.125-second click each 0.5 seconds (= 8 clicks in 4 seconds = 120 BPM).
Fs = 96000; % SAMPLE RATE OF AUDIO FILE
% CREATE SINE WAVE PULSE
sine1 = dsp.SineWave();
sine1.SamplesPerFrame = Fs;
sine1.Frequency = 5;
fSine = sine1();
zF = load('Click Track TEST.mat');
zOUT = zeros(Fs*zF.cZ(end,6),1);
zz = 0;
for ii = 1:size(zF.cZ,1)
N = round((zF.cZ(ii,6) - zF.cZ(ii,5)) * Fs);
if zF.cZ(ii,3) == 75
zOUT(zz+1:zz+N,1) = fSine(1:N);
end
zz = zz + N;
end
% WRITE FILE AS WAVE AUDIO
fileOUT = ' Click Test 96K 2023.wav';
audiowrite(fileOUT,zOUT, Fs);
plot((1:zz)/Fs,zOUT)
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Simulation, Tuning, and Visualization 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!