Control MIDI left and right volume

Started by
2 comments, last by LorenzoGatti 17 years ago
-------------------------------------------------------------------------------- Hi, I have some problem by using the midi file. I wish to control the left and the right channels volumes, and i got some information from msdn library, but it didn't tell me the exact way to do it. Could anyone tell me what is the meaning of "The low-order word contains the left-channel volume setting, and the high-order word contains the right-channel setting. A value of 0xFFFF represents full volume, and a value of 0x0000 is silence." The sentence above i copy from the the msdn library of MidiOutGetVolume and midiOutSetVolume. Does it mean the low order is 0x000 to 0x7777(left channel) and 0x8000 to 0xFFFF is high order (right channel)? The code below is modified from an example from internet. Although I set the midiOutSetVolume(hdev, 0xF000); But it didn't work at all. Anyone have similar example could control the left and right volumes? I already stuck on this step quite a while. I wish someone could give some suggestion for me. Thanks a lot.

#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "Winmm.lib")
#define NOTE_ON 0x90
#define NOTE_OFF 0x80

//command, note, velocity
#define MAKE_MSG(X, Y, Z) (X + (Y<<8) + (Z<<16))

int playChord(HMIDIOUT hdev)
{
 --->  midiOutSetVolume(hdev, 0x0000);
       midiOutShortMsg(hdev, MAKE_MSG(NOTE_ON, 62, 65));
       Sleep(1000);
 --->  midiOutSetVolume(hdev, 0xF000);
       midiOutShortMsg(hdev, MAKE_MSG(NOTE_ON, 62, 65));
       Sleep(1000);
 --->  midiOutSetVolume(hdev, 0x5555);
       midiOutShortMsg(hdev, MAKE_MSG(NOTE_ON, 62, 65));
       Sleep(1000);
 --->  midiOutSetVolume(hdev, 0xFFF0);
       midiOutShortMsg(hdev, MAKE_MSG(NOTE_ON, 62, 65));

       Sleep(1000);

       midiOutShortMsg(hdev, MAKE_MSG(NOTE_OFF, 62, 65));
       midiOutShortMsg(hdev, MAKE_MSG(NOTE_OFF, 62, 65));
       midiOutShortMsg(hdev, MAKE_MSG(NOTE_OFF, 62, 65));
       midiOutShortMsg(hdev, MAKE_MSG(NOTE_OFF, 62, 65));

       return 0;
}

int main()
{
       HMIDIOUT hdev;
       static MIDIOUTCAPS devCaps;
       static LPMIDIOUTCAPS lpCaps = &devCaps;
       DWORD abc;

  ---> devCaps.dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME;

       abc = devCaps.dwSupport;
       if (devCaps.dwSupport == MIDICAPS_VOLUME|MIDICAPS_LRVOLUME)
       {
              wprintf(L"abc");
       }

       midiOutGetDevCaps(0, lpCaps, sizeof(MIDIOUTCAPS)); // Get device capabilities for first device (curDevice == 0)
       midiOutOpen(&hdev, -1, NULL, NULL, CALLBACK_NULL);

       midiOutSetVolume(hdev, 0x0000);

       wchar_t menu_sel = 0;

       while(menu_sel != 'q')
       {
              wprintf(L"Midi test app\nc: play chord\nd: change device\nv: set volume\nq: quit\n");
              wscanf(L" %c", &menu_sel);

              switch(menu_sel)
              {
              case 'q':
                     break;
              case 'c':
                     playChord(hdev);
                     break;
              default:
                     wprintf(L"try again\n");
                     break;
              }
       }
       midiOutClose(hdev);

       return 0;
}


Advertisement
By high and low order it's referring to packaging two words together to form a single 32-bit integer. That is, 0xFFFFFFFF is both channels full volume, 0xFFFF0000 is right channel full on and left channel off, 0x80008000 is both channels at half-way and 0x00008000 is left channel at half-way.

You can pack them together by using bitwise shifts and OR;

int Left = 0xFFFF;int Right = 0x8000;int Packed = (Right << 16) | Left;// Packed = 0x8000FFFF


(I haven't used this function before, so am going by what you've said in your post alone).

[Website] [+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++]

Quote:Original post by benryves
By high and low order it's referring to packaging two words together to form a single 32-bit integer. That is, 0xFFFFFFFF is both channels full volume, 0xFFFF0000 is right channel full on and left channel off, 0x80008000 is both channels at half-way and 0x00008000 is left channel at half-way.

You can pack them together by using bitwise shifts and OR;

int Left = 0xFFFF;int Right = 0x8000;int Packed = (Right << 16) | Left;// Packed = 0x8000FFFF


(I haven't used this function before, so am going by what you've said in your post alone).



hi i already try your's way, but it still didn't work. The text below i copied from msdn library. I think i understand the first paragraph. But i'm not really understand the paragraph 2 and 3. Could you give me some suggestion?

http://msdn2.microsoft.com/en-us/library/ms711639.aspx

"You can also determine whether the device supports volume control on both the left and right channels by querying the device using the midiOutGetDevCaps function and the MIDICAPS_LRVOLUME flag.

Devices that do not support a full 16 bits of volume-level control use the high-order bits of the requested volume setting. For example, a device that supports 4 bits of volume control produces the same volume setting for the following volume-level values: 0x4000, 0x43be, and 0x4fff. The midiOutGetVolume function returns the full 16-bit value, as set by midiOutSetVolume, irrespective of the device's capabilities.

Volume settings are interpreted logarithmically. This means that the perceived increase in volume is the same when increasing the volume level from 0x5000 to 0x6000 as it is from 0x4000 to 0x5000."
I guess you should use MIDI pan and/or balance controller change messages. You'll need to use midiOutShortMsg, there is no ad hoc function (by the way volume is a 14-bit controller change, not a special feature of the Windows Multimedia API).

Omae Wa Mou Shindeiru

This topic is closed to new replies.

Advertisement