944,155 Members | Top Members by Rank

Ad:
  • C++ Code Snippet
  • Views: 42641
  • C++ RSS
3

Play a MIDI voice (Dev C++ console program)

by on Nov 22nd, 2004
You can access the sound chip to play midi voices using winmm.lib, or in case of Dev C++ the libwinmm.a library. There are 128 midi voices to pick from, anything from the Acoustic Grand Piano = 0 to the Gunshot = 127.
C++ Code Snippet (Toggle Plain Text)
  1. // sound a tugboat toot using a midi voice from the winmm.lib
  2. // in case of Dev C++ link with libwinmm.a via
  3. // Project>>Project Options>>Parameters>>Add Lib>>libwinmm.a
  4. // BCX generated C code painstakingly modified for Dev C++
  5. //
  6. // Sound(Frequency,Duration[,Volume,Voice,Tempo])
  7. // Volume = 0 to 127 (off to loudest)
  8. // Voice = 0 to 127 (Shanai = 111, Tuba = 58, Accordion = 21)
  9. // more midi voices:
  10. // Rock Organ = 18, Marimba = 12, Steel String Guitar = 25
  11. // Choir Aahs = 52, Alto Sax = 65, Bird Tweet = 123, Sitar = 104
  12. // FX 8 (sci-fi) = 103, FX 3 (crystal) = 98, Glockenspiel = 9
  13. //
  14. // a Dev-C++ tested Console Application by vegaseat 21nov2004
  15.  
  16. #include <cmath>
  17. #include <windows.h>
  18. #include <mmsystem.h>
  19.  
  20. using namespace std;
  21.  
  22. #define SNDQUE 10000
  23.  
  24. typedef struct _soundtype
  25. {
  26. double Freq;
  27. int Dura;
  28. int Vol;
  29. int Voice;
  30. double Tempo;
  31. int sndTid;
  32. } soundtype, *LPSOUNDTYPE;
  33.  
  34. static soundtype SndPmtr[SNDQUE+1];
  35. static int gTenter;
  36. static int gTwait;
  37. static int gTexit;
  38. static int gTarray;
  39. static BOOL gTsig;
  40. static HANDLE gSThread = NULL;
  41.  
  42. double Round (double,int);
  43. double Abs (double);
  44. int Sound (float,int=0,int=127,int=0,float=1);
  45. // changed this from int PlaySnd(void) to:
  46. DWORD WINAPI PlaySnd (LPVOID);
  47.  
  48.  
  49. int main()
  50. {
  51. // Tugboat whistle sound 95 hertz, 2000ms, 127 = loud, 111 = Shanai
  52. // experiment with your own sounds, it's fun ...
  53. Sound(95,2000,127,111); // 2 second blast
  54. Sound( 1,1000, 0,111); // 1 second of silence
  55. Sound(95,2000,127,111); // 2 second blast
  56. Sound( 1,1000, 0,111); // 1 second of silence
  57. Sound(95,2000,127,111); // 2 second blast
  58.  
  59. // wait till que is empty
  60. while(Sound(0) != 0)
  61. {
  62. Sleep(10);
  63. }
  64.  
  65. return 0;
  66. }
  67.  
  68.  
  69. double Round (double n, int d)
  70. {
  71. return (floor((n)*pow(10.0,(d))+0.5)/pow(10.0,(d)));
  72. }
  73.  
  74.  
  75. double Abs (double a)
  76. {
  77. if (a < 0) return -a;
  78. return a;
  79. }
  80.  
  81.  
  82. int Sound (float Freq,int Dura,int Vol,int Voice,float Tempo)
  83. {
  84. DWORD dwThreadId;
  85.  
  86. if (Freq == 0 && Dura < 1) return gTenter-gTexit;
  87. // silence
  88. if (Freq == 0) Vol = 0;
  89. if (Dura < 5) Dura = 5;
  90. gTenter++;
  91. gTsig = FALSE;
  92. if (gTenter >= SNDQUE)
  93. {
  94. gTarray = gTenter % SNDQUE+1;
  95. }
  96. else
  97. {
  98. gTarray=gTenter;
  99. }
  100. SndPmtr[gTarray].Freq = Freq;
  101. SndPmtr[gTarray].Dura = Dura;
  102. SndPmtr[gTarray].Tempo = Tempo;
  103. SndPmtr[gTarray].Vol = Vol;
  104. SndPmtr[gTarray].Voice = Voice;
  105. SndPmtr[gTarray].sndTid = gTenter;
  106. if (gSThread == NULL && (Freq == Abs(Freq) || Freq == 0))
  107. {
  108. // "PlaySnd" needs casting (void *)
  109. gSThread = CreateThread(NULL,0,PlaySnd,(void *)"PlaySnd",0,&dwThreadId);
  110. Sleep(1);
  111. return 0;
  112. }
  113. if (Freq != Abs(Freq))
  114. {
  115. if (Freq == -1)
  116. {
  117. Freq = 0;
  118. SndPmtr[gTarray].Vol=0;
  119. }
  120. SndPmtr[gTarray].Freq=Abs(Freq);
  121. gTsig=TRUE;
  122. while(gSThread!=NULL)
  123. {
  124. Sleep(10);
  125. }
  126. gTexit = gTenter-1;
  127. gTwait = gTenter-1;
  128. gTsig = FALSE;
  129. return PlaySnd(0); // needs some kind of argument
  130. }
  131. return 0;
  132. }
  133.  
  134.  
  135. DWORD WINAPI PlaySnd (LPVOID)
  136. {
  137. soundtype LocSndPar;
  138. int lTarray;
  139.  
  140. while(gTenter > gTexit && gTsig == FALSE)
  141. {
  142. gTwait++;
  143. if (gTwait >= SNDQUE)
  144. lTarray = gTwait % SNDQUE+1;
  145. else
  146. lTarray = gTwait;
  147. LocSndPar = SndPmtr[lTarray];
  148. int Note = 0;
  149. int Phrase = 0;
  150. HMIDIOUT hMidi;
  151. midiOutOpen(&hMidi,(UINT)-1,0,0,CALLBACK_NULL);
  152. midiOutShortMsg(hMidi,(256*LocSndPar.Voice)+192);
  153. // convert frequency to midi note
  154. Note = (int)Round((log(LocSndPar.Freq)-log(440.0))/log(2.0)*12+69,0);
  155. Phrase = (LocSndPar.Vol*256+Note)*256+144;
  156. midiOutShortMsg(hMidi,Phrase);
  157. Sleep((int)(LocSndPar.Dura*(1/LocSndPar.Tempo+0.0001)));
  158. Phrase = (LocSndPar.Vol*256+Note)*256+128;
  159. midiOutShortMsg(hMidi,Phrase);
  160. midiOutClose(hMidi);
  161. gTexit++;
  162. }
  163. CloseHandle(gSThread);
  164. gSThread = NULL;
  165. return 0;
  166. }
  167.  
