Community

SCI Programming => SCI Development Tools => Topic started by: MusicallyInspired on May 25, 2021, 07:10:16 PM

Title: Set channel properties for Sound resources in Companion?
Post by: MusicallyInspired on May 25, 2021, 07:10:16 PM
I may have brought this up before, I don't remember. I discovered while streaming today that Companion doesn't seem to have the ability to alter channel properties on Sound resources. Mainly the "Initial Voices" value. This is important for Adlib because if it's not set no notes will be played at all. Ravi's SoundBox program can set this but it's only compatible with SCI0 Sound resources, which makes it unhelpful for SCI1+ games.

What the Initial Voices value does is set the polyphony limit for the channel it's set on. I think Adlib has a maximum limit of 8 voices across all Adlib channels total. I think some stereo OPL drivers (sndblast?) ignore this and have a higher polyphony limit but I'd like to be able to to support the original mono adl.drv driver too.

Unless Companion already supports this and I've missed it lol. The source for SoundBox is freely available so I'm going to take a look at it later tonight too.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: MusicallyInspired on May 27, 2021, 07:02:27 PM
Thankfully, it seems that setting the "initial voices" flag on each channel is handled right in the header of each sound resource (which makes sense) so it is probably easy enough to add this functionality to Companion for SCI0 resources anyway. I'm checking out the source to see how Companion handles SCI1 sound resources to see if I can find where(/if) it sets this flag there...

EDIT: Kawa, I'm trying to open your Companion fork source in Visual Studio but it's giving me errors saying it can't find any DIALOGs. Any idea what's going on there? I don't have much experience working with MFC program stuff...
Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on May 28, 2021, 08:05:13 AM
Kawa, I'm trying to open your Companion fork source in Visual Studio but it's giving me errors saying it can't find any DIALOGs. Any idea what's going on there? I don't have much experience working with MFC program stuff...
I got nothing. I open it in 2015 Community and I can build all three variations, regular mild and kawa, with no issues 🤷‍♀️
Title: Re: Set channel properties for Sound resources in Companion?
Post by: troflip on May 28, 2021, 07:04:33 PM
Make sure you have the MFC components installed for your visual studio.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: MusicallyInspired on May 28, 2021, 11:40:03 PM
I do. I had to do so to open the SoundBox source. And I can see those Dialogs just fine. But with Companion when I try to open anything it says it can't find any Dialogs and gives me the option to just edit the code instead. I guess I should try and earlier version then.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: EricOakford on October 21, 2021, 12:44:52 AM
It would be a good idea to add the ability to set the initial voices. I have managed to export the title and death music for SQ:TLC into MIDI for the purpose of bringing them into the SCI01 remake. I can then import the MIDI files into the game, but the music won't play.

Naturally, Soundbox only supports SCI0, and the sounds need to be in SCI1 format.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: MusicallyInspired on October 21, 2021, 01:03:18 AM
I gave up trying to edit the Companion source because of the error messages I keep getting and I can't seem to get an earlier version of Visual Studio working either.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: doomlazer on October 21, 2021, 03:26:33 PM
I've run into this sound issue several times as well.

I couldn't find a working version of VS 2015 Community, but I was able to get Kawa's SC fork to build without errors from a fresh install of Visual Studio Community 2019. It required adding the MFC Build Tools (see attached pic for reference) and installing the windows 8.1 SDK manually from here: https://go.microsoft.com/fwlink/p/?LinkId=323507 as they removed that SDK in 2019. Then I was able to clone the repo, choose not to upgrade the targets, and build without error.

Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 21, 2021, 03:55:48 PM
What I find interesting here is this part:
This is important for Adlib because if it's not set no notes will be played at all.
I know for a fact the music in The Dating Pool works fine on AdLib, which I import from .mid files in SCI Companion. Of course, that's an SCI11 game, not SCI1...
Title: Re: Set channel properties for Sound resources in Companion?
Post by: MusicallyInspired on October 22, 2021, 12:22:42 AM
What I find interesting here is this part:
This is important for Adlib because if it's not set no notes will be played at all.
I know for a fact the music in The Dating Pool works fine on AdLib, which I import from .mid files in SCI Companion. Of course, that's an SCI11 game, not SCI1...

There's a difference in drivers too remember. There is a stereo OPL driver that ignores the initial voices value, but the original ADL.DRV won't play notes without that value set.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: doomlazer on October 22, 2021, 01:32:47 AM
I'm checking out the source to see how Companion handles SCI1 sound resources to see if I can find where(/if) it sets this flag there...

I found _onImportMidi(). Would adding all six devices to every imported midi solve the problem?

