Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
ccc5af8b
Commit
ccc5af8b
authored
Sep 08, 2023
by
Rémi Bernon
Committed by
Alexandre Julliard
Oct 11, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dmsynth: Create fluid_preset and fluid_voice from instrument.
parent
07aa6b5d
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
299 additions
and
3 deletions
+299
-3
synth.c
dlls/dmsynth/synth.c
+299
-3
No files found.
dlls/dmsynth/synth.c
View file @
ccc5af8b
...
@@ -36,6 +36,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(dmsynth);
...
@@ -36,6 +36,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(dmsynth);
#define CONN_SRC_CC2 0x0082
#define CONN_SRC_CC2 0x0082
#define CONN_SRC_RPN0 0x0100
#define CONN_SRC_RPN0 0x0100
#define CONN_TRN_BIPOLAR (1<<4)
#define CONN_TRN_INVERT (1<<5)
static
const
char
*
debugstr_conn_src
(
UINT
src
)
static
const
char
*
debugstr_conn_src
(
UINT
src
)
{
{
switch
(
src
)
switch
(
src
)
...
@@ -267,6 +270,11 @@ struct instrument
...
@@ -267,6 +270,11 @@ struct instrument
struct
synth
*
synth
;
struct
synth
*
synth
;
};
};
static
void
instrument_addref
(
struct
instrument
*
instrument
)
{
InterlockedIncrement
(
&
instrument
->
ref
);
}
static
void
instrument_release
(
struct
instrument
*
instrument
)
static
void
instrument_release
(
struct
instrument
*
instrument
)
{
{
ULONG
ref
=
InterlockedDecrement
(
&
instrument
->
ref
);
ULONG
ref
=
InterlockedDecrement
(
&
instrument
->
ref
);
...
@@ -1274,6 +1282,277 @@ static const IKsControlVtbl synth_control_vtbl =
...
@@ -1274,6 +1282,277 @@ static const IKsControlVtbl synth_control_vtbl =
synth_control_KsEvent
,
synth_control_KsEvent
,
};
};
static
const
char
*
synth_preset_get_name
(
fluid_preset_t
*
fluid_preset
)
{
return
"DirectMusicSynth"
;
}
static
int
synth_preset_get_bank
(
fluid_preset_t
*
fluid_preset
)
{
TRACE
(
"(%p)
\n
"
,
fluid_preset
);
return
0
;
}
static
int
synth_preset_get_num
(
fluid_preset_t
*
fluid_preset
)
{
struct
instrument
*
instrument
=
fluid_preset_get_data
(
fluid_preset
);
TRACE
(
"(%p)
\n
"
,
fluid_preset
);
if
(
!
instrument
)
return
0
;
return
instrument
->
patch
;
}
static
BOOL
fluid_gen_from_connection
(
CONNECTION
*
conn
,
UINT
*
gen
)
{
switch
(
conn
->
usDestination
)
{
case
CONN_DST_FILTER_CUTOFF
:
*
gen
=
GEN_FILTERFC
;
return
TRUE
;
case
CONN_DST_FILTER_Q
:
*
gen
=
GEN_FILTERQ
;
return
TRUE
;
case
CONN_DST_CHORUS
:
*
gen
=
GEN_CHORUSSEND
;
return
TRUE
;
case
CONN_DST_REVERB
:
*
gen
=
GEN_REVERBSEND
;
return
TRUE
;
case
CONN_DST_PAN
:
*
gen
=
GEN_PAN
;
return
TRUE
;
case
CONN_DST_LFO_STARTDELAY
:
*
gen
=
GEN_MODLFODELAY
;
return
TRUE
;
case
CONN_DST_LFO_FREQUENCY
:
*
gen
=
GEN_MODLFOFREQ
;
return
TRUE
;
case
CONN_DST_VIB_STARTDELAY
:
*
gen
=
GEN_VIBLFODELAY
;
return
TRUE
;
case
CONN_DST_VIB_FREQUENCY
:
*
gen
=
GEN_VIBLFOFREQ
;
return
TRUE
;
case
CONN_DST_EG2_DELAYTIME
:
*
gen
=
GEN_MODENVDELAY
;
return
TRUE
;
case
CONN_DST_EG2_ATTACKTIME
:
*
gen
=
GEN_MODENVATTACK
;
return
TRUE
;
case
CONN_DST_EG2_HOLDTIME
:
*
gen
=
GEN_MODENVHOLD
;
return
TRUE
;
case
CONN_DST_EG2_DECAYTIME
:
*
gen
=
GEN_MODENVDECAY
;
return
TRUE
;
case
CONN_DST_EG2_SUSTAINLEVEL
:
*
gen
=
GEN_MODENVSUSTAIN
;
return
TRUE
;
case
CONN_DST_EG2_RELEASETIME
:
*
gen
=
GEN_MODENVRELEASE
;
return
TRUE
;
case
CONN_DST_EG1_DELAYTIME
:
*
gen
=
GEN_VOLENVDELAY
;
return
TRUE
;
case
CONN_DST_EG1_ATTACKTIME
:
*
gen
=
GEN_VOLENVATTACK
;
return
TRUE
;
case
CONN_DST_EG1_HOLDTIME
:
*
gen
=
GEN_VOLENVHOLD
;
return
TRUE
;
case
CONN_DST_EG1_DECAYTIME
:
*
gen
=
GEN_VOLENVDECAY
;
return
TRUE
;
case
CONN_DST_EG1_SUSTAINLEVEL
:
*
gen
=
GEN_VOLENVSUSTAIN
;
return
TRUE
;
case
CONN_DST_EG1_RELEASETIME
:
*
gen
=
GEN_VOLENVRELEASE
;
return
TRUE
;
case
CONN_DST_GAIN
:
*
gen
=
GEN_ATTENUATION
;
return
TRUE
;
case
CONN_DST_PITCH
:
*
gen
=
GEN_PITCH
;
return
TRUE
;
default:
FIXME
(
"Unsupported connection %s
\n
"
,
debugstr_connection
(
conn
));
return
FALSE
;
}
}
static
BOOL
set_gen_from_connection
(
fluid_voice_t
*
fluid_voice
,
CONNECTION
*
conn
)
{
UINT
gen
;
if
(
conn
->
usControl
!=
CONN_SRC_NONE
)
return
FALSE
;
if
(
conn
->
usTransform
!=
CONN_TRN_NONE
)
return
FALSE
;
if
(
conn
->
usSource
==
CONN_SRC_NONE
)
{
if
(
!
fluid_gen_from_connection
(
conn
,
&
gen
))
return
FALSE
;
}
if
(
conn
->
usSource
==
CONN_SRC_KEYNUMBER
)
{
switch
(
conn
->
usDestination
)
{
case
CONN_DST_EG2_HOLDTIME
:
gen
=
GEN_KEYTOMODENVHOLD
;
break
;
case
CONN_DST_EG2_DECAYTIME
:
gen
=
GEN_KEYTOMODENVDECAY
;
break
;
case
CONN_DST_EG1_HOLDTIME
:
gen
=
GEN_KEYTOVOLENVHOLD
;
break
;
case
CONN_DST_EG1_DECAYTIME
:
gen
=
GEN_KEYTOVOLENVDECAY
;
break
;
default:
return
FALSE
;
}
}
else
if
(
conn
->
usSource
==
CONN_SRC_LFO
)
{
switch
(
conn
->
usDestination
)
{
case
CONN_DST_PITCH
:
gen
=
GEN_MODLFOTOPITCH
;
break
;
case
CONN_DST_FILTER_CUTOFF
:
gen
=
GEN_MODLFOTOFILTERFC
;
break
;
case
CONN_DST_GAIN
:
gen
=
GEN_MODLFOTOVOL
;
break
;
default:
return
FALSE
;
}
}
else
if
(
conn
->
usSource
==
CONN_SRC_EG2
)
{
switch
(
conn
->
usDestination
)
{
case
CONN_DST_PITCH
:
gen
=
GEN_MODENVTOPITCH
;
break
;
case
CONN_DST_FILTER_CUTOFF
:
gen
=
GEN_MODENVTOFILTERFC
;
break
;
default:
return
FALSE
;
}
}
else
if
(
conn
->
usSource
==
CONN_SRC_VIBRATO
)
{
switch
(
conn
->
usDestination
)
{
case
CONN_DST_PITCH
:
gen
=
GEN_VIBLFOTOPITCH
;
break
;
default:
return
FALSE
;
}
}
else
{
return
FALSE
;
}
fluid_voice_gen_set
(
fluid_voice
,
gen
,
conn
->
lScale
);
return
TRUE
;
}
static
BOOL
fluid_source_from_connection
(
USHORT
source
,
USHORT
transform
,
UINT
*
fluid_source
,
UINT
*
fluid_flags
)
{
UINT
flags
=
FLUID_MOD_GC
;
if
(
source
>=
CONN_SRC_CC1
&&
source
<=
CONN_SRC_CC1
+
0x7f
)
{
*
fluid_source
=
source
;
flags
=
FLUID_MOD_CC
;
}
else
switch
(
source
)
{
case
CONN_SRC_NONE
:
*
fluid_source
=
FLUID_MOD_NONE
;
break
;
case
CONN_SRC_KEYONVELOCITY
:
*
fluid_source
=
FLUID_MOD_VELOCITY
;
break
;
case
CONN_SRC_KEYNUMBER
:
*
fluid_source
=
FLUID_MOD_KEY
;
break
;
case
CONN_SRC_PITCHWHEEL
:
*
fluid_source
=
FLUID_MOD_PITCHWHEEL
;
break
;
case
CONN_SRC_POLYPRESSURE
:
*
fluid_source
=
FLUID_MOD_KEYPRESSURE
;
break
;
case
CONN_SRC_CHANNELPRESSURE
:
*
fluid_source
=
FLUID_MOD_CHANNELPRESSURE
;
break
;
case
CONN_SRC_RPN0
:
*
fluid_source
=
FLUID_MOD_PITCHWHEELSENS
;
break
;
default:
return
FALSE
;
}
if
(
transform
&
CONN_TRN_INVERT
)
flags
|=
FLUID_MOD_NEGATIVE
;
if
(
transform
&
CONN_TRN_BIPOLAR
)
flags
|=
FLUID_MOD_BIPOLAR
;
switch
(
transform
&
CONN_TRN_SWITCH
)
{
case
CONN_TRN_NONE
:
flags
|=
FLUID_MOD_LINEAR
;
break
;
case
CONN_TRN_CONCAVE
:
flags
|=
FLUID_MOD_CONCAVE
;
break
;
case
CONN_TRN_CONVEX
:
flags
|=
FLUID_MOD_CONVEX
;
break
;
case
CONN_TRN_SWITCH
:
flags
|=
FLUID_MOD_SWITCH
;
break
;
}
*
fluid_flags
=
flags
;
return
TRUE
;
}
static
BOOL
add_mod_from_connection
(
fluid_voice_t
*
fluid_voice
,
CONNECTION
*
conn
,
UINT
src1
,
UINT
flags1
,
UINT
src2
,
UINT
flags2
)
{
fluid_mod_t
*
mod
;
UINT
gen
=
-
1
;
switch
(
MAKELONG
(
conn
->
usSource
,
conn
->
usDestination
))
{
case
MAKELONG
(
CONN_SRC_LFO
,
CONN_DST_PITCH
):
gen
=
GEN_MODLFOTOPITCH
;
break
;
case
MAKELONG
(
CONN_SRC_VIBRATO
,
CONN_DST_PITCH
):
gen
=
GEN_VIBLFOTOPITCH
;
break
;
case
MAKELONG
(
CONN_SRC_EG2
,
CONN_DST_PITCH
):
gen
=
GEN_MODENVTOPITCH
;
break
;
case
MAKELONG
(
CONN_SRC_LFO
,
CONN_DST_FILTER_CUTOFF
):
gen
=
GEN_MODLFOTOFILTERFC
;
break
;
case
MAKELONG
(
CONN_SRC_EG2
,
CONN_DST_FILTER_CUTOFF
):
gen
=
GEN_MODENVTOFILTERFC
;
break
;
case
MAKELONG
(
CONN_SRC_LFO
,
CONN_DST_GAIN
):
gen
=
GEN_MODLFOTOVOL
;
break
;
case
MAKELONG
(
CONN_SRC_KEYNUMBER
,
CONN_DST_EG2_HOLDTIME
):
gen
=
GEN_KEYTOMODENVHOLD
;
break
;
case
MAKELONG
(
CONN_SRC_KEYNUMBER
,
CONN_DST_EG2_DECAYTIME
):
gen
=
GEN_KEYTOMODENVDECAY
;
break
;
case
MAKELONG
(
CONN_SRC_KEYNUMBER
,
CONN_DST_EG1_HOLDTIME
):
gen
=
GEN_KEYTOVOLENVHOLD
;
break
;
case
MAKELONG
(
CONN_SRC_KEYNUMBER
,
CONN_DST_EG1_DECAYTIME
):
gen
=
GEN_KEYTOVOLENVDECAY
;
break
;
}
if
(
conn
->
usControl
!=
CONN_SRC_NONE
&&
gen
!=
-
1
)
{
src1
=
src2
;
flags1
=
flags2
;
src2
=
0
;
flags2
=
0
;
}
if
(
gen
==
-
1
&&
!
fluid_gen_from_connection
(
conn
,
&
gen
))
return
FALSE
;
if
(
!
(
mod
=
new_fluid_mod
()))
return
FALSE
;
fluid_mod_set_source1
(
mod
,
src1
,
flags1
);
fluid_mod_set_source2
(
mod
,
src2
,
flags2
);
fluid_mod_set_dest
(
mod
,
gen
);
fluid_mod_set_amount
(
mod
,
conn
->
lScale
);
fluid_voice_add_mod
(
fluid_voice
,
mod
,
FLUID_VOICE_OVERWRITE
);
return
TRUE
;
}
static
void
fluid_voice_add_articulation
(
fluid_voice_t
*
fluid_voice
,
struct
articulation
*
articulation
)
{
UINT
i
;
for
(
i
=
0
;
i
<
articulation
->
list
.
cConnections
;
i
++
)
{
UINT
src1
=
FLUID_MOD_NONE
,
flags1
=
0
,
src2
=
FLUID_MOD_NONE
,
flags2
=
0
;
CONNECTION
*
conn
=
articulation
->
connections
+
i
;
if
(
set_gen_from_connection
(
fluid_voice
,
conn
))
continue
;
if
(
!
fluid_source_from_connection
(
conn
->
usSource
,
(
conn
->
usTransform
>>
10
)
&
0x3f
,
&
src1
,
&
flags1
))
continue
;
if
(
!
fluid_source_from_connection
(
conn
->
usControl
,
(
conn
->
usControl
>>
4
)
&
0x3f
,
&
src2
,
&
flags2
))
continue
;
add_mod_from_connection
(
fluid_voice
,
conn
,
src1
,
flags1
,
src2
,
flags2
);
}
}
static
void
fluid_voice_add_articulations
(
fluid_voice_t
*
fluid_voice
,
struct
list
*
list
)
{
struct
articulation
*
articulation
;
LIST_FOR_EACH_ENTRY
(
articulation
,
list
,
struct
articulation
,
entry
)
fluid_voice_add_articulation
(
fluid_voice
,
articulation
);
}
static
int
synth_preset_noteon
(
fluid_preset_t
*
fluid_preset
,
fluid_synth_t
*
fluid_synth
,
int
chan
,
int
key
,
int
vel
)
{
struct
instrument
*
instrument
=
fluid_preset_get_data
(
fluid_preset
);
struct
synth
*
synth
=
instrument
->
synth
;
fluid_sample_t
*
fluid_sample
;
fluid_voice_t
*
fluid_voice
;
struct
region
*
region
;
TRACE
(
"(%p, %p, %u, %u, %u)
\n
"
,
fluid_preset
,
fluid_synth
,
chan
,
key
,
vel
);
if
(
!
instrument
)
return
FLUID_FAILED
;
LIST_FOR_EACH_ENTRY
(
region
,
&
instrument
->
regions
,
struct
region
,
entry
)
{
struct
wave
*
wave
=
region
->
wave
;
if
(
key
<
region
->
key_range
.
usLow
||
key
>
region
->
key_range
.
usHigh
)
continue
;
if
(
vel
<
region
->
vel_range
.
usLow
||
vel
>
region
->
vel_range
.
usHigh
)
continue
;
if
(
!
(
fluid_sample
=
new_fluid_sample
()))
{
WARN
(
"Failed to allocate FluidSynth sample
\n
"
);
return
FLUID_FAILED
;
}
fluid_sample_set_sound_data
(
fluid_sample
,
wave
->
samples
,
NULL
,
wave
->
sample_count
,
wave
->
format
.
nSamplesPerSec
,
TRUE
);
if
(
region
->
wave_sample
.
cSampleLoops
)
{
WLOOP
*
loop
=
region
->
wave_loops
;
fluid_sample_set_loop
(
fluid_sample
,
loop
->
ulStart
,
loop
->
ulStart
+
loop
->
ulLength
);
}
fluid_sample_set_pitch
(
fluid_sample
,
region
->
wave_sample
.
usUnityNote
,
region
->
wave_sample
.
sFineTune
);
if
(
!
(
fluid_voice
=
fluid_synth_alloc_voice
(
synth
->
fluid_synth
,
fluid_sample
,
chan
,
key
,
vel
)))
{
WARN
(
"Failed to allocate FluidSynth voice
\n
"
);
delete_fluid_sample
(
fluid_sample
);
return
FLUID_FAILED
;
}
fluid_voice_add_articulations
(
fluid_voice
,
&
instrument
->
articulations
);
fluid_voice_add_articulations
(
fluid_voice
,
&
region
->
articulations
);
fluid_synth_start_voice
(
synth
->
fluid_synth
,
fluid_voice
);
return
FLUID_OK
;
}
WARN
(
"Failed to find instrument matching note / velocity
\n
"
);
return
FLUID_FAILED
;
}
static
void
synth_preset_free
(
fluid_preset_t
*
fluid_preset
)
{
struct
instrument
*
instrument
=
fluid_preset_get_data
(
fluid_preset
);
fluid_preset_set_data
(
fluid_preset
,
NULL
);
if
(
instrument
)
instrument_release
(
instrument
);
}
static
const
char
*
synth_sfont_get_name
(
fluid_sfont_t
*
fluid_sfont
)
static
const
char
*
synth_sfont_get_name
(
fluid_sfont_t
*
fluid_sfont
)
{
{
return
"DirectMusicSynth"
;
return
"DirectMusicSynth"
;
...
@@ -1283,17 +1562,34 @@ static fluid_preset_t *synth_sfont_get_preset(fluid_sfont_t *fluid_sfont, int ba
...
@@ -1283,17 +1562,34 @@ static fluid_preset_t *synth_sfont_get_preset(fluid_sfont_t *fluid_sfont, int ba
{
{
struct
synth
*
synth
=
fluid_sfont_get_data
(
fluid_sfont
);
struct
synth
*
synth
=
fluid_sfont_get_data
(
fluid_sfont
);
struct
instrument
*
instrument
;
struct
instrument
*
instrument
;
fluid_preset_t
*
fluid_preset
;
TRACE
(
"(%p, %d, %d)
\n
"
,
fluid_sfont
,
bank
,
patch
);
TRACE
(
"(%p, %d, %d)
\n
"
,
fluid_sfont
,
bank
,
patch
);
if
(
!
synth
)
return
NULL
;
if
(
!
synth
)
return
NULL
;
EnterCriticalSection
(
&
synth
->
cs
);
LIST_FOR_EACH_ENTRY
(
instrument
,
&
synth
->
instruments
,
struct
instrument
,
entry
)
LIST_FOR_EACH_ENTRY
(
instrument
,
&
synth
->
instruments
,
struct
instrument
,
entry
)
if
(
instrument
->
patch
==
patch
)
break
;
if
(
instrument
->
patch
==
patch
)
break
;
if
(
&
instrument
->
entry
==
&
synth
->
instruments
)
return
NULL
;
FIXME
(
"Preset not implemented yet
\n
"
);
if
(
&
instrument
->
entry
==
&
synth
->
instruments
)
return
NULL
;
{
fluid_preset
=
NULL
;
WARN
(
"Could not find instrument with patch %#x
\n
"
,
patch
);
}
else
if
((
fluid_preset
=
new_fluid_preset
(
fluid_sfont
,
synth_preset_get_name
,
synth_preset_get_bank
,
synth_preset_get_num
,
synth_preset_noteon
,
synth_preset_free
)))
{
fluid_preset_set_data
(
fluid_preset
,
instrument
);
instrument_addref
(
instrument
);
TRACE
(
"Created fluid_preset %p for instrument %p
\n
"
,
fluid_preset
,
instrument
);
}
LeaveCriticalSection
(
&
synth
->
cs
);
return
fluid_preset
;
}
}
static
void
synth_sfont_iter_start
(
fluid_sfont_t
*
fluid_sfont
)
static
void
synth_sfont_iter_start
(
fluid_sfont_t
*
fluid_sfont
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment