static int mp3_read (song_s *song, char *buffer) { static int i; static int ret; static struct audio_dither dither; static char buffer2[BUF_SIZE]; static char *out_ptr = buffer2; static char *out_buf_end = buffer2 + BUF_SIZE; mp3_s *mp3 = song->songlib->mp3; mad_timer_add (&mp3->timer, mp3->frame.header.duration); mad_synth_frame (&mp3->synth, &mp3->frame); mp3->elapsed_time = ((float)mad_timer_count (mp3->timer, MAD_UNITS_MILLISECONDS))/1000.0; for (i = 0; i < mp3->synth.pcm.length; i++) { signed int sample; sample = (signed int)audio_linear_dither (16, mp3->synth.pcm.samples[0][i], &dither); *(out_ptr++) = sample & 0xff; *(out_ptr++) = sample >> 8; if (MAD_NCHANNELS (&(mp3->frame).header) == 2) { sample = (signed int) audio_linear_dither (16, mp3->synth.pcm.samples[1][i], &dither); *(out_ptr++) = sample & 0xff; *(out_ptr++) = sample >> 8; } if (out_ptr == out_buf_end) { memcpy (buffer, buffer2, BUF_SIZE); bossao_play_chunk (song, buffer, BUF_SIZE); out_ptr = buffer2; } }
static unsigned int pack_pcm(unsigned char *data, unsigned int nsamples, mad_fixed_t const *left, mad_fixed_t const *right, int resolution, struct audio_stats *stats) { static struct audio_dither left_dither, right_dither; unsigned char const *start; register signed long sample0, sample1; int effective, bytes; start = data; effective = (resolution > 24) ? 24 : resolution; bytes = resolution / 8; if (right) { /* stereo */ while (nsamples--) { #ifdef LINEAR_DITHER sample0 = audio_linear_dither(effective, *left++, &left_dither, stats); sample1 = audio_linear_dither(effective, *right++, &right_dither, stats); #else sample0 = audio_linear_round(effective, *left++, stats); sample1 = audio_linear_round(effective, *right++, stats); #endif switch (resolution) { case 8: data[0] = sample0 + 0x80; data[1] = sample1 + 0x80; break; case 32: sample0 <<= 8; sample1 <<= 8; data[ 3] = sample0 >> 24; data[bytes + 3] = sample1 >> 24; case 24: data[ 2] = sample0 >> 16; data[bytes + 2] = sample1 >> 16; case 16: data[ 1] = sample0 >> 8; data[bytes + 1] = sample1 >> 8; data[ 0] = sample0 >> 0; data[bytes + 0] = sample1 >> 0; } data += bytes * 2; } } else { /* mono */ while (nsamples--) {
//*************************************************************************** enum mad_flow Kwave::MP3Decoder::processOutput(void */*data*/, struct mad_header const */*header*/, struct mad_pcm *pcm) { static Kwave::audio_dither dither; qint32 sample; Kwave::SampleArray buffer(pcm->length); // loop over all tracks const unsigned int tracks = m_dest->tracks(); for (unsigned int track = 0; track < tracks; ++track) { unsigned int nsamples = pcm->length; mad_fixed_t const *p = pcm->samples[track]; unsigned int ofs = 0; // and render samples into Kwave's internal format while (nsamples--) { sample = static_cast<qint32>(audio_linear_dither(SAMPLE_BITS, static_cast<mad_fixed_t>(*p++), &dither)); buffer[ofs++] = static_cast<sample_t>(sample); } *(*m_dest)[track] << buffer; } return MAD_FLOW_CONTINUE; }
static int play(struct audio_play *play) { unsigned int len; mad_fixed_t const *left, *right; unsigned long mask; len = play->nsamples; left = play->samples[0]; right = play->samples[1]; mask = (1L << bitdepth) - 1; switch (play->mode) { case AUDIO_MODE_ROUND: while (len--) { fprintf(outfile, format_str, audio_linear_round(bitdepth, *left++, play->stats) & mask); if (right) { fprintf(outfile, format_str, audio_linear_round(bitdepth, *right++, play->stats) & mask); } } break; case AUDIO_MODE_DITHER: { static struct audio_dither left_dither, right_dither; while (len--) { fprintf(outfile, format_str, audio_linear_dither(bitdepth, *left++, &left_dither, play->stats) & mask); if (right) { fprintf(outfile, format_str, audio_linear_dither(bitdepth, *right++, &right_dither, play->stats) & mask); } } } break; } return 0; }
static enum mad_flow audeng_mad_output (void *data, struct mad_header const *header, struct mad_pcm *pcm) { unsigned int nsamples = pcm->length; mad_fixed_t const *left_ch, *right_ch; static struct audeng_dither_t dither; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; audeng_sample_pos += 1152; if (audeng_mode == stopped) { return MAD_FLOW_STOP; } //return MAD_FLOW_CONTINUE; while (nsamples--) { signed int sample; sample = audio_linear_dither(16, *left_ch++, &dither); putc(sample, audeng_output_fd); putc(sample >> 8, audeng_output_fd); if (pcm->channels == 2) { sample = audio_linear_dither(16, *right_ch++, &dither); putc(sample, audeng_output_fd); putc(sample >> 8, audeng_output_fd); } else {
enum mad_flow output(void *data, struct mad_header const *header, struct mad_pcm *pcm) { register int nsamples = pcm->length; mad_fixed_t const *left_ch = pcm->samples[0], *right_ch = pcm->samples[1]; static unsigned char stream[1152*4]; /* 1152 because that's what mad has as a max; *4 because there are 4 distinct bytes per sample (in 2 channel case) */ static unsigned int rate = 0; static int channels = 0; static struct audio_dither dither; register char * ptr = stream; register signed int sample; register mad_fixed_t tempsample; /* Semaphore operations */ static struct sembuf read_sops = {0, -1, 0}; static struct sembuf write_sops = {1, 1, 0}; if(options.opt & MPG321_ENABLE_BUFFER) { semop(semarray,&read_sops,1); ptr = (Output_Queue+mad_decoder_position)->data; memcpy(&((Output_Queue+mad_decoder_position)->header),header,sizeof(struct mad_header)); }else{ /* We need to know information about the file before we can open the playdevice in some cases. So, we do it here. */ if (!playdevice) { channels = MAD_NCHANNELS(header); rate = header->samplerate; open_ao_playdevice(header); } else if ((channels != MAD_NCHANNELS(header) || rate != header->samplerate) && playdevice_is_live()) { ao_close(playdevice); channels = MAD_NCHANNELS(header); rate = header->samplerate; open_ao_playdevice(header); } } static int peak_rate = 0; static unsigned short int peak = 0; if (pcm->channels == 2) { while (nsamples--) { tempsample = mad_f_mul(*left_ch++, options.volume); sample = (signed int) audio_linear_dither(16, tempsample, &dither); peak = abs(sample) > peak ? abs(sample) : peak; #ifndef WORDS_BIGENDIAN *ptr++ = (unsigned char) (sample >> 0); *ptr++ = (unsigned char) (sample >> 8); #else *ptr++ = (unsigned char) (sample >> 8); *ptr++ = (unsigned char) (sample >> 0); #endif tempsample = mad_f_mul(*right_ch++, options.volume); sample = (signed int) audio_linear_dither(16, tempsample, &dither); peak = abs(sample) > peak ? abs(sample) : peak; #ifndef WORDS_BIGENDIAN *ptr++ = (unsigned char) (sample >> 0); *ptr++ = (unsigned char) (sample >> 8); #else *ptr++ = (unsigned char) (sample >> 8); *ptr++ = (unsigned char) (sample >> 0); #endif } process_fft(stream, pcm->length * 4); if(options.opt & MPG321_ENABLE_BUFFER) { (Output_Queue+mad_decoder_position)->length = pcm->length * 4; }else { ao_play(playdevice, stream, pcm->length * 4); } } else if (options.opt & MPG321_FORCE_STEREO)
process_fft(stream, pcm->length * 4); if(options.opt & MPG321_ENABLE_BUFFER) { (Output_Queue+mad_decoder_position)->length = pcm->length * 4; }else { ao_play(playdevice, stream, pcm->length * 4); } } else if (options.opt & MPG321_FORCE_STEREO) { while (nsamples--) { tempsample = mad_f_mul(*left_ch++, options.volume); sample = (signed int) audio_linear_dither(16, tempsample, &dither); peak = abs(sample) > peak ? abs(sample) : peak; /* Just duplicate the sample across both channels. */ #ifndef WORDS_BIGENDIAN *ptr++ = (unsigned char) (sample >> 0); *ptr++ = (unsigned char) (sample >> 8); *ptr++ = (unsigned char) (sample >> 0); *ptr++ = (unsigned char) (sample >> 8); #else *ptr++ = (unsigned char) (sample >> 8); *ptr++ = (unsigned char) (sample >> 0); *ptr++ = (unsigned char) (sample >> 8); *ptr++ = (unsigned char) (sample >> 0); #endif
enum mad_flow output(void *data, struct mad_header const *header, struct mad_pcm *pcm) { register int nsamples = pcm->length; mad_fixed_t const *left_ch = pcm->samples[0], *right_ch = pcm->samples[1]; static unsigned char stream[1152*4]; /* 1152 because that's what mad has as a max; *4 because there are 4 distinct bytes per sample (in 2 channel case) */ static unsigned int rate = 0; static int channels = 0; static struct audio_dither dither; register char * ptr = stream; register signed int sample; register mad_fixed_t tempsample; /* We need to know information about the file before we can open the playdevice in some cases. So, we do it here. */ if (!playdevice) { channels = MAD_NCHANNELS(header); rate = header->samplerate; open_ao_playdevice(header); } else if ((channels != MAD_NCHANNELS(header) || rate != header->samplerate) && playdevice_is_live()) { ao_close(playdevice); channels = MAD_NCHANNELS(header); rate = header->samplerate; open_ao_playdevice(header); } if (pcm->channels == 2) { while (nsamples--) { tempsample = (mad_fixed_t)((*left_ch++ * (double)options.volume)/MAD_F_ONE); sample = (signed int) audio_linear_dither(16, tempsample, &dither); #ifndef WORDS_BIGENDIAN *ptr++ = (unsigned char) (sample >> 0); *ptr++ = (unsigned char) (sample >> 8); #else *ptr++ = (unsigned char) (sample >> 8); *ptr++ = (unsigned char) (sample >> 0); #endif tempsample = (mad_fixed_t)((*right_ch++ * (double)options.volume)/MAD_F_ONE); sample = (signed int) audio_linear_dither(16, tempsample, &dither); #ifndef WORDS_BIGENDIAN *ptr++ = (unsigned char) (sample >> 0); *ptr++ = (unsigned char) (sample >> 8); #else *ptr++ = (unsigned char) (sample >> 8); *ptr++ = (unsigned char) (sample >> 0); #endif } ao_play(playdevice, stream, pcm->length * 4); } else if (options.opt & MPG321_FORCE_STEREO)
if (audeng_mode == stopped) { return MAD_FLOW_STOP; } //return MAD_FLOW_CONTINUE; while (nsamples--) { signed int sample; sample = audio_linear_dither(16, *left_ch++, &dither); putc(sample, audeng_output_fd); putc(sample >> 8, audeng_output_fd); if (pcm->channels == 2) { sample = audio_linear_dither(16, *right_ch++, &dither); putc(sample, audeng_output_fd); putc(sample >> 8, audeng_output_fd); } else { sample = audio_linear_dither(16, *left_ch++, &dither); putc(sample, audeng_output_fd); putc(sample >> 8, audeng_output_fd); } } return MAD_FLOW_CONTINUE; } static int audeng_mp3_bufferframes () { audeng_mp3_frame cur_frame; int x; audeng_mp3_findframe(audeng_song, audeng_song_pos, &cur_frame); audeng_song_pos = cur_frame.start; x = cur_frame.size;
case 24: data[ 2] = sample0 >> 16; data[bytes + 2] = sample1 >> 16; case 16: data[ 1] = sample0 >> 8; data[bytes + 1] = sample1 >> 8; data[ 0] = sample0 >> 0; data[bytes + 0] = sample1 >> 0; } data += bytes * 2; } } else { /* mono */ while (nsamples--) { #ifdef LINEAR_DITHER sample0 = audio_linear_dither(effective, *left++, &left_dither, stats); #else sample0 = audio_linear_round(effective, *left++, stats); #endif switch (resolution) { case 8: data[0] = sample0 + 0x80; break; case 32: sample0 <<= 8; data[3] = sample0 >> 24; case 24: data[2] = sample0 >> 16; case 16: data[1] = sample0 >> 8; data[0] = sample0 >> 0;
static enum mad_flow mad_output(void *data, struct mad_header const *header, struct mad_pcm *pcm) { unsigned int nchannels, nsamples; mad_fixed_t const *left_ch, *right_ch; char *buf, *ptr; int i; slimaudio_t *audio = (slimaudio_t *) data; /* pthread_mutex_lock(&audio->decoder_mutex); if (audio->decoder_state != STREAM_PLAYING) { pthread_mutex_unlock(&audio->decoder_mutex); return MAD_FLOW_STOP; } pthread_mutex_unlock(&audio->decoder_mutex); */ /* pcm->samplerate contains the sampling frequency */ nchannels = pcm->channels; nsamples = pcm->length; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; VDEBUGF("decode_output state=%i nchannels=%i nsamples=%i\n", audio->decoder_state, nchannels, nsamples); buf = (char *) malloc(nsamples * 2 * 2 ); /* always stereo output */ ptr = buf; #ifdef __BIG_ENDIAN__ for (i=0; i<nsamples; i++) { signed int sample; /* left */ sample = audio_linear_dither(16, *left_ch++, &left_dither, &stats); *ptr++ = (sample >> 8) & 0xff; *ptr++ = (sample >> 0) & 0xff; /* right */ if (nchannels == 2) { sample = audio_linear_dither(16, *right_ch++, &right_dither, &stats); } *ptr++ = (sample >> 8) & 0xff; *ptr++ = (sample >> 0) & 0xff; } #else /* __LITTLE_ENDIAN__ */ for (i=0; i<nsamples; i++) { signed int sample; /* left */ sample = audio_linear_dither(16, *left_ch++, &left_dither, &stats); *ptr++ = (sample >> 0) & 0xff; *ptr++ = (sample >> 8) & 0xff; /* right */ if (nchannels == 2) { sample = audio_linear_dither(16, *right_ch++, &right_dither, &stats); } *ptr++ = (sample >> 0) & 0xff; *ptr++ = (sample >> 8) & 0xff; } #endif slimaudio_buffer_write(audio->output_buffer, buf, nsamples * 2 * 2 /* always stero output */); free(buf); return MAD_FLOW_CONTINUE; }