Code: [Select]
void CSoundDoc::_OnImportMidi()
{
std::unique_ptr<ResourceEntity> pSound = GetResource()->Clone();

// Import to devices (tracks) that are standard by default.
std::vector<DeviceType> devices;
if (appState->GetVersion().SoundFormat == SoundFormat::SCI1)
{
// REVIEW: Sounds appear not to play properly if these three devices don't appear in the sound resource.
devices.insert(devices.end(), { DeviceType::SCI1_Adlib, DeviceType::SCI1_GM, DeviceType::SCI1_RolandGM });
}
else
{
devices.insert(devices.end(), { DeviceType::Adlib, DeviceType::NewGM, DeviceType::RolandMT32 });
}
Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 22, 2021, 05:58:36 AM
In Resources\Sound.cpp there's this part at line 1214:
Code: [Select]
// Channel information:
for (size_t i = 0; i < SCI0ChannelCount; i++)
{
// Each word tells us which devices use this channel.
// We can leave the lower byte blank (it should be ignored), and the upper 8 bits indicate which devices.
uint16_t channelMask = 0;
for (const auto &trackInfo : soundCopy._tracks)
{
for (int channelId : trackInfo.ChannelIds)
{
if (soundCopy._allChannels[channelId].Number == i)
{
// This channel is used for this device.
channelMask |= (trackInfo.Type << 8);
}
}
}
byteStream.WriteWord(channelMask);
}
byteStream.WriteWord(0); // Digital sample offset - we don't care about this for SCI0.

And on the ScummVM wiki, on a page originally written by Ravi no less:
Quote
The upper 4 bits of that byte specify how many voices each logical MIDI channel will be playing. The lower 4 bits specify which drivers should react on that channel. Bit 0 set means AdLib shall react. Bit 1 set means PCjr shall react. MT32 will react on all channels. Bit 3 signals the control channel.

Now look at that first part of the code again.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: doomlazer on October 22, 2021, 11:42:00 AM
What I'm taking from your reply is that adding more DeviceTypes to the array isn't going to affect the bit 0, so that's not the answer.

I really haven't spent much time with C++ and even less with bitwise operations, so I think I might be missing some subtlety of this operation:

Code: [Select]
channelMask |= (trackInfo.Type << 8);
I looked at the DeviceType enum and there only seems to be two relevant adlib types, SCI1_Adlib and Adlib. Is that << shift messing things up when SCI1_Adlib is used? I'll read up on the bitwise stuff to see if I can better understand what's happening there.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 22, 2021, 12:11:17 PM
Okay so channel mask starts out as zero, which is where the fun relevant to this thread's entire purpose begins.

Device types are listed in Sound.h, line 31-56:
Code: [Select]
enum class DeviceType
{
// SCI0 - these can be OR'd together
RolandMT32 = 0x01,
YamahaFB01 = 0x02,
Adlib = 0x04,
Casio = 0x08,
Tandy1000 = 0x10,
PCSpeaker = 0x20,
AmigaMac = 0x40,
NewGM = 0x80,

// SCI1 - these cannot.
SCI1_Adlib = 0x00,
SCI1_GM = 0x07,
SCI1_GameBlaster = 0x09,
SCI1_RolandGM = 0x0c,
SCI1_PCSpeaker = 0x12,
SCI1_Tandy = 0x13,
SCI1_AmigaMac = 0x06,
SCI1_Unknown08 = 0x08,
SCI1_Unkonwn0b = 0x0b,

// Not really a device
Digital = 0xff
};

So if you have a track in the song set to play only on AdLib, that's device type 0x04. Channel mask starts as zero, which is then bitwise-OR'd to include that 4, but shifted over one byte, to make 0x0400. Should a track be set to play on multiple devices, like the MT-32 and PC Speaker, it'll get 0x04000 (AdLib) OR 0x0100 (MT-32) OR 0x2000 (PC Speaker) = 0x2500.

I looked at the DeviceType enum and there only seems to be two relevant adlib types, SCI1_Adlib and Adlib. Is that << shift messing things up when SCI1_Adlib is used?
That's where you read it wrong. SCI0 and SCI1 have different functions to save, load, and handle music, and the SCI0 paths will only use RolandMT32 through NewGM, plus Digital even though we can't do much with that one. The SCI1 functions only use the SCI1_ devicetypes.

So it's not so much mistakenly mixing SCI1_Adlib (0x00) and SCI0 Adlib (0x04). It just doesn't completely fill in the channel mask, leaving the part where it says how many voices to use zero, which the original ADL.DRV takes at face value.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: doomlazer on October 22, 2021, 12:34:41 PM
Hmm, understanding this a little bit more, but still not quite getting it.

Is the solution to check if it's SCI1_Adlib when it's setting the channel mask and insert 0x04 instead of 0x00?
Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 22, 2021, 01:09:48 PM
No, because you can't set SCI1_Adlib on an SCI0 sound resource to begin with. The solution is to put the correct information (the initial voice count) in the other eight bits of channelMask.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: doomlazer on October 22, 2021, 01:35:38 PM
I think my lack of bitwise experience is really hurting me here. I'll need to do a deep dive on that stuff to fill some big holes in my understanding.

In the meantime, would you mind showing me what the correct solution looks like?



Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 22, 2021, 02:23:46 PM
Okay, check this shit.

You have two bits, A and B. They can be 0 or 1, as bits are wont to do. You can combine them in various ways to get another bit value.
A byte is just eight bits in a row, and a short is 16 of them. Here endeth that lesson.

channelMask is considered in the SCI Companion source code to be a short (uint16_t, or "unsigned integer, 16 bits", where unsigned means it can't go below zero so you get a 0-65535 range), but from what I understand it's actually two separate bytes, one of them being the channel mask and the other the initial voices count. The << 8 bit is only there so the values from enum DeviceType end up in the channel mask byte, not the initial voices byte.

What the |= means is "take the channel mask value so far, and OR-combine this new value with it." This is done bit-by-bit.

And these are the bits:

MT-320x010000.0001
FB-010x020000.0010
AdLib0x040000.0100
Casio0x080000.1000
Tandy0x100001.0000
PC Spkr0x200010.0000
Ami/Mac0x400100.0000
GM0x801000.0000

Notice how each of them has a different bit set? That means a channel meant to play on MT-32 and AdLib both would have the bits 0000.0101 set, which is 0x05 in hexadecimal.

<THEORY>

But because apparently (and this is entirely my conjecture here) the channel mask isn't a 16-bit value but only 8-bit, and the other eight are the initial voice value, that means they have to be shifted up eight spaces.

Code: [Select]
0x05 0x03
  |    |____ Initial voices value: we'll play at most three notes at once on this track.
  |_________ Channel mask: this is for MT-32 and AdLib.

And that would thus be packed into a single 16-bit value, 0x0503.

</THEORY>
Title: Re: Set channel properties for Sound resources in Companion?
Post by: doomlazer on October 22, 2021, 03:56:18 PM
So, if this loop is setting the DeviceType in to the channelMask,

Code: [Select]
if (soundCopy._allChannels[channelId].Number == i)
{
// This channel is used for this device.
channelMask |= (trackInfo.Type << 8);
}


Where is the Initial voices value coming from? I'm still not seeing how that getting applied to the mask.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 22, 2021, 05:36:21 PM
You don't see it getting applied because

... hold onto your butt, this is gonna blow your mind.

Ready?

Because it's not getting applied at all, anywhere. The entire thing about initial voice counts is missing! That's why the channel mask is mistakenly 16-bits in the first place!
Title: Re: Set channel properties for Sound resources in Companion?
Post by: doomlazer on October 22, 2021, 06:32:36 PM
I apologize if I'm being annoying. One final question and I'll just drop it.

Is there not a way to easily determine the initial voice count for each channelID? I'm struggling to find any information about that in any online midi programming tutorials.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 22, 2021, 07:20:34 PM
That's what I'd like to know myself. And whether or not my hypothesis about where that value should go is correct.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: gumby on October 22, 2021, 07:53:36 PM
What about just be empirical about this?  Can we just take an existing sound resource (as a patch file) that doesn't currently work with AdLib, use a hex editor and just modify the header byte in question?  Muck with it till it works (or doesn't)?
Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 22, 2021, 08:43:44 PM
Excellent idea! I'd also suggest studying a contemporary sound resource already known to work. That would at the very least tell us exactly where the value goes.

If nothing else I can try to add a field to the UI so you can manually set the damn thing.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: MusicallyInspired on October 22, 2021, 08:51:37 PM
Is there not a way to easily determine the initial voice count for each channelID? I'm struggling to find any information about that in any online midi programming tutorials.

The initial voice count must be set manually by the composer. This is easily done in Ravi's SoundBox tool for SCI0 sound resources. But this is of no help for SCI1.0. Adlib has a max of 8 voices across all channels that are flagged as Adlib channels. If you have more than that you're going to get missing/dropped notes. The composer also has to ensure that no more than the max number voices (notes) are playing at the same time in an Adlib channel at once when composing. It's all part of that process pre-game implementation. You do not want this to be generated automatically. At least, not unless you already have the max number of notes playing at a time while you're composing the MIDI so that setting it automatically will be safe. But you have to be sure. I'd just like to have the ability to set it manually. That was my whole idea.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 22, 2021, 09:01:11 PM
Extra field in the side bar, then?
Title: Re: Set channel properties for Sound resources in Companion?
Post by: MusicallyInspired on October 22, 2021, 09:13:48 PM
That makes the most sense.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 22, 2021, 09:14:24 PM
Just gotta confirm where the value goes, then.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: MusicallyInspired on October 22, 2021, 09:31:26 PM
Yeah. Maybe I'll spend more time on this figuring it out over the weekend.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: doomlazer on October 22, 2021, 09:33:27 PM
Not sure if this confirms anything, but the pic below compares an SCI0 patch edited in Soundbox - the only change was setting channel 2 initial voices from 0 to 3. Looks like that 4th byte is all that changes, which lines up with your theory, right or no?
Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 22, 2021, 09:36:01 PM
I'll have to look again when I'm back on my laptop instead of my phone but I think you might be on to something, Doomie.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: doomlazer on October 22, 2021, 09:43:16 PM
Yes, I think it might be confirmed. Further changing channel 1 (0) from 0 IVs to 1 increments the second byte.

Code: [Select]
0x0000  00 01 FF 03 FF 00...
Title: Re: Set channel properties for Sound resources in Companion?
Post by: MusicallyInspired on October 23, 2021, 12:18:38 AM
I've already worked this out with Ravi's writeup on the ScummVM SCI wiki (Kawa referenced earlier). All the answers are there. It's the SCI1.0 sound resource format I'm not sure of. I know what to change for SCI0 sound resources I just couldn't edit the Companion source. (also, I don't fully know how to implement setting byte values in a binary file within the GUI realm)
Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 23, 2021, 07:20:04 AM
Back on the laptop, will study Doomie's findings later.

