/*
|
/*
|
* mad - MPEG audio decoder
|
* mad - MPEG audio decoder
|
* Copyright (C) 2000-2001 Robert Leslie
|
* Copyright (C) 2000-2001 Robert Leslie
|
*
|
*
|
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
* (at your option) any later version.
|
* (at your option) any later version.
|
*
|
*
|
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
*
|
*
|
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
*
|
*
|
* $Id: audio.c,v 1.3 2001-11-06 17:01:07 simons Exp $
|
* $Id: audio.c,v 1.3 2001-11-06 17:01:07 simons Exp $
|
*/
|
*/
|
|
|
# ifdef HAVE_CONFIG_H
|
# ifdef HAVE_CONFIG_H
|
# include "config.h"
|
# include "config.h"
|
# endif
|
# endif
|
|
|
# include "audio.h"
|
# include "audio.h"
|
# include "mad.h"
|
# include "mad.h"
|
|
|
#ifndef EMBED
|
#ifndef EMBED
|
# include <string.h>
|
# include <string.h>
|
# include <stdio.h>
|
# include <stdio.h>
|
extern FILE *fo;
|
extern FILE *fo;
|
int printf(char *fmt, ...);
|
int printf(char *fmt, ...);
|
#endif
|
#endif
|
|
|
char const *audio_error;
|
char const *audio_error;
|
|
|
static mad_fixed_t left_err, right_err;
|
static mad_fixed_t left_err, right_err;
|
|
|
#define AUDIO_DBG 0
|
#define AUDIO_DBG 0
|
|
|
#if AUDIO_DBG
|
#if AUDIO_DBG
|
//unsigned short wave_dump[(0x40000/2)];
|
//unsigned short wave_dump[(0x40000/2)];
|
//int wave_seg_index[0x10000];
|
//int wave_seg_index[0x10000];
|
int wave_seg_nb = 0;
|
int wave_seg_nb = 0;
|
int wave_index = 0;
|
int wave_index = 0;
|
#endif
|
#endif
|
|
|
/*
|
/*
|
* NAME: audio_linear_dither()
|
* NAME: audio_linear_dither()
|
* DESCRIPTION: generic linear sample quantize and dither routine
|
* DESCRIPTION: generic linear sample quantize and dither routine
|
*/
|
*/
|
inline
|
inline
|
signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample,
|
signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample,
|
mad_fixed_t *error, struct audio_stats *stats)
|
mad_fixed_t *error, struct audio_stats *stats)
|
{
|
{
|
mad_fixed_t quantized;
|
mad_fixed_t quantized;
|
|
|
/* dither */
|
/* dither */
|
sample += *error;
|
sample += *error;
|
|
|
# if 1
|
# if 1
|
/* clip */
|
/* clip */
|
quantized = sample;
|
quantized = sample;
|
if (sample >= stats->peak_sample) {
|
if (sample >= stats->peak_sample) {
|
if (sample >= MAD_F_ONE) {
|
if (sample >= MAD_F_ONE) {
|
quantized = MAD_F_ONE - 1;
|
quantized = MAD_F_ONE - 1;
|
++stats->clipped_samples;
|
++stats->clipped_samples;
|
if (sample - quantized > stats->peak_clipping &&
|
if (sample - quantized > stats->peak_clipping &&
|
mad_f_abs(*error) < (MAD_F_ONE >> (MAD_F_FRACBITS + 1 - bits)))
|
mad_f_abs(*error) < (MAD_F_ONE >> (MAD_F_FRACBITS + 1 - bits)))
|
stats->peak_clipping = sample - quantized;
|
stats->peak_clipping = sample - quantized;
|
}
|
}
|
stats->peak_sample = quantized;
|
stats->peak_sample = quantized;
|
}
|
}
|
else if (sample < -stats->peak_sample) {
|
else if (sample < -stats->peak_sample) {
|
if (sample < -MAD_F_ONE) {
|
if (sample < -MAD_F_ONE) {
|
quantized = -MAD_F_ONE;
|
quantized = -MAD_F_ONE;
|
++stats->clipped_samples;
|
++stats->clipped_samples;
|
if (quantized - sample > stats->peak_clipping &&
|
if (quantized - sample > stats->peak_clipping &&
|
mad_f_abs(*error) < (MAD_F_ONE >> (MAD_F_FRACBITS + 1 - bits)))
|
mad_f_abs(*error) < (MAD_F_ONE >> (MAD_F_FRACBITS + 1 - bits)))
|
stats->peak_clipping = quantized - sample;
|
stats->peak_clipping = quantized - sample;
|
}
|
}
|
stats->peak_sample = -quantized;
|
stats->peak_sample = -quantized;
|
}
|
}
|
# else
|
# else
|
/* clip */
|
/* clip */
|
quantized = sample;
|
quantized = sample;
|
if (sample >= MAD_F_ONE)
|
if (sample >= MAD_F_ONE)
|
quantized = MAD_F_ONE - 1;
|
quantized = MAD_F_ONE - 1;
|
else if (sample < -MAD_F_ONE)
|
else if (sample < -MAD_F_ONE)
|
quantized = -MAD_F_ONE;
|
quantized = -MAD_F_ONE;
|
# endif
|
# endif
|
|
|
/* quantize */
|
/* quantize */
|
quantized &= ~((1L << (MAD_F_FRACBITS + 1 - bits)) - 1);
|
quantized &= ~((1L << (MAD_F_FRACBITS + 1 - bits)) - 1);
|
|
|
/* error */
|
/* error */
|
*error = sample - quantized;
|
*error = sample - quantized;
|
|
|
/* scale */
|
/* scale */
|
return quantized >> (MAD_F_FRACBITS + 1 - bits);
|
return quantized >> (MAD_F_FRACBITS + 1 - bits);
|
}
|
}
|
|
|
|
|
static struct audio_stats stats;
|
static struct audio_stats stats;
|
|
|
/*
|
/*
|
* NAME: audio_pcm_s16le()
|
* NAME: audio_pcm_s16le()
|
* DESCRIPTION: write a block of signed 16-bit little-endian PCM samples
|
* DESCRIPTION: write a block of signed 16-bit little-endian PCM samples
|
*/
|
*/
|
unsigned int audio_pcm_s16le(unsigned char *data, unsigned int nsamples,
|
unsigned int audio_pcm_s16le(unsigned char *data, unsigned int nsamples,
|
mad_fixed_t const *left, mad_fixed_t const *right)
|
mad_fixed_t const *left, mad_fixed_t const *right)
|
{
|
{
|
unsigned int len;
|
unsigned int len;
|
register signed int sample0, sample1;
|
register signed int sample0, sample1;
|
|
|
len = nsamples;
|
len = nsamples;
|
#if AUDIO_DBG
|
#if AUDIO_DBG
|
// wave_seg_index[wave_seg_nb] = wave_index;
|
// wave_seg_index[wave_seg_nb] = wave_index;
|
// wave_seg_nb++;
|
// wave_seg_nb++;
|
report(wave_index);
|
report(wave_index);
|
#endif
|
#endif
|
|
|
while (len--) {
|
while (len--) {
|
sample0 = audio_linear_dither(16, *left++, &left_err, &stats);
|
sample0 = audio_linear_dither(16, *left++, &left_err, &stats);
|
sample1 = audio_linear_dither(16, *right++, &right_err, &stats);
|
sample1 = audio_linear_dither(16, *right++, &right_err, &stats);
|
|
|
#ifdef EMBED
|
#ifdef EMBED
|
#ifdef OR1K
|
#ifdef OR1K
|
#ifndef OR1K_SIM
|
#ifndef OR1K_SIM
|
*(volatile unsigned short *)0x40000000 = sample0;
|
*(volatile unsigned short *)0x40000000 = sample0;
|
// *(volatile unsigned long *)0x40000000 = sample0;
|
// *(volatile unsigned long *)0x40000000 = sample0;
|
// *(volatile unsigned long *)0x40000000 = sample1;
|
// *(volatile unsigned long *)0x40000000 = sample1;
|
// *(volatile unsigned long *)0x40000000 = sample1;
|
// *(volatile unsigned long *)0x40000000 = sample1;
|
|
|
#if AUDIO_DBG
|
#if AUDIO_DBG
|
// wave_dump[wave_index] = (unsigned short)sample0;
|
// wave_dump[wave_index] = (unsigned short)sample0;
|
wave_index++;
|
wave_index++;
|
// wave_dump[wave_index] = (unsigned short)sample1;
|
// wave_dump[wave_index] = (unsigned short)sample1;
|
wave_index++;
|
wave_index++;
|
#endif
|
#endif
|
|
|
#else
|
#else
|
// asm volatile("l.mtspr r0,%0,0x01234" : : "r" (sample0 | (sample1 << 16)));
|
// asm volatile("l.mtspr r0,%0,0x01234" : : "r" (sample0 | (sample1 << 16)));
|
asm volatile("l.mtspr r0,%0,0x0FFFE" : : "r" (sample0 >> 0));
|
asm volatile("l.mtspr r0,%0,0x0FFFE" : : "r" (sample0 >> 0));
|
asm volatile("l.mtspr r0,%0,0x0FFFE" : : "r" (sample0 >> 8));
|
asm volatile("l.mtspr r0,%0,0x0FFFE" : : "r" (sample0 >> 8));
|
asm volatile("l.mtspr r0,%0,0x0FFFE" : : "r" (sample1 >> 0));
|
asm volatile("l.mtspr r0,%0,0x0FFFE" : : "r" (sample1 >> 0));
|
asm volatile("l.mtspr r0,%0,0x0FFFE" : : "r" (sample1 >> 8));
|
asm volatile("l.mtspr r0,%0,0x0FFFE" : : "r" (sample1 >> 8));
|
#endif
|
#endif
|
#else
|
#else
|
printf("l.mtspr (0x0000FFFE) <- %x\n", (sample0 >> 0));
|
printf("l.mtspr (0x0000FFFE) <- %x\n", (sample0 >> 0));
|
printf("l.mtspr (0x0000FFFE) <- %x\n", (sample0 >> 8));
|
printf("l.mtspr (0x0000FFFE) <- %x\n", (sample0 >> 8));
|
printf("l.mtspr (0x0000FFFE) <- %x\n", (sample1 >> 0));
|
printf("l.mtspr (0x0000FFFE) <- %x\n", (sample1 >> 0));
|
printf("l.mtspr (0x0000FFFE) <- %x\n", (sample1 >> 8));
|
printf("l.mtspr (0x0000FFFE) <- %x\n", (sample1 >> 8));
|
#endif
|
#endif
|
#else
|
#else
|
data[0] = sample0 >> 0;
|
data[0] = sample0 >> 0;
|
data[1] = sample0 >> 8;
|
data[1] = sample0 >> 8;
|
data[2] = sample1 >> 0;
|
data[2] = sample1 >> 0;
|
data[3] = sample1 >> 8;
|
data[3] = sample1 >> 8;
|
if (fo) {
|
if (fo) {
|
fputc (data[0], fo);
|
fputc (data[0], fo);
|
fputc (data[1], fo);
|
fputc (data[1], fo);
|
fputc (data[2], fo);
|
fputc (data[2], fo);
|
fputc (data[3], fo);
|
fputc (data[3], fo);
|
}
|
}
|
data += 4;
|
data += 4;
|
#endif
|
#endif
|
}
|
}
|
return nsamples * 2 * 2;
|
return nsamples * 2 * 2;
|
}
|
}
|
|
|