summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/pcmbuf.c78
1 files changed, 43 insertions, 35 deletions
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c
index a6b82baf25..1a2324baaf 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -42,6 +42,14 @@
#define PCMBUF_MUTING
#endif
+/* Clip sample to signed 16 bit range */
+static inline int32_t clip_sample_16(int32_t sample)
+{
+ if ((int16_t)sample != sample)
+ sample = 0x7fff ^ (sample >> 31);
+ return sample;
+}
+
/* Keep watermark high for iPods at least (2s) */
#define PCMBUF_WATERMARK (NATIVE_FREQUENCY * 4 * 2)
@@ -564,8 +572,8 @@ static void crossfade_process_buffer(size_t fade_in_delay,
while (block_rem > 0 && fade_out_chunk != NULL)
{
/* Fade one sample */
- short *buf = (short *)(fade_out_chunk->addr);
- int sample = buf[fade_out_sample];
+ int16_t *buf = (int16_t *)fade_out_chunk->addr;
+ int32_t sample = buf[fade_out_sample];
buf[fade_out_sample++] = (sample * factor) >> 8;
block_rem -= 2;
@@ -665,16 +673,16 @@ static void crossfade_start(void)
/* Returns the number of bytes _NOT_ mixed */
static size_t crossfade_fade_mix(int factor, const char *buf, size_t fade_rem)
{
- const short *input_buf = (const short *)buf;
- short *output_buf = (short *)(crossfade_chunk->addr);
- short *chunk_end = (short *)((size_t)output_buf + crossfade_chunk->size);
+ const int16_t *input_buf = (const int16_t *)buf;
+ int16_t *output_buf = (int16_t *)(crossfade_chunk->addr);
+ int16_t *chunk_end = SKIPBYTES(output_buf, crossfade_chunk->size);
output_buf = &output_buf[crossfade_sample];
while (fade_rem)
{
int sample = *input_buf++;
sample = ((sample * factor) >> 8) + *output_buf;
- *output_buf++ = MIN(32767, MAX(-32768, sample));
+ *output_buf++ = clip_sample_16(sample);
fade_rem -= 2;
if (output_buf >= chunk_end)
@@ -682,26 +690,26 @@ static size_t crossfade_fade_mix(int factor, const char *buf, size_t fade_rem)
crossfade_chunk = crossfade_chunk->link;
if (!crossfade_chunk)
return fade_rem;
- output_buf = (short *)(crossfade_chunk->addr);
- chunk_end = (short *)((size_t)output_buf + crossfade_chunk->size);
+ output_buf = (int16_t *)crossfade_chunk->addr;
+ chunk_end = SKIPBYTES(output_buf, crossfade_chunk->size);
}
}
- crossfade_sample = (size_t)(output_buf - (short *)(crossfade_chunk->addr));
+ crossfade_sample = output_buf - (int16_t *)crossfade_chunk->addr;
return 0;
}
/* Returns the number of bytes _NOT_ mixed */
static size_t crossfade_mix(const char *buf, size_t length)
{
- const short *input_buf = (const short *)buf;
- short *output_buf = (short *)(crossfade_chunk->addr);
- short *chunk_end = (short *)((size_t)output_buf + crossfade_chunk->size);
+ const int16_t *input_buf = (const int16_t *)buf;
+ int16_t *output_buf = (int16_t *)crossfade_chunk->addr;
+ int16_t *chunk_end = SKIPBYTES(output_buf, crossfade_chunk->size);
output_buf = &output_buf[crossfade_sample];
while (length)
{
int sample = *input_buf++ + *output_buf;
- *output_buf++ = MIN(32767, MAX(-32768, sample));
+ *output_buf++ = clip_sample_16(sample);
length -= 2;
if (output_buf >= chunk_end)
@@ -709,11 +717,11 @@ static size_t crossfade_mix(const char *buf, size_t length)
crossfade_chunk = crossfade_chunk->link;
if (!crossfade_chunk)
return length;
- output_buf = (short *)(crossfade_chunk->addr);
- chunk_end = (short *)((size_t)output_buf + crossfade_chunk->size);
+ output_buf = (int16_t *)(crossfade_chunk->addr);
+ chunk_end = SKIPBYTES(output_buf, crossfade_chunk->size);
}
}
- crossfade_sample = (size_t)(output_buf - (short *)(crossfade_chunk->addr));
+ crossfade_sample = output_buf - (int16_t *)crossfade_chunk->addr;
return 0;
}
@@ -742,7 +750,7 @@ static void flush_crossfade(char *buf, size_t length)
if (crossfade_fade_in_rem)
{
size_t samples;
- short *input_buf;
+ int16_t *input_buf;
/* Fade factor for this packet */
int factor =
@@ -768,11 +776,11 @@ static void flush_crossfade(char *buf, size_t length)
}
samples = fade_rem / 2;
- input_buf = (short *)buf;
+ input_buf = (int16_t *)buf;
/* Fade remaining samples in place */
while (samples)
{
- int sample = *input_buf;
+ int32_t sample = *input_buf;
*input_buf++ = (sample * factor) >> 8;
samples--;
}
@@ -940,9 +948,9 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude)
{
unsigned int count = 0, i = 0;
unsigned int interval = NATIVE_FREQUENCY / frequency;
- long sample;
- short *buf;
- short *pcmbuf_end = (short *)fadebuf;
+ int32_t sample;
+ int16_t *buf;
+ int16_t *pcmbuf_end = (int16_t *)fadebuf;
size_t samples = NATIVE_FREQUENCY / 1000 * duration;
if (pcm_is_playing() && pcmbuf_read != NULL)
@@ -952,7 +960,7 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude)
/* Get the next chunk */
char *pcmbuf_mix_buf = pcmbuf_read->link->addr;
/* Give at least 1/8s clearance. */
- buf = (short *)&pcmbuf_mix_buf[NATIVE_FREQUENCY * 4 / 8];
+ buf = (int16_t *)&pcmbuf_mix_buf[NATIVE_FREQUENCY * 4 / 8];
}
else
{
@@ -963,11 +971,11 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude)
while (i++ < samples)
{
sample = *buf;
- *buf++ = MIN(MAX(sample + amplitude, -32768), 32767);
+ *buf++ = clip_sample_16(sample + amplitude);
if (buf > pcmbuf_end)
- buf = (short *)audiobuffer;
+ buf = (int16_t *)audiobuffer;
sample = *buf;
- *buf++ = MIN(MAX(sample + amplitude, -32768), 32767);
+ *buf++ = clip_sample_16(sample + amplitude);
/* Toggle square wav side */
if (++count >= interval)
@@ -976,17 +984,17 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude)
amplitude = -amplitude;
}
if (buf > pcmbuf_end)
- buf = (short *)audiobuffer;
+ buf = (int16_t *)audiobuffer;
}
}
else
{
- buf = (short *)audiobuffer;
+ buf = (int16_t *)audiobuffer;
while (i++ < samples)
{
*buf++ = amplitude;
if (buf > pcmbuf_end)
- buf = (short *)audiobuffer;
+ buf = (int16_t *)audiobuffer;
*buf++ = amplitude;
/* Toggle square wav side */
@@ -996,7 +1004,7 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude)
amplitude = -amplitude;
}
if (buf > pcmbuf_end)
- buf = (short *)audiobuffer;
+ buf = (int16_t *)audiobuffer;
}
pcm_play_data(NULL, (unsigned char *)audiobuffer, samples * 4);
}
@@ -1013,7 +1021,7 @@ int pcmbuf_mix_free(void)
if (pcmbuf_mix_chunk)
{
size_t my_mix_end =
- (size_t)&((short *)pcmbuf_mix_chunk->addr)[pcmbuf_mix_sample];
+ (size_t)&((int16_t *)pcmbuf_mix_chunk->addr)[pcmbuf_mix_sample];
size_t my_write_pos = (size_t)&audiobuffer[audiobuffer_pos];
if (my_write_pos < my_mix_end)
my_write_pos += pcmbuf_size;
@@ -1024,8 +1032,8 @@ int pcmbuf_mix_free(void)
void pcmbuf_mix_voice(int count)
{
- short *ibuf = (short *)voicebuf;
- short *obuf;
+ int16_t *ibuf = (int16_t *)voicebuf;
+ int16_t *obuf;
size_t chunk_samples;
if (pcmbuf_mix_chunk == NULL && pcmbuf_read != NULL)
@@ -1037,7 +1045,7 @@ void pcmbuf_mix_voice(int count)
if (!pcmbuf_mix_chunk)
return;
- obuf = (short *)pcmbuf_mix_chunk->addr;
+ obuf = (int16_t *)pcmbuf_mix_chunk->addr;
chunk_samples = pcmbuf_mix_chunk->size / 2;
count <<= 1;
@@ -1054,7 +1062,7 @@ void pcmbuf_mix_voice(int count)
chunk_samples = pcmbuf_mix_chunk->size / 2;
}
sample += obuf[pcmbuf_mix_sample] >> 2;
- obuf[pcmbuf_mix_sample++] = MIN(MAX(sample, -32768), 32767);
+ obuf[pcmbuf_mix_sample++] = clip_sample_16(sample);
}
}