mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
API CHANGE: Replace ma_sine_wave with ma_waveform.
The ma_waveform API is a more general API supporting different waveform including sine, square, triangle and sawtooth.
This commit is contained in:
@@ -18,25 +18,25 @@ void main_loop__em()
|
|||||||
|
|
||||||
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||||
{
|
{
|
||||||
ma_sine_wave* pSineWave;
|
ma_waveform* pSineWave;
|
||||||
|
|
||||||
MA_ASSERT(pDevice->playback.channels == DEVICE_CHANNELS);
|
MA_ASSERT(pDevice->playback.channels == DEVICE_CHANNELS);
|
||||||
|
|
||||||
pSineWave = (ma_sine_wave*)pDevice->pUserData;
|
pSineWave = (ma_waveform*)pDevice->pUserData;
|
||||||
MA_ASSERT(pSineWave != NULL);
|
MA_ASSERT(pSineWave != NULL);
|
||||||
|
|
||||||
ma_sine_wave_read_pcm_frames(pSineWave, pOutput, frameCount, ma_format_f32, DEVICE_CHANNELS);
|
ma_waveform_read_pcm_frames(pSineWave, pOutput, frameCount, ma_format_f32, DEVICE_CHANNELS);
|
||||||
|
|
||||||
(void)pInput; /* Unused. */
|
(void)pInput; /* Unused. */
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
ma_sine_wave sineWave;
|
ma_waveform sineWave;
|
||||||
ma_device_config deviceConfig;
|
ma_device_config deviceConfig;
|
||||||
ma_device device;
|
ma_device device;
|
||||||
|
|
||||||
ma_sine_wave_init(0.2, 400, DEVICE_SAMPLE_RATE, &sineWave);
|
ma_waveform_init(ma_waveform_type_sine, 0.2, 220, DEVICE_SAMPLE_RATE, &sineWave);
|
||||||
|
|
||||||
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||||
deviceConfig.playback.format = DEVICE_FORMAT;
|
deviceConfig.playback.format = DEVICE_FORMAT;
|
||||||
|
|||||||
+180
-40
@@ -105,8 +105,10 @@ Other less major API changes have also been made in version 0.10.
|
|||||||
|
|
||||||
`ma_device_set_stop_callback()` has been removed. You now must set the stop callback via the device config just like the data callback.
|
`ma_device_set_stop_callback()` has been removed. You now must set the stop callback via the device config just like the data callback.
|
||||||
|
|
||||||
`ma_sine_wave_read_f32()` and `ma_sine_wave_read_f32_ex()` have been removed and replaced with `ma_sine_wave_process_pcm_frames()` which supports outputting
|
The `ma_sine_wave` API has been replaced with a more general API called `ma_waveform`. This supports generation of different types of waveforms, including
|
||||||
PCM frames in any format (specified by a parameter).
|
sine, square, triangle and sawtooth. Use `ma_waveform_init()` in place of `ma_sine_wave_init()` to initialize the waveform object. This takes the same
|
||||||
|
parameters, except an additional `ma_waveform_type` value which you would set to `ma_waveform_type_sine`. Use `ma_waveform_read_pcm_frames()` in place of
|
||||||
|
`ma_sine_wave_read_f32()` and `ma_sine_wave_read_f32_ex()`.
|
||||||
|
|
||||||
`ma_convert_frames()` and `ma_convert_frames_ex()` have been changed. Both of these functions now take a new parameter called `frameCountOut` which specifies
|
`ma_convert_frames()` and `ma_convert_frames_ex()` have been changed. Both of these functions now take a new parameter called `frameCountOut` which specifies
|
||||||
the size of the output buffer in PCM frames. This has been added for safety. In addition to this, the parameters for `ma_convert_frames_ex()` have changed to
|
the size of the output buffer in PCM frames. This has been added for safety. In addition to this, the parameters for `ma_convert_frames_ex()` have changed to
|
||||||
@@ -127,6 +129,13 @@ filters together. Low-pass filtering is achieved via the `ma_lpf` API. Since the
|
|||||||
point and 16-bit signed integer formats.
|
point and 16-bit signed integer formats.
|
||||||
|
|
||||||
|
|
||||||
|
Sine, Square, Triangle and Sawtooth Waveforms
|
||||||
|
---------------------------------------------
|
||||||
|
Previously miniaudio supported only sine wave generation. This has now been generalized to support sine, square, triangle and sawtooth waveforms. The old
|
||||||
|
`ma_sine_wave` API has been removed and replaced with the `ma_waveform` API. Use `ma_waveform_init()` to initialize the waveform. Here you specify tyhe type of
|
||||||
|
waveform you want to generated. You then read data using `ma_waveform_read_pcm_frames()`.
|
||||||
|
|
||||||
|
|
||||||
Miscellaneous Changes
|
Miscellaneous Changes
|
||||||
---------------------
|
---------------------
|
||||||
Internal functions have all been made static where possible. If you get warnings about unused functions, please submit a bug report.
|
Internal functions have all been made static where possible. If you get warnings about unused functions, please submit a bug report.
|
||||||
@@ -4714,16 +4723,25 @@ ma_result ma_decode_memory(const void* pData, size_t dataSize, ma_decoder_config
|
|||||||
Generation
|
Generation
|
||||||
|
|
||||||
************************************************************************************************************************************************************/
|
************************************************************************************************************************************************************/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ma_waveform_type_sine,
|
||||||
|
ma_waveform_type_square,
|
||||||
|
ma_waveform_type_triangle,
|
||||||
|
ma_waveform_type_sawtooth
|
||||||
|
} ma_waveform_type;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
ma_waveform_type type;
|
||||||
double amplitude;
|
double amplitude;
|
||||||
double periodsPerSecond;
|
double frequency;
|
||||||
double delta;
|
double deltaTime;
|
||||||
double time;
|
double time;
|
||||||
} ma_sine_wave;
|
} ma_waveform;
|
||||||
|
|
||||||
ma_result ma_sine_wave_init(double amplitude, double period, ma_uint32 sampleRate, ma_sine_wave* pSineWave);
|
ma_result ma_waveform_init(ma_waveform_type type, double amplitude, double frequency, ma_uint32 sampleRate, ma_waveform* pWaveform);
|
||||||
ma_uint64 ma_sine_wave_read_pcm_frames(ma_sine_wave* pSineWave, void* pFramesOut, ma_uint64 frameCount, ma_format format, ma_uint32 channels);
|
ma_uint64 ma_waveform_read_pcm_frames(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount, ma_format format, ma_uint32 channels);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
@@ -5300,6 +5318,7 @@ Standard Library Stuff
|
|||||||
#define ma_countof(x) (sizeof(x) / sizeof(x[0]))
|
#define ma_countof(x) (sizeof(x) / sizeof(x[0]))
|
||||||
#define ma_max(x, y) (((x) > (y)) ? (x) : (y))
|
#define ma_max(x, y) (((x) > (y)) ? (x) : (y))
|
||||||
#define ma_min(x, y) (((x) < (y)) ? (x) : (y))
|
#define ma_min(x, y) (((x) < (y)) ? (x) : (y))
|
||||||
|
#define ma_abs(x) (((x) > 0) ? (x) : -(x))
|
||||||
#define ma_clamp(x, lo, hi) (ma_max(lo, ma_min(x, hi)))
|
#define ma_clamp(x, lo, hi) (ma_max(lo, ma_min(x, hi)))
|
||||||
#define ma_offset_ptr(p, offset) (((ma_uint8*)(p)) + (offset))
|
#define ma_offset_ptr(p, offset) (((ma_uint8*)(p)) + (offset))
|
||||||
|
|
||||||
@@ -5344,8 +5363,6 @@ static MA_INLINE float ma_log10f(float x)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Return Values:
|
Return Values:
|
||||||
0: Success
|
0: Success
|
||||||
@@ -37860,61 +37877,184 @@ ma_result ma_decode_memory(const void* pData, size_t dataSize, ma_decoder_config
|
|||||||
Generation
|
Generation
|
||||||
|
|
||||||
**************************************************************************************************************************************************************/
|
**************************************************************************************************************************************************************/
|
||||||
ma_result ma_sine_wave_init(double amplitude, double periodsPerSecond, ma_uint32 sampleRate, ma_sine_wave* pSineWave)
|
ma_result ma_waveform_init(ma_waveform_type type, double amplitude, double frequency, ma_uint32 sampleRate, ma_waveform* pWaveform)
|
||||||
{
|
{
|
||||||
if (pSineWave == NULL) {
|
if (pWaveform == NULL) {
|
||||||
return MA_INVALID_ARGS;
|
|
||||||
}
|
|
||||||
MA_ZERO_OBJECT(pSineWave);
|
|
||||||
|
|
||||||
if (amplitude == 0 || periodsPerSecond == 0) {
|
|
||||||
return MA_INVALID_ARGS;
|
return MA_INVALID_ARGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amplitude > 1) {
|
MA_ZERO_OBJECT(pWaveform);
|
||||||
amplitude = 1;
|
|
||||||
}
|
|
||||||
if (amplitude < -1) {
|
|
||||||
amplitude = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pSineWave->amplitude = amplitude;
|
pWaveform->type = type;
|
||||||
pSineWave->periodsPerSecond = periodsPerSecond;
|
pWaveform->amplitude = amplitude;
|
||||||
pSineWave->delta = MA_TAU_D / sampleRate;
|
pWaveform->frequency = frequency;
|
||||||
pSineWave->time = 0;
|
pWaveform->deltaTime = 1.0 / sampleRate;
|
||||||
|
pWaveform->time = 0;
|
||||||
|
|
||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ma_uint64 ma_sine_wave_read_pcm_frames(ma_sine_wave* pSineWave, void* pFramesOut, ma_uint64 frameCount, ma_format format, ma_uint32 channels)
|
static float ma_waveform_sine_f32(double time, double frequency, double amplitude)
|
||||||
{
|
{
|
||||||
if (pSineWave == NULL) {
|
return (float)(ma_sin(MA_TAU_D * time * frequency) * amplitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float ma_waveform_square_f32(double time, double frequency, double amplitude)
|
||||||
|
{
|
||||||
|
double t = time * frequency;
|
||||||
|
double f = t - (ma_uint64)t;
|
||||||
|
double r;
|
||||||
|
|
||||||
|
if (f < 0.5) {
|
||||||
|
r = amplitude;
|
||||||
|
} else {
|
||||||
|
r = -amplitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (float)r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float ma_waveform_triangle_f32(double time, double frequency, double amplitude)
|
||||||
|
{
|
||||||
|
double t = time * frequency;
|
||||||
|
double f = t - (ma_uint64)t;
|
||||||
|
double r;
|
||||||
|
|
||||||
|
r = 2 * ma_abs(2 * (f - 0.5)) - 1;
|
||||||
|
|
||||||
|
return (float)(r * amplitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float ma_waveform_sawtooth_f32(double time, double frequency, double amplitude)
|
||||||
|
{
|
||||||
|
double t = time * frequency;
|
||||||
|
double f = t - (ma_uint64)t;
|
||||||
|
double r;
|
||||||
|
|
||||||
|
r = 2 * (f - 0.5);
|
||||||
|
|
||||||
|
return (float)(r * amplitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ma_waveform_read_pcm_frames__sine(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount, ma_format format, ma_uint32 channels)
|
||||||
|
{
|
||||||
|
ma_uint64 iFrame;
|
||||||
|
ma_uint64 iChannel;
|
||||||
|
ma_uint32 bpf = ma_get_bytes_per_frame(format, channels);
|
||||||
|
ma_uint32 bps = ma_get_bytes_per_sample(format);
|
||||||
|
|
||||||
|
MA_ASSERT(pWaveform != NULL);
|
||||||
|
MA_ASSERT(pFramesOut != NULL);
|
||||||
|
|
||||||
|
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
||||||
|
float s = ma_waveform_sine_f32(pWaveform->time, pWaveform->frequency, pWaveform->amplitude);
|
||||||
|
pWaveform->time += pWaveform->deltaTime;
|
||||||
|
|
||||||
|
for (iChannel = 0; iChannel < channels; iChannel += 1) {
|
||||||
|
ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), format, &s, ma_format_f32, 1, ma_dither_mode_none);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ma_waveform_read_pcm_frames__square(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount, ma_format format, ma_uint32 channels)
|
||||||
|
{
|
||||||
|
ma_uint64 iFrame;
|
||||||
|
ma_uint64 iChannel;
|
||||||
|
ma_uint32 bpf = ma_get_bytes_per_frame(format, channels);
|
||||||
|
ma_uint32 bps = ma_get_bytes_per_sample(format);
|
||||||
|
|
||||||
|
MA_ASSERT(pWaveform != NULL);
|
||||||
|
MA_ASSERT(pFramesOut != NULL);
|
||||||
|
|
||||||
|
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
||||||
|
float s = ma_waveform_square_f32(pWaveform->time, pWaveform->frequency, pWaveform->amplitude);
|
||||||
|
pWaveform->time += pWaveform->deltaTime;
|
||||||
|
|
||||||
|
for (iChannel = 0; iChannel < channels; iChannel += 1) {
|
||||||
|
ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), format, &s, ma_format_f32, 1, ma_dither_mode_none);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ma_waveform_read_pcm_frames__triangle(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount, ma_format format, ma_uint32 channels)
|
||||||
|
{
|
||||||
|
ma_uint64 iFrame;
|
||||||
|
ma_uint64 iChannel;
|
||||||
|
ma_uint32 bpf = ma_get_bytes_per_frame(format, channels);
|
||||||
|
ma_uint32 bps = ma_get_bytes_per_sample(format);
|
||||||
|
|
||||||
|
MA_ASSERT(pWaveform != NULL);
|
||||||
|
MA_ASSERT(pFramesOut != NULL);
|
||||||
|
|
||||||
|
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
||||||
|
float s = ma_waveform_triangle_f32(pWaveform->time, pWaveform->frequency, pWaveform->amplitude);
|
||||||
|
pWaveform->time += pWaveform->deltaTime;
|
||||||
|
|
||||||
|
for (iChannel = 0; iChannel < channels; iChannel += 1) {
|
||||||
|
ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), format, &s, ma_format_f32, 1, ma_dither_mode_none);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ma_waveform_read_pcm_frames__sawtooth(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount, ma_format format, ma_uint32 channels)
|
||||||
|
{
|
||||||
|
ma_uint64 iFrame;
|
||||||
|
ma_uint64 iChannel;
|
||||||
|
ma_uint32 bpf = ma_get_bytes_per_frame(format, channels);
|
||||||
|
ma_uint32 bps = ma_get_bytes_per_sample(format);
|
||||||
|
|
||||||
|
MA_ASSERT(pWaveform != NULL);
|
||||||
|
MA_ASSERT(pFramesOut != NULL);
|
||||||
|
|
||||||
|
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
||||||
|
float s = ma_waveform_sawtooth_f32(pWaveform->time, pWaveform->frequency, pWaveform->amplitude);
|
||||||
|
pWaveform->time += pWaveform->deltaTime;
|
||||||
|
|
||||||
|
for (iChannel = 0; iChannel < channels; iChannel += 1) {
|
||||||
|
ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), format, &s, ma_format_f32, 1, ma_dither_mode_none);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ma_uint64 ma_waveform_read_pcm_frames(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount, ma_format format, ma_uint32 channels)
|
||||||
|
{
|
||||||
|
if (pWaveform == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pFramesOut != NULL) {
|
if (pFramesOut != NULL) {
|
||||||
ma_uint64 iFrame;
|
switch (pWaveform->type)
|
||||||
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
{
|
||||||
ma_uint64 iChannel;
|
case ma_waveform_type_sine:
|
||||||
float s;
|
{
|
||||||
|
ma_waveform_read_pcm_frames__sine(pWaveform, pFramesOut, frameCount, format, channels);
|
||||||
|
} break;
|
||||||
|
|
||||||
s = (float)(ma_sin(pSineWave->time * pSineWave->periodsPerSecond) * pSineWave->amplitude);
|
case ma_waveform_type_square:
|
||||||
pSineWave->time += pSineWave->delta;
|
{
|
||||||
|
ma_waveform_read_pcm_frames__square(pWaveform, pFramesOut, frameCount, format, channels);
|
||||||
|
} break;
|
||||||
|
|
||||||
for (iChannel = 0; iChannel < channels; iChannel += 1) {
|
case ma_waveform_type_triangle:
|
||||||
ma_uint32 bpf = ma_get_bytes_per_frame(format, channels);
|
{
|
||||||
ma_uint32 bps = ma_get_bytes_per_sample(format);
|
ma_waveform_read_pcm_frames__triangle(pWaveform, pFramesOut, frameCount, format, channels);
|
||||||
|
} break;
|
||||||
|
|
||||||
ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), format, &s, ma_format_f32, 1, ma_dither_mode_none);
|
case ma_waveform_type_sawtooth:
|
||||||
}
|
{
|
||||||
|
ma_waveform_read_pcm_frames__sawtooth(pWaveform, pFramesOut, frameCount, format, channels);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pSineWave->time += pSineWave->delta * (ma_int64)frameCount; /* Cast to int64 required for VC6. Won't affect anything in practice. */
|
pWaveform->time += pWaveform->deltaTime * (ma_int64)frameCount; /* Cast to int64 required for VC6. Won't affect anything in practice. */
|
||||||
}
|
}
|
||||||
|
|
||||||
return frameCount;
|
return frameCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* End globally disabled warnings. */
|
/* End globally disabled warnings. */
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|||||||
Reference in New Issue
Block a user