mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-06 17:34:06 +00:00
dmusic: Implement SoundFont2 wave sample parsing.
This commit is contained in:
parent
b733a46ada
commit
215a55d603
|
@ -580,6 +580,29 @@ static HRESULT parse_sfbk_chunk(struct collection *This, IStream *stream, struct
|
|||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT size = offsetof(struct pool, cues[soundfont.sample_count]);
|
||||
if (!(This->pool = calloc(1, size))) return E_OUTOFMEMORY;
|
||||
This->pool->table.cbSize = sizeof(This->pool->table);
|
||||
}
|
||||
|
||||
for (i = 0; SUCCEEDED(hr) && i < soundfont.sample_count; i++)
|
||||
{
|
||||
struct wave_entry *entry;
|
||||
|
||||
if (!(entry = malloc(sizeof(*entry)))) return E_OUTOFMEMORY;
|
||||
hr = wave_create_from_soundfont(&soundfont, i, &entry->wave);
|
||||
if (FAILED(hr)) free(entry);
|
||||
else
|
||||
{
|
||||
entry->offset = i;
|
||||
This->pool->table.cCues++;
|
||||
This->pool->cues[i].ulOffset = i;
|
||||
list_add_tail(&This->waves, &entry->entry);
|
||||
}
|
||||
}
|
||||
|
||||
free(soundfont.phdr);
|
||||
free(soundfont.pbag);
|
||||
free(soundfont.pmod);
|
||||
|
|
|
@ -91,12 +91,14 @@ extern HRESULT DMUSIC_CreateReferenceClockImpl (LPCGUID lpcGUID, LPVOID* ppobj,
|
|||
|
||||
extern HRESULT download_create(DWORD size, IDirectMusicDownload **ret_iface);
|
||||
|
||||
struct soundfont;
|
||||
extern HRESULT instrument_create_from_chunk(IStream *stream, struct chunk_entry *parent,
|
||||
struct collection *collection, DMUS_OBJECTDESC *desc, IDirectMusicInstrument **ret_iface);
|
||||
extern HRESULT instrument_download_to_port(IDirectMusicInstrument *iface, IDirectMusicPortDownload *port,
|
||||
IDirectMusicDownloadedInstrument **downloaded);
|
||||
extern HRESULT instrument_unload_from_port(IDirectMusicDownloadedInstrument *iface, IDirectMusicPortDownload *port);
|
||||
|
||||
extern HRESULT wave_create_from_soundfont(struct soundfont *soundfont, UINT index, IUnknown **out);
|
||||
extern HRESULT wave_create_from_chunk(IStream *stream, struct chunk_entry *parent, IUnknown **out);
|
||||
extern HRESULT wave_download_to_port(IUnknown *iface, IDirectMusicPortDownload *port, DWORD *id);
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#include "dmusic_private.h"
|
||||
#include "soundfont.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dmusic);
|
||||
|
||||
|
@ -216,6 +217,85 @@ HRESULT wave_create_from_chunk(IStream *stream, struct chunk_entry *parent, IUnk
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT wave_create_from_soundfont(struct soundfont *soundfont, UINT index, IUnknown **ret_iface)
|
||||
{
|
||||
struct sf_sample *sf_sample = soundfont->shdr + index;
|
||||
struct sample *sample = NULL;
|
||||
WAVEFORMATEX *format = NULL;
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
UINT data_size, offset;
|
||||
struct wave *This;
|
||||
void *data = NULL;
|
||||
IUnknown *iface;
|
||||
|
||||
TRACE("(%p, %u, %p)\n", soundfont, index, ret_iface);
|
||||
|
||||
if (sf_sample->sample_link) FIXME("Stereo sample not supported\n");
|
||||
|
||||
if (!(format = calloc(1, sizeof(*format)))) goto failed;
|
||||
format->wFormatTag = WAVE_FORMAT_PCM;
|
||||
format->nChannels = 1;
|
||||
format->wBitsPerSample = 16;
|
||||
format->nSamplesPerSec = sf_sample->sample_rate;
|
||||
format->nBlockAlign = format->wBitsPerSample * format->nChannels / 8;
|
||||
format->nAvgBytesPerSec = format->nBlockAlign * format->nSamplesPerSec;
|
||||
|
||||
if (!(sample = calloc(1, offsetof(struct sample, loops[1])))) goto failed;
|
||||
sample->head.cbSize = sizeof(sample->head);
|
||||
sample->head.cSampleLoops = 1;
|
||||
sample->loops[0].ulStart = sf_sample->start_loop - sf_sample->start;
|
||||
sample->loops[0].ulLength = sf_sample->end_loop - sf_sample->start_loop;
|
||||
|
||||
data_size = sf_sample->end - sf_sample->start;
|
||||
if (!(data = malloc(data_size * format->nBlockAlign))) goto failed;
|
||||
offset = sf_sample->start * format->nBlockAlign / format->nChannels;
|
||||
memcpy(data, soundfont->sdta + offset, data_size);
|
||||
|
||||
if (FAILED(hr = wave_create(&iface))) goto failed;
|
||||
|
||||
This = impl_from_IUnknown(iface);
|
||||
This->format = format;
|
||||
This->sample = sample;
|
||||
This->data_size = data_size;
|
||||
This->data = data;
|
||||
|
||||
if (TRACE_ON(dmusic))
|
||||
{
|
||||
UINT i;
|
||||
|
||||
TRACE("*** Created DirectMusicWave %p\n", This);
|
||||
TRACE(" - format: %p\n", This->format);
|
||||
if (This->format)
|
||||
{
|
||||
TRACE(" - wFormatTag: %u\n", This->format->wFormatTag);
|
||||
TRACE(" - nChannels: %u\n", This->format->nChannels);
|
||||
TRACE(" - nSamplesPerSec: %lu\n", This->format->nSamplesPerSec);
|
||||
TRACE(" - nAvgBytesPerSec: %lu\n", This->format->nAvgBytesPerSec);
|
||||
TRACE(" - nBlockAlign: %u\n", This->format->nBlockAlign);
|
||||
TRACE(" - wBitsPerSample: %u\n", This->format->wBitsPerSample);
|
||||
TRACE(" - cbSize: %u\n", This->format->cbSize);
|
||||
}
|
||||
|
||||
TRACE(" - sample: {size: %lu, unity_note: %u, fine_tune: %d, attenuation: %ld, options: %#lx, loops: %lu}\n",
|
||||
This->sample->head.cbSize, This->sample->head.usUnityNote,
|
||||
This->sample->head.sFineTune, This->sample->head.lAttenuation,
|
||||
This->sample->head.fulOptions, This->sample->head.cSampleLoops);
|
||||
for (i = 0; i < This->sample->head.cSampleLoops; i++)
|
||||
TRACE(" - loops[%u]: {size: %lu, type: %lu, start: %lu, length: %lu}\n", i,
|
||||
This->sample->loops[i].cbSize, This->sample->loops[i].ulType,
|
||||
This->sample->loops[i].ulStart, This->sample->loops[i].ulLength);
|
||||
}
|
||||
|
||||
*ret_iface = iface;
|
||||
return S_OK;
|
||||
|
||||
failed:
|
||||
free(data);
|
||||
free(sample);
|
||||
free(format);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT wave_download_to_port(IUnknown *iface, IDirectMusicPortDownload *port, DWORD *id)
|
||||
{
|
||||
struct download_buffer
|
||||
|
|
Loading…
Reference in a new issue