The thing about Ravi's writeup is that at least the part I referenced doesn't match my hypothesis:
Quote
The upper 4 bits of that byte specify how many voices each logical MIDI channel will be playing. The lower 4 bits specify which drivers should react on that channel. Bit 0 set means AdLib shall react. Bit 1 set means PCjr shall react. MT32 will react on all channels. Bit 3 signals the control channel.
Not only does that imply AdLib's channelMask is 0x01 (it's 0x04) but I wasn't aware the PCJr was able to run SCI so that's something I'd prefer to take heavily salted.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 23, 2021, 08:50:31 AM
Having looked closely at Doomie's data, there's one thing I'd like to confirm first: what devices are those two channels set to play on?
Title: Re: Set channel properties for Sound resources in Companion?
Post by: MusicallyInspired on October 23, 2021, 09:43:46 AM
Back on the laptop, will study Doomie's findings later.

The thing about Ravi's writeup is that at least the part I referenced doesn't match my hypothesis:
Quote
The upper 4 bits of that byte specify how many voices each logical MIDI channel will be playing. The lower 4 bits specify which drivers should react on that channel. Bit 0 set means AdLib shall react. Bit 1 set means PCjr shall react. MT32 will react on all channels. Bit 3 signals the control channel.
Not only does that imply AdLib's channelMask is 0x01 (it's 0x04) but I wasn't aware the PCJr was able to run SCI so that's something I'd prefer to take heavily salted.

