home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mmoshead.zip / samples / rhythm / rhythm.cc < prev    next >
Text File  |  1994-02-24  |  12KB  |  551 lines

  1. ///////////////////////////////////////
  2. // rhythm - waveaudio playlist sample
  3. //
  4. // using emx 0.8h, mm4emx 1.0
  5. //
  6. //
  7. // Marc E.E. van Woerkom, 2/94
  8. //
  9.  
  10.  
  11. #include <os2.h>
  12.  
  13. #define  INCL_OS2MM
  14. #include <os2me.h>
  15.  
  16. #include <iostream.h>
  17. #include <iomanip.h>
  18.  
  19.  
  20. // prototypes 
  21.  
  22. void mci_err(ULONG);
  23. void mmio_err(ULONG);
  24.  
  25.  
  26. //
  27. // mmaudioheader
  28. //
  29.  
  30. class mmaudioheader {
  31.     MMAUDIOHEADER mmah;
  32. public:
  33.     mmaudioheader();
  34.     MMAUDIOHEADER* get_addr() { return &mmah; }
  35.     LONG           get_size() { return sizeof(mmah); }
  36. };
  37.  
  38.  
  39. mmaudioheader::mmaudioheader()
  40. {
  41.     char* p = (char*) &mmah;
  42.     for (int i=0; i<sizeof(mmah); i++) p[i] = 0;
  43. }
  44.  
  45.  
  46. //
  47. // mem_wav: a waveaudio file loaded into memory
  48. //
  49.  
  50. class mem_wav {
  51.     HMMIO  hmmio;
  52.     PSZ    bptr;
  53.     ULONG  bsize;
  54.     ULONG  SamplesPerSec;
  55.     USHORT BitsPerSample;
  56. public:
  57.     mem_wav(char*);
  58.     ~mem_wav();
  59.     PSZ    get_bptr() { return bptr; }
  60.     ULONG  get_bsize() { return bsize; }
  61.     ULONG  get_SamplesPerSec() { return SamplesPerSec; }
  62.     USHORT get_BitsPerSample() { return BitsPerSample; }
  63. };
  64.  
  65.  
  66. mem_wav::mem_wav(char* name)
  67. {
  68.     // open the file
  69.  
  70.     hmmio = mmioOpen(name, 0, MMIO_READ);
  71.  
  72.  
  73.     // get header
  74.  
  75.     mmaudioheader mmah;
  76.  
  77.     ULONG BytesRead = 0;
  78.  
  79.     ULONG rc = mmioGetHeader(hmmio, mmah.get_addr(), mmah.get_size(),
  80.                              &BytesRead, 0, 0);
  81.  
  82.     if (rc != MMIO_SUCCESS) mmio_err(rc);
  83.  
  84.  
  85.     // get some infos about the waveaudio file
  86.  
  87.     SamplesPerSec = mmah.get_addr()->mmXWAVHeader.WAVEHeader.ulSamplesPerSec;
  88.     BitsPerSample = mmah.get_addr()->mmXWAVHeader.WAVEHeader.usBitsPerSample;
  89.  
  90.     bsize = mmah.get_addr()->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes;
  91.     bptr  = new CHAR[bsize];
  92.  
  93.  
  94.     // read file
  95.  
  96.     rc = mmioRead(hmmio, bptr, bsize);
  97.  
  98.     if (rc == MMIO_ERROR) mmio_err(rc);
  99.  
  100.     cout << "[file " << name
  101.          << ": read" << setw(7) << rc
  102.          << " bytes of" << setw(7) << bsize << "]\n";
  103.  
  104.  
  105.     // close file
  106.  
  107.     rc = mmioClose(hmmio, 0);
  108.     if (rc != MMIO_SUCCESS) mmio_err(rc);
  109. }
  110.  
  111.  
  112. mem_wav::~mem_wav()
  113. {
  114.     delete[] bptr;
  115. }
  116.  
  117.  
  118. //
  119. // ple: a playlist entry
  120. //
  121.  
  122. struct ple {
  123.     ULONG operation;
  124.     ULONG operand1;
  125.     ULONG operand2;
  126.     ULONG operand3;
  127. };
  128.  
  129.  
  130. //
  131. // playlist: a waveaudio playlist
  132. //
  133.  
  134. class playlist {
  135.     ple*     pl;
  136.     int      size, used;
  137.     mem_wav& m0, m1, m2, m3, m4, m5, s1, p1;
  138.     void setup();
  139. public:
  140.     playlist(mem_wav&, mem_wav&, mem_wav&, mem_wav&,
  141.              mem_wav&, mem_wav&, mem_wav&, mem_wav&, int);
  142.     ~playlist();
  143.     ple* get_addr() { return pl; }
  144.     int add(ULONG =0, ULONG =0, ULONG =0, ULONG =0);
  145.     int add_branch(ULONG);
  146.     int add_call(ULONG);
  147.     int add_data(mem_wav&);
  148.     int add_exit();
  149.     int add_return();
  150. };
  151.  
  152.  
  153. playlist::playlist(mem_wav& M0, mem_wav& M1, mem_wav& M2, mem_wav& M3,
  154.                    mem_wav& M4, mem_wav& M5, mem_wav& S1, mem_wav& P1,
  155.                    int Size)
  156.     : m0(M0), m1(M1), m2(M2), m3(M3), m4(M4), m5(M5), s1(S1), p1(P1),
  157.       size(Size)
  158. {
  159.     if (size < 1) cerr << "error: wrong playlist size!\n";
  160.  
  161.     pl = new ple[size];
  162.     used = 0;
  163.  
  164.     setup();
  165. }
  166.  
  167.  
  168. playlist::~playlist()
  169. {
  170.     delete[] pl;
  171. }
  172.  
  173.  
  174. int playlist::add(ULONG op=0, ULONG opd1=0, ULONG opd2=0, ULONG opd3=0)
  175. {
  176.     if (used >= size) {
  177.         cerr << "error: playlist is too small!\n";
  178.         return -1;
  179.     }
  180.  
  181.     pl[used].operation = op;
  182.     pl[used].operand1  = opd1;
  183.     pl[used].operand2  = opd2;
  184.     pl[used].operand3  = opd3;
  185.  
  186.     return used++;
  187. }
  188.  
  189.  
  190. int playlist::add_branch(ULONG addr)
  191. {
  192.     return add(BRANCH_OPERATION, 0, addr);
  193. }
  194.  
  195.  
  196. int playlist::add_call(ULONG addr)
  197. {
  198.     return add(CALL_OPERATION, 0, addr);
  199. }
  200.  
  201.  
  202. int playlist::add_data(mem_wav& mw)
  203. {
  204.     return add(DATA_OPERATION, ULONG(mw.get_bptr()), mw.get_bsize());
  205. }
  206.  
  207.  
  208. int playlist::add_exit()
  209. {
  210.     return add(EXIT_OPERATION);
  211. }
  212.  
  213.  
  214. int playlist::add_return()
  215. {
  216.     return add(RETURN_OPERATION);
  217. }
  218.  
  219.  
  220. void playlist::setup()
  221. {
  222.                   add_branch(70);
  223.  
  224.     ULONG Intro = add_data(m0);
  225.                   add_data(m1);
  226.                   add_data(m1);
  227.                   add_return();
  228.  
  229.     ULONG A10a =  add_data(m2);
  230.                   add_data(s1);
  231.                   add_data(p1);
  232.                   add_data(m3);
  233.                   add_data(m4);
  234.                   add_data(m5);
  235.                   add_data(m4);
  236.                   add_data(m5);
  237.                   add_data(m4);
  238.                   add_data(m5);
  239.                   add_return();
  240.  
  241.     ULONG A10 =   add_data(m2);
  242.                   add_data(s1);
  243.                   add_data(p1);
  244.                   add_data(m5);
  245.                   add_data(m4);
  246.                   add_data(m5);
  247.                   add_data(m4);
  248.                   add_data(m5);
  249.                   add_data(m4);
  250.                   add_data(m5);
  251.                   add_return();
  252.  
  253.     ULONG B10 =   add_data(m2);
  254.                   add_data(s1);
  255.                   add_data(p1);
  256.                   add_data(m1);
  257.                   add_data(m1);
  258.                   add_data(m1);
  259.                   add_data(m1);
  260.                   add_data(m1);
  261.                   add_data(m1);
  262.                   add_data(m1);
  263.                   add_return();
  264.  
  265.     ULONG C10 =   add_data(m2);
  266.                   add_data(s1);
  267.                   add_data(p1);
  268.                   add_data(m2);
  269.                   add_data(m2);
  270.                   add_data(m2);
  271.                   add_data(m2);
  272.                   add_data(m2);
  273.                   add_data(m2);
  274.                   add_data(m2);
  275.                   add_return();
  276.  
  277.     ULONG A6 =    add_data(m2);
  278.                   add_data(s1);
  279.                   add_data(p1);
  280.                   add_data(m5);
  281.                   add_data(m4);
  282.                   add_data(m5);
  283.                   add_return();
  284.  
  285.     ULONG B6 =    add_data(m2);
  286.                   add_data(s1);
  287.                   add_data(p1);
  288.                   add_data(m1);
  289.                   add_data(m1);
  290.                   add_data(m1);
  291.                   add_return();
  292.  
  293.     ULONG C6 =    add_data(m2);
  294.                   add_data(s1);
  295.                   add_data(p1);
  296.                   add_data(m2);
  297.                   add_data(m2);
  298.                   add_data(m2);
  299.                   add_return();
  300. // #70
  301.                   add_call(Intro);
  302.                   add_call(A10a);
  303.                   add_call(B10);
  304.                   add_call(A10);
  305.                   add_call(B10);
  306.                   add_call(A10);
  307.                   add_call(C10);
  308.                   add_call(A6);
  309.                   add_call(B6);
  310.                   add_call(A6);
  311.                   add_call(C10);
  312.                   add_call(A10);
  313.                   add_call(C10);
  314.                   add_call(A10);
  315.                   add_call(A10);
  316.                   add_call(A10);
  317.                   add_call(C10);
  318.                   add_call(A6);
  319.                   add_call(C6);
  320.                   add_call(A6);
  321.                   add_call(B10);
  322.                   add_data(s1);
  323.                   add_exit();
  324. }
  325.  
  326.  
  327. //
  328. // waveaudio: a waveaudio device
  329. //
  330.  
  331. class waveaudio {
  332.     MCI_OPEN_PARMS mop;
  333. public:
  334.     waveaudio(playlist&, mem_wav&);
  335.     ~waveaudio();
  336.     void play();
  337. };
  338.  
  339.  
  340. waveaudio::waveaudio(playlist& pl, mem_wav& mw)
  341. {
  342.     // open device
  343.  
  344.     mop.hwndCallback   = 0;
  345.     mop.usDeviceID     = 0;
  346.     mop.pszDeviceType  = MCI_DEVTYPE_WAVEFORM_AUDIO_NAME;
  347.     mop.pszElementName = PSZ(pl.get_addr());
  348.  
  349.     ULONG rc = mciSendCommand(0,
  350.                               MCI_OPEN,                        // open message
  351.                               MCI_WAIT | MCI_OPEN_SHAREABLE |  // message flags
  352.                               MCI_OPEN_PLAYLIST,
  353.                               &mop,                            // parameters
  354.                               0);
  355.  
  356.     if (rc != MCIERR_SUCCESS) mci_err(rc);
  357.  
  358.  
  359.     // set device parameters
  360.  
  361.     MCI_WAVE_SET_PARMS wsp;
  362.  
  363.     wsp.hwndCallback    = 0;
  364.     wsp.ulSamplesPerSec = mw.get_SamplesPerSec();
  365.     wsp.usBitsPerSample = mw.get_BitsPerSample();
  366.  
  367.     rc = mciSendCommand(mop.usDeviceID,
  368.                         MCI_SET,
  369.                         MCI_WAIT |
  370.                         MCI_WAVE_SET_SAMPLESPERSEC |
  371.                         MCI_WAVE_SET_BITSPERSAMPLE,
  372.                         &wsp,
  373.                         0);
  374.  
  375.     if (rc != MCIERR_SUCCESS) mci_err(rc);
  376. }
  377.  
  378.  
  379. waveaudio::~waveaudio()
  380. {
  381.     // close device
  382.  
  383.     MCI_GENERIC_PARMS mgp;
  384.  
  385.     mgp.hwndCallback = 0;
  386.  
  387.     ULONG rc = mciSendCommand(mop.usDeviceID,
  388.                               MCI_CLOSE,
  389.                               MCI_WAIT,
  390.                               &mgp,
  391.                               0);
  392.  
  393.     if (rc != MCIERR_SUCCESS) mci_err(rc);
  394. }
  395.  
  396.  
  397. void waveaudio::play()
  398. {
  399.     // play the playlist
  400.  
  401.     MCI_PLAY_PARMS mpp;
  402.  
  403.     mpp.hwndCallback = 0;
  404.  
  405.     ULONG rc = mciSendCommand(mop.usDeviceID,
  406.                               MCI_PLAY,
  407.                               MCI_WAIT,
  408.                               &mpp,
  409.                               0);
  410.  
  411.     if (rc != MCIERR_SUCCESS) mci_err(rc);
  412. }
  413.  
  414.  
  415. //
  416. // mci_err: translate the MCI return code into an error string
  417. //
  418.  
  419. void mci_err(ULONG rc)
  420. {
  421.     const rsize = 128;
  422.     char rbuff[rsize];
  423.  
  424.     ULONG rc2 = mciGetErrorString(rc,      // error code
  425.                                   rbuff,   // return buffer
  426.                                   rsize);  // rbuff size
  427.  
  428.     if (rc2 == MCIERR_SUCCESS)
  429.         cerr << "MCI error: " << rbuff << "\n\n";
  430.     else
  431.         cerr << "error #" << rc << " has occured!\n\n";
  432. }
  433.  
  434.  
  435. //
  436. // mmio_err: translate MMIO error code into a string
  437. //
  438.  
  439. void mmio_err(ULONG rc)
  440. {
  441.     cerr << "MMIO error: ";
  442.  
  443.     char* s;
  444.  
  445.     switch (rc) {
  446.     case MMIO_SUCCESS:
  447.         s = "SUCCESS (huh?)";
  448.         break;
  449.     case MMIOERR_UNBUFFERED:
  450.         s = "UNBUFFERD";
  451.         break;
  452.     case MMIOERR_INVALID_HANDLE:
  453.         s = "INVALID HANDLE";
  454.         break;
  455.     case MMIOERR_INVALID_PARAMETER:
  456.         s = "INVALID PARAMETER";
  457.         break;
  458.     case MMIOERR_READ_ONLY_FILE:
  459.         s = "READ ONLY FILE";
  460.         break;
  461.     case MMIOERR_WRITE_ONLY_FILE:
  462.         s = "WRITE ONLY FILE";
  463.         break;
  464.     case MMIOERR_WRITE_FAILED:
  465.         s = "WRITE FAILED";
  466.         break;
  467.     case MMIOERR_READ_FAILED:
  468.         s = "READ FAILED";
  469.         break;
  470.     case MMIOERR_SEEK_FAILED:
  471.         s = "SEEK FAILED";
  472.         break;
  473.     case MMIOERR_NO_FLUSH_NEEDED:
  474.         s = "NO FLUSH NEEDED";
  475.         break;
  476.     case MMIOERR_OUTOFMEMORY:
  477.         s = "OUT OF MEMORY";
  478.         break;
  479.     case MMIOERR_CANNOTEXPAND:
  480.         s = "CANNOT EXPAND";
  481.         break;
  482.     case MMIOERR_FREE_FAILED:
  483.         s = "FREE FAILED";
  484.         break;
  485.     case MMIOERR_CHUNKNOTFOUND:
  486.         s = "CHUNK NOT FOUND";
  487.         break;
  488.     case MMIO_ERROR:
  489.         s = "ERROR";
  490.         break;
  491.     case MMIO_WARNING:
  492.         s = "WARNING";
  493.         break;
  494.     case MMIO_CF_FAILURE:
  495.         s = "CF FAILURE";
  496.         break;
  497.     default:
  498.         cerr << rc;
  499.         s = " (hmm...)";
  500.     }
  501.  
  502.     cerr << s << "\n";
  503. }
  504.  
  505.  
  506. //
  507. // main
  508. //
  509.  
  510. int main()
  511. {
  512.     cout << "rhythm -- a Rhythm Generator\n\n";
  513.  
  514.  
  515.     // load waveaudio files into memory
  516.  
  517.     cout << "loading waveaudio files into memory ...\n\n";
  518.  
  519.     mem_wav m0("m0.wav");
  520.     mem_wav m1("m1.wav");
  521.     mem_wav m2("m2.wav");
  522.     mem_wav m3("m3.wav");
  523.     mem_wav m4("m4.wav");
  524.     mem_wav m5("m5.wav");
  525.     mem_wav s1("s1.wav");
  526.     mem_wav p1("p1.wav");
  527.  
  528.  
  529.     // set up playlist
  530.  
  531.     cout << "\nsetting up playlist ...\n\n";
  532.  
  533.     playlist pl(m0, m1, m2, m3, m4, m5, s1, p1, 100);
  534.  
  535.  
  536.     // play playlist
  537.  
  538.     cout << "and ... go!   (you should pump up the volume :-)\n\n";
  539.  
  540.     waveaudio wav(pl, m0);
  541.     wav.play();
  542.      
  543.  
  544.     // that's all folks!
  545.  
  546.     cout << "... done. yeah!\n";
  547.  
  548.     return 0;
  549. }
  550.  
  551.