Commit 479d36c2 authored by David Reid's avatar David Reid

Add support for Brownian noise.

parent 8c96ca4c
...@@ -5190,7 +5190,8 @@ typedef struct ...@@ -5190,7 +5190,8 @@ typedef struct
typedef enum typedef enum
{ {
ma_noise_type_white, ma_noise_type_white,
ma_noise_type_pink ma_noise_type_pink,
ma_noise_type_brownian
} ma_noise_type; } ma_noise_type;
typedef struct typedef struct
...@@ -5217,6 +5218,10 @@ typedef struct ...@@ -5217,6 +5218,10 @@ typedef struct
double accumulation[MA_MAX_CHANNELS]; double accumulation[MA_MAX_CHANNELS];
ma_uint32 counter[MA_MAX_CHANNELS]; ma_uint32 counter[MA_MAX_CHANNELS];
} pink; } pink;
struct
{
double accumulation[MA_MAX_CHANNELS];
} brownian;
} state; } state;
} ma_noise; } ma_noise;
...@@ -40699,6 +40704,13 @@ ma_result ma_noise_init(const ma_noise_config* pConfig, ma_noise* pNoise) ...@@ -40699,6 +40704,13 @@ ma_result ma_noise_init(const ma_noise_config* pConfig, ma_noise* pNoise)
} }
} }
if (pNoise->config.type == ma_noise_type_brownian) {
ma_uint32 iChannel;
for (iChannel = 0; iChannel < pConfig->channels; iChannel += 1) {
pNoise->state.brownian.accumulation[iChannel] = 0;
}
}
return MA_SUCCESS; return MA_SUCCESS;
} }
...@@ -40811,7 +40823,8 @@ static MA_INLINE float ma_noise_f32_pink(ma_noise* pNoise, ma_uint32 iChannel) ...@@ -40811,7 +40823,8 @@ static MA_INLINE float ma_noise_f32_pink(ma_noise* pNoise, ma_uint32 iChannel)
pNoise->state.pink.accumulation[iChannel] += (binNext - binPrev); pNoise->state.pink.accumulation[iChannel] += (binNext - binPrev);
pNoise->state.pink.counter[iChannel] += 1; pNoise->state.pink.counter[iChannel] += 1;
result = (ma_lcg_rand_f64(&pNoise->lcg) + pNoise->state.pink.accumulation[iChannel]) / 10; result = (ma_lcg_rand_f64(&pNoise->lcg) + pNoise->state.pink.accumulation[iChannel]);
result /= 10;
return (float)(result * pNoise->config.amplitude); return (float)(result * pNoise->config.amplitude);
} }
...@@ -40882,6 +40895,86 @@ static MA_INLINE ma_uint64 ma_noise_read_pcm_frames__pink(ma_noise* pNoise, void ...@@ -40882,6 +40895,86 @@ static MA_INLINE ma_uint64 ma_noise_read_pcm_frames__pink(ma_noise* pNoise, void
return frameCount; return frameCount;
} }
static MA_INLINE float ma_noise_f32_brownian(ma_noise* pNoise, ma_uint32 iChannel)
{
double result;
result = (ma_lcg_rand_f64(&pNoise->lcg) + pNoise->state.brownian.accumulation[iChannel]);
result /= 1.005; /* Don't escape the -1..1 range on average. */
pNoise->state.brownian.accumulation[iChannel] = result;
result /= 20;
return (float)(result * pNoise->config.amplitude);
}
static MA_INLINE ma_int16 ma_noise_s16_brownian(ma_noise* pNoise, ma_uint32 iChannel)
{
return ma_pcm_sample_f32_to_s16(ma_noise_f32_brownian(pNoise, iChannel));
}
static MA_INLINE ma_uint64 ma_noise_read_pcm_frames__brownian(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount)
{
ma_uint64 iFrame;
ma_uint32 iChannel;
if (pNoise->config.format == ma_format_f32) {
float* pFramesOutF32 = (float*)pFramesOut;
if (pNoise->config.duplicateChannels) {
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
float s = ma_noise_f32_brownian(pNoise, 0);
for (iChannel = 0; iChannel < pNoise->config.channels; iChannel += 1) {
pFramesOutF32[iFrame*pNoise->config.channels + iChannel] = s;
}
}
} else {
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
for (iChannel = 0; iChannel < pNoise->config.channels; iChannel += 1) {
pFramesOutF32[iFrame*pNoise->config.channels + iChannel] = ma_noise_f32_brownian(pNoise, iChannel);
}
}
}
} else if (pNoise->config.format == ma_format_s16) {
ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
if (pNoise->config.duplicateChannels) {
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
ma_int16 s = ma_noise_s16_brownian(pNoise, 0);
for (iChannel = 0; iChannel < pNoise->config.channels; iChannel += 1) {
pFramesOutS16[iFrame*pNoise->config.channels + iChannel] = s;
}
}
} else {
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
for (iChannel = 0; iChannel < pNoise->config.channels; iChannel += 1) {
pFramesOutS16[iFrame*pNoise->config.channels + iChannel] = ma_noise_s16_brownian(pNoise, iChannel);
}
}
}
} else {
ma_uint32 bps = ma_get_bytes_per_sample(pNoise->config.format);
ma_uint32 bpf = bps * pNoise->config.channels;
if (pNoise->config.duplicateChannels) {
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
float s = ma_noise_f32_brownian(pNoise, 0);
for (iChannel = 0; iChannel < pNoise->config.channels; iChannel += 1) {
ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
}
}
} else {
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
for (iChannel = 0; iChannel < pNoise->config.channels; iChannel += 1) {
float s = ma_noise_f32_brownian(pNoise, iChannel);
ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
}
}
}
}
return frameCount;
}
ma_uint64 ma_noise_read_pcm_frames(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount) ma_uint64 ma_noise_read_pcm_frames(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount)
{ {
if (pNoise == NULL) { if (pNoise == NULL) {
...@@ -40896,6 +40989,10 @@ ma_uint64 ma_noise_read_pcm_frames(ma_noise* pNoise, void* pFramesOut, ma_uint64 ...@@ -40896,6 +40989,10 @@ ma_uint64 ma_noise_read_pcm_frames(ma_noise* pNoise, void* pFramesOut, ma_uint64
return ma_noise_read_pcm_frames__pink(pNoise, pFramesOut, frameCount); return ma_noise_read_pcm_frames__pink(pNoise, pFramesOut, frameCount);
} }
if (pNoise->config.type == ma_noise_type_brownian) {
return ma_noise_read_pcm_frames__brownian(pNoise, pFramesOut, frameCount);
}
/* Should never get here. */ /* Should never get here. */
MA_ASSERT(MA_FALSE); MA_ASSERT(MA_FALSE);
return 0; return 0;
...@@ -49,6 +49,11 @@ ma_result test_noise__f32() ...@@ -49,6 +49,11 @@ ma_result test_noise__f32()
hasError = MA_TRUE; hasError = MA_TRUE;
} }
result = test_noise__by_format_and_type(ma_format_f32, ma_noise_type_brownian, "output/noise_f32_brownian.wav");
if (result != MA_SUCCESS) {
hasError = MA_TRUE;
}
if (hasError) { if (hasError) {
return MA_ERROR; return MA_ERROR;
} else { } else {
...@@ -66,6 +71,16 @@ ma_result test_noise__s16() ...@@ -66,6 +71,16 @@ ma_result test_noise__s16()
hasError = MA_TRUE; hasError = MA_TRUE;
} }
result = test_noise__by_format_and_type(ma_format_s16, ma_noise_type_pink, "output/noise_s16_pink.wav");
if (result != MA_SUCCESS) {
hasError = MA_TRUE;
}
result = test_noise__by_format_and_type(ma_format_s16, ma_noise_type_brownian, "output/noise_s16_brownian.wav");
if (result != MA_SUCCESS) {
hasError = MA_TRUE;
}
if (hasError) { if (hasError) {
return MA_ERROR; return MA_ERROR;
} else { } else {
...@@ -83,6 +98,16 @@ ma_result test_noise__u8() ...@@ -83,6 +98,16 @@ ma_result test_noise__u8()
hasError = MA_TRUE; hasError = MA_TRUE;
} }
result = test_noise__by_format_and_type(ma_format_u8, ma_noise_type_pink, "output/noise_u8_pink.wav");
if (result != MA_SUCCESS) {
hasError = MA_TRUE;
}
result = test_noise__by_format_and_type(ma_format_u8, ma_noise_type_brownian, "output/noise_u8_brownian.wav");
if (result != MA_SUCCESS) {
hasError = MA_TRUE;
}
if (hasError) { if (hasError) {
return MA_ERROR; return MA_ERROR;
} else { } else {
......
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