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
ba3080d0
Commit
ba3080d0
authored
Dec 10, 2021
by
David Reid
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for partial processing to nodes.
This includes a leading trimming node to act as a test.
parent
b8d04bdd
Changes
4
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
376 additions
and
115 deletions
+376
-115
extras/nodes/ma_ltrim_node/ma_ltrim_node.c
extras/nodes/ma_ltrim_node/ma_ltrim_node.c
+102
-0
extras/nodes/ma_ltrim_node/ma_ltrim_node.h
extras/nodes/ma_ltrim_node/ma_ltrim_node.h
+35
-0
extras/nodes/ma_ltrim_node/ma_ltrim_node_example.c
extras/nodes/ma_ltrim_node/ma_ltrim_node_example.c
+115
-0
miniaudio.h
miniaudio.h
+124
-115
No files found.
extras/nodes/ma_ltrim_node/ma_ltrim_node.c
0 → 100644
View file @
ba3080d0
#include "ma_ltrim_node.h"
MA_API
ma_ltrim_node_config
ma_ltrim_node_config_init
(
ma_uint32
channels
,
float
threshold
)
{
ma_ltrim_node_config
config
;
MA_ZERO_OBJECT
(
&
config
);
config
.
nodeConfig
=
ma_node_config_init
();
/* Input and output channels will be set in ma_ltrim_node_init(). */
config
.
channels
=
channels
;
config
.
threshold
=
threshold
;
return
config
;
}
static
void
ma_ltrim_node_process_pcm_frames
(
ma_node
*
pNode
,
const
float
**
ppFramesIn
,
ma_uint32
*
pFrameCountIn
,
float
**
ppFramesOut
,
ma_uint32
*
pFrameCountOut
)
{
ma_ltrim_node
*
pTrimNode
=
(
ma_ltrim_node
*
)
pNode
;
ma_uint32
framesProcessedIn
=
0
;
ma_uint32
framesProcessedOut
=
0
;
ma_uint32
channelCount
=
ma_node_get_input_channels
(
pNode
,
0
);
/*
If we haven't yet found the start, skip over every input sample until we find a frame outside
of the threshold.
*/
if
(
pTrimNode
->
foundStart
==
MA_FALSE
)
{
while
(
framesProcessedIn
<
*
pFrameCountIn
)
{
ma_uint32
iChannel
=
0
;
for
(
iChannel
=
0
;
iChannel
<
channelCount
;
iChannel
+=
1
)
{
float
sample
=
ppFramesIn
[
0
][
framesProcessedIn
*
channelCount
+
iChannel
];
if
(
sample
<
-
pTrimNode
->
threshold
||
sample
>
pTrimNode
->
threshold
)
{
pTrimNode
->
foundStart
=
MA_TRUE
;
break
;
}
}
if
(
pTrimNode
->
foundStart
)
{
break
;
/* The start has been found. Get out of this loop and finish off processing. */
}
else
{
framesProcessedIn
+=
1
;
}
}
}
/* If there's anything left, just copy it over. */
framesProcessedOut
=
ma_min
(
*
pFrameCountOut
,
*
pFrameCountIn
-
framesProcessedIn
);
ma_copy_pcm_frames
(
ppFramesOut
[
0
],
&
ppFramesIn
[
0
][
framesProcessedIn
],
framesProcessedOut
,
ma_format_f32
,
channelCount
);
framesProcessedIn
+=
framesProcessedOut
;
/* We always "process" every input frame, but we may only done a partial output. */
*
pFrameCountIn
=
framesProcessedIn
;
*
pFrameCountOut
=
framesProcessedOut
;
}
static
ma_node_vtable
g_ma_ltrim_node_vtable
=
{
ma_ltrim_node_process_pcm_frames
,
NULL
,
1
,
/* 1 input channel. */
1
,
/* 1 output channel. */
MA_NODE_FLAG_DIFFERENT_PROCESSING_RATES
};
MA_API
ma_result
ma_ltrim_node_init
(
ma_node_graph
*
pNodeGraph
,
const
ma_ltrim_node_config
*
pConfig
,
const
ma_allocation_callbacks
*
pAllocationCallbacks
,
ma_ltrim_node
*
pTrimNode
)
{
ma_result
result
;
ma_node_config
baseConfig
;
if
(
pTrimNode
==
NULL
)
{
return
MA_INVALID_ARGS
;
}
MA_ZERO_OBJECT
(
pTrimNode
);
if
(
pConfig
==
NULL
)
{
return
MA_INVALID_ARGS
;
}
pTrimNode
->
threshold
=
pConfig
->
threshold
;
pTrimNode
->
foundStart
=
MA_FALSE
;
baseConfig
=
pConfig
->
nodeConfig
;
baseConfig
.
vtable
=
&
g_ma_ltrim_node_vtable
;
baseConfig
.
pInputChannels
=
&
pConfig
->
channels
;
baseConfig
.
pOutputChannels
=
&
pConfig
->
channels
;
result
=
ma_node_init
(
pNodeGraph
,
&
baseConfig
,
pAllocationCallbacks
,
&
pTrimNode
->
baseNode
);
if
(
result
!=
MA_SUCCESS
)
{
return
result
;
}
return
MA_SUCCESS
;
}
MA_API
void
ma_ltrim_node_uninit
(
ma_ltrim_node
*
pTrimNode
,
const
ma_allocation_callbacks
*
pAllocationCallbacks
)
{
/* The base node is always uninitialized first. */
ma_node_uninit
(
pTrimNode
,
pAllocationCallbacks
);
}
extras/nodes/ma_ltrim_node/ma_ltrim_node.h
0 → 100644
View file @
ba3080d0
/* Include ma_ltrim_node.h after miniaudio.h */
#ifndef ma_ltrim_node_h
#define ma_ltrim_node_h
#ifdef __cplusplus
extern
"C"
{
#endif
/*
The trim node has one input and one output.
*/
typedef
struct
{
ma_node_config
nodeConfig
;
ma_uint32
channels
;
float
threshold
;
}
ma_ltrim_node_config
;
MA_API
ma_ltrim_node_config
ma_ltrim_node_config_init
(
ma_uint32
channels
,
float
threshold
);
typedef
struct
{
ma_node_base
baseNode
;
float
threshold
;
ma_bool32
foundStart
;
}
ma_ltrim_node
;
MA_API
ma_result
ma_ltrim_node_init
(
ma_node_graph
*
pNodeGraph
,
const
ma_ltrim_node_config
*
pConfig
,
const
ma_allocation_callbacks
*
pAllocationCallbacks
,
ma_ltrim_node
*
pTrimNode
);
MA_API
void
ma_ltrim_node_uninit
(
ma_ltrim_node
*
pTrimNode
,
const
ma_allocation_callbacks
*
pAllocationCallbacks
);
#ifdef __cplusplus
}
#endif
#endif
/* ma_ltrim_node_h */
extras/nodes/ma_ltrim_node/ma_ltrim_node_example.c
0 → 100644
View file @
ba3080d0
#define MINIAUDIO_IMPLEMENTATION
#include "../../../miniaudio.h"
#include "ma_ltrim_node.c"
#include <stdio.h>
#define DEVICE_FORMAT ma_format_f32
/* Must always be f32 for this example because the node graph system only works with this. */
#define DEVICE_CHANNELS 0
/* The input file will determine the channel count. */
#define DEVICE_SAMPLE_RATE 0
/* The input file will determine the sample rate. */
static
ma_decoder
g_decoder
;
/* The decoder that we'll read data from. */
static
ma_data_source_node
g_dataSupplyNode
;
/* The node that will sit at the root level. Will be reading data from g_dataSupply. */
static
ma_ltrim_node
g_trimNode
;
/* The trim node. */
static
ma_node_graph
g_nodeGraph
;
/* The main node graph that we'll be feeding data through. */
void
data_callback
(
ma_device
*
pDevice
,
void
*
pOutput
,
const
void
*
pInput
,
ma_uint32
frameCount
)
{
(
void
)
pInput
;
(
void
)
pDevice
;
/* All we need to do is read from the node graph. */
ma_node_graph_read_pcm_frames
(
&
g_nodeGraph
,
pOutput
,
frameCount
,
NULL
);
}
int
main
(
int
argc
,
char
**
argv
)
{
ma_result
result
;
ma_decoder_config
decoderConfig
;
ma_device_config
deviceConfig
;
ma_device
device
;
ma_node_graph_config
nodeGraphConfig
;
ma_ltrim_node_config
trimNodeConfig
;
ma_data_source_node_config
dataSupplyNodeConfig
;
if
(
argc
<
1
)
{
printf
(
"No input file.
\n
"
);
return
-
1
;
}
/* Decoder. */
decoderConfig
=
ma_decoder_config_init
(
DEVICE_FORMAT
,
DEVICE_CHANNELS
,
DEVICE_SAMPLE_RATE
);
result
=
ma_decoder_init_file
(
argv
[
1
],
&
decoderConfig
,
&
g_decoder
);
if
(
result
!=
MA_SUCCESS
)
{
printf
(
"Failed to load decoder.
\n
"
);
return
-
1
;
}
/* Device. */
deviceConfig
=
ma_device_config_init
(
ma_device_type_playback
);
deviceConfig
.
playback
.
pDeviceID
=
NULL
;
deviceConfig
.
playback
.
format
=
g_decoder
.
outputFormat
;
deviceConfig
.
playback
.
channels
=
g_decoder
.
outputChannels
;
deviceConfig
.
sampleRate
=
g_decoder
.
outputSampleRate
;
deviceConfig
.
dataCallback
=
data_callback
;
result
=
ma_device_init
(
NULL
,
&
deviceConfig
,
&
device
);
if
(
result
!=
MA_SUCCESS
)
{
return
result
;
}
/* Node graph. */
nodeGraphConfig
=
ma_node_graph_config_init
(
device
.
playback
.
channels
);
result
=
ma_node_graph_init
(
&
nodeGraphConfig
,
NULL
,
&
g_nodeGraph
);
if
(
result
!=
MA_SUCCESS
)
{
printf
(
"Failed to initialize node graph."
);
goto
done0
;
}
/* Trimmer. Attached straight to the endpoint. Input will be the data source node. */
trimNodeConfig
=
ma_ltrim_node_config_init
(
device
.
playback
.
channels
,
0
);
result
=
ma_ltrim_node_init
(
&
g_nodeGraph
,
&
trimNodeConfig
,
NULL
,
&
g_trimNode
);
if
(
result
!=
MA_SUCCESS
)
{
printf
(
"Failed to initialize ltrim node."
);
goto
done1
;
}
ma_node_attach_output_bus
(
&
g_trimNode
,
0
,
ma_node_graph_get_endpoint
(
&
g_nodeGraph
),
0
);
/* Data supply. */
dataSupplyNodeConfig
=
ma_data_source_node_config_init
(
&
g_decoder
);
result
=
ma_data_source_node_init
(
&
g_nodeGraph
,
&
dataSupplyNodeConfig
,
NULL
,
&
g_dataSupplyNode
);
if
(
result
!=
MA_SUCCESS
)
{
printf
(
"Failed to initialize data source node."
);
goto
done2
;
}
ma_node_attach_output_bus
(
&
g_dataSupplyNode
,
0
,
&
g_trimNode
,
0
);
/* Now we just start the device and wait for the user to terminate the program. */
ma_device_start
(
&
device
);
printf
(
"Press Enter to quit...
\n
"
);
getchar
();
/* It's important that we stop the device first or else we'll uninitialize the graph from under the device. */
ma_device_stop
(
&
device
);
/*done3:*/
ma_data_source_node_uninit
(
&
g_dataSupplyNode
,
NULL
);
done2:
ma_ltrim_node_uninit
(
&
g_trimNode
,
NULL
);
done1:
ma_node_graph_uninit
(
&
g_nodeGraph
,
NULL
);
done0:
ma_device_uninit
(
&
device
);
return
0
;
}
\ No newline at end of file
miniaudio.h
View file @
ba3080d0
This diff is collapsed.
Click to expand it.
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