Comments on this Code Snippet
Jan 31st, 2005
0

Re: Play a MIDI voice (Dev C++ console program)

Replaced Mr. Bloat header iostream with the correct cmath header. This brought the exe file size down from 400k to 19k. Sorry about any discommode!
DaniWeb's Hypocrite
vegaseat is offline Offline
5,792 posts
since Oct 2004
Mar 9th, 2007
0

Re: Play a MIDI voice (Dev C++ console program)

The code works perfect in DEV C++, but it does not for VC++ (I am running Visual Studio 2005).
Light Poster
Tales is offline Offline
37 posts
since Mar 2007
Nov 24th, 2007
0

Re: Play a MIDI voice (Dev C++ console program)

To compile in Visual Studio, add
C++ Syntax (Toggle Plain Text)
  1. #pragma comment(lib, "winmm.lib")
Posting Whiz in Training
bugmenot is offline Offline
224 posts
since Nov 2006
Sep 1st, 2008
0

Re: Play a MIDI voice (Dev C++ console program)

This is good code, but I am trying to turn my keyboard into a piano for a fun console app (u dont know how boring cubicles are until u live in one). I do graphics (mostly) and have no experience in sound beyond system bells. Can someone provide some simple musical note code?
Newbie Poster
t3ch|\/|4n is offline Offline
6 posts
since Aug 2008
Sep 30th, 2009
0

