11 #include "../stdafx.h"
12 #ifdef WIN32_LEAN_AND_MEAN
13 # undef WIN32_LEAN_AND_MEAN // Don't exclude rarely-used stuff from Windows headers
16 #include "../os/windows/win32.h"
17 #include "../core/mem_func.hpp"
18 #include "../thread.h"
19 #include "../fileio_func.h"
20 #include "../base_media_base.h"
22 #include "midifile.hpp"
30 #include "../safeguards.h"
33 # pragma comment(lib, "ole32.lib")
40 #define FOURCC_INFO mmioFOURCC('I','N','F','O')
41 #define FOURCC_fmt mmioFOURCC('f','m','t',' ')
42 #define FOURCC_data mmioFOURCC('d','a','t','a')
52 std::vector<WLOOP> wave_loops;
53 std::vector<CONNECTION> articulators;
60 std::vector<CONNECTION> articulators;
61 std::vector<DLSRegion> regions;
69 std::vector<BYTE> data;
72 std::vector<WLOOP> wave_loops;
74 bool operator ==(
long offset)
const {
75 return this->file_offset == offset;
79 std::vector<DLSInstrument> instruments;
80 std::vector<POOLCUE> pool_cues;
81 std::vector<DLSWave> waves;
92 bool ReadDLSRegion(FILE *f, DWORD list_length, std::vector<DLSRegion> &out);
100 bool ReadDLSWave(FILE *f, DWORD list_length,
long offset);
104 PACK_N(
struct ChunkHeader {
110 PACK_N(
struct WAVE_DOWNLOAD {
111 DMUS_DOWNLOADINFO dlInfo;
112 ULONG ulOffsetTable[2];
114 DMUS_WAVEDATA dmWaveData;
146 static IDirectMusicPort *
_port =
nullptr;
158 while (list_length > 0) {
160 if (fread(&chunk,
sizeof(chunk), 1, f) != 1)
return false;
161 list_length -= chunk.length +
sizeof(chunk);
163 if (chunk.type == FOURCC_ART1) {
164 CONNECTIONLIST conns;
165 if (fread(&conns,
sizeof(conns), 1, f) != 1)
return false;
166 fseek(f, conns.cbSize -
sizeof(conns), SEEK_CUR);
169 for (ULONG i = 0; i < conns.cConnections; i++) {
171 if (fread(&con,
sizeof(con), 1, f) != 1)
return false;
175 fseek(f, chunk.length, SEEK_CUR);
188 region.wave_sample.cbSize = 0;
190 while (list_length > 0) {
192 if (fread(&chunk,
sizeof(chunk), 1, f) != 1)
return false;
193 list_length -= chunk.length +
sizeof(chunk);
195 if (chunk.type == FOURCC_LIST) {
197 if (fread(&chunk.type,
sizeof(chunk.type), 1, f) != 1)
return false;
198 chunk.length -=
sizeof(chunk.type);
201 switch (chunk.type) {
203 if (fread(®ion.hdr,
sizeof(region.hdr), 1, f) != 1)
return false;
207 if (fread(®ion.wave_sample,
sizeof(region.wave_sample), 1, f) != 1)
return false;
208 fseek(f, region.wave_sample.cbSize -
sizeof(region.wave_sample), SEEK_CUR);
211 for (ULONG i = 0; i < region.wave_sample.cSampleLoops; i++) {
213 if (fread(&loop,
sizeof(loop), 1, f) != 1)
return false;
214 region.wave_loops.push_back(loop);
219 if (fread(®ion.wave,
sizeof(region.wave), 1, f) != 1)
return false;
228 fseek(f, chunk.length, SEEK_CUR);
232 Debug(driver, 7,
"DLS: Ignoring unknown chunk {}{}{}{}", (
char)(chunk.type & 0xFF), (
char)((chunk.type >> 8) & 0xFF), (
char)((chunk.type >> 16) & 0xFF), (
char)((chunk.type >> 24) & 0xFF));
233 fseek(f, chunk.length, SEEK_CUR);
243 while (list_length > 0) {
245 if (fread(&chunk,
sizeof(chunk), 1, f) != 1)
return false;
246 list_length -= chunk.length +
sizeof(chunk);
248 if (chunk.type == FOURCC_LIST) {
250 if (fread(&list_type,
sizeof(list_type), 1, f) != 1)
return false;
252 if (list_type == FOURCC_RGN) {
253 this->
ReadDLSRegion(f, chunk.length -
sizeof(list_type), instrument.regions);
255 Debug(driver, 7,
"DLS: Ignoring unknown list chunk of type {}{}{}{}", (
char)(list_type & 0xFF), (
char)((list_type >> 8) & 0xFF), (
char)((list_type >> 16) & 0xFF), (
char)((list_type >> 24) & 0xFF));
256 fseek(f, chunk.length -
sizeof(list_type), SEEK_CUR);
259 Debug(driver, 7,
"DLS: Ignoring chunk {}{}{}{}", (
char)(chunk.type & 0xFF), (
char)((chunk.type >> 8) & 0xFF), (
char)((chunk.type >> 16) & 0xFF), (
char)((chunk.type >> 24) & 0xFF));
260 fseek(f, chunk.length, SEEK_CUR);
272 while (list_length > 0) {
274 if (fread(&chunk,
sizeof(chunk), 1, f) != 1)
return false;
275 list_length -= chunk.length +
sizeof(chunk);
277 if (chunk.type == FOURCC_LIST) {
279 if (fread(&chunk.type,
sizeof(chunk.type), 1, f) != 1)
return false;
280 chunk.length -=
sizeof(chunk.type);
283 switch (chunk.type) {
285 if (fread(&instrument.hdr,
sizeof(instrument.hdr), 1, f) != 1)
return false;
298 fseek(f, chunk.length, SEEK_CUR);
302 Debug(driver, 7,
"DLS: Ignoring unknown chunk {}{}{}{}", (
char)(chunk.type & 0xFF), (
char)((chunk.type >> 8) & 0xFF), (
char)((chunk.type >> 16) & 0xFF), (
char)((chunk.type >> 24) & 0xFF));
303 fseek(f, chunk.length, SEEK_CUR);
313 while (list_length > 0) {
315 if (fread(&chunk,
sizeof(chunk), 1, f) != 1)
return false;
316 list_length -= chunk.length +
sizeof(chunk);
318 if (chunk.type == FOURCC_LIST) {
320 if (fread(&list_type,
sizeof(list_type), 1, f) != 1)
return false;
322 if (list_type == FOURCC_INS) {
323 Debug(driver, 6,
"DLS: Reading instrument {}", (
int)instruments.size());
327 Debug(driver, 7,
"DLS: Ignoring unknown list chunk of type {}{}{}{}", (
char)(list_type & 0xFF), (
char)((list_type >> 8) & 0xFF), (
char)((list_type >> 16) & 0xFF), (
char)((list_type >> 24) & 0xFF));
328 fseek(f, chunk.length -
sizeof(list_type), SEEK_CUR);
331 Debug(driver, 7,
"DLS: Ignoring chunk {}{}{}{}", (
char)(chunk.type & 0xFF), (
char)((chunk.type >> 8) & 0xFF), (
char)((chunk.type >> 16) & 0xFF), (
char)((chunk.type >> 24) & 0xFF));
332 fseek(f, chunk.length, SEEK_CUR);
341 this->waves.push_back(
DLSWave());
342 DLSWave &wave = this->waves.back();
346 wave.wave_sample.cbSize =
sizeof(WSMPL);
347 wave.wave_sample.usUnityNote = 60;
348 wave.file_offset = offset;
350 while (list_length > 0) {
352 if (fread(&chunk,
sizeof(chunk), 1, f) != 1)
return false;
353 list_length -= chunk.length +
sizeof(chunk);
355 if (chunk.type == FOURCC_LIST) {
357 if (fread(&chunk.type,
sizeof(chunk.type), 1, f) != 1)
return false;
358 chunk.length -=
sizeof(chunk.type);
361 switch (chunk.type) {
363 if (fread(&wave.fmt,
sizeof(wave.fmt), 1, f) != 1)
return false;
364 if (chunk.length >
sizeof(wave.fmt)) fseek(f, chunk.length -
sizeof(wave.fmt), SEEK_CUR);
368 if (fread(&wave.wave_sample,
sizeof(wave.wave_sample), 1, f) != 1)
return false;
369 fseek(f, wave.wave_sample.cbSize -
sizeof(wave.wave_sample), SEEK_CUR);
372 for (ULONG i = 0; i < wave.wave_sample.cSampleLoops; i++) {
374 if (fread(&loop,
sizeof(loop), 1, f) != 1)
return false;
375 wave.wave_loops.push_back(loop);
380 wave.data.resize(chunk.length);
381 if (fread(&wave.data[0],
sizeof(BYTE), wave.data.size(), f) != wave.data.size())
return false;
386 fseek(f, chunk.length, SEEK_CUR);
390 Debug(driver, 7,
"DLS: Ignoring unknown chunk {}{}{}{}", (
char)(chunk.type & 0xFF), (
char)((chunk.type >> 8) & 0xFF), (
char)((chunk.type >> 16) & 0xFF), (
char)((chunk.type >> 24) & 0xFF));
391 fseek(f, chunk.length, SEEK_CUR);
401 long base_offset = ftell(f);
403 while (list_length > 0) {
404 long chunk_offset = ftell(f);
407 if (fread(&chunk,
sizeof(chunk), 1, f) != 1)
return false;
408 list_length -= chunk.length +
sizeof(chunk);
410 if (chunk.type == FOURCC_LIST) {
412 if (fread(&list_type,
sizeof(list_type), 1, f) != 1)
return false;
414 if (list_type == FOURCC_wave) {
415 Debug(driver, 6,
"DLS: Reading wave {}", waves.size());
417 if (!this->
ReadDLSWave(f, chunk.length -
sizeof(list_type), chunk_offset - base_offset))
return false;
419 Debug(driver, 7,
"DLS: Ignoring unknown list chunk of type {}{}{}{}", (
char)(list_type & 0xFF), (
char)((list_type >> 8) & 0xFF), (
char)((list_type >> 16) & 0xFF), (
char)((list_type >> 24) & 0xFF));
420 fseek(f, chunk.length -
sizeof(list_type), SEEK_CUR);
423 Debug(driver, 7,
"DLS: Ignoring chunk {}{}{}{}", (
char)(chunk.type & 0xFF), (
char)((chunk.type >> 8) & 0xFF), (
char)((chunk.type >> 16) & 0xFF), (
char)((chunk.type >> 24) & 0xFF));
424 fseek(f, chunk.length, SEEK_CUR);
433 Debug(driver, 2,
"DMusic: Try to load DLS file {}",
FS2OTTD(file));
435 FILE *f = _wfopen(file, L
"rb");
436 if (f ==
nullptr)
return false;
443 if (fread(&hdr,
sizeof(hdr), 1, f) != 1)
return false;
444 if (fread(&dls_type,
sizeof(dls_type), 1, f) != 1)
return false;
445 if (hdr.type != FOURCC_RIFF || dls_type != FOURCC_DLS)
return false;
447 hdr.length -=
sizeof(FOURCC);
449 Debug(driver, 2,
"DMusic: Parsing DLS file");
455 while (hdr.length > 0) {
457 if (fread(&chunk,
sizeof(chunk), 1, f) != 1)
return false;
458 hdr.length -= chunk.length +
sizeof(chunk);
460 if (chunk.type == FOURCC_LIST) {
462 if (fread(&chunk.type,
sizeof(chunk.type), 1, f) != 1)
return false;
463 chunk.length -=
sizeof(chunk.type);
466 switch (chunk.type) {
468 if (fread(&header,
sizeof(header), 1, f) != 1)
return false;
481 if (fread(&ptbl,
sizeof(ptbl), 1, f) != 1)
return false;
482 fseek(f, ptbl.cbSize -
sizeof(ptbl), SEEK_CUR);
485 for (ULONG i = 0; i < ptbl.cCues; i++) {
487 if (fread(&cue,
sizeof(cue), 1, f) != 1)
return false;
488 this->pool_cues.push_back(cue);
494 fseek(f, chunk.length, SEEK_CUR);
498 Debug(driver, 7,
"DLS: Ignoring unknown chunk {}{}{}{}", (
char)(chunk.type & 0xFF), (
char)((chunk.type >> 8) & 0xFF), (
char)((chunk.type >> 16) & 0xFF), (
char)((chunk.type >> 24) & 0xFF));
499 fseek(f, chunk.length, SEEK_CUR);
505 if (header.cInstruments != this->instruments.size())
return false;
508 for (std::vector<POOLCUE>::iterator cue = this->pool_cues.begin(); cue != this->pool_cues.end(); cue++) {
509 std::vector<DLSWave>::iterator w = std::find(this->waves.begin(), this->waves.end(), cue->ulOffset);
510 if (w != this->waves.end()) {
511 cue->ulOffset = (ULONG)(w - this->waves.begin());
521 static byte ScaleVolume(
byte original,
byte scale)
523 return original * scale / 127;
526 static void TransmitChannelMsg(IDirectMusicBuffer *buffer, REFERENCE_TIME rt,
byte status,
byte p1,
byte p2 = 0)
528 if (buffer->PackStructured(rt, 0, status | (p1 << 8) | (p2 << 16)) == E_OUTOFMEMORY) {
530 _port->PlayBuffer(buffer);
533 buffer->PackStructured(rt, 0, status | (p1 << 8) | (p2 << 16));
537 static void TransmitSysex(IDirectMusicBuffer *buffer, REFERENCE_TIME rt,
const byte *&msg_start,
size_t &remaining)
540 const byte *msg_end = msg_start;
541 while (*msg_end != MIDIST_ENDSYSEX) msg_end++;
544 if (buffer->PackUnstructured(rt, 0, msg_end - msg_start,
const_cast<LPBYTE
>(msg_start)) == E_OUTOFMEMORY) {
546 _port->PlayBuffer(buffer);
549 buffer->PackUnstructured(rt, 0, msg_end - msg_start,
const_cast<LPBYTE
>(msg_start));
553 remaining -= msg_end - msg_start;
557 static void TransmitStandardSysex(IDirectMusicBuffer *buffer, REFERENCE_TIME rt, MidiSysexMessage msg)
560 const byte *data = MidiGetStandardSysexMessage(msg, length);
561 TransmitSysex(buffer, rt, data, length);
565 static void TransmitNotesOff(IDirectMusicBuffer *buffer, REFERENCE_TIME block_time, REFERENCE_TIME cur_time)
567 for (
int ch = 0; ch < 16; ch++) {
568 TransmitChannelMsg(
_buffer, block_time + 10, MIDIST_CONTROLLER | ch, MIDICT_MODE_ALLNOTESOFF, 0);
569 TransmitChannelMsg(
_buffer, block_time + 10, MIDIST_CONTROLLER | ch, MIDICT_SUSTAINSW, 0);
570 TransmitChannelMsg(
_buffer, block_time + 10, MIDIST_CONTROLLER | ch, MIDICT_MODE_RESETALLCTRL, 0);
574 TransmitStandardSysex(
_buffer, block_time + 20, MidiSysexMessage::ResetGM);
575 TransmitStandardSysex(
_buffer, block_time + 30, MidiSysexMessage::RolandSetReverb);
586 static void MidiThreadProc()
588 Debug(driver, 2,
"DMusic: Entering playback thread");
590 REFERENCE_TIME last_volume_time = 0;
591 REFERENCE_TIME block_time = 0;
600 IReferenceClock *clock;
601 _port->GetLatencyClock(&clock);
603 REFERENCE_TIME cur_time;
604 clock->GetTime(&cur_time);
609 DWORD next_timeout = 1000;
612 DWORD wfso = WaitForSingleObject(
_thread_event, next_timeout);
614 if (_playback.shutdown) {
615 _playback.playing =
false;
619 if (_playback.do_stop) {
620 Debug(driver, 2,
"DMusic thread: Stopping playback");
623 clock->GetTime(&cur_time);
626 _playback.playing =
false;
627 _playback.do_stop =
false;
633 if (wfso == WAIT_OBJECT_0) {
634 if (_playback.do_start) {
635 Debug(driver, 2,
"DMusic thread: Starting playback");
644 _playback.playing =
true;
645 _playback.do_start =
false;
649 clock->GetTime(&cur_time);
660 if (_playback.playing) {
666 size_t preload_bytes = 0;
669 preload_bytes += block.
data.size();
672 Debug(driver, 2,
"DMusic: timer: loop from block {} (ticktime {}, realtime {:.3f}, bytes {})", bl, block.
ticktime, ((
int)block.
realtime) / 1000.0, preload_bytes);
679 Debug(driver, 2,
"DMusic: timer: start from block {} (ticktime {}, realtime {:.3f}, bytes {})", bl, block.
ticktime, ((
int)block.
realtime) / 1000.0, preload_bytes);
688 REFERENCE_TIME current_time;
689 clock->GetTime(¤t_time);
694 Debug(driver, 2,
"DMusic thread: volume change");
696 last_volume_time = current_time;
697 for (
int ch = 0; ch < 16; ch++) {
699 TransmitChannelMsg(
_buffer, block_time + 1, MIDIST_CONTROLLER | ch, MIDICT_CHANVOLUME, vol);
712 Debug(driver, 2,
"DMusic thread: Looping song");
716 _playback.do_stop =
true;
734 const byte *data = block.
data.data();
735 size_t remaining = block.
data.size();
736 byte last_status = 0;
737 while (remaining > 0) {
740 byte status = data[0];
742 last_status = status;
746 status = last_status;
748 switch (status & 0xF0) {
750 case MIDIST_CHANPRESS:
752 TransmitChannelMsg(
_buffer, block_time, status, data[0]);
758 case MIDIST_POLYPRESS:
759 case MIDIST_PITCHBEND:
761 TransmitChannelMsg(
_buffer, block_time, status, data[0], data[1]);
765 case MIDIST_CONTROLLER:
767 if (data[0] == MIDICT_CHANVOLUME) {
771 TransmitChannelMsg(
_buffer, block_time, status, data[0], vol);
774 TransmitChannelMsg(
_buffer, block_time, status, data[0], data[1]);
783 TransmitSysex(
_buffer, block_time, data, remaining);
785 case MIDIST_TC_QFRAME:
790 case MIDIST_SONGPOSPTR:
805 DWORD used_buffer = 0;
806 _buffer->GetUsedBytes(&used_buffer);
807 if (used_buffer > 0) {
818 _playback.do_stop =
true;
825 Debug(driver, 2,
"DMusic: Exiting playback thread");
828 clock->GetTime(&cur_time);
830 Sleep(_playback.preload_time * 4);
835 static void * DownloadArticulationData(
int base_offset,
void *data,
const std::vector<CONNECTION> &artic)
837 DMUS_ARTICULATION2 *art = (DMUS_ARTICULATION2 *)data;
838 art->ulArtIdx = base_offset + 1;
839 art->ulFirstExtCkIdx = 0;
840 art->ulNextArtIdx = 0;
842 CONNECTIONLIST *con_list = (CONNECTIONLIST *)(art + 1);
843 con_list->cbSize =
sizeof(CONNECTIONLIST);
844 con_list->cConnections = (ULONG)artic.size();
845 MemCpyT((CONNECTION *)(con_list + 1), &artic.front(), artic.size());
847 return (CONNECTION *)(con_list + 1) + artic.size();
850 static const char *LoadDefaultDLSFile(
const char *user_dls)
854 caps.dwSize =
sizeof(DMUS_PORTCAPS);
855 _port->GetCaps(&caps);
858 if ((caps.dwFlags & (DMUS_PC_DLS | DMUS_PC_DLS2)) != 0 && (caps.dwFlags & DMUS_PC_GMINHARDWARE) == 0) {
861 if (user_dls ==
nullptr) {
864 if (SUCCEEDED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, L
"Software\\Microsoft\\DirectMusic", 0, KEY_READ, &hkDM))) {
865 wchar_t dls_path[MAX_PATH];
866 DWORD buf_size =
sizeof(dls_path);
867 if (SUCCEEDED(RegQueryValueEx(hkDM, L
"GMFilePath",
nullptr,
nullptr, (LPBYTE)dls_path, &buf_size))) {
868 wchar_t expand_path[MAX_PATH * 2];
869 ExpandEnvironmentStrings(dls_path, expand_path,
lengthof(expand_path));
870 if (!dls_file.
LoadFile(expand_path))
Debug(driver, 1,
"Failed to load default GM DLS file from registry");
876 if (dls_file.instruments.size() == 0) {
877 static const wchar_t *DLS_GM_FILE = L
"%windir%\\System32\\drivers\\gm.dls";
878 wchar_t path[MAX_PATH];
879 ExpandEnvironmentStrings(DLS_GM_FILE, path,
lengthof(path));
881 if (!dls_file.
LoadFile(path))
return "Can't load GM DLS collection";
884 if (!dls_file.
LoadFile(
OTTD2FS(user_dls).c_str()))
return "Can't load GM DLS collection";
888 IDirectMusicPortDownload *download_port =
nullptr;
889 if (FAILED(
_port->QueryInterface(IID_IDirectMusicPortDownload, (LPVOID *)&download_port)))
return "Can't get download port";
891 DWORD dlid_wave = 0, dlid_inst = 0;
892 if (FAILED(download_port->GetDLId(&dlid_wave, (DWORD)dls_file.waves.size())) || FAILED(download_port->GetDLId(&dlid_inst, (DWORD)dls_file.instruments.size()))) {
893 download_port->Release();
894 return "Can't get enough DLS ids";
898 download_port->GetAppend(&dwAppend);
901 for (DWORD i = 0; i < dls_file.waves.size(); i++) {
902 IDirectMusicDownload *dl_wave =
nullptr;
903 if (FAILED(download_port->AllocateBuffer((DWORD)(
sizeof(WAVE_DOWNLOAD) + dwAppend * dls_file.waves[i].fmt.wf.nBlockAlign + dls_file.waves[i].data.size()), &dl_wave))) {
904 download_port->Release();
905 return "Can't allocate wave download buffer";
910 if (FAILED(dl_wave->GetBuffer((LPVOID *)&wave, &wave_size))) {
912 download_port->Release();
913 return "Can't get wave download buffer";
918 wave->dlInfo.dwDLType = DMUS_DOWNLOADINFO_WAVE;
919 wave->dlInfo.cbSize = wave_size;
920 wave->dlInfo.dwDLId = dlid_wave + i;
921 wave->dlInfo.dwNumOffsetTableEntries = 2;
922 wave->ulOffsetTable[0] = offsetof(WAVE_DOWNLOAD, dmWave);
923 wave->ulOffsetTable[1] = offsetof(WAVE_DOWNLOAD, dmWaveData);
924 wave->dmWave.ulWaveDataIdx = 1;
925 MemCpyT((PCMWAVEFORMAT *)&wave->dmWave.WaveformatEx, &dls_file.waves[i].fmt, 1);
926 wave->dmWaveData.cbSize = (DWORD)dls_file.waves[i].data.size();
927 MemCpyT(wave->dmWaveData.byData, &dls_file.waves[i].data[0], dls_file.waves[i].data.size());
930 if (FAILED(download_port->Download(dl_wave))) {
931 download_port->Release();
932 return "Downloading DLS wave failed";
937 for (DWORD i = 0; i < dls_file.instruments.size(); i++) {
938 DWORD offsets = 1 + (DWORD)dls_file.instruments[i].regions.size();
941 size_t i_size =
sizeof(DMUS_DOWNLOADINFO) +
sizeof(DMUS_INSTRUMENT);
942 if (dls_file.instruments[i].articulators.size() > 0) {
945 i_size +=
sizeof(DMUS_ARTICULATION2) +
sizeof(CONNECTIONLIST) +
sizeof(CONNECTION) * dls_file.instruments[i].articulators.size();
948 for (std::vector<DLSFile::DLSRegion>::iterator rgn = dls_file.instruments[i].regions.begin(); rgn != dls_file.instruments[i].regions.end(); rgn++) {
949 if (rgn->articulators.size() > 0) {
951 i_size +=
sizeof(DMUS_ARTICULATION2) +
sizeof(CONNECTIONLIST) +
sizeof(CONNECTION) * rgn->articulators.size();
956 if (rgn->wave_sample.cbSize != 0) {
957 i_size +=
sizeof(DMUS_REGION) -
sizeof(DMUS_REGION::WLOOP) +
sizeof(WLOOP) * rgn->wave_loops.size();
959 i_size +=
sizeof(DMUS_REGION) -
sizeof(DMUS_REGION::WLOOP) +
sizeof(WLOOP) * dls_file.waves[dls_file.pool_cues[rgn->wave.ulTableIndex].ulOffset].wave_loops.size();
963 i_size += offsets *
sizeof(ULONG);
966 IDirectMusicDownload *dl_inst =
nullptr;
967 if (FAILED(download_port->AllocateBuffer((DWORD)i_size, &dl_inst))) {
968 download_port->Release();
969 return "Can't allocate instrument download buffer";
974 if (FAILED(dl_inst->GetBuffer((LPVOID *)&instrument, &inst_size))) {
976 download_port->Release();
977 return "Can't get instrument download buffer";
979 char *inst_base = (
char *)instrument;
982 DMUS_DOWNLOADINFO *d_info = (DMUS_DOWNLOADINFO *)instrument;
983 d_info->dwDLType = DMUS_DOWNLOADINFO_INSTRUMENT2;
984 d_info->cbSize = inst_size;
985 d_info->dwDLId = dlid_inst + i;
986 d_info->dwNumOffsetTableEntries = offsets;
987 instrument = d_info + 1;
990 ULONG *offset_table = (ULONG *)instrument;
991 instrument = offset_table + offsets;
995 DMUS_INSTRUMENT *inst_data = (DMUS_INSTRUMENT *)instrument;
997 offset_table[last_offset++] = (
char *)inst_data - inst_base;
998 inst_data->ulPatch = (dls_file.instruments[i].hdr.Locale.ulBank & F_INSTRUMENT_DRUMS) | ((dls_file.instruments[i].hdr.Locale.ulBank & 0x7F7F) << 8) | (dls_file.instruments[i].hdr.Locale.ulInstrument & 0x7F);
999 instrument = inst_data + 1;
1002 if (dls_file.instruments[i].articulators.size() > 0) {
1003 inst_data->ulGlobalArtIdx = last_offset;
1004 offset_table[last_offset++] = (
char *)instrument - inst_base;
1005 offset_table[last_offset++] = (
char *)instrument +
sizeof(DMUS_ARTICULATION2) - inst_base;
1007 instrument = DownloadArticulationData(inst_data->ulGlobalArtIdx, instrument, dls_file.instruments[i].articulators);
1008 assert((
char *)instrument - inst_base <= (ptrdiff_t)inst_size);
1012 inst_data->ulFirstRegionIdx = last_offset;
1013 for (uint j = 0; j < dls_file.instruments[i].regions.size(); j++) {
1016 DMUS_REGION *inst_region = (DMUS_REGION *)instrument;
1017 offset_table[last_offset++] = (
char *)inst_region - inst_base;
1018 inst_region->RangeKey = rgn.hdr.RangeKey;
1019 inst_region->RangeVelocity = rgn.hdr.RangeVelocity;
1020 inst_region->fusOptions = rgn.hdr.fusOptions;
1021 inst_region->usKeyGroup = rgn.hdr.usKeyGroup;
1022 inst_region->ulFirstExtCkIdx = 0;
1024 ULONG wave_id = dls_file.pool_cues[rgn.wave.ulTableIndex].ulOffset;
1025 inst_region->WaveLink = rgn.wave;
1026 inst_region->WaveLink.ulTableIndex = wave_id + dlid_wave;
1029 if (rgn.wave_sample.cbSize != 0) {
1030 inst_region->WSMP = rgn.wave_sample;
1031 if (rgn.wave_loops.size() > 0)
MemCpyT(inst_region->WLOOP, &rgn.wave_loops.front(), rgn.wave_loops.size());
1033 instrument = (
char *)(inst_region + 1) -
sizeof(DMUS_REGION::WLOOP) +
sizeof(WLOOP) * rgn.wave_loops.size();
1035 inst_region->WSMP = rgn.wave_sample;
1036 if (dls_file.waves[wave_id].wave_loops.size() > 0)
MemCpyT(inst_region->WLOOP, &dls_file.waves[wave_id].wave_loops.front(), dls_file.waves[wave_id].wave_loops.size());
1038 instrument = (
char *)(inst_region + 1) -
sizeof(DMUS_REGION::WLOOP) +
sizeof(WLOOP) * dls_file.waves[wave_id].wave_loops.size();
1042 if (rgn.articulators.size() > 0) {
1043 inst_region->ulRegionArtIdx = last_offset;
1044 offset_table[last_offset++] = (
char *)instrument - inst_base;
1045 offset_table[last_offset++] = (
char *)instrument +
sizeof(DMUS_ARTICULATION2) - inst_base;
1047 instrument = DownloadArticulationData(inst_region->ulRegionArtIdx, instrument, rgn.articulators);
1049 inst_region->ulRegionArtIdx = 0;
1051 assert((
char *)instrument - inst_base <= (ptrdiff_t)inst_size);
1054 inst_region->ulNextRegionIdx = j < dls_file.instruments[i].regions.size() - 1 ? last_offset : 0;
1058 if (FAILED(download_port->Download(dl_inst))) {
1059 download_port->Release();
1060 return "Downloading DLS instrument failed";
1064 download_port->Release();
1074 if (FAILED(CoInitializeEx(
nullptr, COINIT_MULTITHREADED)))
return "COM initialization failed";
1077 if (FAILED(CoCreateInstance(
1084 return "Failed to create the music object";
1088 if (FAILED(
_music->SetDirectSound(
nullptr,
nullptr)))
return "Can't set DirectSound interface";
1095 if (_debug_driver_level > 0) {
1097 char desc[DMUS_MAX_DESCRIPTION];
1101 caps.dwSize =
sizeof(DMUS_PORTCAPS);
1103 Debug(driver, 1,
"Detected DirectMusic ports:");
1104 for (
int i = 0;
_music->EnumPort(i, &caps) == S_OK; i++) {
1105 if (caps.dwClass == DMUS_PC_OUTPUTCLASS) {
1116 caps.dwSize =
sizeof(DMUS_PORTCAPS);
1117 if (FAILED(
_music->EnumPort(pIdx, &caps)))
return "Supplied port parameter is not a valid port";
1118 if (caps.dwClass != DMUS_PC_OUTPUTCLASS)
return "Supplied port parameter is not an output port";
1119 guidPort = caps.guidPort;
1121 if (FAILED(
_music->GetDefaultPort(&guidPort)))
return "Can't query default music port";
1125 DMUS_PORTPARAMS params;
1127 params.dwSize =
sizeof(DMUS_PORTPARAMS);
1128 params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS;
1129 params.dwChannelGroups = 1;
1130 if (FAILED(
_music->CreatePort(guidPort, ¶ms, &
_port,
nullptr)))
return "Failed to create port";
1132 if (FAILED(
_port->Activate(TRUE)))
return "Failed to activate port";
1135 DMUS_BUFFERDESC desc;
1137 desc.dwSize =
sizeof(DMUS_BUFFERDESC);
1138 desc.guidBufferFormat = KSDATAFORMAT_SUBTYPE_DIRECTMUSIC;
1139 desc.cbBuffer = 1024;
1140 if (FAILED(
_music->CreateMusicBuffer(&desc, &
_buffer,
nullptr)))
return "Failed to create music buffer";
1143 const char *dls = LoadDefaultDLSFile(
GetDriverParam(parm,
"dls"));
1144 if (dls !=
nullptr)
return dls;
1147 _thread_event = CreateEvent(
nullptr, FALSE, FALSE,
nullptr);
1148 if (
_thread_event ==
nullptr)
return "Can't create thread shutdown event";
1156 MusicDriver_DMusic::~MusicDriver_DMusic()
1164 if (_dmusic_thread.joinable()) {
1165 _playback.shutdown =
true;
1172 IDirectMusicPortDownload *download_port =
nullptr;
1173 _port->QueryInterface(IID_IDirectMusicPortDownload, (LPVOID *)&download_port);
1177 for (std::vector<IDirectMusicDownload *>::reverse_iterator i =
_dls_downloads.rbegin(); download_port !=
nullptr && i !=
_dls_downloads.rend(); i++) {
1178 download_port->Unload(*i);
1183 if (download_port !=
nullptr) download_port->Release();
1191 if (
_port !=
nullptr) {
1192 _port->Activate(FALSE);
1212 if (!_playback.next_file.LoadSong(song))
return;
1216 _playback.next_segment.loop = song.
loop;
1218 _playback.do_start =
true;
1225 _playback.do_stop =
true;
1232 return _playback.playing || _playback.do_start;
1238 _playback.new_volume = vol;