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
2b526f69
Commit
2b526f69
authored
Jan 09, 2020
by
David Reid
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add experimental code for biquad and low-pass filters.
parent
45499c8b
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
411 additions
and
48 deletions
+411
-48
research/ma_lpf.h
research/ma_lpf.h
+237
-0
research/ma_resampler.h
research/ma_resampler.h
+51
-42
research/tests/ma_lpf_test_0.c
research/tests/ma_lpf_test_0.c
+109
-0
tests/ma_test_0.vcxproj
tests/ma_test_0.vcxproj
+8
-6
tests/ma_test_0.vcxproj.filters
tests/ma_test_0.vcxproj.filters
+6
-0
No files found.
research/ma_lpf.h
0 → 100644
View file @
2b526f69
#ifndef ma_lpf_h
#define ma_lpf_h
/*
TODO:
- Document passthrough behaviour of the biquad filter and how it doesn't update previous inputs and outputs.
- Document how changing biquad constants requires reinitialization of the filter (due to issue above).
*/
typedef
struct
{
ma_format
format
;
ma_uint32
channels
;
float
a0
;
float
a1
;
float
a2
;
float
b0
;
float
b1
;
float
b2
;
}
ma_biquad_config
;
ma_biquad_config
ma_biquad_config_init
(
ma_format
format
,
ma_uint32
channels
,
float
a0
,
float
a1
,
float
a2
,
float
b0
,
float
b1
,
float
b2
);
typedef
struct
{
ma_biquad_config
config
;
ma_bool32
isPassthrough
;
ma_uint32
prevFrameCount
;
float
x1
[
MA_MAX_CHANNELS
];
/* x[n-1] */
float
x2
[
MA_MAX_CHANNELS
];
/* x[n-2] */
float
y1
[
MA_MAX_CHANNELS
];
/* y[n-1] */
float
y2
[
MA_MAX_CHANNELS
];
/* y[n-2] */
}
ma_biquad
;
ma_result
ma_biquad_init
(
const
ma_biquad_config
*
pConfig
,
ma_biquad
*
pBQ
);
ma_result
ma_biquad_process
(
ma_biquad
*
pBQ
,
void
*
pFramesOut
,
const
void
*
pFramesIn
,
ma_uint64
frameCount
);
typedef
struct
{
ma_format
format
;
ma_uint32
channels
;
ma_uint32
sampleRate
;
ma_uint32
cutoffFrequency
;
}
ma_lpf_config
;
ma_lpf_config
ma_lpf_config_init
(
ma_format
format
,
ma_uint32
channels
,
ma_uint32
sampleRate
,
ma_uint32
cutoffFrequency
);
typedef
struct
{
ma_biquad
bq
;
/* The low-pass filter is implemented as a biquad filter. */
ma_lpf_config
config
;
}
ma_lpf
;
ma_result
ma_lpf_init
(
const
ma_lpf_config
*
pConfig
,
ma_lpf
*
pLPF
);
ma_result
ma_lpf_process
(
ma_lpf
*
pLPF
,
void
*
pFramesOut
,
const
void
*
pFramesIn
,
ma_uint64
frameCount
);
#endif
/* ma_lpf_h */
#if defined(MINIAUDIO_IMPLEMENTATION)
ma_biquad_config
ma_biquad_config_init
(
ma_format
format
,
ma_uint32
channels
,
float
a0
,
float
a1
,
float
a2
,
float
b0
,
float
b1
,
float
b2
)
{
ma_biquad_config
config
;
MA_ZERO_OBJECT
(
&
config
);
config
.
format
=
format
;
config
.
channels
=
channels
;
config
.
a0
=
a0
;
config
.
a1
=
a1
;
config
.
a2
=
a2
;
config
.
b0
=
b0
;
config
.
b1
=
b1
;
config
.
b2
=
b2
;
return
config
;
}
ma_result
ma_biquad_init
(
const
ma_biquad_config
*
pConfig
,
ma_biquad
*
pBQ
)
{
if
(
pBQ
==
NULL
)
{
return
MA_INVALID_ARGS
;
}
MA_ZERO_OBJECT
(
pBQ
);
if
(
pConfig
==
NULL
)
{
return
MA_INVALID_ARGS
;
}
if
(
pConfig
->
a0
==
0
)
{
return
MA_INVALID_ARGS
;
/* Division by zero. */
}
/* Currently only supporting f32, but support for other formats will be added later. */
if
(
pConfig
->
format
!=
ma_format_f32
)
{
return
MA_INVALID_ARGS
;
}
pBQ
->
config
=
*
pConfig
;
if
(
pConfig
->
a0
==
1
&&
pConfig
->
a1
==
0
&&
pConfig
->
a2
==
0
&&
pConfig
->
b0
==
1
&&
pConfig
->
b1
==
0
&&
pConfig
->
b2
==
0
)
{
pBQ
->
isPassthrough
=
MA_TRUE
;
}
/* Normalize. */
pBQ
->
config
.
a1
/=
pBQ
->
config
.
a0
;
pBQ
->
config
.
a2
/=
pBQ
->
config
.
a0
;
pBQ
->
config
.
b0
/=
pBQ
->
config
.
a0
;
pBQ
->
config
.
b1
/=
pBQ
->
config
.
a0
;
pBQ
->
config
.
b2
/=
pBQ
->
config
.
a0
;
return
MA_SUCCESS
;
}
ma_result
ma_biquad_process
(
ma_biquad
*
pBQ
,
void
*
pFramesOut
,
const
void
*
pFramesIn
,
ma_uint64
frameCount
)
{
ma_uint32
n
;
ma_uint32
c
;
float
a1
=
pBQ
->
config
.
a1
;
float
a2
=
pBQ
->
config
.
a2
;
float
b0
=
pBQ
->
config
.
b0
;
float
b1
=
pBQ
->
config
.
b1
;
float
b2
=
pBQ
->
config
.
b2
;
if
(
pBQ
==
NULL
||
pFramesOut
==
NULL
||
pFramesIn
==
NULL
)
{
return
MA_INVALID_ARGS
;
}
/* Fast path for passthrough. */
if
(
pBQ
->
isPassthrough
)
{
ma_copy_memory_64
(
pFramesOut
,
pFramesIn
,
frameCount
*
ma_get_bytes_per_frame
(
pBQ
->
config
.
format
,
pBQ
->
config
.
channels
));
return
MA_SUCCESS
;
}
/* Currently only supporting f32. */
if
(
pBQ
->
config
.
format
==
ma_format_f32
)
{
float
*
pY
=
(
float
*
)
pFramesOut
;
const
float
*
pX
=
(
const
float
*
)
pFramesIn
;
for
(
n
=
0
;
n
<
frameCount
;
n
+=
1
)
{
for
(
c
=
0
;
c
<
pBQ
->
config
.
channels
;
c
+=
1
)
{
float
x2
=
pBQ
->
x2
[
c
];
float
x1
=
pBQ
->
x1
[
c
];
float
x0
=
pX
[
n
*
pBQ
->
config
.
channels
+
c
];
float
y2
=
pBQ
->
y2
[
c
];
float
y1
=
pBQ
->
y1
[
c
];
float
y0
=
b0
*
x0
+
b1
*
x1
+
b2
*
x2
-
a1
*
y1
-
a2
*
y2
;
pY
[
n
*
pBQ
->
config
.
channels
+
c
]
=
y0
;
pBQ
->
x2
[
c
]
=
x1
;
pBQ
->
x1
[
c
]
=
x0
;
pBQ
->
y2
[
c
]
=
y1
;
pBQ
->
y1
[
c
]
=
y0
;
}
}
}
else
{
return
MA_INVALID_ARGS
;
/* Format not supported. Should never hit this because it's checked in ma_biquad_init(). */
}
return
MA_SUCCESS
;
}
ma_lpf_config
ma_lpf_config_init
(
ma_format
format
,
ma_uint32
channels
,
ma_uint32
sampleRate
,
ma_uint32
cutoffFrequency
)
{
ma_lpf_config
config
;
MA_ZERO_OBJECT
(
&
config
);
config
.
format
=
format
;
config
.
channels
=
channels
;
config
.
sampleRate
=
sampleRate
;
config
.
cutoffFrequency
=
cutoffFrequency
;
return
config
;
}
ma_result
ma_lpf_init
(
const
ma_lpf_config
*
pConfig
,
ma_lpf
*
pLPF
)
{
ma_result
result
;
ma_biquad_config
bqConfig
;
double
q
;
double
w
;
double
s
;
double
c
;
double
a
;
if
(
pLPF
==
NULL
)
{
return
MA_INVALID_ARGS
;
}
MA_ZERO_OBJECT
(
pLPF
);
if
(
pConfig
==
NULL
)
{
return
MA_INVALID_ARGS
;
}
pLPF
->
config
=
*
pConfig
;
q
=
1
/
sqrt
(
2
);
w
=
2
*
MA_PI_D
*
pConfig
->
cutoffFrequency
/
pConfig
->
sampleRate
;
s
=
sin
(
w
);
c
=
cos
(
w
);
a
=
s
/
(
2
*
q
);
bqConfig
.
a0
=
(
float
)(
1
+
a
);
bqConfig
.
a1
=
(
float
)(
-
2
*
c
);
bqConfig
.
a2
=
(
float
)(
1
-
a
);
bqConfig
.
b0
=
(
float
)((
1
-
c
)
/
2
);
bqConfig
.
b1
=
(
float
)(
1
-
c
);
bqConfig
.
b2
=
(
float
)((
1
-
c
)
/
2
);
bqConfig
.
format
=
pConfig
->
format
;
bqConfig
.
channels
=
pConfig
->
channels
;
result
=
ma_biquad_init
(
&
bqConfig
,
&
pLPF
->
bq
);
if
(
result
!=
MA_SUCCESS
)
{
return
result
;
}
return
MA_SUCCESS
;
}
ma_result
ma_lpf_process
(
ma_lpf
*
pLPF
,
void
*
pFramesOut
,
const
void
*
pFramesIn
,
ma_uint64
frameCount
)
{
if
(
pLPF
==
NULL
)
{
return
MA_INVALID_ARGS
;
}
return
ma_biquad_process
(
&
pLPF
->
bq
,
pFramesOut
,
pFramesIn
,
frameCount
);
}
#endif
\ No newline at end of file
research/ma_resampler.h
View file @
2b526f69
...
...
@@ -3,49 +3,43 @@
#ifndef ma_resampler_h
#define ma_resampler_h
#include "ma_lpf.h"
typedef
enum
{
ma_resample_algorithm_linear
=
0
,
/* Fastest, lowest quality
. */
ma_resample_algorithm_linear
_lpf
,
/* Linear with a biquad low pass filter
. */
ma_resample_algorithm_linear
_lpf
=
0
,
/* Linear with a biquad low pass filter. Default
. */
ma_resample_algorithm_linear
,
/* Fastest, lowest quality
. */
}
ma_resample_algorithm
;
typedef
struct
{
ma_resample_algorithm
algorithm
;
ma_format
format
;
/* Must be either ma_format_f32 or ma_format_s16. */
ma_uint32
channels
;
ma_uint32
sampleRateIn
;
ma_uint32
sampleRateOut
;
ma_uint32
channels
;
ma_format
format
;
/* Must be either ma_format_f32 or ma_format_s16. */
ma_resample_algorithm
algorithm
;
struct
{
int
_unused
;
}
linear
;
struct
{
int
_unused
;
ma_uint32
cutoffFrequency
;
}
linearLPF
;
}
ma_resampler_config
;
ma_resampler_config
ma_resampler_config_init
(
ma_format
format
,
ma_uint32
channels
,
ma_uint32
sampleRateIn
,
ma_uint32
sampleRateOut
,
ma_resample_algorithm
algorithm
);
typedef
struct
{
ma_resampler_config
config
;
float
timeX
;
/* Input time. */
float
timeY
;
/* Output time. */
union
{
struct
{
float
timeX
;
/* Input time. */
float
timeY
;
/* Output time. */
struct
{
float
yprev1
;
/* y-1 */
float
yprev2
;
/* y-2 */
float
a0
;
float
a1
;
float
a2
;
float
b0
;
float
b1
;
float
b2
;
}
lpf
;
ma_lpf
lpf
;
}
linear
;
}
state
;
}
ma_resampler
;
...
...
@@ -75,7 +69,7 @@ It is an error for [pFramesOut] to be non-NULL and [pFrameCountOut] to be NULL.
It is an error for both [pFrameCountOut] and [pFrameCountIn] to be NULL.
*/
ma_result
ma_resampler_process
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
void
*
pFramesOut
,
ma_uint64
*
pFrameCountIn
,
void
*
pFramesIn
);
ma_result
ma_resampler_process
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
void
*
pFramesOut
,
ma_uint64
*
pFrameCountIn
,
const
void
*
pFramesIn
);
/*
...
...
@@ -99,37 +93,52 @@ Implementation
#define MA_RESAMPLER_MAX_RATIO 48.0
#endif
ma_resampler_config
ma_resampler_config_init
(
ma_format
format
,
ma_uint32
channels
,
ma_uint32
sampleRateIn
,
ma_uint32
sampleRateOut
,
ma_resample_algorithm
algorithm
)
{
ma_resampler_config
config
;
MA_ZERO_OBJECT
(
&
config
);
config
.
format
=
format
;
config
.
channels
=
channels
;
config
.
sampleRateIn
=
sampleRateIn
;
config
.
sampleRateOut
=
sampleRateOut
;
config
.
algorithm
=
algorithm
;
return
config
;
}
ma_result
ma_resampler_init
(
const
ma_resampler_config
*
pConfig
,
ma_resampler
*
pResampler
)
{
ma_result
result
;
if
(
pConfig
==
NULL
||
pResampler
==
NULL
)
{
return
MA_INVALID_ARGS
;
}
MA_ZERO_OBJECT
(
pResampler
);
pResampler
->
config
=
*
pConfig
;
pResampler
->
timeX
=
0
.
0
f
;
pResampler
->
timeY
=
0
.
0
f
;
switch
(
pConfig
->
algorithm
)
{
case
ma_resample_algorithm_linear
:
{
pResampler
->
state
.
linear
.
timeX
=
0
.
0
f
;
pResampler
->
state
.
linear
.
timeY
=
0
.
0
f
;
}
break
;
case
ma_resample_algorithm_linear_lpf
:
{
pResampler
->
state
.
linear
.
timeX
=
0
.
0
f
;
pResampler
->
state
.
linear
.
timeY
=
0
.
0
f
;
pResampler
->
state
.
linear
.
lpf
.
yprev1
=
0
.
0
f
;
pResampler
->
state
.
linear
.
lpf
.
yprev2
=
0
.
0
f
;
/* TODO: Biquad LPF filter coefficients. */
pResampler
->
state
.
linear
.
lpf
.
a0
=
0
.
0
f
;
pResampler
->
state
.
linear
.
lpf
.
a1
=
0
.
0
f
;
pResampler
->
state
.
linear
.
lpf
.
a2
=
0
.
0
f
;
pResampler
->
state
.
linear
.
lpf
.
b0
=
0
.
0
f
;
pResampler
->
state
.
linear
.
lpf
.
b1
=
0
.
0
f
;
pResampler
->
state
.
linear
.
lpf
.
b2
=
0
.
0
f
;
ma_lpf_config
lpfConfig
;
lpfConfig
=
ma_lpf_config_init
(
pConfig
->
format
,
pConfig
->
channels
,
pConfig
->
sampleRateOut
,
pConfig
->
linearLPF
.
cutoffFrequency
);
if
(
lpfConfig
.
cutoffFrequency
==
0
)
{
lpfConfig
.
cutoffFrequency
=
ma_min
(
pConfig
->
sampleRateIn
,
pConfig
->
sampleRateOut
)
/
2
;
}
result
=
ma_lpf_init
(
&
lpfConfig
,
&
pResampler
->
state
.
linear
.
lpf
);
if
(
result
!=
MA_SUCCESS
)
{
return
result
;
}
}
break
;
default:
return
MA_INVALID_ARGS
;
...
...
@@ -138,7 +147,7 @@ ma_result ma_resampler_init(const ma_resampler_config* pConfig, ma_resampler* pR
return
MA_SUCCESS
;
}
static
ma_result
ma_resampler_process__seek__linear
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
ma_uint64
*
pFrameCountIn
,
void
*
pFramesIn
)
static
ma_result
ma_resampler_process__seek__linear
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
ma_uint64
*
pFrameCountIn
,
const
void
*
pFramesIn
)
{
MA_ASSERT
(
pResampler
!=
NULL
);
...
...
@@ -163,13 +172,13 @@ static ma_result ma_resampler_process__seek__linear(ma_resampler* pResampler, ma
return
MA_SUCCESS
;
}
static
ma_result
ma_resampler_process__seek__linear_lpf
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
ma_uint64
*
pFrameCountIn
,
void
*
pFramesIn
)
static
ma_result
ma_resampler_process__seek__linear_lpf
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
ma_uint64
*
pFrameCountIn
,
const
void
*
pFramesIn
)
{
/* TODO: Proper linear LPF implementation. */
return
ma_resampler_process__seek__linear
(
pResampler
,
pFrameCountOut
,
pFrameCountIn
,
pFramesIn
);
}
static
ma_result
ma_resampler_process__seek
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
ma_uint64
*
pFrameCountIn
,
void
*
pFramesIn
)
static
ma_result
ma_resampler_process__seek
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
ma_uint64
*
pFrameCountIn
,
const
void
*
pFramesIn
)
{
MA_ASSERT
(
pResampler
!=
NULL
);
...
...
@@ -190,7 +199,7 @@ static ma_result ma_resampler_process__seek(ma_resampler* pResampler, ma_uint64*
}
static
ma_result
ma_resampler_process__read__linear
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
void
*
pFramesOut
,
ma_uint64
*
pFrameCountIn
,
void
*
pFramesIn
)
static
ma_result
ma_resampler_process__read__linear
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
void
*
pFramesOut
,
ma_uint64
*
pFrameCountIn
,
const
void
*
pFramesIn
)
{
MA_ASSERT
(
pResampler
!=
NULL
);
MA_ASSERT
(
pFramesOut
!=
NULL
);
...
...
@@ -205,13 +214,13 @@ static ma_result ma_resampler_process__read__linear(ma_resampler* pResampler, ma
return
MA_SUCCESS
;
}
static
ma_result
ma_resampler_process__read__linear_lpf
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
void
*
pFramesOut
,
ma_uint64
*
pFrameCountIn
,
void
*
pFramesIn
)
static
ma_result
ma_resampler_process__read__linear_lpf
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
void
*
pFramesOut
,
ma_uint64
*
pFrameCountIn
,
const
void
*
pFramesIn
)
{
/* TODO: Proper linear LPF implementation. */
return
ma_resampler_process__read__linear
(
pResampler
,
pFrameCountOut
,
pFramesOut
,
pFrameCountIn
,
pFramesIn
);
}
static
ma_result
ma_resampler_process__read
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
void
*
pFramesOut
,
ma_uint64
*
pFrameCountIn
,
void
*
pFramesIn
)
static
ma_result
ma_resampler_process__read
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
void
*
pFramesOut
,
ma_uint64
*
pFrameCountIn
,
const
void
*
pFramesIn
)
{
MA_ASSERT
(
pResampler
!=
NULL
);
MA_ASSERT
(
pFramesOut
!=
NULL
);
...
...
@@ -237,13 +246,13 @@ static ma_result ma_resampler_process__read(ma_resampler* pResampler, ma_uint64*
}
}
ma_result
ma_resampler_process
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
void
*
pFramesOut
,
ma_uint64
*
pFrameCountIn
,
void
*
pFramesIn
)
ma_result
ma_resampler_process
(
ma_resampler
*
pResampler
,
ma_uint64
*
pFrameCountOut
,
void
*
pFramesOut
,
ma_uint64
*
pFrameCountIn
,
const
void
*
pFramesIn
)
{
if
(
pResampler
==
NULL
)
{
return
MA_INVALID_ARGS
;
}
if
(
pFrameCountOut
!
=
NULL
&&
pFrameCountIn
==
NULL
)
{
if
(
pFrameCountOut
=
=
NULL
&&
pFrameCountIn
==
NULL
)
{
return
MA_INVALID_ARGS
;
}
...
...
research/tests/ma_lpf_test_0.c
0 → 100644
View file @
2b526f69
#define DR_FLAC_IMPLEMENTATION
#include "../../extras/dr_flac.h"
/* Enables FLAC decoding. */
#define DR_MP3_IMPLEMENTATION
#include "../../extras/dr_mp3.h"
/* Enables MP3 decoding. */
#define DR_WAV_IMPLEMENTATION
#include "../../extras/dr_wav.h"
/* Enables WAV decoding. */
#define MA_DEBUG_OUTPUT
#define MINIAUDIO_IMPLEMENTATION
#include "../../miniaudio.h"
#include "../ma_lpf.h"
ma_lpf
g_lpf
;
void
data_callback
(
ma_device
*
pDevice
,
void
*
pOutput
,
const
void
*
pInput
,
ma_uint32
frameCount
)
{
ma_uint32
framesProcessed
=
0
;
ma_decoder
*
pDecoder
=
(
ma_decoder
*
)
pDevice
->
pUserData
;
if
(
pDecoder
==
NULL
)
{
return
;
}
/* We need to read into a temporary buffer and then run it through the low pass filter. */
while
(
framesProcessed
<
frameCount
)
{
float
tempBuffer
[
4096
];
ma_uint32
framesToProcessThisIteration
;
framesToProcessThisIteration
=
frameCount
-
framesProcessed
;
if
(
framesToProcessThisIteration
>
ma_countof
(
tempBuffer
)
/
pDecoder
->
internalChannels
)
{
framesToProcessThisIteration
=
ma_countof
(
tempBuffer
)
/
pDecoder
->
internalChannels
;
}
#if 0
ma_decoder_read_pcm_frames(pDecoder, ma_offset_ptr(pOutput, framesProcessed * ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels)), framesToProcessThisIteration);
#else
ma_decoder_read_pcm_frames
(
pDecoder
,
tempBuffer
,
framesToProcessThisIteration
);
/* Out the results from the low pass filter straight into our output buffer. */
ma_lpf_process
(
&
g_lpf
,
ma_offset_ptr
(
pOutput
,
framesProcessed
*
ma_get_bytes_per_frame
(
pDevice
->
playback
.
format
,
pDevice
->
playback
.
channels
)),
tempBuffer
,
framesToProcessThisIteration
);
#endif
framesProcessed
+=
framesToProcessThisIteration
;
}
(
void
)
pInput
;
}
int
main
(
int
argc
,
char
**
argv
)
{
ma_result
result
;
ma_decoder_config
decoderConfig
;
ma_decoder
decoder
;
ma_lpf_config
lpfConfig
;
ma_device_config
deviceConfig
;
ma_device
device
;
if
(
argc
<
2
)
{
printf
(
"No input file.
\n
"
);
return
-
1
;
}
decoderConfig
=
ma_decoder_config_init
(
ma_format_f32
,
0
,
0
);
result
=
ma_decoder_init_file
(
argv
[
1
],
&
decoderConfig
,
&
decoder
);
if
(
result
!=
MA_SUCCESS
)
{
return
-
2
;
}
lpfConfig
.
format
=
decoderConfig
.
format
;
lpfConfig
.
channels
=
decoder
.
internalChannels
;
lpfConfig
.
sampleRate
=
decoder
.
internalSampleRate
;
lpfConfig
.
cutoffFrequency
=
lpfConfig
.
sampleRate
/
4
;
result
=
ma_lpf_init
(
&
lpfConfig
,
&
g_lpf
);
if
(
result
!=
MA_SUCCESS
)
{
return
-
100
;
}
deviceConfig
=
ma_device_config_init
(
ma_device_type_playback
);
deviceConfig
.
playback
.
format
=
decoder
.
outputFormat
;
deviceConfig
.
playback
.
channels
=
decoder
.
outputChannels
;
deviceConfig
.
sampleRate
=
decoder
.
outputSampleRate
;
deviceConfig
.
dataCallback
=
data_callback
;
deviceConfig
.
pUserData
=
&
decoder
;
if
(
ma_device_init
(
NULL
,
&
deviceConfig
,
&
device
)
!=
MA_SUCCESS
)
{
printf
(
"Failed to open playback device.
\n
"
);
ma_decoder_uninit
(
&
decoder
);
return
-
3
;
}
if
(
ma_device_start
(
&
device
)
!=
MA_SUCCESS
)
{
printf
(
"Failed to start playback device.
\n
"
);
ma_device_uninit
(
&
device
);
ma_decoder_uninit
(
&
decoder
);
return
-
4
;
}
printf
(
"Press Enter to quit..."
);
getchar
();
ma_device_uninit
(
&
device
);
ma_decoder_uninit
(
&
decoder
);
return
0
;
}
tests/ma_test_0.vcxproj
View file @
2b526f69
...
...
@@ -327,13 +327,14 @@
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Release|x64'"
>
true
</ExcludedFromBuild>
</ClCompile>
<ClCompile
Include=
"..\examples\simple_playback_emscripten.c"
>
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Debug|Win32'"
>
fals
e
</ExcludedFromBuild>
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Release|Win32'"
>
fals
e
</ExcludedFromBuild>
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Debug|ARM'"
>
fals
e
</ExcludedFromBuild>
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Release|ARM'"
>
fals
e
</ExcludedFromBuild>
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Debug|x64'"
>
fals
e
</ExcludedFromBuild>
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Release|x64'"
>
fals
e
</ExcludedFromBuild>
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Debug|Win32'"
>
tru
e
</ExcludedFromBuild>
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Release|Win32'"
>
tru
e
</ExcludedFromBuild>
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Debug|ARM'"
>
tru
e
</ExcludedFromBuild>
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Release|ARM'"
>
tru
e
</ExcludedFromBuild>
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Debug|x64'"
>
tru
e
</ExcludedFromBuild>
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Release|x64'"
>
tru
e
</ExcludedFromBuild>
</ClCompile>
<ClCompile
Include=
"..\research\tests\ma_lpf_test_0.c"
/>
<ClCompile
Include=
"..\research\tests\ma_resampler_test_0.c"
>
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Debug|Win32'"
>
true
</ExcludedFromBuild>
<ExcludedFromBuild
Condition=
"'$(Configuration)|$(Platform)'=='Release|Win32'"
>
true
</ExcludedFromBuild>
...
...
@@ -409,6 +410,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude
Include=
"..\miniaudio.h"
/>
<ClInclude
Include=
"..\research\ma_lpf.h"
/>
<ClInclude
Include=
"..\research\ma_resampler.h"
/>
</ItemGroup>
<Import
Project=
"$(VCTargetsPath)\Microsoft.Cpp.targets"
/>
...
...
tests/ma_test_0.vcxproj.filters
View file @
2b526f69
...
...
@@ -69,6 +69,9 @@
<ClCompile
Include=
"..\examples\fixed_size_callback.c"
>
<Filter>
Source Files
</Filter>
</ClCompile>
<ClCompile
Include=
"..\research\tests\ma_lpf_test_0.c"
>
<Filter>
Source Files
</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude
Include=
"..\miniaudio.h"
>
...
...
@@ -77,5 +80,8 @@
<ClInclude
Include=
"..\research\ma_resampler.h"
>
<Filter>
Source Files
</Filter>
</ClInclude>
<ClInclude
Include=
"..\research\ma_lpf.h"
>
<Filter>
Source Files
</Filter>
</ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file
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