Example #1
0
int output_synth_data(mpgedit_madbuf_t *ctx)
{
    int i;
    int rsts;

    for(i=0;i<ctx->Synth.pcm.length;i++) {
        signed short    Sample;

        /* Left channel */
        Sample=MadFixedToSshort(ctx->Synth.pcm.samples[0][i]);
        *(ctx->OutputPtr++) = Sample & 0xff;
        *(ctx->OutputPtr++) = Sample >> 8;

        /* Right channel. If the decoded stream is monophonic then
         * the right output channel is the same as the left one.
         */
        if(MAD_NCHANNELS(&ctx->Frame.header)==2) {
            Sample=MadFixedToSshort(ctx->Synth.pcm.samples[1][i]);
            *(ctx->OutputPtr++) = Sample & 0xff;
            *(ctx->OutputPtr++) = Sample >> 8;
        }

        /* Flush the output buffer if it is full. */
        if (ctx->OutputPtr >= ctx->OutputBufferEnd) {
            rsts = fwrite(ctx->OutputBuffer, 1, OUTPUT_BUFFER_SIZE, ctx->outfp);
            if (rsts != OUTPUT_BUFFER_SIZE) {
                fprintf(stderr,"%s: PCM write error (%s).\n",
                        "main" ,strerror(errno));
                return 1;
            }
            ctx->OutputPtr = ctx->OutputBuffer;
        }
    }
Example #2
0
void
mp3_mad_decode (mp3_info_t *info) {
    // copy synthesized samples into readbuffer
    int idx = info->mad_synth.pcm.length-info->buffer.decode_remaining;
    // stereo
    if (MAD_NCHANNELS(&info->mad_frame.header) == 2 && info->info.fmt.channels == 2) {
        while (info->buffer.decode_remaining > 0 && info->buffer.readsize > 0) {
            *((int16_t*)info->buffer.out) = MadFixedToSshort (info->mad_synth.pcm.samples[0][idx]);
            info->buffer.readsize -= 2;
            info->buffer.out += 2;
            *((int16_t*)info->buffer.out) = MadFixedToSshort (info->mad_synth.pcm.samples[1][idx]);
            info->buffer.readsize -= 2;
            info->buffer.out += 2;
            info->buffer.decode_remaining--;
            idx++;
        }
    }
    // mono
    else if (MAD_NCHANNELS(&info->mad_frame.header) == 1 && info->info.fmt.channels == 1){
        while (info->buffer.decode_remaining > 0 && info->buffer.readsize > 0) {
            *((int16_t*)info->buffer.out) = MadFixedToSshort (info->mad_synth.pcm.samples[0][idx]);
            info->buffer.readsize -= 2;
            info->buffer.out += 2;
            info->buffer.decode_remaining--;
            idx++;
        }
    }
    // workaround for bad mp3s that have both mono and stereo frames
    else if (MAD_NCHANNELS(&info->mad_frame.header) == 1 && info->info.fmt.channels == 2) {
        while (info->buffer.decode_remaining > 0 && info->buffer.readsize > 0) {
            int16_t sample = MadFixedToSshort (info->mad_synth.pcm.samples[0][idx]);
            *((int16_t*)info->buffer.out) = sample;
            info->buffer.readsize -= 2;
            info->buffer.out += 2;
            *((int16_t*)info->buffer.out) = sample;
            info->buffer.readsize -= 2;
            info->buffer.out += 2;
            info->buffer.decode_remaining--;
            idx++;
        }
    }
    else if (MAD_NCHANNELS(&info->mad_frame.header) == 2 && info->info.fmt.channels == 1) {
        while (info->buffer.decode_remaining > 0 && info->buffer.readsize > 0) {
            int16_t sample = MadFixedToSshort (info->mad_synth.pcm.samples[0][idx]);
            *((int16_t*)info->buffer.out) = sample;
            info->buffer.readsize -= 2;
            info->buffer.out += 2;
            info->buffer.decode_remaining--;
            idx++;
        }
    }
}
int32 MADDecoder::Decode(uint8* buffer, int32 max_length)
{
	int32 bytes_decoded = 0;
	if (stereo) 
		max_length = max_length - 3;
	else
		max_length = max_length - 1;

	while (bytes_decoded < max_length)
	{
		if (sample < Synth.pcm.length)
		{
			int16 sample_data;
			sample_data = MadFixedToSshort(Synth.pcm.samples[0][sample]);
#ifdef ALEPHONE_LITTLE_ENDIAN
			buffer[bytes_decoded++] = sample_data & 0xff;
			buffer[bytes_decoded++] = sample_data >> 8;
#else
			buffer[bytes_decoded++] = sample_data >> 8;
			buffer[bytes_decoded++] = sample_data & 0xff;

#endif
			if (stereo)
			{
				sample_data = MadFixedToSshort(Synth.pcm.samples[1][sample]);
#ifdef ALEPHONE_LITTLE_ENDIAN
				buffer[bytes_decoded++] = sample_data & 0xff;
				buffer[bytes_decoded++] = sample_data >> 8;
#else
				buffer[bytes_decoded++] = sample_data >> 8;
				buffer[bytes_decoded++] = sample_data & 0xff;
#endif
			}

			sample++;
		}
		else if (!DecodeFrame())
Example #4
0
/**
 * MP3音乐播放回调函数,
 * 负责将解码数据填充声音缓存区
 *
 * @note 声音缓存区的格式为双声道,16位低字序
 *
 * @param buf 声音缓冲区指针
 * @param reqn 缓冲区帧大小
 * @param pdata 用户数据,无用
 */
static int mp3_audiocallback(void *buf, unsigned int reqn, void *pdata)
{
	int avail_frame;
	int snd_buf_frame_size = (int) reqn;
	int ret;
	double incr;
	signed short *audio_buf = buf;
	unsigned i;
	uint16_t *output;

	UNUSED(pdata);

	if (g_status != ST_PLAYING) {
		if (handle_seek() == -1) {
			__end();
			return -1;
		}

		xAudioClearSndBuf(buf, snd_buf_frame_size);
		xrKernelDelayThread(100000);
		return 0;
	}

	while (snd_buf_frame_size > 0) {
		avail_frame = g_buff_frame_size - g_buff_frame_start;

		if (avail_frame >= snd_buf_frame_size) {
			send_to_sndbuf(audio_buf,
						   &g_buff[g_buff_frame_start * 2],
						   snd_buf_frame_size, 2);
			g_buff_frame_start += snd_buf_frame_size;
			audio_buf += snd_buf_frame_size * 2;
			snd_buf_frame_size = 0;
		} else {
			send_to_sndbuf(audio_buf,
						   &g_buff[g_buff_frame_start * 2], avail_frame, 2);
			snd_buf_frame_size -= avail_frame;
			audio_buf += avail_frame * 2;

			if (stream.buffer == NULL || stream.error == MAD_ERROR_BUFLEN) {
				size_t read_size, remaining = 0;
				uint8_t *read_start;
				int bufsize;

				if (stream.next_frame != NULL) {
					remaining = stream.bufend - stream.next_frame;
					memmove(g_input_buff, stream.next_frame, remaining);
					read_start = g_input_buff + remaining;
					read_size = BUFF_SIZE - remaining;
				} else {
					read_size = BUFF_SIZE;
					read_start = g_input_buff;
					remaining = 0;
				}

				if (mp3_data.use_buffer)
					bufsize =
						buffered_reader_read(mp3_data.r, read_start, read_size);
				else
					bufsize = xrIoRead(mp3_data.fd, read_start, read_size);

				if (bufsize <= 0) {
					__end();
					return -1;
				}
				if (bufsize < read_size) {
					uint8_t *guard = read_start + read_size;

					memset(guard, 0, MAD_BUFFER_GUARD);
					read_size += MAD_BUFFER_GUARD;
				}
				mad_stream_buffer(&stream, g_input_buff, read_size + remaining);
				stream.error = 0;
			}

			ret = mad_frame_decode(&frame, &stream);

			if (ret == -1) {
				if (MAD_RECOVERABLE(stream.error)
					|| stream.error == MAD_ERROR_BUFLEN) {
					if (stream.error == MAD_ERROR_LOSTSYNC) {
						long tagsize = id3_tag_query(stream.this_frame,
													 stream.bufend -
													 stream.this_frame);

						if (tagsize > 0) {
							mad_stream_skip(&stream, tagsize);
						}

						if (mad_header_decode(&frame.header, &stream) == -1) {
							if (stream.error != MAD_ERROR_BUFLEN) {
								if (!MAD_RECOVERABLE(stream.error)) {
									__end();
									return -1;
								}
							}
						} else {
							stream.error = MAD_ERROR_NONE;
						}
					}

					g_buff_frame_size = 0;
					g_buff_frame_start = 0;
					continue;
				} else {
					__end();
					return -1;
				}
			}

			output = &g_buff[0];

			if (stream.error != MAD_ERROR_NONE) {
				continue;
			}

			mad_synth_frame(&synth, &frame);
			for (i = 0; i < synth.pcm.length; i++) {
				signed short sample;

				if (MAD_NCHANNELS(&frame.header) == 2) {
					/* Left channel */
					sample = MadFixedToSshort(synth.pcm.samples[0][i]);
					*(output++) = sample;
					sample = MadFixedToSshort(synth.pcm.samples[1][i]);
					*(output++) = sample;
				} else {
					sample = MadFixedToSshort(synth.pcm.samples[0][i]);
					*(output++) = sample;
					*(output++) = sample;
				}
			}

			g_buff_frame_size = synth.pcm.length;
			g_buff_frame_start = 0;
			incr = frame.header.duration.seconds;
			incr +=
				mad_timer_fraction(frame.header.duration,
								   MAD_UNITS_MILLISECONDS) / 1000.0;
			g_play_time += incr;
			add_bitrate(&g_inst_br, frame.header.bitrate, incr);
		}
	}

	return 0;
}
Example #5
0
  bool madaudiofile::getNextAudioFrame() {
#ifdef HAVE_MAD_H
#ifdef MADAUDIO_PRINT_DEBUG
    printf("Now in getNextAudioFrame()\n");
#endif      
    u_int8_t *OutputPtr = OutputBuffer;
    u_int8_t *GuardPtr = NULL;

    while(OutputPtr < OutputBufferEnd) {
      /* The input bucket must be filled if it becomes empty or if
       * it's the first execution of the loop.
       */
      if(Stream->buffer==NULL || Stream->error==MAD_ERROR_BUFLEN || 
	 frame_count == 0) {
	size_t ReadSize,Remaining;
	unsigned char *ReadStart;
          
	/* {2} libmad may not consume all bytes of the input
	 * buffer. If the last frame in the buffer is not wholly
	 * contained by it, then that frame's start is pointed by
	 * the next_frame member of the Stream structure. This
	 * common situation occurs when mad_frame_decode() fails,
	 * sets the stream error code to MAD_ERROR_BUFLEN, and
	 * sets the next_frame pointer to a non NULL value. (See
	 * also the comment marked {4} bellow.)
	 *
	 * When this occurs, the remaining unused bytes must be
	 * put back at the beginning of the buffer and taken in
	 * account before refilling the buffer. This means that
	 * the input buffer must be large enough to hold a whole
	 * frame at the highest observable bit-rate (currently 448
	 * kb/s). XXX=XXX Is 2016 bytes the size of the largest
	 * frame? (448000*(1152/32000))/8
	 */
	if(Stream->next_frame!=NULL) {
	  Remaining=Stream->bufend-Stream->next_frame;
	  memmove(InputBuffer,Stream->next_frame,Remaining);
	  ReadStart=InputBuffer+Remaining;
	  ReadSize=INPUT_BUFFER_SIZE-Remaining;
	}
	else
	  ReadSize=INPUT_BUFFER_SIZE,
	    ReadStart=InputBuffer,
	    Remaining=0;
          
	/* Fill-in the buffer. If an error occurs print a message
	 * and leave the decoding loop. If the end of stream is
	 * reached we also leave the loop but the return status is
	 * left untouched.
	 */
	ReadSize=readData(ReadStart,1,ReadSize,file);
	if(ReadSize<=0) {
	  break; // probably end of file reached and nothing was read
	}
          
	/* {3} When decoding the last frame of a file, it must be
	 * followed by MAD_BUFFER_GUARD zero bytes if one wants to
	 * decode that last frame. When the end of file is
	 * detected we append that quantity of bytes at the end of
	 * the available data. Note that the buffer can't overflow
	 * as the guard size was allocated but not used the the
	 * buffer management code. (See also the comment marked
	 * {1}.)
	 *
	 * In a message to the mad-dev mailing list on May 29th,
	 * 2001, Rob Leslie explains the guard zone as follows:
	 *
	 *    "The reason for MAD_BUFFER_GUARD has to do with the
	 *    way decoding is performed. In Layer III, Huffman
	 *    decoding may inadvertently read a few bytes beyond
	 *    the end of the buffer in the case of certain invalid
	 *    input. This is not detected until after the fact. To
	 *    prevent this from causing problems, and also to
	 *    ensure the next frame's main_data_begin pointer is
	 *    always accessible, MAD requires MAD_BUFFER_GUARD
	 *    (currently 8) bytes to be present in the buffer past
	 *    the end of the current frame in order to decode the
	 *    frame."
	 */
	if(reachedEOF) {
	  GuardPtr=ReadStart+ReadSize;
	  memset(GuardPtr,0,MAD_BUFFER_GUARD);
	  ReadSize+=MAD_BUFFER_GUARD;
	}
          
	/* Pipe the new buffer content to libmad's stream decoder
	 * facility.
	 */
	mad_stream_buffer(Stream,InputBuffer,ReadSize+Remaining);
	Stream->error=(mad_error)0;
      }
        
      /* Decode the next MPEG frame. The streams is read from the
       * buffer, its constituents are break down and stored the the
       * Frame structure, ready for examination/alteration or PCM
       * synthesis. Decoding options are carried in the Frame
       * structure from the Stream structure.
       *
       * Error handling: mad_frame_decode() returns a non zero value
       * when an error occurs. The error condition can be checked in
       * the error member of the Stream structure. A mad error is
       * recoverable or fatal, the error status is checked with the
       * MAD_RECOVERABLE macro.
       *
       * {4} When a fatal error is encountered all decoding
       * activities shall be stopped, except when a MAD_ERROR_BUFLEN
       * is signaled. This condition means that the
       * mad_frame_decode() function needs more input to complete
       * its work. One shall refill the buffer and repeat the
       * mad_frame_decode() call. Some bytes may be left unused at
       * the end of the buffer if those bytes forms an incomplete
       * frame. Before refilling, the remaining bytes must be moved
       * to the beginning of the buffer and used for input for the
       * next mad_frame_decode() invocation. (See the comments
       * marked {2} earlier for more details.)
       *
       * Recoverable errors are caused by malformed bit-streams, in
       * this case one can call again mad_frame_decode() in order to
       * skip the faulty part and re-sync to the next frame.
       */
      if(mad_frame_decode(Frame,Stream)) {
	if(MAD_RECOVERABLE(Stream->error)) {
	  /* Do not print a message if the error is a loss of
	   * synchronization and this loss is due to the end of
	   * stream guard bytes. (See the comments marked {3}
	   * supra for more informations about guard bytes.)
	   */
	  if(Stream->error!=MAD_ERROR_LOSTSYNC ||
	     Stream->this_frame!=GuardPtr) {
	  }
	  continue;
	}
	else
	  if(Stream->error==MAD_ERROR_BUFLEN)
	    continue; // end of buffer reached --> read more from the file
	  else {
	    fprintf(stderr,
		    "madaudiofile: unrecoverable frame level error (%i).\n",
		    Stream->error);
	    break;
	  }
      }

        
      if(frame_count == 0) {
	samplerate = Frame->header.samplerate;
#ifdef MADAUDIO_PRINT_DEBUG
	printf("Initially setting samplerate to %i\n",samplerate);
#endif
      }
#ifdef MADAUDIO_PRINT_DEBUG
      if(Frame->header.samplerate != samplerate)
	printf("Obs: samplerate changed to %i!\n",Frame->header.samplerate);
#endif        
      /* Accounting. The computed frame duration is in the frame
       * header structure. It is expressed as a fixed point number
       * whole data type is mad_timer_t. It is different from the
       * samples fixed point format and unlike it, it can't directly
       * be added or subtracted. The timer module provides several
       * functions to operate on such numbers. Be careful there, as
       * some functions of libmad's timer module receive some of
       * their mad_timer_t arguments by value!
       */
      frame_count++;
      mad_timer_add(Timer,Frame->header.duration);
        
      /* Once decoded the frame is synthesized to PCM samples. No errors
       * are reported by mad_synth_frame();
       */
      mad_synth_frame(Synth,Frame);
        
      /* Synthesized samples must be converted from libmad's fixed
       * point number to the consumer format. Here we use unsigned
       * 16 bit big endian integers on two channels. Integer samples
       * are temporarily stored in a buffer that is flushed when
       * full.
       */
      int unsigned sr = 0;
      for(int i=0;i<Synth->pcm.length;i++) {
	signed short    Sample;

	u_int8_t left[2];
	u_int8_t right[2];
	/* Left channel */
	Sample=MadFixedToSshort(Synth->pcm.samples[0][i]);
	left[0]=Sample>>8;
	left[1]=Sample&0xff;
            
	/* Right channel. If the decoded stream is monophonic then
	 * the right output channel is the same as the left one.
	 */
	if(MAD_NCHANNELS(&Frame->header)==2)
	  Sample=MadFixedToSshort(Synth->pcm.samples[1][i]);
	right[0]=Sample>>8;
	right[1]=Sample&0xff;

	while(sr < samplerate) {
	  /* Left channel */
	  *(OutputPtr++)=left[1];
	  *(OutputPtr++)=left[0];
            
	  /* Right channel. If the decoded stream is monophonic then
	   * the right output channel is the same as the left one.
	   */
	  *(OutputPtr++)=right[1];
	  *(OutputPtr++)=right[0];

	  sr += Synth->pcm.samplerate;
	}
	sr -= samplerate;
      }
        
      if (OutputPtr>=OutputBufferEnd+OUTPUT_BUFFER_SAFETY) {
	char cstr[200];
	sprintf(cstr,"getNextAudioFrame() writing outside of OutputBuffer:"
		" %p >= %p VERY BAD!!!\n", OutputPtr,
		OutputBufferEnd+OUTPUT_BUFFER_SAFETY);
	throw(string(cstr));
      }
        
    } // while(OutputPtr < OutputBufferEnd)
    outputLength = OutputPtr-OutputBuffer;
    outputPosition = 0;

    if (outputLength == 0)
      reachedEOF = true;

    // If we have breaked out of the loop, but it wasn't because of EOF,
    // return false.
    if (OutputPtr < OutputBufferEnd && !reachedEOF) 
      return false;

    return true;
#else
    cerr << "libmad not available" << endl;
    return false;
#endif // HAVE_MAD_H
  }
Example #6
0
static int
MP3Callback_22k(void *_buf2, unsigned int numSamples, void *pdata)
{
  int i;
  short *_buf = (short *)_buf2;
  unsigned long samplesOut = 0;

  numSamples /= 2;
  //  Playing , so mix up a buffer
  if (samplesInOutput > 0) 
  {
    if (samplesInOutput > numSamples) {
      write22k_buf((short *) _buf, (short *) OutputBuffer, numSamples * 2);
      samplesOut = numSamples;
      samplesInOutput -= numSamples;
    } else {
      write22k_buf((short *) _buf, (short *) OutputBuffer, samplesInOutput * 2);
      samplesOut = samplesInOutput;
      samplesInOutput = 0;
    }
  }
  while (samplesOut < numSamples) 
  {
    if (Stream.buffer == NULL) {
      Stream.error = 0;
      mad_stream_buffer(&Stream, mp3_data, size);
    }
    if (Stream.error == MAD_ERROR_BUFLEN) {
      Stream.error = 0;
      if (isRepeatMode) {
        MP3_Restart();
        mad_stream_buffer(&Stream, mp3_data, size);
        samplesInOutput = 0;
      } else {
        MP3_Stop();
        return 0;
      }
    }

    if (mad_frame_decode(&Frame, &Stream)) {
      if (MAD_RECOVERABLE(Stream.error)) {
        return 0;
      } else
      if (Stream.error == MAD_ERROR_BUFLEN) {
        if (! isRepeatMode) {
          MP3_Stop();
          return 0;
        }
      } else {
        MP3_Stop();
      }
    }

    FrameCount++;
    mad_timer_add(&Timer, Frame.header.duration);
    mad_synth_frame(&Synth, &Frame);

    for (i = 0; i < Synth.pcm.length; i++) {
      signed short Sample;
      if (samplesOut < numSamples) {
        /* Left channel */
        Sample = MadFixedToSshort(Synth.pcm.samples[0][i]);
        _buf[((samplesOut * 2) * 2)    ] = Sample;
        _buf[((samplesOut * 2) * 2) + 1] = Sample;
     
        /* Right channel. If the decoded stream is monophonic then
         * the right output channel is the same as the left one.
         */
        if (MAD_NCHANNELS(&Frame.header) == 2) {
          Sample = MadFixedToSshort(Synth.pcm.samples[1][i]);
        }
        _buf[(((samplesOut * 2) + 1) * 2)    ] = Sample;
        _buf[(((samplesOut * 2) + 1) * 2) + 1] = Sample;
        samplesOut++;
      } else {
        Sample = MadFixedToSshort(Synth.pcm.samples[0][i]);
        OutputBuffer[samplesInOutput * 2] = Sample;
        if (MAD_NCHANNELS(&Frame.header) == 2) {
          Sample = MadFixedToSshort(Synth.pcm.samples[1][i]);
        }
        OutputBuffer[samplesInOutput * 2 + 1] = Sample;
        samplesInOutput++;
      }
    }
  } 
  
  return isPlaying;
}
bool Mp3AudioFileReader::run(AudioProcessor& processor)
{
    if (file_ == nullptr) {
        return false;
    }

    enum {
        STATUS_OK,
        STATUS_INIT_ERROR,
        STATUS_READ_ERROR,
        STATUS_PROCESS_ERROR
    } status = STATUS_OK;

    unsigned char input_buffer[INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD];
    unsigned char* guard_ptr = nullptr;
    unsigned long frame_count = 0;

    short output_buffer[OUTPUT_BUFFER_SIZE];
    short* output_ptr = output_buffer;
    const short* const output_buffer_end = output_buffer + OUTPUT_BUFFER_SIZE;

    int channels = 0;

    // Decoding options can here be set in the options field of the stream
    // structure.

    // {1} When decoding from a file we need to know when the end of the file is
    // reached at the same time as the last bytes are read (see also the comment
    // marked {3} below). Neither the standard C fread() function nor the POSIX
    // read() system call provides this feature. We thus need to perform our
    // reads through an interface having this feature, this is implemented here
    // by the bstdfile.c module.

    BStdFile bstd_file(file_);

    // Initialize the structures used by libmad.
    MadStream stream;
    MadFrame frame;
    MadSynth synth;

    mad_timer_t timer;
    mad_timer_reset(&timer);

    // This is the decoding loop.

    for (;;) {
        // The input bucket must be filled if it becomes empty or if it's the
        // first execution of the loop.

        if (stream.buffer == nullptr || stream.error == MAD_ERROR_BUFLEN) {
            size_t read_size;
            size_t remaining;
            unsigned char* read_start;

            // {2} libmad may not consume all bytes of the input buffer. If the
            // last frame in the buffer is not wholly contained by it, then that
            // frame's start is pointed by the next_frame member of the stream
            // structure. This common situation occurs when mad_frame_decode()
            // fails, sets the stream error code to MAD_ERROR_BUFLEN, and sets
            // the next_frame pointer to a non-NULL value. (See also the comment
            // marked {4} below.)
            //
            // When this occurs, the remaining unused bytes must be put back at
            // the beginning of the buffer and taken in account before refilling
            // the buffer. This means that the input buffer must be large enough
            // to hold a whole frame at the highest observable bit-rate
            // (currently 448 kb/s). XXX=XXX Is 2016 bytes the size of the
            // largest frame? (448000*(1152/32000))/8

            if (stream.next_frame != nullptr) {
                remaining = stream.bufend - stream.next_frame;
                memmove(input_buffer, stream.next_frame, remaining);
                read_start = input_buffer + remaining;
                read_size  = INPUT_BUFFER_SIZE - remaining;
            }
            else {
                read_size  = INPUT_BUFFER_SIZE;
                read_start = input_buffer;
                remaining = 0;
            }

            // Fill-in the buffer. If an error occurs print a message and leave
            // the decoding loop. If the end of stream is reached we also leave
            // the loop but the return status is left untouched.

            read_size = bstd_file.read(read_start, 1, read_size);

            if (read_size <= 0) {
                if (ferror(file_)) {
                    error_stream << "\nRead error on bit-stream: "
                                 << strerror(errno) << '\n';
                    status = STATUS_READ_ERROR;
                }

                break;
            }

            // {3} When decoding the last frame of a file, it must be followed
            // by MAD_BUFFER_GUARD zero bytes if one wants to decode that last
            // frame. When the end of file is detected we append that quantity
            // of bytes at the end of the available data. Note that the buffer
            // can't overflow as the guard size was allocated but not used the
            // the buffer management code. (See also the comment marked {1}.)
            //
            // In a message to the mad-dev mailing list on May 29th, 2001, Rob
            // Leslie explains the guard zone as follows:
            //
            //    "The reason for MAD_BUFFER_GUARD has to do with the way
            //    decoding is performed. In Layer III, Huffman decoding may
            //    inadvertently read a few bytes beyond the end of the buffer in
            //    the case of certain invalid input. This is not detected until
            //    after the fact. To prevent this from causing problems, and
            //    also to ensure the next frame's main_data_begin pointer is
            //    always accessible, MAD requires MAD_BUFFER_GUARD (currently 8)
            //    bytes to be present in the buffer past the end of the current
            //    frame in order to decode the frame."

            if (bstd_file.eof()) {
                guard_ptr = read_start + read_size;
                memset(guard_ptr, 0, MAD_BUFFER_GUARD);
                read_size += MAD_BUFFER_GUARD;
            }

            // Pipe the new buffer content to libmad's stream decoder facility.
            mad_stream_buffer(&stream, input_buffer, read_size + remaining);
            stream.error = MAD_ERROR_NONE;
        }

        // Decode the next MPEG frame. The streams is read from the buffer, its
        // constituents are break down and stored the the frame structure, ready
        // for examination/alteration or PCM synthesis. Decoding options are
        // carried in the frame structure from the stream structure.
        //
        // Error handling: mad_frame_decode() returns a non zero value when an
        // error occurs. The error condition can be checked in the error member
        // of the stream structure. A mad error is recoverable or fatal, the
        // error status is checked with the MAD_RECOVERABLE macro.
        //
        // {4} When a fatal error is encountered all decoding activities shall
        // be stopped, except when a MAD_ERROR_BUFLEN is signaled. This
        // condition means that the mad_frame_decode() function needs more input
        // to complete its work. One shall refill the buffer and repeat the
        // mad_frame_decode() call. Some bytes may be left unused at the end of
        // the buffer if those bytes forms an incomplete frame. Before
        // refilling, the remaining bytes must be moved to the beginning of the
        // buffer and used for input for the next mad_frame_decode() invocation.
        // (See the comments marked {2} earlier for more details.)
        //
        // Recoverable errors are caused by malformed bit-streams, in this case
        // one can call again mad_frame_decode() in order to skip the faulty
        // part and re-sync to the next frame.

        if (mad_frame_decode(&frame, &stream)) {
            if (MAD_RECOVERABLE(stream.error)) {
                // Do not print a message if the error is a loss of
                // synchronization and this loss is due to the end of stream
                // guard bytes. (See the comment marked {3} above for more
                // information about guard bytes.)

                if (stream.error != MAD_ERROR_LOSTSYNC ||
                    stream.this_frame != guard_ptr) {

                    // For any MP3 file we typically see two errors in the
                    // first frame processed:
                    // - lost synchronization
                    // - reserved header layer value
                    // This seems to be OK, so don't print these

                    if (frame_count != 0) {
                        error_stream << "\nRecoverable frame level error: "
                                     << mad_stream_errorstr(&stream) << '\n';
                    }
                }

                continue;
            }
            else {
                if (stream.error == MAD_ERROR_BUFLEN) {
                    continue;
                }
                else {
                    error_stream << "\nUnrecoverable frame level error: "
                                 << mad_stream_errorstr(&stream) << '\n';
                    status = STATUS_READ_ERROR;
                    break;
                }
            }
        }

        // Display the characteristics of the stream's first frame. The first
        // frame is representative of the entire stream.

        if (frame_count == 0) {
            const int sample_rate = frame.header.samplerate;
            channels = MAD_NCHANNELS(&frame.header);

            dumpInfo(output_stream, frame.header);

            if (!processor.init(sample_rate, channels, OUTPUT_BUFFER_SIZE)) {
                status = STATUS_PROCESS_ERROR;
                break;
            }

            showProgress(0, file_size_);
        }

        // Accounting. The computed frame duration is in the frame header
        // structure. It is expressed as a fixed point number whole data type is
        // mad_timer_t. It is different from the samples fixed point format and
        // unlike it, it can't directly be added or subtracted. The timer module
        // provides several functions to operate on such numbers. Be careful
        // there, as some functions of libmad's timer module receive some of
        // their mad_timer_t arguments by value!

        frame_count++;
        mad_timer_add(&timer, frame.header.duration);

        // Once decoded the frame is synthesized to PCM samples. No errors are
        // reported by mad_synth_frame();

        mad_synth_frame(&synth, &frame);

        // Synthesized samples must be converted from libmad's fixed point
        // number to the consumer format. Here we use signed 16 bit integers on
        // two channels. Integer samples are temporarily stored in a buffer that
        // is flushed when full.

        for (int i = 0; i < synth.pcm.length; i++) {
            // Left channel
            short sample = MadFixedToSshort(synth.pcm.samples[0][i]);

            *output_ptr++ = sample;

            // Right channel. If the decoded stream is monophonic then the right
            // output channel is the same as the left one.

            if (MAD_NCHANNELS(&frame.header) == 2) {
                sample = MadFixedToSshort(synth.pcm.samples[1][i]);
                *output_ptr++ = sample;
            }

            // Flush the output buffer if it is full

            if (output_ptr == output_buffer_end) {
                long pos = ftell(file_);

                showProgress(pos, file_size_);

                bool success = processor.process(
                    output_buffer,
                    OUTPUT_BUFFER_SIZE / channels
                );

                if (!success) {
                    status = STATUS_PROCESS_ERROR;
                    break;
                }

                output_ptr = output_buffer;
            }
        }
    }

    // If the output buffer is not empty and no error occurred during the last
    // write, then flush it.

    if (output_ptr != output_buffer && status != STATUS_PROCESS_ERROR) {
        int buffer_size = static_cast<int>(output_ptr - output_buffer);

        bool success = processor.process(output_buffer, buffer_size / channels);

        if (!success) {
            status = STATUS_PROCESS_ERROR;
        }
    }

    // Accounting report if no error occurred.

    if (status == STATUS_OK) {
        // Report 100% done.
        showProgress(file_size_, file_size_);

        char buffer[80];

        // The duration timer is converted to a human readable string with the
        // versatile, but still constrained mad_timer_string() function, in a
        // fashion not unlike strftime(). The main difference is that the timer
        // is broken into several values according some of its arguments. The
        // units and fracunits arguments specify the intended conversion to be
        // executed.
        //
        // The conversion unit (MAD_UNIT_MINUTES in our example) also specify
        // the order and kind of conversion specifications that can be used in
        // the format string.
        //
        // It is best to examine libmad's timer.c source-code for details of the
        // available units, fraction of units, their meanings, the format
        // arguments, etc.

        mad_timer_string(timer, buffer, "%lu:%02lu.%03u",
            MAD_UNITS_MINUTES, MAD_UNITS_MILLISECONDS, 0);

        output_stream << "\nFrames decoded: " << frame_count
                      << " (" << buffer << ")\n";
    }

    processor.done();

    close();

    return status == STATUS_OK;
}
Example #8
0
/****************************************************************************
 * Main decoding loop. This is where mad is used.							*
 ****************************************************************************/
#define INPUT_BUFFER_SIZE	(5*8192)
#define OUTPUT_BUFFER_SIZE	8192 /* Must be an integer multiple of 4. */
static int MpegAudioDecoder(FILE *InputFp, FILE *OutputFp)
{
	struct mad_stream	Stream;
	struct mad_frame	Frame;
	struct mad_synth	Synth;
	mad_timer_t			Timer;
	unsigned char		InputBuffer[INPUT_BUFFER_SIZE+MAD_BUFFER_GUARD],
						OutputBuffer[OUTPUT_BUFFER_SIZE],
						*OutputPtr=OutputBuffer,
						*GuardPtr=NULL;
	const unsigned char	*OutputBufferEnd=OutputBuffer+OUTPUT_BUFFER_SIZE;
	int					Status=0,
						i;
	unsigned long		FrameCount=0;
	bstdfile_t			*BstdFile;

	/* First the structures used by libmad must be initialized. */
	mad_stream_init(&Stream);
	mad_frame_init(&Frame);
	mad_synth_init(&Synth);
	mad_timer_reset(&Timer);

	/* Decoding options can here be set in the options field of the
	 * Stream structure.
	 */

	/* {1} When decoding from a file we need to know when the end of
	 * the file is reached at the same time as the last bytes are read
	 * (see also the comment marked {3} bellow). Neither the standard
	 * C fread() function nor the POSIX read() system call provides
	 * this feature. We thus need to perform our reads through an
	 * interface having this feature, this is implemented here by the
	 * bstdfile.c module.
	 */
	BstdFile=NewBstdFile(InputFp);
	if(BstdFile==NULL)
	{
		fprintf(stderr,"%s: can't create a new bstdfile_t (%s).\n",
				ProgName,strerror(errno));
		return(1);
	}

	/* This is the decoding loop. */
	do
	{
		/* The input bucket must be filled if it becomes empty or if
		 * it's the first execution of the loop.
		 */
		if(Stream.buffer==NULL || Stream.error==MAD_ERROR_BUFLEN)
		{
			size_t			ReadSize,
							Remaining;
			unsigned char	*ReadStart;

			/* {2} libmad may not consume all bytes of the input
			 * buffer. If the last frame in the buffer is not wholly
			 * contained by it, then that frame's start is pointed by
			 * the next_frame member of the Stream structure. This
			 * common situation occurs when mad_frame_decode() fails,
			 * sets the stream error code to MAD_ERROR_BUFLEN, and
			 * sets the next_frame pointer to a non NULL value. (See
			 * also the comment marked {4} bellow.)
			 *
			 * When this occurs, the remaining unused bytes must be
			 * put back at the beginning of the buffer and taken in
			 * account before refilling the buffer. This means that
			 * the input buffer must be large enough to hold a whole
			 * frame at the highest observable bit-rate (currently 448
			 * kb/s). XXX=XXX Is 2016 bytes the size of the largest
			 * frame? (448000*(1152/32000))/8
			 */
			if(Stream.next_frame!=NULL)
			{
				Remaining=Stream.bufend-Stream.next_frame;
				memmove(InputBuffer,Stream.next_frame,Remaining);
				ReadStart=InputBuffer+Remaining;
				ReadSize=INPUT_BUFFER_SIZE-Remaining;
			}
			else
				ReadSize=INPUT_BUFFER_SIZE,
					ReadStart=InputBuffer,
					Remaining=0;

			/* Fill-in the buffer. If an error occurs print a message
			 * and leave the decoding loop. If the end of stream is
			 * reached we also leave the loop but the return status is
			 * left untouched.
			 */
			ReadSize=BstdRead(ReadStart,1,ReadSize,BstdFile);
			if(ReadSize<=0)
			{
				if(ferror(InputFp))
				{
					fprintf(stderr,"%s: read error on bit-stream (%s)\n",
							ProgName,strerror(errno));
					Status=1;
				}
				if(feof(InputFp))
					fprintf(stderr,"%s: end of input stream\n",ProgName);
				break;
			}

			/* {3} When decoding the last frame of a file, it must be
			 * followed by MAD_BUFFER_GUARD zero bytes if one wants to
			 * decode that last frame. When the end of file is
			 * detected we append that quantity of bytes at the end of
			 * the available data. Note that the buffer can't overflow
			 * as the guard size was allocated but not used the the
			 * buffer management code. (See also the comment marked
			 * {1}.)
			 *
			 * In a message to the mad-dev mailing list on May 29th,
			 * 2001, Rob Leslie explains the guard zone as follows:
			 *
			 *    "The reason for MAD_BUFFER_GUARD has to do with the
			 *    way decoding is performed. In Layer III, Huffman
			 *    decoding may inadvertently read a few bytes beyond
			 *    the end of the buffer in the case of certain invalid
			 *    input. This is not detected until after the fact. To
			 *    prevent this from causing problems, and also to
			 *    ensure the next frame's main_data_begin pointer is
			 *    always accessible, MAD requires MAD_BUFFER_GUARD
			 *    (currently 8) bytes to be present in the buffer past
			 *    the end of the current frame in order to decode the
			 *    frame."
			 */
			if(BstdFileEofP(BstdFile))
			{
				GuardPtr=ReadStart+ReadSize;
				memset(GuardPtr,0,MAD_BUFFER_GUARD);
				ReadSize+=MAD_BUFFER_GUARD;
			}

			/* Pipe the new buffer content to libmad's stream decoder
             * facility.
			 */
			mad_stream_buffer(&Stream,InputBuffer,ReadSize+Remaining);
			Stream.error=0;
		}

		/* Decode the next MPEG frame. The streams is read from the
		 * buffer, its constituents are break down and stored the the
		 * Frame structure, ready for examination/alteration or PCM
		 * synthesis. Decoding options are carried in the Frame
		 * structure from the Stream structure.
		 *
		 * Error handling: mad_frame_decode() returns a non zero value
		 * when an error occurs. The error condition can be checked in
		 * the error member of the Stream structure. A mad error is
		 * recoverable or fatal, the error status is checked with the
		 * MAD_RECOVERABLE macro.
		 *
		 * {4} When a fatal error is encountered all decoding
		 * activities shall be stopped, except when a MAD_ERROR_BUFLEN
		 * is signaled. This condition means that the
		 * mad_frame_decode() function needs more input to complete
		 * its work. One shall refill the buffer and repeat the
		 * mad_frame_decode() call. Some bytes may be left unused at
		 * the end of the buffer if those bytes forms an incomplete
		 * frame. Before refilling, the remaining bytes must be moved
		 * to the beginning of the buffer and used for input for the
		 * next mad_frame_decode() invocation. (See the comments
		 * marked {2} earlier for more details.)
		 *
		 * Recoverable errors are caused by malformed bit-streams, in
		 * this case one can call again mad_frame_decode() in order to
		 * skip the faulty part and re-sync to the next frame.
		 */
		if(mad_frame_decode(&Frame,&Stream))
		{
			if(MAD_RECOVERABLE(Stream.error))
			{
				/* Do not print a message if the error is a loss of
				 * synchronization and this loss is due to the end of
				 * stream guard bytes. (See the comments marked {3}
				 * supra for more informations about guard bytes.)
				 */
				if(Stream.error!=MAD_ERROR_LOSTSYNC ||
				   Stream.this_frame!=GuardPtr)
				{
					fprintf(stderr,"%s: recoverable frame level error (%s)\n",
							ProgName,MadErrorString(&Stream));
					fflush(stderr);
				}
				continue;
			}
			else
				if(Stream.error==MAD_ERROR_BUFLEN)
					continue;
				else
				{
					fprintf(stderr,"%s: unrecoverable frame level error (%s).\n",
							ProgName,MadErrorString(&Stream));
					Status=1;
					break;
				}
		}

		/* The characteristics of the stream's first frame is printed
		 * on stderr. The first frame is representative of the entire
		 * stream.
		 */
		if(FrameCount==0)
			if(PrintFrameInfo(stderr,&Frame.header))
			{
				Status=1;
				break;
			}

		/* Accounting. The computed frame duration is in the frame
		 * header structure. It is expressed as a fixed point number
		 * whole data type is mad_timer_t. It is different from the
		 * samples fixed point format and unlike it, it can't directly
		 * be added or subtracted. The timer module provides several
		 * functions to operate on such numbers. Be careful there, as
		 * some functions of libmad's timer module receive some of
		 * their mad_timer_t arguments by value!
		 */
		FrameCount++;
		mad_timer_add(&Timer,Frame.header.duration);

		/* Between the frame decoding and samples synthesis we can
		 * perform some operations on the audio data. We do this only
		 * if some processing was required. Detailed explanations are
		 * given in the ApplyFilter() function.
		 */
		if(DoFilter)
			ApplyFilter(&Frame);

		/* Once decoded the frame is synthesized to PCM samples. No errors
		 * are reported by mad_synth_frame();
		 */
		mad_synth_frame(&Synth,&Frame);

		/* Synthesized samples must be converted from libmad's fixed
		 * point number to the consumer format. Here we use unsigned
		 * 16 bit big endian integers on two channels. Integer samples
		 * are temporarily stored in a buffer that is flushed when
		 * full.
		 */
		for(i=0;i<Synth.pcm.length;i++)
		{
			signed short	Sample;

			/* Left channel */
			Sample=MadFixedToSshort(Synth.pcm.samples[0][i]);
			*(OutputPtr++)=Sample>>8;
			*(OutputPtr++)=Sample&0xff;

			/* Right channel. If the decoded stream is monophonic then
			 * the right output channel is the same as the left one.
			 */
			if(MAD_NCHANNELS(&Frame.header)==2)
				Sample=MadFixedToSshort(Synth.pcm.samples[1][i]);
			*(OutputPtr++)=Sample>>8;
			*(OutputPtr++)=Sample&0xff;

			/* Flush the output buffer if it is full. */
			if(OutputPtr==OutputBufferEnd)
			{
				if(fwrite(OutputBuffer,1,OUTPUT_BUFFER_SIZE,OutputFp)!=OUTPUT_BUFFER_SIZE)
				{
					fprintf(stderr,"%s: PCM write error (%s).\n",
							ProgName,strerror(errno));
					Status=2;
					break;
				}
				OutputPtr=OutputBuffer;
			}
		}
	}while(1);

	/* The input file was completely read; the memory allocated by our
	 * reading module must be reclaimed.
	 */
	BstdFileDestroy(BstdFile);

	/* Mad is no longer used, the structures that were initialized must
     * now be cleared.
	 */
	mad_synth_finish(&Synth);
	mad_frame_finish(&Frame);
	mad_stream_finish(&Stream);

	/* If the output buffer is not empty and no error occurred during
     * the last write, then flush it.
	 */
	if(OutputPtr!=OutputBuffer && Status!=2)
	{
		size_t	BufferSize=OutputPtr-OutputBuffer;

		if(fwrite(OutputBuffer,1,BufferSize,OutputFp)!=BufferSize)
		{
			fprintf(stderr,"%s: PCM write error (%s).\n",
					ProgName,strerror(errno));
			Status=2;
		}
	}

	/* Accounting report if no error occurred. */
	if(!Status)
	{
		char	Buffer[80];

		/* The duration timer is converted to a human readable string
		 * with the versatile, but still constrained mad_timer_string()
		 * function, in a fashion not unlike strftime(). The main
		 * difference is that the timer is broken into several
		 * values according some of it's arguments. The units and
		 * fracunits arguments specify the intended conversion to be
		 * executed.
		 *
		 * The conversion unit (MAD_UNIT_MINUTES in our example) also
		 * specify the order and kind of conversion specifications
		 * that can be used in the format string.
		 *
		 * It is best to examine libmad's timer.c source-code for details
		 * of the available units, fraction of units, their meanings,
		 * the format arguments, etc.
		 */
		mad_timer_string(Timer,Buffer,"%lu:%02lu.%03u",
						 MAD_UNITS_MINUTES,MAD_UNITS_MILLISECONDS,0);
		fprintf(stderr,"%s: %lu frames decoded (%s).\n",
				ProgName,FrameCount,Buffer);
	}

	/* That's the end of the world (in the H. G. Wells way). */
	return(Status);
}