mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Update website.
This commit is contained in:
@@ -0,0 +1,409 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>miniaudio - A single file audio playback and capture library.</title>
|
||||
<meta name="description" content="miniaudio is a single file audio playback and capture library written in C.">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<link rel="icon" href="../../img/favicon.png">
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-81135233-2"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'UA-81135233-2');
|
||||
</script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family:sans-serif;
|
||||
font-size:11pt;
|
||||
line-height:18pt;
|
||||
background-color:#003800;
|
||||
}
|
||||
|
||||
h1,h2 {
|
||||
color:#333;
|
||||
line-height:0.2em;
|
||||
margin-bottom:0;
|
||||
padding:0;
|
||||
}
|
||||
h1.man {
|
||||
margin-top:2em;
|
||||
}
|
||||
h2.man {
|
||||
margin-top:1.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration:none;
|
||||
color:#28f;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration:underline;
|
||||
color:#26d;
|
||||
}
|
||||
|
||||
.a-download {
|
||||
text-decoration:none;
|
||||
color:#ddd;
|
||||
border:solid 1px #000;
|
||||
border-radius:4px;
|
||||
padding:16px 32px;
|
||||
background-color:#003800;
|
||||
}
|
||||
.a-download:hover {
|
||||
background-color:#003000;
|
||||
text-decoration:none;
|
||||
color:#ddd;
|
||||
}
|
||||
|
||||
.a-sublink {
|
||||
font-size:11pt;
|
||||
}
|
||||
|
||||
#preview {
|
||||
font-family:monospace;
|
||||
font-size:10pt;
|
||||
text-align:left;
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
margin: 0px;
|
||||
margin-bottom: 10px;
|
||||
padding: 0px;
|
||||
}
|
||||
.footer-links li {
|
||||
display: inline;
|
||||
padding: 0 2px;
|
||||
}
|
||||
.footer-links li:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.feature-header {
|
||||
color:#666;
|
||||
font-size: 24pt;
|
||||
font-weight:bold;
|
||||
}
|
||||
.feature-header2 {
|
||||
color:#444;
|
||||
font-size: 1.5em;
|
||||
font-weight:bold;
|
||||
/*margin-bottom:1em;*/
|
||||
line-height: 1em;
|
||||
text-align:left;
|
||||
}
|
||||
|
||||
.header-link-table {
|
||||
}
|
||||
.header-link-table td {
|
||||
padding:0.5em 0;
|
||||
padding-right:2em;
|
||||
vertical-align:center;
|
||||
}
|
||||
.header-link-table a {
|
||||
color:#e0d7cf;
|
||||
text-decoration:none;
|
||||
}
|
||||
.header-link-table a:hover {
|
||||
color:#ffffff;
|
||||
}
|
||||
|
||||
.footer-link {
|
||||
color:#e0d7cf;
|
||||
text-decoration:none;
|
||||
}
|
||||
.footer-link:hover {
|
||||
color:#ffffff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.mobile-main-link {
|
||||
text-align:left;
|
||||
background-color:#e0d7cf;
|
||||
color:#036;
|
||||
border-bottom:solid 1px #333;
|
||||
padding-left:16px;
|
||||
}
|
||||
.mobile-main-link a {
|
||||
display:block;
|
||||
padding-top:8px;
|
||||
padding-bottom:8px;
|
||||
color:#036;
|
||||
width:100%;
|
||||
height:100%;
|
||||
max-width:100%;
|
||||
}
|
||||
|
||||
|
||||
table.doc {
|
||||
border:solid 0px #333;
|
||||
border-collapse:collapse;
|
||||
}
|
||||
|
||||
th.doc, td.doc {
|
||||
padding:0.5em;
|
||||
}
|
||||
|
||||
th.doc {
|
||||
border:solid 1px #003800;
|
||||
background-color:#003800;
|
||||
color:#FFF;
|
||||
text-align:left;
|
||||
}
|
||||
|
||||
td.doc {
|
||||
border:solid 1px #666;
|
||||
}
|
||||
|
||||
td.doc p, th.doc p {
|
||||
padding:0;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
a.doc-navigation {
|
||||
display:block;
|
||||
padding:0.5em;
|
||||
color:#003800;
|
||||
border-bottom:solid 1px #bbbbbb;
|
||||
}
|
||||
|
||||
a.doc-navigation:hover {
|
||||
color:#fff;
|
||||
background-color:#003800;
|
||||
text-decoration:none;
|
||||
/*border-bottom:solid 1px #003800;*/
|
||||
}
|
||||
|
||||
/*
|
||||
a.doc-navigation:hover {
|
||||
background-color:#c5ecc5;
|
||||
text-decoration:none;
|
||||
}
|
||||
*/
|
||||
|
||||
a.doc-navigation-active {
|
||||
background-color:#cccccc;
|
||||
}
|
||||
a.doc-navigation-active:hover {
|
||||
color:#003800;
|
||||
background-color:#cccccc;
|
||||
}
|
||||
|
||||
a.doc-navigation-l1 {
|
||||
padding:0.1em;
|
||||
padding-left:1.5em;
|
||||
}
|
||||
a.doc-navigation-l2 {
|
||||
padding:0.1em;
|
||||
padding-left:3em;
|
||||
}
|
||||
a.doc-navigation-l3 {
|
||||
padding:0.1em;
|
||||
padding-left:4em;
|
||||
}
|
||||
a.doc-navigation-l4 {
|
||||
padding:0.1em;
|
||||
padding-left:5em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body style="margin:0; padding:0">
|
||||
<div style="background-color:#003800; color:#bfa792;">
|
||||
<div style="max-width:75%; width:100%; margin:0 auto;">
|
||||
<table class="header-link-table" style="">
|
||||
<tr>
|
||||
<td style="padding:0; width:100%; text-align:left;">
|
||||
<table class="header-link-table" style="">
|
||||
<tr>
|
||||
<td style="vertical-align:center; padding-right:2em;"><a href="../../index.html"><img src="../../img/logo1_large_white.png" style="height:24px; min-width:100%;"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td style="padding:0; width:25%; text-align:right; vertical-align:center;">
|
||||
<a style="padding:0;" href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="padding:0; height:32px; width:32px;"></a>
|
||||
</td>
|
||||
<td style="padding:0; width:25%; text-align:right; vertical-align:center;">
|
||||
<a style="padding:0;" href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="padding:0; height:32px; width:32px;"></a>
|
||||
</td>
|
||||
<td style="padding:0; width:25%; text-align:right; vertical-align:center;">
|
||||
<a style="padding:0;" href="https://github.com/dr-soft/miniaudio"><img src="../../img/github_white.png" style="padding:0; height:24px; width:24px;"></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
|
||||
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000;"><tr>
|
||||
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:300px; border:solid 0px #000; padding:0; margin:0;">
|
||||
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Fixed Size Callback</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
|
||||
<h1>Fixed Size Callback</h1><p>
|
||||
Shows one way to implement a data callback that is called with a fixed frame count.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
miniaudio does not have built-in support for firing the data callback with fixed sized buffers. In order to support
|
||||
this you need to implement a layer that sits on top of the normal data callback. This example demonstrates one way of
|
||||
doing this.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
This example uses a ring buffer to act as the intermediary buffer between the low-level device callback and the fixed
|
||||
sized callback. You do not need to use a ring buffer here, but it's a good opportunity to demonstrate how to use
|
||||
miniaudio's ring buffer API. The ring buffer in this example is in global scope for simplicity, but you can pass it
|
||||
around as user data for the device (device.pUserData).
|
||||
</p>
|
||||
<p>
|
||||
|
||||
This example only works for output devices, but can be implemented for input devices by simply swapping the direction
|
||||
of data movement.</p>
|
||||
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em;"><pre style="margin:0.5em 1em; padding:0; line-height:125%">
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "../miniaudio.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define DEVICE_FORMAT ma_format_f32
|
||||
#define DEVICE_CHANNELS 1
|
||||
#define DEVICE_SAMPLE_RATE 48000
|
||||
|
||||
#define PCM_FRAME_CHUNK_SIZE 1234 /* <-- Play around with this to control your fixed sized buffer. */
|
||||
|
||||
ma_waveform g_sineWave;
|
||||
ma_pcm_rb g_rb; /* The ring buffer. */
|
||||
|
||||
void data_callback_fixed(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||
{
|
||||
/*
|
||||
This callback will have a guaranteed and consistent size for frameCount. In this example we just fill the output buffer with a sine wave. This
|
||||
is where you would handle the callback just like normal, only now you can assume frameCount is a fixed size.
|
||||
*/
|
||||
printf("frameCount=%d\n", frameCount);
|
||||
|
||||
ma_waveform_read_pcm_frames(&g_sineWave, pOutput, frameCount);
|
||||
|
||||
/* Unused in this example. */
|
||||
(void)pDevice;
|
||||
(void)pInput;
|
||||
}
|
||||
|
||||
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||
{
|
||||
/*
|
||||
This is the device's main data callback. This will handle all of the fixed sized buffer management for you and will call data_callback_fixed()
|
||||
for you. You should do all of your normal callback stuff in data_callback_fixed().
|
||||
*/
|
||||
ma_uint32 pcmFramesAvailableInRB;
|
||||
ma_uint32 pcmFramesProcessed = 0;
|
||||
ma_uint8* pRunningOutput = (ma_uint8*)pOutput;
|
||||
|
||||
MA_ASSERT(pDevice->playback.channels == DEVICE_CHANNELS);
|
||||
|
||||
/*
|
||||
The first thing to do is check if there's enough data available in the ring buffer. If so we can read from it. Otherwise we need to keep filling
|
||||
the ring buffer until there's enough, making sure we only fill the ring buffer in chunks of PCM_FRAME_CHUNK_SIZE.
|
||||
*/
|
||||
while (pcmFramesProcessed < frameCount) { /* Keep going until we've filled the output buffer. */
|
||||
ma_uint32 framesRemaining = frameCount - pcmFramesProcessed;
|
||||
|
||||
pcmFramesAvailableInRB = ma_pcm_rb_available_read(&g_rb);
|
||||
if (pcmFramesAvailableInRB > 0) {
|
||||
ma_uint32 framesToRead = (framesRemaining < pcmFramesAvailableInRB) ? framesRemaining : pcmFramesAvailableInRB;
|
||||
void* pReadBuffer;
|
||||
|
||||
ma_pcm_rb_acquire_read(&g_rb, &framesToRead, &pReadBuffer);
|
||||
{
|
||||
memcpy(pRunningOutput, pReadBuffer, framesToRead * ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels));
|
||||
}
|
||||
ma_pcm_rb_commit_read(&g_rb, framesToRead, pReadBuffer);
|
||||
|
||||
pRunningOutput += framesToRead * ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
|
||||
pcmFramesProcessed += framesToRead;
|
||||
} else {
|
||||
/*
|
||||
There's nothing in the buffer. Fill it with more data from the callback. We reset the buffer first so that the read and write pointers
|
||||
are reset back to the start so we can fill the ring buffer in chunks of PCM_FRAME_CHUNK_SIZE which is what we initialized it with. Note
|
||||
that this is not how you would want to do it in a multi-threaded environment. In this case you would want to seek the write pointer
|
||||
forward via the producer thread and the read pointer forward via the consumer thread (this thread).
|
||||
*/
|
||||
ma_uint32 framesToWrite = PCM_FRAME_CHUNK_SIZE;
|
||||
void* pWriteBuffer;
|
||||
|
||||
ma_pcm_rb_reset(&g_rb);
|
||||
ma_pcm_rb_acquire_write(&g_rb, &framesToWrite, &pWriteBuffer);
|
||||
{
|
||||
MA_ASSERT(framesToWrite == PCM_FRAME_CHUNK_SIZE); /* <-- This should always work in this example because we just reset the ring buffer. */
|
||||
data_callback_fixed(pDevice, pWriteBuffer, NULL, framesToWrite);
|
||||
}
|
||||
ma_pcm_rb_commit_write(&g_rb, framesToWrite, pWriteBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unused in this example. */
|
||||
(void)pInput;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
ma_waveform_config waveformConfig;
|
||||
ma_device_config deviceConfig;
|
||||
ma_device device;
|
||||
|
||||
waveformConfig = ma_waveform_config_init(DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, ma_waveform_type_sine, 0.1, 220);
|
||||
ma_waveform_init(&waveformConfig, &g_sineWave);
|
||||
|
||||
ma_pcm_rb_init(DEVICE_FORMAT, DEVICE_CHANNELS, PCM_FRAME_CHUNK_SIZE, NULL, NULL, &g_rb);
|
||||
|
||||
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||
deviceConfig.playback.format = DEVICE_FORMAT;
|
||||
deviceConfig.playback.channels = DEVICE_CHANNELS;
|
||||
deviceConfig.sampleRate = DEVICE_SAMPLE_RATE;
|
||||
deviceConfig.dataCallback = data_callback;
|
||||
deviceConfig.pUserData = NULL; /* <-- Set this to a pointer to the ring buffer if you don't want it in global scope. */
|
||||
|
||||
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
|
||||
printf("Failed to open playback device.\n");
|
||||
ma_pcm_rb_uninit(&g_rb);
|
||||
return -4;
|
||||
}
|
||||
|
||||
printf("Device Name: %s\n", device.playback.name);
|
||||
|
||||
if (ma_device_start(&device) != MA_SUCCESS) {
|
||||
printf("Failed to start playback device.\n");
|
||||
ma_pcm_rb_uninit(&g_rb);
|
||||
ma_device_uninit(&device);
|
||||
return -5;
|
||||
}
|
||||
|
||||
printf("Press Enter to quit...\n");
|
||||
getchar();
|
||||
|
||||
ma_device_uninit(&device);
|
||||
ma_pcm_rb_uninit(&g_rb);
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return 0;
|
||||
}
|
||||
</pre></div></td>
|
||||
</tr></table>
|
||||
</div>
|
||||
<table style="margin:0 auto; padding:1em 0px; text-align:center;">
|
||||
<tr>
|
||||
<td style="vertical-align:center;"><a style="padding:0;" href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="padding:0; height:32px; width:32px;"></a></td>
|
||||
<td style="vertical-align:center;"><a style="padding:0;" href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="padding:0; height:32px; width:32px;"></a></td>
|
||||
<td style="vertical-align:center;"><a style="padding:0;" href="https://github.com/dr-soft/miniaudio"><img src="../../img/github_white.png" style="padding:0; height:24px; width:24px;"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div style="color:#e0d7cf; font-size:9pt; padding:2em 0px; text-align:center;">
|
||||
Copyright © 2020 David Reid<br/>
|
||||
Developed by David Reid - <a class="footer-link" href="mailto:davidreidsoftware@gmail.com">davidreidsoftware@gmail.com</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user