Re: Play a MIDI voice (Dev C++ console program)

Thanks for the code, but when I tried to run it (in Dev C++ and Codeblocks) it was having problem with midiOutOpen()

Did I miss something?
Newbie Poster
Pepperonio is offline Offline
2 posts
since Sep 2009
Sep 30th, 2009
-2

Re: Play a MIDI voice (Dev C++ console program)

Use Petzold code instead, 10 x better.
Junior Poster
marco93 is offline Offline
132 posts
since Apr 2008
Oct 1st, 2009
0

Re: Play a MIDI voice (Dev C++ console program)

Dear Vegaseat,

I am interested to hear music or sound from your midi program using Dev-C++. And I did the following as well:

Project>>Project Options>>Parameters>>Add Lib>>libwinmm.a

I created a console application. In Main.cpp, I pasted your whole program. Managed to compile successfully.

When I executed the compiled program, I got a blank screen with a blinking cursor on the top right hand corner, but no sound output.

What could I have done incorrectly?

Regards,
Junior Poster in Training
yonghc is offline Offline
55 posts
since Aug 2009
Nov 14th, 2009
0

Re: Play a MIDI voice (Dev C++ console program)

thank you vegaseat your snippet up above worked perfectly in my dev c++. I've gone to the "add to reputation" page where I've left you a nod. thanks again. though ... I was wondering about this BCX that was talked about on an other page I looked at. I've been building things in classic vb6 since 1999 now & was curious to know if this BCX could translate its code to compile some working C/C++ apps. otherwise i might have to migrate over to quick basic if BCX might be finicky about what type of basic code it can translate. I've done some audio work with vb6 and have a certain project where I've "installed" a directx 8 reference and built a sound generator. It sounds pretty nice, the blending of the multi-oscillator output is very sweet, plus i have added an additional feature that could render a singular *.wav sound. though with all that could be in C/C++ or vb6 programming, I would seriously love to develop VST synth plugins with C/C++. I suppose that would take some time doing, but in any case thanks so much for your midi tutorial I've learned much from it in the time that I've studied it.

though if i could ask for one small favor possibly ? any chance i could find a snippet to allow a windows frame accompanied with buttons to play separate sounds ? and then possibly a selector where different MIDI fonts could be chosen at runtime ? i'm always trying to enhance what i could learn about audio programming. i've built some fairly decent VST plugins in max/msp. (www.cycling74.com)
max/msp has helped me to learn much of a different type of visual programming. it is a visual OOP environment, though, it does have its drawbacks/shortcomings to a slight extent. please pardon my sounding a bit greedy for information, i wasnt trying to be,... though i would love to know as much as i can about EVERYTHING audio where vb6/C/C++ is concerned. and i thank you ever so much for your showing the snippet.

5/5 stars. Nice concise code. Great comments. Compiled and run on MSVC 6.0 no problem after commenting out

5/5 stars. Nice concise code. Great comments. Compiled and run on MSVC 6.0 no problem after commenting out the using namespace std;

using namespace std;
Last edited by peter_budo; Apr 24th, 2010 at 6:31 am. Reason: Merging multiple comments
Newbie Poster
aseire is offline Offline
1 posts
since Apr 2010
Jan 24th, 2011
0

Grat solution

Great solution Vegaseat, I used this code for playing notes by frequency and it was a lot of fun-->

http://latecladeescape.com/recetas-algoritmicas/frecuencia-de-las-notas-musicales.html
Newbie Poster
Metalpeich is offline Offline
1 posts
since Jan 2011
Message:
Previous Thread in C++ Forum Timeline: How to terminate character read without EOF
Next Thread in C++ Forum Timeline: windows.h





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC