Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
miniaudio
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
miniaudio
Commits
eb70fb5d
Commit
eb70fb5d
authored
Jan 06, 2017
by
David Reid
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Experimental work on an improved format conversion pipeline.
parent
5b444592
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
395 additions
and
166 deletions
+395
-166
mini_al.h
mini_al.h
+395
-166
No files found.
mini_al.h
View file @
eb70fb5d
...
@@ -346,6 +346,12 @@ typedef enum
...
@@ -346,6 +346,12 @@ typedef enum
mal_format_f32
=
4
,
mal_format_f32
=
4
,
}
mal_format
;
}
mal_format
;
typedef
enum
{
mal_channel_mix_mode_basic
,
// Drop excess channels; zeroed out extra channels.
mal_channel_mix_mode_blend
,
// Blend channels based on locality.
}
mal_channel_mix_mode
;
typedef
union
typedef
union
{
{
// Just look at this shit...
// Just look at this shit...
...
@@ -367,17 +373,36 @@ typedef struct
...
@@ -367,17 +373,36 @@ typedef struct
int64_t
counter
;
int64_t
counter
;
}
mal_timer
;
}
mal_timer
;
typedef
mal_uint32
(
*
mal_dsp_read_proc
)(
mal_uint32
frameCount
,
void
*
pSamplesOut
,
void
*
pUserData
);
typedef
struct
mal_dsp
mal_dsp
;
typedef
mal_uint32
(
*
mal_dsp_read_proc
)
(
mal_uint32
frameCount
,
void
*
pSamplesOut
,
void
*
pUserData
);
typedef
mal_uint32
(
*
mal_dsp_process_proc
)(
mal_dsp
*
pDSP
,
mal_dsp_read_proc
onRead
,
void
*
pUserData
,
void
*
pFramesOut
,
mal_uint32
frameCount
);
typedef
struct
typedef
struct
{
{
mal_format
formatIn
;
mal_format
formatIn
;
mal_uint32
channelsIn
;
mal_uint32
channelsIn
;
mal_uint32
sampleRateIn
;
mal_uint32
sampleRateIn
;
mal_uint8
channelMapIn
[
MAL_MAX_CHANNELS
];
mal_format
formatOut
;
mal_format
formatOut
;
mal_uint32
channelsOut
;
mal_uint32
channelsOut
;
mal_uint32
sampleRateOut
;
mal_uint32
sampleRateOut
;
float
bin
[
256
];
// Only used with SRC.
mal_uint8
channelMapOut
[
MAL_MAX_CHANNELS
];
}
mal_dsp
;
}
mal_dsp_config
;
struct
mal_dsp
{
mal_dsp_config
config
;
mal_dsp_process_proc
onProcess
;
mal_bool32
isUsingForeignChannelMap
:
1
;
struct
{
float
ratio
;
float
bin
[
256
];
// Will hold previous samples for handling interpolation and whatnot.
}
src
;
};
typedef
struct
typedef
struct
{
{
...
@@ -894,15 +919,6 @@ mal_uint32 mal_get_sample_size_in_bytes(mal_format format);
...
@@ -894,15 +919,6 @@ mal_uint32 mal_get_sample_size_in_bytes(mal_format format);
// DSP
// DSP
//
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
typedef
struct
{
mal_format
formatIn
;
mal_uint32
channelsIn
;
mal_uint32
sampleRateIn
;
mal_format
formatOut
;
mal_uint32
channelsOut
;
mal_uint32
sampleRateOut
;
}
mal_dsp_config
;
// Initializes a DSP object.
// Initializes a DSP object.
mal_result
mal_dsp_init
(
mal_dsp_config
*
pConfig
,
mal_dsp
*
pDSP
);
mal_result
mal_dsp_init
(
mal_dsp_config
*
pConfig
,
mal_dsp
*
pDSP
);
...
@@ -5393,6 +5409,7 @@ mal_result mal_device_init(mal_context* pContext, mal_device_type type, mal_devi
...
@@ -5393,6 +5409,7 @@ mal_result mal_device_init(mal_context* pContext, mal_device_type type, mal_devi
// Some flags need to be set if the backend is using a different internal format, channel count or sample rate.
// Some flags need to be set if the backend is using a different internal format, channel count or sample rate.
// TODO: Verify that these flags are still being used.
if
(
pDevice
->
format
!=
pDevice
->
internalFormat
)
{
if
(
pDevice
->
format
!=
pDevice
->
internalFormat
)
{
pDevice
->
flags
|=
MAL_DEVICE_FLAG_USING_FOREIGN_FORMAT
;
pDevice
->
flags
|=
MAL_DEVICE_FLAG_USING_FOREIGN_FORMAT
;
}
}
...
@@ -5413,12 +5430,12 @@ mal_result mal_device_init(mal_context* pContext, mal_device_type type, mal_devi
...
@@ -5413,12 +5430,12 @@ mal_result mal_device_init(mal_context* pContext, mal_device_type type, mal_devi
// When we do channel shuffling we will need to know how each channel index maps between the client and the device.
// When we do channel shuffling we will need to know how each channel index maps between the client and the device.
if
(
pDevice
->
flags
&
MAL_DEVICE_FLAG_USING_FOREIGN_CHANNEL_MAP
)
{
if
(
pDevice
->
flags
&
MAL_DEVICE_FLAG_USING_FOREIGN_CHANNEL_MAP
)
{
if
(
type
==
mal_device_type_playback
)
{
if
(
type
==
mal_device_type_playback
)
{
for
(
mal_uint32
i
=
0
;
i
<
pDevice
->
channels
;
++
i
)
{
for
(
mal_uint32
i
=
0
;
i
<
pDevice
->
channels
&&
i
<
pDevice
->
internalChannels
;
++
i
)
{
pDevice
->
channelShuffleTable
[
i
]
=
(
mal_uint8
)
i
;
}
}
}
else
{
}
else
{
for
(
mal_uint32
i
=
0
;
i
<
pDevice
->
internalChannels
;
++
i
)
{
for
(
mal_uint32
i
=
0
;
i
<
pDevice
->
channels
&&
i
<
pDevice
->
internalChannels
;
++
i
)
{
pDevice
->
channelShuffleTable
[
i
]
=
(
mal_uint8
)
i
;
}
}
}
}
}
}
...
@@ -5431,16 +5448,20 @@ mal_result mal_device_init(mal_context* pContext, mal_device_type type, mal_devi
...
@@ -5431,16 +5448,20 @@ mal_result mal_device_init(mal_context* pContext, mal_device_type type, mal_devi
dspConfig
.
formatIn
=
pDevice
->
format
;
dspConfig
.
formatIn
=
pDevice
->
format
;
dspConfig
.
channelsIn
=
pDevice
->
channels
;
dspConfig
.
channelsIn
=
pDevice
->
channels
;
dspConfig
.
sampleRateIn
=
pDevice
->
sampleRate
;
dspConfig
.
sampleRateIn
=
pDevice
->
sampleRate
;
mal_copy_memory
(
dspConfig
.
channelMapIn
,
pDevice
->
channelMap
,
sizeof
(
dspConfig
.
channelMapIn
));
dspConfig
.
formatOut
=
pDevice
->
internalFormat
;
dspConfig
.
formatOut
=
pDevice
->
internalFormat
;
dspConfig
.
channelsOut
=
pDevice
->
internalChannels
;
dspConfig
.
channelsOut
=
pDevice
->
internalChannels
;
dspConfig
.
sampleRateOut
=
pDevice
->
internalSampleRate
;
dspConfig
.
sampleRateOut
=
pDevice
->
internalSampleRate
;
mal_copy_memory
(
dspConfig
.
channelMapOut
,
pDevice
->
internalChannelMap
,
sizeof
(
dspConfig
.
channelMapOut
));
}
else
{
}
else
{
dspConfig
.
formatIn
=
pDevice
->
internalFormat
;
dspConfig
.
formatIn
=
pDevice
->
internalFormat
;
dspConfig
.
channelsIn
=
pDevice
->
internalChannels
;
dspConfig
.
channelsIn
=
pDevice
->
internalChannels
;
dspConfig
.
sampleRateIn
=
pDevice
->
internalSampleRate
;
dspConfig
.
sampleRateIn
=
pDevice
->
internalSampleRate
;
mal_copy_memory
(
dspConfig
.
channelMapIn
,
pDevice
->
internalChannelMap
,
sizeof
(
dspConfig
.
channelMapIn
));
dspConfig
.
formatOut
=
pDevice
->
format
;
dspConfig
.
formatOut
=
pDevice
->
format
;
dspConfig
.
channelsOut
=
pDevice
->
channels
;
dspConfig
.
channelsOut
=
pDevice
->
channels
;
dspConfig
.
sampleRateOut
=
pDevice
->
sampleRate
;
dspConfig
.
sampleRateOut
=
pDevice
->
sampleRate
;
mal_copy_memory
(
dspConfig
.
channelMapOut
,
pDevice
->
channelMap
,
sizeof
(
dspConfig
.
channelMapOut
));
}
}
mal_dsp_init
(
&
dspConfig
,
&
pDevice
->
dsp
);
mal_dsp_init
(
&
dspConfig
,
&
pDevice
->
dsp
);
...
@@ -5769,10 +5790,12 @@ static void mal_pcm_convert(void* pOut, mal_format formatOut, const void* pIn, m
...
@@ -5769,10 +5790,12 @@ static void mal_pcm_convert(void* pOut, mal_format formatOut, const void* pIn, m
}
}
}
}
static
void
mal_rearrange_channels
(
float
*
pFrame
,
mal_uint32
channels
,
mal_uint32
channelMap
[
1
6
])
static
void
mal_rearrange_channels
(
float
*
pFrame
,
mal_uint32
channels
,
mal_uint32
channelMap
[
1
8
])
{
{
float
temp
;
float
temp
;
switch
(
channels
)
{
switch
(
channels
)
{
case
18
:
temp
=
pFrame
[
17
];
pFrame
[
17
]
=
pFrame
[
channelMap
[
17
]];
pFrame
[
channelMap
[
17
]]
=
temp
;
case
17
:
temp
=
pFrame
[
16
];
pFrame
[
16
]
=
pFrame
[
channelMap
[
16
]];
pFrame
[
channelMap
[
16
]]
=
temp
;
case
16
:
temp
=
pFrame
[
15
];
pFrame
[
15
]
=
pFrame
[
channelMap
[
15
]];
pFrame
[
channelMap
[
15
]]
=
temp
;
case
16
:
temp
=
pFrame
[
15
];
pFrame
[
15
]
=
pFrame
[
channelMap
[
15
]];
pFrame
[
channelMap
[
15
]]
=
temp
;
case
15
:
temp
=
pFrame
[
14
];
pFrame
[
14
]
=
pFrame
[
channelMap
[
14
]];
pFrame
[
channelMap
[
14
]]
=
temp
;
case
15
:
temp
=
pFrame
[
14
];
pFrame
[
14
]
=
pFrame
[
channelMap
[
14
]];
pFrame
[
channelMap
[
14
]]
=
temp
;
case
14
:
temp
=
pFrame
[
13
];
pFrame
[
13
]
=
pFrame
[
channelMap
[
13
]];
pFrame
[
channelMap
[
13
]]
=
temp
;
case
14
:
temp
=
pFrame
[
13
];
pFrame
[
13
]
=
pFrame
[
channelMap
[
13
]];
pFrame
[
channelMap
[
13
]]
=
temp
;
...
@@ -5792,92 +5815,284 @@ static void mal_rearrange_channels(float* pFrame, mal_uint32 channels, mal_uint3
...
@@ -5792,92 +5815,284 @@ static void mal_rearrange_channels(float* pFrame, mal_uint32 channels, mal_uint3
}
}
}
}
static
void
mal_convert_channels_to_mono
(
float
*
pFrame
,
mal_uint32
channels
)
static
void
mal_dsp_mix_channels__dec
(
float
*
pFramesOut
,
mal_uint32
channelsOut
,
const
float
*
pFramesIn
,
mal_uint32
channelsIn
,
mal_uint32
frameCount
,
mal_channel_mix_mode
mode
)
{
{
// Mono is just an averaging of each channel.
mal_assert
(
pFramesOut
!=
NULL
);
float
total
=
0
;
mal_assert
(
channelsOut
>
0
);
switch
(
channels
)
{
mal_assert
(
pFramesIn
!=
NULL
);
case
16
:
total
+=
pFrame
[
15
];
mal_assert
(
channelsIn
>
0
);
case
15
:
total
+=
pFrame
[
14
];
mal_assert
(
channelsOut
<
channelsIn
);
case
14
:
total
+=
pFrame
[
13
];
case
13
:
total
+=
pFrame
[
12
];
if
(
mode
==
mal_channel_mix_mode_basic
)
{
case
12
:
total
+=
pFrame
[
11
];
// Basic mode is where we just drop excess channels.
case
11
:
total
+=
pFrame
[
10
];
for
(
mal_uint32
iFrame
=
0
;
iFrame
<
frameCount
;
++
iFrame
)
{
case
10
:
total
+=
pFrame
[
9
];
switch
(
channelsOut
)
{
case
9
:
total
+=
pFrame
[
8
];
case
17
:
pFramesOut
[
iFrame
*
channelsOut
+
16
]
=
pFramesIn
[
iFrame
*
channelsIn
+
16
];
case
8
:
total
+=
pFrame
[
7
];
case
16
:
pFramesOut
[
iFrame
*
channelsOut
+
15
]
=
pFramesIn
[
iFrame
*
channelsIn
+
15
];
case
7
:
total
+=
pFrame
[
6
];
case
15
:
pFramesOut
[
iFrame
*
channelsOut
+
14
]
=
pFramesIn
[
iFrame
*
channelsIn
+
14
];
case
6
:
total
+=
pFrame
[
5
];
case
14
:
pFramesOut
[
iFrame
*
channelsOut
+
13
]
=
pFramesIn
[
iFrame
*
channelsIn
+
13
];
case
5
:
total
+=
pFrame
[
4
];
case
13
:
pFramesOut
[
iFrame
*
channelsOut
+
12
]
=
pFramesIn
[
iFrame
*
channelsIn
+
12
];
case
4
:
total
+=
pFrame
[
3
];
case
12
:
pFramesOut
[
iFrame
*
channelsOut
+
11
]
=
pFramesIn
[
iFrame
*
channelsIn
+
11
];
case
3
:
total
+=
pFrame
[
2
];
case
11
:
pFramesOut
[
iFrame
*
channelsOut
+
10
]
=
pFramesIn
[
iFrame
*
channelsIn
+
10
];
case
2
:
total
+=
pFrame
[
1
];
case
10
:
pFramesOut
[
iFrame
*
channelsOut
+
9
]
=
pFramesIn
[
iFrame
*
channelsIn
+
9
];
case
1
:
total
+=
pFrame
[
0
];
case
9
:
pFramesOut
[
iFrame
*
channelsOut
+
8
]
=
pFramesIn
[
iFrame
*
channelsIn
+
8
];
}
case
8
:
pFramesOut
[
iFrame
*
channelsOut
+
7
]
=
pFramesIn
[
iFrame
*
channelsIn
+
7
];
case
7
:
pFramesOut
[
iFrame
*
channelsOut
+
6
]
=
pFramesIn
[
iFrame
*
channelsIn
+
6
];
pFrame
[
0
]
=
total
/
channels
;
case
6
:
pFramesOut
[
iFrame
*
channelsOut
+
5
]
=
pFramesIn
[
iFrame
*
channelsIn
+
5
];
}
case
5
:
pFramesOut
[
iFrame
*
channelsOut
+
4
]
=
pFramesIn
[
iFrame
*
channelsIn
+
4
];
case
4
:
pFramesOut
[
iFrame
*
channelsOut
+
3
]
=
pFramesIn
[
iFrame
*
channelsIn
+
3
];
static
void
mal_convert_channels_from_mono
(
float
*
pFrame
,
mal_uint32
channels
)
case
3
:
pFramesOut
[
iFrame
*
channelsOut
+
2
]
=
pFramesIn
[
iFrame
*
channelsIn
+
2
];
{
case
2
:
pFramesOut
[
iFrame
*
channelsOut
+
1
]
=
pFramesIn
[
iFrame
*
channelsIn
+
1
];
// Just copy the mono channel to each other channel.
case
1
:
pFramesOut
[
iFrame
*
channelsOut
+
0
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
switch
(
channels
)
{
}
case
16
:
pFrame
[
15
]
=
pFrame
[
0
];
}
case
15
:
pFrame
[
14
]
=
pFrame
[
0
];
}
else
{
case
14
:
pFrame
[
13
]
=
pFrame
[
0
];
// Blend mode is where we just use simple averaging to blend based on spacial locality.
case
13
:
pFrame
[
12
]
=
pFrame
[
0
];
case
12
:
pFrame
[
11
]
=
pFrame
[
0
];
case
11
:
pFrame
[
10
]
=
pFrame
[
0
];
case
10
:
pFrame
[
9
]
=
pFrame
[
0
];
case
9
:
pFrame
[
8
]
=
pFrame
[
0
];
case
8
:
pFrame
[
7
]
=
pFrame
[
0
];
case
7
:
pFrame
[
6
]
=
pFrame
[
0
];
case
6
:
pFrame
[
5
]
=
pFrame
[
0
];
case
5
:
pFrame
[
4
]
=
pFrame
[
0
];
case
4
:
pFrame
[
3
]
=
pFrame
[
0
];
case
3
:
pFrame
[
2
]
=
pFrame
[
0
];
case
2
:
pFrame
[
1
]
=
pFrame
[
0
];
case
1
:
pFrame
[
0
]
=
pFrame
[
0
];
}
}
static
void
mal_convert_channels__dec
(
float
*
pFrameIn
,
mal_uint32
channelsIn
,
mal_uint32
channelsOut
)
{
if
(
channelsOut
==
1
)
{
if
(
channelsOut
==
1
)
{
mal_convert_channels_to_mono
(
pFrameIn
,
channelsIn
);
for
(
mal_uint32
iFrame
=
0
;
iFrame
<
frameCount
;
++
iFrame
)
{
return
;
float
total
=
0
;
switch
(
channelsIn
)
{
case
18
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
17
];
case
17
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
16
];
case
16
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
15
];
case
15
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
14
];
case
14
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
13
];
case
13
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
12
];
case
12
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
11
];
case
11
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
10
];
case
10
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
9
];
case
9
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
8
];
case
8
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
7
];
case
7
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
6
];
case
6
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
5
];
case
5
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
4
];
case
4
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
3
];
case
3
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
2
];
case
2
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
1
];
case
1
:
total
+=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
}
pFramesOut
[
iFrame
+
0
]
=
total
/
channelsIn
;
}
}
else
if
(
channelsOut
==
2
)
{
// TODO: Implement proper stereo blending.
mal_dsp_mix_channels__dec
(
pFramesOut
,
channelsOut
,
pFramesIn
,
channelsIn
,
frameCount
,
mal_channel_mix_mode_basic
);
}
else
{
// Fall back to basic mode.
mal_dsp_mix_channels__dec
(
pFramesOut
,
channelsOut
,
pFramesIn
,
channelsIn
,
frameCount
,
mal_channel_mix_mode_basic
);
}
}
}
static
void
mal_dsp_mix_channels__inc
(
float
*
pFramesOut
,
mal_uint32
channelsOut
,
const
float
*
pFramesIn
,
mal_uint32
channelsIn
,
mal_uint32
frameCount
,
mal_channel_mix_mode
mode
)
{
mal_assert
(
pFramesOut
!=
NULL
);
mal_assert
(
channelsOut
>
0
);
mal_assert
(
pFramesIn
!=
NULL
);
mal_assert
(
channelsIn
>
0
);
mal_assert
(
channelsOut
>
channelsIn
);
if
(
mode
==
mal_channel_mix_mode_basic
)
{
\
// Basic mode is where we just zero out extra channels.
for
(
mal_uint32
iFrame
=
0
;
iFrame
<
frameCount
;
++
iFrame
)
{
switch
(
channelsIn
)
{
case
17
:
pFramesOut
[
iFrame
*
channelsOut
+
16
]
=
pFramesIn
[
iFrame
*
channelsIn
+
16
];
case
16
:
pFramesOut
[
iFrame
*
channelsOut
+
15
]
=
pFramesIn
[
iFrame
*
channelsIn
+
15
];
case
15
:
pFramesOut
[
iFrame
*
channelsOut
+
14
]
=
pFramesIn
[
iFrame
*
channelsIn
+
14
];
case
14
:
pFramesOut
[
iFrame
*
channelsOut
+
13
]
=
pFramesIn
[
iFrame
*
channelsIn
+
13
];
case
13
:
pFramesOut
[
iFrame
*
channelsOut
+
12
]
=
pFramesIn
[
iFrame
*
channelsIn
+
12
];
case
12
:
pFramesOut
[
iFrame
*
channelsOut
+
11
]
=
pFramesIn
[
iFrame
*
channelsIn
+
11
];
case
11
:
pFramesOut
[
iFrame
*
channelsOut
+
10
]
=
pFramesIn
[
iFrame
*
channelsIn
+
10
];
case
10
:
pFramesOut
[
iFrame
*
channelsOut
+
9
]
=
pFramesIn
[
iFrame
*
channelsIn
+
9
];
case
9
:
pFramesOut
[
iFrame
*
channelsOut
+
8
]
=
pFramesIn
[
iFrame
*
channelsIn
+
8
];
case
8
:
pFramesOut
[
iFrame
*
channelsOut
+
7
]
=
pFramesIn
[
iFrame
*
channelsIn
+
7
];
case
7
:
pFramesOut
[
iFrame
*
channelsOut
+
6
]
=
pFramesIn
[
iFrame
*
channelsIn
+
6
];
case
6
:
pFramesOut
[
iFrame
*
channelsOut
+
5
]
=
pFramesIn
[
iFrame
*
channelsIn
+
5
];
case
5
:
pFramesOut
[
iFrame
*
channelsOut
+
4
]
=
pFramesIn
[
iFrame
*
channelsIn
+
4
];
case
4
:
pFramesOut
[
iFrame
*
channelsOut
+
3
]
=
pFramesIn
[
iFrame
*
channelsIn
+
3
];
case
3
:
pFramesOut
[
iFrame
*
channelsOut
+
2
]
=
pFramesIn
[
iFrame
*
channelsIn
+
2
];
case
2
:
pFramesOut
[
iFrame
*
channelsOut
+
1
]
=
pFramesIn
[
iFrame
*
channelsIn
+
1
];
case
1
:
pFramesOut
[
iFrame
*
channelsOut
+
0
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
}
// Zero out extra channels.
switch
(
channelsOut
-
channelsIn
)
{
case
17
:
pFramesOut
[
iFrame
*
channelsOut
+
16
]
=
0
;
case
16
:
pFramesOut
[
iFrame
*
channelsOut
+
15
]
=
0
;
case
15
:
pFramesOut
[
iFrame
*
channelsOut
+
14
]
=
0
;
case
14
:
pFramesOut
[
iFrame
*
channelsOut
+
13
]
=
0
;
case
13
:
pFramesOut
[
iFrame
*
channelsOut
+
12
]
=
0
;
case
12
:
pFramesOut
[
iFrame
*
channelsOut
+
11
]
=
0
;
case
11
:
pFramesOut
[
iFrame
*
channelsOut
+
10
]
=
0
;
case
10
:
pFramesOut
[
iFrame
*
channelsOut
+
9
]
=
0
;
case
9
:
pFramesOut
[
iFrame
*
channelsOut
+
8
]
=
0
;
case
8
:
pFramesOut
[
iFrame
*
channelsOut
+
7
]
=
0
;
case
7
:
pFramesOut
[
iFrame
*
channelsOut
+
6
]
=
0
;
case
6
:
pFramesOut
[
iFrame
*
channelsOut
+
5
]
=
0
;
case
5
:
pFramesOut
[
iFrame
*
channelsOut
+
4
]
=
0
;
case
4
:
pFramesOut
[
iFrame
*
channelsOut
+
3
]
=
0
;
case
3
:
pFramesOut
[
iFrame
*
channelsOut
+
2
]
=
0
;
case
2
:
pFramesOut
[
iFrame
*
channelsOut
+
1
]
=
0
;
case
1
:
pFramesOut
[
iFrame
*
channelsOut
+
0
]
=
0
;
}
}
}
else
{
// Using blended mixing mode. Basically this is just the mode where audio is distributed across all channels
// based on spacial locality.
if
(
channelsIn
==
1
)
{
for
(
mal_uint32
iFrame
=
0
;
iFrame
<
frameCount
;
++
iFrame
)
{
switch
(
channelsOut
)
{
case
18
:
pFramesOut
[
iFrame
*
channelsOut
+
17
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
17
:
pFramesOut
[
iFrame
*
channelsOut
+
16
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
16
:
pFramesOut
[
iFrame
*
channelsOut
+
15
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
15
:
pFramesOut
[
iFrame
*
channelsOut
+
14
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
14
:
pFramesOut
[
iFrame
*
channelsOut
+
13
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
13
:
pFramesOut
[
iFrame
*
channelsOut
+
12
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
12
:
pFramesOut
[
iFrame
*
channelsOut
+
11
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
11
:
pFramesOut
[
iFrame
*
channelsOut
+
10
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
10
:
pFramesOut
[
iFrame
*
channelsOut
+
9
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
9
:
pFramesOut
[
iFrame
*
channelsOut
+
8
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
8
:
pFramesOut
[
iFrame
*
channelsOut
+
7
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
7
:
pFramesOut
[
iFrame
*
channelsOut
+
6
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
6
:
pFramesOut
[
iFrame
*
channelsOut
+
5
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
5
:
pFramesOut
[
iFrame
*
channelsOut
+
4
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
4
:
pFramesOut
[
iFrame
*
channelsOut
+
3
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
3
:
pFramesOut
[
iFrame
*
channelsOut
+
2
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
2
:
pFramesOut
[
iFrame
*
channelsOut
+
1
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
case
1
:
pFramesOut
[
iFrame
*
channelsOut
+
0
]
=
pFramesIn
[
iFrame
*
channelsIn
+
0
];
}
}
}
else
if
(
channelsIn
==
2
)
{
// TODO: Implement an optimized stereo conversion.
mal_dsp_mix_channels__dec
(
pFramesOut
,
channelsOut
,
pFramesIn
,
channelsIn
,
frameCount
,
mal_channel_mix_mode_basic
);
}
else
{
// Fall back to basic mixing mode.
mal_dsp_mix_channels__dec
(
pFramesOut
,
channelsOut
,
pFramesIn
,
channelsIn
,
frameCount
,
mal_channel_mix_mode_basic
);
}
}
}
// For now we are just dropping excess channels.
}
}
static
void
mal_
convert_channels__inc
(
float
*
pFrameIn
,
mal_uint32
channelsIn
,
mal_uint32
channelsOut
)
static
void
mal_
dsp_mix_channels
(
float
*
pFramesOut
,
mal_uint32
channelsOut
,
const
float
*
pFramesIn
,
mal_uint32
channelsIn
,
mal_uint32
frameCount
,
mal_channel_mix_mode
mode
)
{
{
// For now we are just dropping excess channels.
if
(
channelsIn
<
channelsOut
)
{
(
void
)
pFrameIn
;
// Increasing the channel count.
(
void
)
channelsIn
;
mal_dsp_mix_channels__inc
(
pFramesOut
,
channelsOut
,
pFramesIn
,
channelsIn
,
frameCount
,
mode
);
(
void
)
channelsOut
;
}
else
{
// Decreasing the channel count.
mal_dsp_mix_channels__dec
(
pFramesOut
,
channelsOut
,
pFramesIn
,
channelsIn
,
frameCount
,
mode
);
}
}
}
static
void
mal_convert_channels
(
float
*
pFrameIn
,
mal_uint32
channelsIn
,
mal_uint32
channelsOut
)
mal_uint32
mal_dsp_process_passthrough
(
mal_dsp
*
pDSP
,
mal_dsp_read_proc
onRead
,
void
*
pUserData
,
void
*
pFramesOut
,
mal_uint32
frameCount
);
mal_uint32
mal_dsp_process_generic
(
mal_dsp
*
pDSP
,
mal_dsp_read_proc
onRead
,
void
*
pUserData
,
void
*
pFramesOut
,
mal_uint32
frameCount
);
typedef
enum
{
mal_dsp_opcode_pcm_convert
,
mal_dsp_opcode_channel_mix
,
mal_dsp_opcode_channel_shuffle
,
mal_dsp_opcode_src
,
}
mal_dsp_opcode
;
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4201) // nonstandard extension used: nameless struct/union
#endif
typedef
struct
{
mal_dsp_opcode
opcode
;
mal_uint8
*
pInputData
;
mal_format
inputFormat
;
mal_uint32
inputChannels
;
mal_uint32
inputFrameCount
;
mal_uint8
*
pOutputData
;
mal_format
outputFormat
;
mal_uint32
outputChannels
;
mal_uint32
outputFrameCount
;
union
{
struct
{
mal_channel_mix_mode
mode
;
}
channel_mix
;
struct
{
mal_uint8
shuffleTable
;
}
channel_shuffle
;
struct
{
mal_uint32
inputSampleRate
;
mal_uint32
outputSampleRate
;
}
src
;
};
}
mal_dsp_op
;
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
void
mal_dsp_process_do_next_op
(
mal_dsp
*
pDSP
,
mal_dsp_op
*
pOP
)
{
{
if
(
channelsIn
>
channelsOut
)
{
(
void
)
pDSP
;
mal_convert_channels__dec
(
pFrameIn
,
channelsIn
,
channelsOut
);
}
else
if
(
channelsIn
<
channelsOut
)
{
switch
(
pOP
->
opcode
)
mal_convert_channels__inc
(
pFrameIn
,
channelsIn
,
channelsOut
);
{
case
mal_dsp_opcode_pcm_convert
:
// Conversion from pOP->inputFormat to pOP->outputFormat
{
mal_pcm_convert
(
pOP
->
pOutputData
,
pOP
->
outputFormat
,
pOP
->
pInputData
,
pOP
->
inputFormat
,
pOP
->
inputFrameCount
*
pOP
->
inputChannels
);
pOP
->
outputFrameCount
=
pOP
->
inputFrameCount
;
}
break
;
case
mal_dsp_opcode_channel_mix
:
{
mal_assert
(
pOP
->
inputFormat
==
mal_format_f32
);
mal_dsp_mix_channels
((
float
*
)
pOP
->
pOutputData
,
pOP
->
outputChannels
,
(
float
*
)
pOP
->
pInputData
,
pOP
->
inputChannels
,
pOP
->
inputFrameCount
,
mal_channel_mix_mode_blend
);
pOP
->
outputFrameCount
=
pOP
->
inputFrameCount
;
}
break
;
case
mal_dsp_opcode_channel_shuffle
:
{
// TODO: Implement me.
mal_copy_memory
(
pOP
->
pOutputData
,
pOP
->
pInputData
,
pOP
->
inputFrameCount
*
pOP
->
inputChannels
*
mal_get_sample_size_in_bytes
(
pOP
->
inputFormat
));
pOP
->
outputFrameCount
=
pOP
->
inputFrameCount
;
}
break
;
case
mal_dsp_opcode_src
:
{
// TODO: Implement me.
mal_copy_memory
(
pOP
->
pOutputData
,
pOP
->
pInputData
,
pOP
->
inputFrameCount
*
pOP
->
inputChannels
*
mal_get_sample_size_in_bytes
(
pOP
->
inputFormat
));
pOP
->
outputFrameCount
=
pOP
->
inputFrameCount
;
}
break
;
}
}
// The outpus from this operation become the inputs of the next.
pOP
->
pInputData
=
pOP
->
pOutputData
;
pOP
->
inputFormat
=
pOP
->
outputFormat
;
pOP
->
inputChannels
=
pOP
->
outputChannels
;
}
}
mal_result
mal_dsp_init
(
mal_dsp_config
*
pConfig
,
mal_dsp
*
pDSP
)
mal_result
mal_dsp_init
(
mal_dsp_config
*
pConfig
,
mal_dsp
*
pDSP
)
{
{
if
(
pDSP
==
NULL
)
return
MAL_INVALID_ARGS
;
if
(
pDSP
==
NULL
)
return
MAL_INVALID_ARGS
;
pDSP
->
formatIn
=
pConfig
->
formatIn
;
pDSP
->
config
=
*
pConfig
;
pDSP
->
channelsIn
=
pConfig
->
channelsIn
;
pDSP
->
onProcess
=
NULL
;
pDSP
->
sampleRateIn
=
pConfig
->
sampleRateIn
;
pDSP
->
src
.
ratio
=
pDSP
->
config
.
sampleRateIn
/
(
float
)
pDSP
->
config
.
sampleRateOut
;
pDSP
->
formatOut
=
pConfig
->
formatOut
;
mal_zero_memory
(
pDSP
->
src
.
bin
,
sizeof
(
pDSP
->
src
.
bin
));
pDSP
->
channelsOut
=
pConfig
->
channelsOut
;
pDSP
->
sampleRateOut
=
pConfig
->
sampleRateOut
;
pDSP
->
isUsingForeignChannelMap
=
MAL_FALSE
;
mal_zero_memory
(
pDSP
->
bin
,
sizeof
(
pDSP
->
bin
));
for
(
mal_uint32
i
=
0
;
i
<
MAL_MAX_CHANNELS
;
++
i
)
{
if
(
pConfig
->
channelMapIn
[
i
]
!=
pConfig
->
channelMapOut
[
i
])
{
pDSP
->
isUsingForeignChannelMap
=
MAL_TRUE
;
break
;
}
}
if
(
pConfig
->
formatIn
==
pConfig
->
formatOut
&&
pConfig
->
channelsIn
==
pConfig
->
channelsOut
&&
pConfig
->
sampleRateIn
==
pConfig
->
sampleRateOut
&&
!
pDSP
->
isUsingForeignChannelMap
)
{
pDSP
->
onProcess
=
mal_dsp_process_passthrough
;
}
else
{
pDSP
->
onProcess
=
mal_dsp_process_generic
;
}
return
MAL_SUCCESS
;
return
MAL_SUCCESS
;
}
}
...
@@ -5889,103 +6104,117 @@ mal_uint32 mal_dsp_process_passthrough(mal_dsp* pDSP, mal_dsp_read_proc onRead,
...
@@ -5889,103 +6104,117 @@ mal_uint32 mal_dsp_process_passthrough(mal_dsp* pDSP, mal_dsp_read_proc onRead,
return
onRead
(
frameCount
,
pFramesOut
,
pUserData
);
return
onRead
(
frameCount
,
pFramesOut
,
pUserData
);
}
}
mal_uint32
mal_dsp_process_generic
(
mal_dsp
*
pDSP
,
mal_dsp_read_proc
onRead
,
void
*
pUserData
,
void
*
pFramesOut
,
mal_uint32
frameCount
)
mal_uint32
mal_dsp_process_no_src
(
mal_dsp
*
pDSP
,
mal_dsp_read_proc
onRead
,
void
*
pUserData
,
void
*
pFramesOut
,
mal_uint32
frameCount
)
{
{
mal_uint32
totalFramesRead
=
0
;
// The DSP pipline is made up of stages where the output data from one stage becomes the input data of the next.
mal_uint8
pSampleData
[
2
][
256
*
MAL_MAX_CHANNELS
*
4
];
mal_uint32
totalFramesProcessed
=
0
;
mal_uint8
chunkBuffer
[
4096
];
mal_bool32
requiresF32Conversion
=
MAL_FALSE
;
mal_uint32
chunkFrameCount
=
sizeof
(
chunkBuffer
)
/
mal_get_sample_size_in_bytes
(
pDSP
->
formatIn
)
/
pDSP
->
channelsIn
;
if
(
pDSP
->
config
.
formatIn
!=
mal_format_f32
&&
(
pDSP
->
config
.
channelsIn
!=
pDSP
->
config
.
channelsOut
||
pDSP
->
config
.
sampleRateIn
!=
pDSP
->
config
.
sampleRateOut
))
{
requiresF32Conversion
=
MAL_TRUE
;
mal_uint32
framesRemaining
=
frameCount
;
while
(
framesRemaining
>
0
)
{
mal_uint32
framesJustRead
=
onRead
((
chunkFrameCount
<
framesRemaining
)
?
chunkFrameCount
:
framesRemaining
,
chunkBuffer
,
pUserData
);
if
(
framesJustRead
==
0
)
{
break
;
}
}
mal_uint8
*
pFramesOut8
=
(
mal_uint8
*
)
pFramesOut
+
(
totalFramesRead
*
pDSP
->
channelsOut
*
mal_get_sample_size_in_bytes
(
pDSP
->
formatOut
));
mal_uint32
framesToRead
=
(
mal_uint32
)(
frameCount
*
(
1
/
pDSP
->
src
.
ratio
));
if
(
pDSP
->
channelsIn
==
pDSP
->
channelsOut
)
{
while
(
framesToRead
>
0
)
{
// No SRC and no channel conversion.
mal_dsp_op
op
;
mal_pcm_convert
(
pFramesOut8
,
pDSP
->
formatOut
,
chunkBuffer
,
pDSP
->
formatIn
,
framesJustRead
*
pDSP
->
channelsIn
);
op
.
pInputData
=
pSampleData
[
0
];
}
else
{
op
.
inputFormat
=
pDSP
->
config
.
formatIn
;
// Channel conversion + format conversion.
op
.
inputChannels
=
pDSP
->
config
.
channelsIn
;
if
(
pDSP
->
formatIn
==
mal_format_f32
)
{
op
.
pOutputData
=
pSampleData
[
1
];
for
(
mal_uint32
iFrame
=
0
;
iFrame
<
framesJustRead
;
++
iFrame
)
{
float
*
pTempFrameF32
=
(
float
*
)(
chunkBuffer
+
(
iFrame
*
pDSP
->
channelsOut
*
mal_get_sample_size_in_bytes
(
pDSP
->
formatOut
)));
mal_uint32
inputFrameCount
=
sizeof
(
pSampleData
[
0
])
/
mal_get_sample_size_in_bytes
(
pDSP
->
config
.
formatIn
)
/
pDSP
->
config
.
channelsIn
;
mal_convert_channels
(
pTempFrameF32
,
pDSP
->
channelsIn
,
pDSP
->
channelsOut
);
if
(
inputFrameCount
>
framesToRead
)
{
mal_pcm_convert
(
pFramesOut8
+
(
iFrame
*
pDSP
->
channelsOut
*
mal_get_sample_size_in_bytes
(
pDSP
->
formatOut
)),
pDSP
->
formatOut
,
pTempFrameF32
,
mal_format_f32
,
pDSP
->
channelsOut
);
// <-- Evaluates to a memcpy().
inputFrameCount
=
framesToRead
;
}
}
else
{
float
tempFrame
[
MAL_MAX_CHANNELS
];
for
(
mal_uint32
iFrame
=
0
;
iFrame
<
framesJustRead
;
++
iFrame
)
{
mal_pcm_convert
(
tempFrame
,
mal_format_f32
,
chunkBuffer
+
(
iFrame
*
pDSP
->
channelsIn
*
mal_get_sample_size_in_bytes
(
pDSP
->
formatIn
)),
pDSP
->
formatIn
,
pDSP
->
channelsIn
);
mal_convert_channels
(
tempFrame
,
pDSP
->
channelsIn
,
pDSP
->
channelsOut
);
mal_pcm_convert
(
pFramesOut8
+
(
iFrame
*
pDSP
->
channelsOut
*
mal_get_sample_size_in_bytes
(
pDSP
->
formatOut
)),
pDSP
->
formatOut
,
tempFrame
,
mal_format_f32
,
pDSP
->
channelsOut
);
}
}
inputFrameCount
=
onRead
(
inputFrameCount
,
op
.
pInputData
,
pUserData
);
if
(
inputFrameCount
==
0
)
{
break
;
}
}
op
.
inputFrameCount
=
inputFrameCount
;
if
(
requiresF32Conversion
)
{
op
.
opcode
=
mal_dsp_opcode_pcm_convert
;
op
.
outputChannels
=
op
.
inputChannels
;
op
.
outputFormat
=
mal_format_f32
;
mal_dsp_process_do_next_op
(
pDSP
,
&
op
);
}
}
framesRemaining
-=
framesJustRead
;
if
(
pDSP
->
config
.
sampleRateIn
==
pDSP
->
config
.
sampleRateOut
)
{
totalFramesRead
+=
framesJustRead
;
// No SRC.
if
(
pDSP
->
config
.
channelsIn
!=
pDSP
->
config
.
channelsOut
)
{
op
.
opcode
=
mal_dsp_opcode_channel_mix
;
op
.
outputChannels
=
pDSP
->
config
.
channelsOut
;
mal_dsp_process_do_next_op
(
pDSP
,
&
op
);
}
}
return
totalFramesRead
;
if
(
pDSP
->
isUsingForeignChannelMap
)
{
}
op
.
opcode
=
mal_dsp_opcode_channel_shuffle
;
mal_dsp_process_do_next_op
(
pDSP
,
&
op
);
}
}
else
{
// SRC.
if
(
pDSP
->
config
.
sampleRateIn
>
pDSP
->
config
.
sampleRateOut
)
{
// Decimation. Do SRC first.
op
.
opcode
=
mal_dsp_opcode_src
;
op
.
src
.
inputSampleRate
=
pDSP
->
config
.
sampleRateIn
;
op
.
src
.
outputSampleRate
=
pDSP
->
config
.
sampleRateOut
;
mal_dsp_process_do_next_op
(
pDSP
,
&
op
);
if
(
pDSP
->
config
.
channelsIn
!=
pDSP
->
config
.
channelsOut
)
{
op
.
opcode
=
mal_dsp_opcode_channel_mix
;
op
.
outputChannels
=
pDSP
->
config
.
channelsOut
;
mal_dsp_process_do_next_op
(
pDSP
,
&
op
);
}
mal_uint32
mal_dsp_process_src__linear
(
mal_dsp
*
pDSP
,
mal_dsp_read_proc
onRead
,
void
*
pUserData
,
void
*
pFramesOut
,
mal_uint32
frameCount
)
if
(
pDSP
->
isUsingForeignChannelMap
)
{
{
op
.
opcode
=
mal_dsp_opcode_channel_shuffle
;
float
ratioSRC
=
(
float
)
pDSP
->
sampleRateOut
/
pDSP
->
sampleRateIn
;
mal_dsp_process_do_next_op
(
pDSP
,
&
op
);
if
(
ratioSRC
>
0
)
{
}
// The number of frames needing to be read is the
}
else
{
}
else
{
// Upsampling. Do SRC last.
if
(
pDSP
->
config
.
channelsIn
!=
pDSP
->
config
.
channelsOut
)
{
op
.
opcode
=
mal_dsp_opcode_channel_mix
;
op
.
outputChannels
=
pDSP
->
config
.
channelsOut
;
mal_dsp_process_do_next_op
(
pDSP
,
&
op
);
}
if
(
pDSP
->
isUsingForeignChannelMap
)
{
op
.
opcode
=
mal_dsp_opcode_channel_shuffle
;
mal_dsp_process_do_next_op
(
pDSP
,
&
op
);
}
}
return
0
;
op
.
opcode
=
mal_dsp_opcode_src
;
}
op
.
src
.
inputSampleRate
=
pDSP
->
config
.
sampleRateIn
;
op
.
src
.
outputSampleRate
=
pDSP
->
config
.
sampleRateOut
;
mal_dsp_process_do_next_op
(
pDSP
,
&
op
);
}
}
mal_uint32
mal_dsp_process_src__44100_to_48000
(
mal_dsp
*
pDSP
,
mal_dsp_read_proc
onRead
,
void
*
pUserData
,
void
*
pFramesOut
,
mal_uint32
frameCount
)
// Format conversion comes last.
{
if
(
op
.
inputFormat
!=
pDSP
->
config
.
formatOut
)
{
// TODO: Implement an optimized 44100 -> 48000 converter.
op
.
opcode
=
mal_dsp_opcode_pcm_convert
;
return
mal_dsp_process_src__linear
(
pDSP
,
onRead
,
pUserData
,
pFramesOut
,
frameCount
);
op
.
outputFormat
=
pDSP
->
config
.
formatOut
;
}
mal_dsp_process_do_next_op
(
pDSP
,
&
op
);
}
mal_uint32
mal_dsp_process_src__48000_to_44100
(
mal_dsp
*
pDSP
,
mal_dsp_read_proc
onRead
,
void
*
pUserData
,
void
*
pFramesOut
,
mal_uint32
frameCount
)
mal_uint32
frameSizeInBytes
=
pDSP
->
config
.
channelsOut
*
mal_get_sample_size_in_bytes
(
pDSP
->
config
.
formatOut
);
{
mal_copy_memory
((
mal_uint8
*
)
pFramesOut
+
(
totalFramesProcessed
*
frameSizeInBytes
),
op
.
pOutputData
,
op
.
outputFrameCount
*
frameSizeInBytes
);
// TODO: Implement an optimized 48000 -> 44100 converter.
return
mal_dsp_process_src__linear
(
pDSP
,
onRead
,
pUserData
,
pFramesOut
,
frameCount
);
}
mal_uint32
mal_dsp_process_src
(
mal_dsp
*
pDSP
,
mal_dsp_read_proc
onRead
,
void
*
pUserData
,
void
*
pFramesOut
,
mal_uint32
frameCount
)
totalFramesProcessed
+=
op
.
outputFrameCount
;
{
framesToRead
-=
op
.
outputFrameCount
;
// TODO: This can be optimized by moving the branching logic to mal_dsp_init() and using function pointers.
if
(
pDSP
->
sampleRateIn
==
44100
&&
pDSP
->
sampleRateOut
==
48000
)
{
return
mal_dsp_process_src__44100_to_48000
(
pDSP
,
onRead
,
pUserData
,
pFramesOut
,
frameCount
);
}
if
(
pDSP
->
sampleRateIn
==
48000
&&
pDSP
->
sampleRateOut
==
44100
)
{
return
mal_dsp_process_src__48000_to_44100
(
pDSP
,
onRead
,
pUserData
,
pFramesOut
,
frameCount
);
}
}
// Fallback.
return
totalFramesProcessed
;
return
mal_dsp_process_src__linear
(
pDSP
,
onRead
,
pUserData
,
pFramesOut
,
frameCount
);
}
}
mal_uint32
mal_dsp_process
(
mal_dsp
*
pDSP
,
mal_dsp_read_proc
onRead
,
void
*
pUserData
,
void
*
pFramesOut
,
mal_uint32
frameCount
)
mal_uint32
mal_dsp_process
(
mal_dsp
*
pDSP
,
mal_dsp_read_proc
onRead
,
void
*
pUserData
,
void
*
pFramesOut
,
mal_uint32
frameCount
)
{
{
if
(
pDSP
==
NULL
||
pFramesOut
==
NULL
||
onRead
==
NULL
)
return
0
;
if
(
pDSP
==
NULL
||
pFramesOut
==
NULL
||
onRead
==
NULL
||
pDSP
->
onProcess
==
NULL
)
return
0
;
return
pDSP
->
onProcess
(
pDSP
,
onRead
,
pUserData
,
pFramesOut
,
frameCount
);
if
(
pDSP
->
formatIn
==
pDSP
->
formatOut
&&
pDSP
->
channelsIn
==
pDSP
->
channelsOut
&&
pDSP
->
sampleRateIn
==
pDSP
->
sampleRateOut
)
{
return
mal_dsp_process_passthrough
(
pDSP
,
onRead
,
pUserData
,
pFramesOut
,
frameCount
);
}
else
{
if
(
pDSP
->
sampleRateIn
==
pDSP
->
sampleRateOut
)
{
return
mal_dsp_process_no_src
(
pDSP
,
onRead
,
pUserData
,
pFramesOut
,
frameCount
);
}
else
{
return
mal_dsp_process_src
(
pDSP
,
onRead
,
pUserData
,
pFramesOut
,
frameCount
);
}
}
}
}
...
...
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