Commit 8a7a65c2 authored by David Reid's avatar David Reid

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.
parent 415ded56
......@@ -18,25 +18,25 @@ void main_loop__em()
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);
pSineWave = (ma_sine_wave*)pDevice->pUserData;
pSineWave = (ma_waveform*)pDevice->pUserData;
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. */
}
int main(int argc, char** argv)
{
ma_sine_wave sineWave;
ma_waveform sineWave;
ma_device_config deviceConfig;
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.playback.format = DEVICE_FORMAT;
......
......@@ -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_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
PCM frames in any format (specified by a parameter).
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
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
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.
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
---------------------
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
************************************************************************************************************************************************************/
typedef enum
{
ma_waveform_type_sine,
ma_waveform_type_square,
ma_waveform_type_triangle,
ma_waveform_type_sawtooth
} ma_waveform_type;
typedef struct
{
ma_waveform_type type;
double amplitude;
double periodsPerSecond;
double delta;
double frequency;
double deltaTime;
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_uint64 ma_sine_wave_read_pcm_frames(ma_sine_wave* pSineWave, void* pFramesOut, ma_uint64 frameCount, ma_format format, ma_uint32 channels);
ma_result ma_waveform_init(ma_waveform_type type, double amplitude, double frequency, ma_uint32 sampleRate, ma_waveform* pWaveform);
ma_uint64 ma_waveform_read_pcm_frames(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount, ma_format format, ma_uint32 channels);
#ifdef __cplusplus
}
......@@ -5300,6 +5318,7 @@ Standard Library Stuff
#define ma_countof(x) (sizeof(x) / sizeof(x[0]))
#define ma_max(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_offset_ptr(p, offset) (((ma_uint8*)(p)) + (offset))
......@@ -5344,8 +5363,6 @@ static MA_INLINE float ma_log10f(float x)
}
/*
Return Values:
0: Success
......@@ -37860,61 +37877,184 @@ ma_result ma_decode_memory(const void* pData, size_t dataSize, ma_decoder_config
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;
MA_ZERO_OBJECT(pWaveform);
pWaveform->type = type;
pWaveform->amplitude = amplitude;
pWaveform->frequency = frequency;
pWaveform->deltaTime = 1.0 / sampleRate;
pWaveform->time = 0;
return MA_SUCCESS;
}
static float ma_waveform_sine_f32(double time, double frequency, double amplitude)
{
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;
}
if (amplitude > 1) {
amplitude = 1;
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);
}
}
if (amplitude < -1) {
amplitude = -1;
}
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);
}
}
}
pSineWave->amplitude = amplitude;
pSineWave->periodsPerSecond = periodsPerSecond;
pSineWave->delta = MA_TAU_D / sampleRate;
pSineWave->time = 0;
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);
return MA_SUCCESS;
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_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)
{
if (pSineWave == NULL) {
if (pWaveform == NULL) {
return 0;
}
if (pFramesOut != NULL) {
ma_uint64 iFrame;
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
ma_uint64 iChannel;
float s;
switch (pWaveform->type)
{
case ma_waveform_type_sine:
{
ma_waveform_read_pcm_frames__sine(pWaveform, pFramesOut, frameCount, format, channels);
} break;
s = (float)(ma_sin(pSineWave->time * pSineWave->periodsPerSecond) * pSineWave->amplitude);
pSineWave->time += pSineWave->delta;
case ma_waveform_type_square:
{
ma_waveform_read_pcm_frames__square(pWaveform, pFramesOut, frameCount, format, channels);
} break;
for (iChannel = 0; iChannel < channels; iChannel += 1) {
ma_uint32 bpf = ma_get_bytes_per_frame(format, channels);
ma_uint32 bps = ma_get_bytes_per_sample(format);
case ma_waveform_type_triangle:
{
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 {
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;
}
/* End globally disabled warnings. */
#if defined(_MSC_VER)
#pragma warning(pop)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment