Answer the question
In order to leave comments, you need to log in
How to fix big delay between MIDI notes?
I wrote a program for playing melodies that are stored in a text file, when playing between sounds, for some reason there is some kind of delay of about one half a second, although I didn’t seem to indicate it anywhere.
#pragma comment(lib, "Winmm.lib")
#include <cmath>
#include <vector>
#include <map>
#include <fstream>
#include <iostream>
#include <windows.h>
#include <mmsystem.h>
using namespace std;
#define SNDQUE 10000
typedef struct _soundtype
{
double Freq;
int Dura;
int Vol;
int Voice;
double Tempo;
int sndTid;
} soundtype, * LPSOUNDTYPE;
static soundtype SndPmtr[SNDQUE + 1];
static int gTenter;
static int gTwait;
static int gTexit;
static int gTarray;
static BOOL gTsig;
static HANDLE gSThread = NULL;
map<char, double> matchingNotesToFrequency{
{'C', 32.703}, {'D', 36.708}, {'E', 41.203}, // До, Ре, Ми
{'F', 43.654}, {'G', 48.999}, {'A', 55.}, // Фа, Соль, Ля
{'H', 61.735} }; // Си
struct MyNote {
double frequency;
int duration;
int octave;
};
double Round(double, int);
double Abs(double);
vector<MyNote> readNotes(string notespath);
int Sound(float, int = 0, int = 127, int = 0, float = 1);
// changed this from int PlaySnd(void) to:
DWORD WINAPI PlaySnd(LPVOID);
int main()
{
// Tugboat whistle sound 95 hertz, 2000ms, 127 = loud, 111 = Shanai
// experiment with your own sounds, it's fun ...
//Sound(95, 2000, 127, 111); // 2 second blast
//Sound(1, 1000, 0, 111); // 1 second of silence
//Sound(95, 2000, 127, 111); // 2 second blast
//Sound(1, 1000, 0, 111); // 1 second of silence
//Sound(95, 2000, 127, 111); // 2 second blast
vector<MyNote> notes = readNotes("melody.txt");
for (int i = 0; i < notes.size(); i++) {
Sound(notes[i].frequency * notes[i].octave * 10, notes[i].duration, 127, 0);
}
// wait till que is empty
while (Sound(0) != 0)
{
Sleep(10);
}
return 0;
}
double Round(double n, int d)
{
return (floor((n)*pow(10.0, (d)) + 0.5) / pow(10.0, (d)));
}
double Abs(double a)
{
if (a < 0) return -a;
return a;
}
vector<MyNote> readNotes(string notespath)
{
vector<MyNote> notes;
ifstream reader(notespath);
if (reader.is_open())
{
while (!reader.eof()) {
char noteSymbol;
int octave, duration;
MyNote temp;
reader >> noteSymbol;
reader >> octave;
reader >> duration;
temp.frequency = matchingNotesToFrequency[noteSymbol];
temp.octave = octave;
temp.duration = duration;
notes.push_back(temp);
}
}
else
{
cout << "File not open";
}
return notes;
}
int Sound(float Freq, int Dura, int Vol, int Voice, float Tempo)
{
DWORD dwThreadId;
if (Freq == 0 && Dura < 1) return gTenter - gTexit;
// silence
if (Freq == 0) Vol = 0;
if (Dura < 5) Dura = 5;
gTenter++;
gTsig = FALSE;
if (gTenter >= SNDQUE)
{
gTarray = gTenter % SNDQUE + 1;
}
else
{
gTarray = gTenter;
}
SndPmtr[gTarray].Freq = Freq;
SndPmtr[gTarray].Dura = Dura;
SndPmtr[gTarray].Tempo = Tempo;
SndPmtr[gTarray].Vol = Vol;
SndPmtr[gTarray].Voice = Voice;
SndPmtr[gTarray].sndTid = gTenter;
if (gSThread == NULL && (Freq == Abs(Freq) || Freq == 0))
{
// "PlaySnd" needs casting (void *)
gSThread = CreateThread(NULL, 0, PlaySnd, (void*)"PlaySnd", 0, &dwThreadId);
Sleep(1);
return 0;
}
if (Freq != Abs(Freq))
{
if (Freq == -1)
{
Freq = 0;
SndPmtr[gTarray].Vol = 0;
}
SndPmtr[gTarray].Freq = Abs(Freq);
gTsig = TRUE;
while (gSThread != NULL)
{
Sleep(10);
}
gTexit = gTenter - 1;
gTwait = gTenter - 1;
gTsig = FALSE;
return PlaySnd(0); // needs some kind of argument
}
return 0;
}
DWORD WINAPI PlaySnd(LPVOID)
{
soundtype LocSndPar;
int lTarray;
while (gTenter > gTexit && gTsig == FALSE)
{
gTwait++;
if (gTwait >= SNDQUE)
lTarray = gTwait % SNDQUE + 1;
else
lTarray = gTwait;
LocSndPar = SndPmtr[lTarray];
int Note = 0;
int Phrase = 0;
HMIDIOUT hMidi;
midiOutOpen(&hMidi, (UINT)-1, 0, 0, CALLBACK_NULL);
midiOutShortMsg(hMidi, (256 * LocSndPar.Voice) + 192);
// convert frequency to midi note
Note = (int)Round((log(LocSndPar.Freq) - log(440.0)) / log(2.0) * 12 + 69, 0);
Phrase = (LocSndPar.Vol * 256 + Note) * 256 + 144;
midiOutShortMsg(hMidi, Phrase);
Sleep((int)(LocSndPar.Dura * (1 / LocSndPar.Tempo + 0.0001)));
Phrase = (LocSndPar.Vol * 256 + Note) * 256 + 128;
midiOutShortMsg(hMidi, Phrase);
midiOutClose(hMidi);
gTexit++;
}
CloseHandle(gSThread);
gSThread = NULL;
return 0;
}
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question