He's referring to Tandy 3-voice as Tandy and IBM PCjr share the same sound chip (as does the Sega Master System and the Game Gear). Ravi wrote SoundBox which works as you'd expect so no salt needed here.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 23, 2021, 09:58:47 AM
Good, good. Thanks for clearing that up cos I don't like my meals too salty.
Title: Re: Set channel properties for Sound resources in Companion?
Post by: doomlazer on October 23, 2021, 10:08:10 AM
Having looked closely at Doomie's data, there's one thing I'd like to confirm first: what devices are those two channels set to play on?

I had all devices enabled on channels 0 and 1. (initial voices chan0: 1 chan1: 3)
Code: [Select]
0x0000  00 01 FF 03 FF 00 00...
Disabling Adlib on chan1, with no other changes alters the 5th byte
Code: [Select]
0x0000  00 01 FF 03 FB 00 00...
So the Initial voices word comes before the device types I guess and there is 00 at the start.

Edit: Just an observation, but that was with a SCI0 patch altered in Soundbox. I can replicate the same results for SCI0 patches right in SC by disabling Adlib for chan1.

In SCI1, If I try disabling Adlib in a random PQ3 sound patch within SCICompanion, the header is drastically different. In the attached pic the left is with Adlib disabled on chan2 and enabled on the right.




Title: Re: Set channel properties for Sound resources in Companion?
Post by: Kawa on October 23, 2021, 11:36:39 AM
I had all devices enabled on channels 0 and 1. (initial voices chan0: 1 chan1: 3)
Code: [Select]
0x0000  00 01 FF 03 FF 00 00...
Disabling Adlib on chan1, with no other changes alters the 5th byte
Code: [Select]
0x0000  00 01 FF 03 FB 00 00...

All devices enabled would be 0xFF. "And Not" AdLib (4) would be 0xFB. So that makes some sense... guess I'll have to experiment with implementing this now.