Control MIDI left and right volume

500ff421d07d4d8e636c0267f6103691
0
123abcd1983 101 Mar 26, 2007 at 20:38

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;
}

4 Replies

Please log in or register to post a reply.

647e430ca6b2c38d008dc55b1c3a7ecc
0
karligula 101 Mar 27, 2007 at 14:54

This might be totally wrong, but I interpret the sentence you quoted given by the msdn library as saying, the bottom eight bits contain the left channel volume and the top eight bits contain the right channel volume.

So to set the right volume to maximum and the left volume to silence, you’d use:

midiOutSetVolume(hdev, 0xff00);

Never used it myself but it’s worth a try!

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 168 Mar 27, 2007 at 17:41

It’s the low and high order word (16-bit) of a 32 bit value, not the low and high byte of a 16-bit value. So, it should be midiOutSetVolume(hdev, 0xffff0000). Another way to control it would be to set the pan controller, which is a built in MIDI message.

500ff421d07d4d8e636c0267f6103691
0
123abcd1983 101 Mar 28, 2007 at 04:04

@Reedbeta

It’s the low and high order word (16-bit) of a 32 bit value, not the low and high byte of a 16-bit value. So, it should be midiOutSetVolume(hdev, 0xffff0000). Another way to control it would be to set the pan controller, which is a built in MIDI message.

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.”

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 168 Mar 28, 2007 at 04:08

The second paragraph basically means you don’t need to worry about whether the device supports a full 16 bits of volume control or not. You can use the same volume settings anyway. The third paragraph is pretty much irrelevant.

Have you checked the midiOutGetDevCaps function to see if the MIDICAPS_LRVOLUME is supported?