Exemplo n.º 1
0
static void
mp3_data_init(struct mp3_data *data, struct decoder *decoder,
	      struct input_stream *input_stream)
{
	data->mute_frame = MUTEFRAME_NONE;
	data->highest_frame = 0;
	data->max_frames = 0;
	data->frame_offsets = NULL;
	data->times = NULL;
	data->current_frame = 0;
	data->drop_start_frames = 0;
	data->drop_end_frames = 0;
	data->drop_start_samples = 0;
	data->drop_end_samples = 0;
	data->found_xing = false;
	data->found_first_frame = false;
	data->decoded_first_frame = false;
	data->decoder = decoder;
	data->input_stream = input_stream;
	data->layer = 0;

	mad_stream_init(&data->stream);
	mad_stream_options(&data->stream, MAD_OPTION_IGNORECRC);
	mad_frame_init(&data->frame);
	mad_synth_init(&data->synth);
	mad_timer_reset(&data->timer);
}
Exemplo n.º 2
0
int TrackDuration::duration(const QFileInfo &fileinfo)
{
    QString fn = fileinfo.absoluteFilePath();
    if (fn.isEmpty())
        return 0;

    QFile file(fn);
    if (!file.open(QFile::ReadOnly))
        return 0;

    mad_stream infostream;
    mad_header infoheader;
    mad_timer_t infotimer;
    mad_stream_init(&infostream);
    mad_header_init(&infoheader);
    mad_timer_reset(&infotimer);

    qint64 r;
    qint64 l = 0;
    unsigned char* buf = new unsigned char[INPUT_BUFFER_SIZE];

    while (!file.atEnd()) {
        if (l < INPUT_BUFFER_SIZE) {
            r = file.read(reinterpret_cast<char*>(buf) + l, INPUT_BUFFER_SIZE - l);
            l += r;
        }
        mad_stream_buffer(&infostream, buf, l);
        for (;;) {
            if (mad_header_decode(&infoheader, &infostream)) {
                if (!MAD_RECOVERABLE(infostream.error))
                    break;
                if (infostream.error == MAD_ERROR_LOSTSYNC) {
                    TagLib::ID3v2::Header header;
                    uint size = (uint)(infostream.bufend - infostream.this_frame);
                    if (size >= header.size()) {
                        header.setData(TagLib::ByteVector(reinterpret_cast<const char*>(infostream.this_frame), size));
                        uint tagsize = header.tagSize();
                        if (tagsize > 0) {
                            mad_stream_skip(&infostream, qMin(tagsize, size));
                            continue;
                        }
                    }
                }
                qDebug() << "header decode error while getting file info" << infostream.error;
                continue;
            }
            mad_timer_add(&infotimer, infoheader.duration);
        }
        if (infostream.error != MAD_ERROR_BUFLEN && infostream.error != MAD_ERROR_BUFPTR)
            break;
        memmove(buf, infostream.next_frame, &(buf[l]) - infostream.next_frame);
        l -= (infostream.next_frame - buf);
    }

    mad_stream_finish(&infostream);
    mad_header_finish(&infoheader);
    delete[] buf;

    return timerToMs(&infotimer);
}
Exemplo n.º 3
0
    size_t MadDecoder::start(FILE* handle)
    {
        handle_ = handle;

        decodeBuffer_.resize(bufferSize_, false);
        ASSERT(decodeBuffer_.size() == bufferSize_);
        unsigned char* buffer = decodeBuffer_.getHead();

        int64 durationMsec = getDurationMs(buffer, bufferSize_);

        mad_stream_init(&madStream_);
        mad_frame_init(&madFrame_);
        mad_synth_init(&madSynth_);
        mad_timer_reset(&madTimer_);

        // Decode at least one valid frame to find out the input format.
        // The decoded frame will be saved off so that it can be processed later.
        //
        size_t bytesRead = fread(buffer, (size_t)1, bufferSize_, handle_);
        if (bytesRead != bufferSize_ && ferror(handle_))
            THROW(std::exception, "%s", strerror(errno));
        mad_stream_buffer(&madStream_, buffer, bytesRead);

        // Find a valid frame before starting up.
        // This make sure that we have a valid MP3 
        // and also skips past ID3v2 tags at the beginning of the audio file.
        //
        madStream_.error = MAD_ERROR_NONE;
        while (mad_frame_decode(&madFrame_, &madStream_))
        {
            // check whether input buffer needs a refill 
            if (madStream_.error == MAD_ERROR_BUFLEN) {

                if (readMpgFile() == false) break;              // eof
                else continue;
            }
            consumeId3Tag();    // consume any ID3 tags

            // FIXME: We should probably detect when we've read
            // a bunch of non-ID3 data and still haven't found a
            // frame.  In that case we can abort early without
            // scanning the whole file.
            //
            madStream_.error = MAD_ERROR_NONE;
        }

        if (madStream_.error) {
            THROW(std::exception, "No valid MP3 frame found");
        }

        mad_timer_add(&madTimer_, madFrame_.header.duration);
        mad_synth_frame(&madSynth_, &madFrame_);

        //unsigned int precision_ = 16;
        currentFrame_ = 0;
        numMpegFrames_ = 0;
        initialized_ = true;

        return (size_t)(durationMsec * .001 * getSampleRate() + .5);  // number of sample frames
    }
Exemplo n.º 4
0
static void
init_mad_decoder (mp3d_prc_t * ap_prc)
{
  assert (ap_prc);
  mad_stream_init (&ap_prc->stream_);
  mad_frame_init (&ap_prc->frame_);
  mad_synth_init (&ap_prc->synth_);
  mad_timer_reset (&ap_prc->timer_);
}
Exemplo n.º 5
0
void mpgDecoder::reset( )
{
#ifdef HAVE_MAD
	madFile->reset();
    mad_timer_reset( currentPositionTimer );
	mad_stream_init( madStream );
	mad_frame_init( madFrame );
	frameCounter = 0;
#endif
}
Exemplo n.º 6
0
void XMp3Decomp::initMad()
{
	finishMad();
	m_isInitMad = true;
	m_firstBuf = true;
	mad_stream_init(&Stream);
	mad_frame_init(&Frame);
	mad_synth_init(&Synth);
	mad_timer_reset(&Timer);
}
Exemplo n.º 7
0
static void
MP3_Restart()
{
  memset(OutputBuffer, 0, OUTPUT_BUFFER_SIZE);
  samplesInOutput = 0;

  mad_stream_init(&Stream);
  mad_frame_init(&Frame);
  mad_synth_init(&Synth);
  mad_timer_reset(&Timer);
  MP3_getInfo();
}
Exemplo n.º 8
0
void MP3_Init()
{
# ifndef LINUX_MODE
    samplesInOutput = 0;
    isPlaying = 0;
    /* 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);
# endif
}
Exemplo n.º 9
0
static void mp3_init (mp3_s *mp3)
{
  mp3->out_ptr = mp3->out_buf;
  mp3->out_buf_end = mp3->out_buf + BUF_SIZE;
  mp3->frame_count = 0;
  mp3->status = 0;
  mp3->start = 0;
  mad_stream_init (&mp3->stream);
  mad_frame_init (&mp3->frame);
  mad_synth_init (&mp3->synth);
  mad_timer_reset (&mp3->timer);
}
Exemplo n.º 10
0
Mp3Decoder::Mp3Decoder(const u8 * snd, int len)
    : SoundDecoder(snd, len)
{
    SoundType = SOUND_MP3;
    ReadBuffer = NULL;
    mad_timer_reset(&Timer);
    mad_stream_init(&Stream);
    mad_frame_init(&Frame);
    mad_synth_init(&Synth);

    if(!file_fd)
        return;

    OpenFile();
}
Exemplo n.º 11
0
int Mp3Decoder::Rewind()
{
    mad_synth_finish(&Synth);
    mad_frame_finish(&Frame);
    mad_stream_finish(&Stream);
    mad_timer_reset(&Timer);
    mad_stream_init(&Stream);
    mad_frame_init(&Frame);
    mad_synth_init(&Synth);
    SynthPos = 0;
    GuardPtr = NULL;

    if(!file_fd)
        return -1;

    return SoundDecoder::Rewind();
}
Exemplo n.º 12
0
int Init(int channel) {
	pspAudioInit();											// init the audio psp

	mad_stream_init(&stream);								// create the mad variables, streams etc.
	mad_frame_init(&frame); 
	mad_synth_init(&synth); 
	mad_timer_reset(&timer);
	pspAudioSetChannelCallback(channel, fillOutputBuffer, 0);		// set the callback to the function.
	mutex = sceKernelCreateSema("myMutexName", 0, 1, 1, 0);	// create the mutex for threading secure.
	pausesong = 1;											// set the variable to pause so no sound is played.
	started = 0;											// the mp3 has not yet started.
	file = 0;												// set the file to zero
	fileSize = 1;
	filePos = 0;
	printf("MusicEngine is initialized.\n");

	return 1;
};
RageSoundReader_MP3::RageSoundReader_MP3()
{
	mad = new madlib_t;
	m_bAccurateSync = false;

	mad_stream_init( &mad->Stream );
	mad_frame_init( &mad->Frame );
	mad_synth_init( &mad->Synth );

	mad_frame_mute( &mad->Frame );
	mad_timer_reset( &mad->Timer );
	mad->length = -1;
	mad->inbuf_filepos = 0;
	mad->header_bytes = 0;
	mad->has_xing = false;
	mad->timer_accurate = 1;
	mad->bitrate = -1;
	mad->first_frame = true;
}
Exemplo n.º 14
0
mad_data *
mad_openFileRW(SDL_RWops *rw, SDL_AudioSpec *mixer) {
  mad_data *mp3_mad;

  mp3_mad = (mad_data *)malloc(sizeof(mad_data));
  mp3_mad->rw = rw;
  mad_stream_init(&mp3_mad->stream);
  mad_frame_init(&mp3_mad->frame);
  mad_synth_init(&mp3_mad->synth);
  mp3_mad->frames_read = 0;
  mad_timer_reset(&mp3_mad->next_frame_start);
  mp3_mad->volume = 128;
  mp3_mad->status = 0;
  mp3_mad->output_begin = 0;
  mp3_mad->output_end = 0;
  mp3_mad->mixer = *mixer;

  return mp3_mad;
}
Exemplo n.º 15
0
mpgDecoder::mpgDecoder(FILE* File, QObject *parent )
 : fileDecoder(File, parent )
{
	// use QFile as input Buffer, which is needed by libMad, cause it cannot detect EOF....
	madFile = new QFile();
        madFile->open(fHandle, QIODevice::ReadOnly);

    // current position timer needs to be initialized first as its set in scanFile()
    endPositionTimer = new mad_timer_t;

	scanFile();
#ifdef HAVE_MAD
	// Allocate Memory for the MAD decoder Library
	madStream = new mad_stream;
	madFrame = new mad_frame;
	madSynth = new mad_synth;
    currentPositionTimer = new mad_timer_t;
    mad_inputBuffer = new unsigned char[163840+MAD_BUFFER_GUARD];
        memset(mad_inputBuffer,0 , 163840+MAD_BUFFER_GUARD);

	// Initiate libMad structs
	mad_stream_init( madStream );
	mad_frame_init( madFrame );
	mad_synth_init( madSynth );
    mad_timer_reset( currentPositionTimer );
#endif

	//allocate decoder output ringbuffers
	mad_outputBuffer = new soundRingBuffer[2];
	mad_outputBuffer[0].setName("mad_output1");
	mad_outputBuffer[1].setName("mad_output2");
	returnBuffer = new float*[2];
	returnBuffer[0] = new float[8192];
	returnBuffer[1] = new float[8192];
        memset(returnBuffer[0], 0, 8192*sizeof(float));
        memset(returnBuffer[1], 0, 8192*sizeof(float));

	frameCounter=0;
}
Exemplo n.º 16
0
mad_data *
mad_openFileRW(SDL_RWops *src, SDL_AudioSpec *mixer, int freesrc)
{
  mad_data *mp3_mad;

  mp3_mad = (mad_data *)SDL_malloc(sizeof(mad_data));
  if (mp3_mad) {
    mp3_mad->src = src;
    mp3_mad->freesrc = freesrc;
    mad_stream_init(&mp3_mad->stream);
    mad_frame_init(&mp3_mad->frame);
    mad_synth_init(&mp3_mad->synth);
    mp3_mad->frames_read = 0;
    mad_timer_reset(&mp3_mad->next_frame_start);
    mp3_mad->volume = MIX_MAX_VOLUME;
    mp3_mad->status = 0;
    mp3_mad->output_begin = 0;
    mp3_mad->output_end = 0;
    mp3_mad->mixer = *mixer;
  }
  return mp3_mad;
}
Exemplo n.º 17
0
int madx_init ( unsigned char *out_buffer, madx_house *mxhouse  )
{
	

	
	// Initialize libmad structures 
	mad_stream_init(&mxhouse->stream);
	mad_frame_init(&mxhouse->frame);
	mad_synth_init(&mxhouse->synth);
	mad_timer_reset(&mxhouse->timer);	


	// Assign pointer to output buffer. "output_ptr"
	// is used to determine when to flush the output 
	// buffer in madx_read().

	mxhouse->output_ptr = out_buffer;


	return(1);

	
}
bool RageSoundReader_MP3::MADLIB_rewind()
{
	m_pFile->Seek(0);
			
	mad_frame_mute(&mad->Frame);
	mad_synth_mute(&mad->Synth);
	mad_timer_reset(&mad->Timer);
	mad->outpos = mad->outleft = 0;

	mad_stream_finish(&mad->Stream);
	mad_stream_init(&mad->Stream);
	mad_stream_buffer(&mad->Stream, NULL, 0);
	mad->inbuf_filepos = 0;

	/* Be careful.  We need to leave header_bytes alone, so if we try to SetPosition_estimate
	 * immediately after this, we still know the header size.  However, we need to set first_frame
	 * to true, since the first frame is handled specially in do_mad_frame_decode; if we don't
	 * set it, then we'll be desynced by a frame after an accurate seek. */
//	mad->header_bytes = 0;
	mad->first_frame = true;
	mad->Stream.this_frame = NULL;

	return true;
}
Exemplo n.º 19
0
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;
}
Exemplo n.º 20
0
  /* scale */
  return output >> scalebits;
}

#define INPUT_BUFFER_SIZE  (5*8192)
#define OUTPUT_BUFFER_SIZE  8192 /* Must be an integer multiple of 4. */
void real_mpeg_play(char* fname)
{
    unsigned char InputBuffer[INPUT_BUFFER_SIZE],
        OutputBuffer[OUTPUT_BUFFER_SIZE],
        *OutputPtr=OutputBuffer;
    const unsigned char  *OutputBufferEnd=OutputBuffer+OUTPUT_BUFFER_SIZE;
    int Status=0, i, fd;
    unsigned long FrameCount=0;
    sound_t sound;
    struct mp3entry mp3;
    static struct dither d0, d1;
    int key=0;
  
    mp3info(&mp3, fname, false); /* FIXME: honor the v1first setting */

    init_sound(&sound);

    /* Configure sound device for this file - always select Stereo because
       some sound cards don't support mono */
    config_sound(&sound,mp3.frequency,2);

    if ((fd=open(fname,O_RDONLY)) < 0) {
        fprintf(stderr,"could not open %s\n",fname);
        return;
    }

    /* 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);

    do {
        if (Stream.buffer==NULL || Stream.error==MAD_ERROR_BUFLEN) {
            size_t ReadSize,Remaining;
            unsigned char *ReadStart;

            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;
            }

            if ((int)(ReadSize=read(fd,ReadStart,ReadSize)) < 0) {
                fprintf(stderr,"end of input stream\n");
                break;
            }

            mad_stream_buffer(&Stream,InputBuffer,ReadSize+Remaining);
            Stream.error=0;
        }

        if(mad_frame_decode(&Frame,&Stream)) {
            if(MAD_RECOVERABLE(Stream.error)) {
                fprintf(stderr,"recoverable frame level error\n");
                fflush(stderr);
                continue;
            } else {
                if(Stream.error==MAD_ERROR_BUFLEN) {
                    continue;
                } else {
                    fprintf(stderr,"unrecoverable frame level error\n");
                    Status=1;
                    break;
                }
            }
        }

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

        for(i=0;i<Synth.pcm.length;i++) {
            unsigned short  Sample;
            
            /* Left channel */
            Sample=scale(Synth.pcm.samples[0][i],&d0);
            *(OutputPtr++)=Sample&0xff;
            *(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(&Frame.header)==2) {
                Sample=scale(Synth.pcm.samples[1][i],&d1);
            }

            *(OutputPtr++)=Sample&0xff;
            *(OutputPtr++)=Sample>>8;
            
            /* Flush the buffer if it is full. */
            if (OutputPtr==OutputBufferEnd) {
                if (output_sound(&sound, OutputBuffer,
                                 OUTPUT_BUFFER_SIZE)!=OUTPUT_BUFFER_SIZE) {
                    fprintf(stderr,"PCM write error.\n");
                    Status=2;
                    break;
                }
                OutputPtr=OutputBuffer;
            }
            }

        if ((key=button_get(0))==BUTTON_STOP)
	{
            break; 
	}

    }while(1);
    
    /* 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 occured during
     * the last write, then flush it. */
    if(OutputPtr!=OutputBuffer && Status!=2)
        {
            size_t  BufferSize=OutputPtr-OutputBuffer;

            if (output_sound(&sound, OutputPtr, BufferSize)!=(int)BufferSize)
                {
                    fprintf(stderr,"PCM write error\n");
                    Status=2;
                }
        }

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

            mad_timer_string(Timer,Buffer,"%lu:%02lu.%03u",
                             MAD_UNITS_MINUTES,MAD_UNITS_MILLISECONDS,0);
            fprintf(stderr,"%lu frames decoded (%s).\n",FrameCount,Buffer);
        }

    close_sound(&sound);
    /* That's the end of the world (in the H. G. Wells way). */
    return;
}
Exemplo n.º 21
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);
}
Exemplo n.º 22
0
static int startread(sox_format_t * ft)
{
  priv_t *p = (priv_t *) ft->priv;
  size_t ReadSize;
  sox_bool ignore_length = ft->signal.length == SOX_IGNORE_LENGTH;
  int open_library_result;

  LSX_DLLIBRARY_OPEN(
      p,
      mad_dl,
      MAD_FUNC_ENTRIES,
      "MAD decoder library",
      mad_library_names,
      open_library_result);
  if (open_library_result)
    return SOX_EOF;

  p->mp3_buffer_size = sox_globals.bufsiz;
  p->mp3_buffer = lsx_malloc(p->mp3_buffer_size);

  ft->signal.length = SOX_UNSPEC;
  if (ft->seekable) {
#ifdef USING_ID3TAG
    read_comments(ft);
    rewind((FILE*)ft->fp);
    if (!ft->signal.length)
#endif
      if (!ignore_length)
        ft->signal.length = mp3_duration_ms(ft);
  }

  p->mad_stream_init(&p->Stream);
  p->mad_frame_init(&p->Frame);
  p->mad_synth_init(&p->Synth);
  mad_timer_reset(&p->Timer);

  ft->encoding.encoding = SOX_ENCODING_MP3;

  /* Decode at least one valid frame to find out the input
   * format.  The decoded frame will be saved off so that it
   * can be processed later.
   */
  ReadSize = lsx_readbuf(ft, p->mp3_buffer, p->mp3_buffer_size);
  if (ReadSize != p->mp3_buffer_size && ferror((FILE*)ft->fp))
    return SOX_EOF;

  p->mad_stream_buffer(&p->Stream, p->mp3_buffer, ReadSize);

  /* Find a valid frame before starting up.  This makes sure
   * that we have a valid MP3 and also skips past ID3v2 tags
   * at the beginning of the audio file.
   */
  p->Stream.error = 0;
  while (p->mad_frame_decode(&p->Frame,&p->Stream))
  {
      /* check whether input buffer needs a refill */
      if (p->Stream.error == MAD_ERROR_BUFLEN)
      {
          if (sox_mp3_input(ft) == SOX_EOF)
              return SOX_EOF;

          continue;
      }

      /* Consume any ID3 tags */
      sox_mp3_inputtag(ft);

      /* FIXME: We should probably detect when we've read
       * a bunch of non-ID3 data and still haven't found a
       * frame.  In that case we can abort early without
       * scanning the whole file.
       */
      p->Stream.error = 0;
  }

  if (p->Stream.error)
  {
      lsx_fail_errno(ft,SOX_EOF,"No valid MP3 frame found");
      return SOX_EOF;
  }

  switch(p->Frame.header.mode)
  {
      case MAD_MODE_SINGLE_CHANNEL:
      case MAD_MODE_DUAL_CHANNEL:
      case MAD_MODE_JOINT_STEREO:
      case MAD_MODE_STEREO:
          ft->signal.channels = MAD_NCHANNELS(&p->Frame.header);
          break;
      default:
          lsx_fail_errno(ft, SOX_EFMT, "Cannot determine number of channels");
          return SOX_EOF;
  }

  p->FrameCount=1;

  p->mad_timer_add(&p->Timer,p->Frame.header.duration);
  p->mad_synth_frame(&p->Synth,&p->Frame);
  ft->signal.precision = MP3_MAD_PRECISION;
  ft->signal.rate=p->Synth.pcm.samplerate;
  if (ignore_length)
    ft->signal.length = SOX_UNSPEC;
  else {
    ft->signal.length = (uint64_t)(ft->signal.length * .001 * ft->signal.rate + .5);
    ft->signal.length *= ft->signal.channels;  /* Keep separate from line above! */
  }

  p->cursamp = 0;

  return SOX_SUCCESS;
}
Exemplo n.º 23
0
static int sox_mp3seek(sox_format_t * ft, uint64_t offset)
{
  priv_t   * p = (priv_t *) ft->priv;
  size_t   initial_bitrate = p->Frame.header.bitrate;
  size_t   tagsize = 0, consumed = 0;
  sox_bool vbr = sox_false; /* Variable Bit Rate */
  sox_bool depadded = sox_false;
  uint64_t to_skip_samples = 0;

  /* Reset all */
  rewind((FILE*)ft->fp);
  mad_timer_reset(&p->Timer);
  p->FrameCount = 0;

  /* They where opened in startread */
  mad_synth_finish(&p->Synth);
  p->mad_frame_finish(&p->Frame);
  p->mad_stream_finish(&p->Stream);

  p->mad_stream_init(&p->Stream);
  p->mad_frame_init(&p->Frame);
  p->mad_synth_init(&p->Synth);

  offset /= ft->signal.channels;
  to_skip_samples = offset;

  while(sox_true) {  /* Read data from the MP3 file */
    int read, padding = 0;
    size_t leftover = p->Stream.bufend - p->Stream.next_frame;

    memcpy(p->mp3_buffer, p->Stream.this_frame, leftover);
    read = fread(p->mp3_buffer + leftover, (size_t) 1, p->mp3_buffer_size - leftover, (FILE*)ft->fp);
    if (read <= 0) {
      lsx_debug("seek failure. unexpected EOF (frames=%" PRIuPTR " leftover=%" PRIuPTR ")", p->FrameCount, leftover);
      break;
    }
    for (; !depadded && padding < read && !p->mp3_buffer[padding]; ++padding);
    depadded = sox_true;
    p->mad_stream_buffer(&p->Stream, p->mp3_buffer + padding, leftover + read - padding);

    while (sox_true) {  /* Decode frame headers */
      static unsigned short samples;
      p->Stream.error = MAD_ERROR_NONE;

      /* Not an audio frame */
      if (p->mad_header_decode(&p->Frame.header, &p->Stream) == -1) {
        if (p->Stream.error == MAD_ERROR_BUFLEN)
          break;  /* Normal behaviour; get some more data from the file */
        if (!MAD_RECOVERABLE(p->Stream.error)) {
          lsx_warn("unrecoverable MAD error");
          break;
        }
        if (p->Stream.error == MAD_ERROR_LOSTSYNC) {
          unsigned available = (p->Stream.bufend - p->Stream.this_frame);
          tagsize = tagtype(p->Stream.this_frame, (size_t) available);
          if (tagsize) {   /* It's some ID3 tags, so just skip */
            if (tagsize >= available) {
              fseeko((FILE*)ft->fp, (off_t)(tagsize - available), SEEK_CUR);
              depadded = sox_false;
            }
            p->mad_stream_skip(&p->Stream, min(tagsize, available));
          }
          else lsx_warn("MAD lost sync");
        }
        else lsx_warn("recoverable MAD error");
        continue;
      }

      consumed += p->Stream.next_frame - p->Stream.this_frame;
      vbr      |= (p->Frame.header.bitrate != initial_bitrate);

      samples = 32 * MAD_NSBSAMPLES(&p->Frame.header);

      p->FrameCount++;
      p->mad_timer_add(&p->Timer, p->Frame.header.duration);

      if(to_skip_samples <= samples)
      {
        p->mad_frame_decode(&p->Frame,&p->Stream);
        p->mad_synth_frame(&p->Synth, &p->Frame);
        p->cursamp = to_skip_samples;
        return SOX_SUCCESS;
      }
      else to_skip_samples -= samples;

      /* If not VBR, we can extrapolate frame size */
      if (p->FrameCount == 64 && !vbr) {
        p->FrameCount = offset / samples;
        to_skip_samples = offset % samples;

        if (SOX_SUCCESS != lsx_seeki(ft, (off_t)(p->FrameCount * consumed / 64 + tagsize), SEEK_SET))
          return SOX_EOF;

        /* Reset Stream for refilling buffer */
        p->mad_stream_finish(&p->Stream);
        p->mad_stream_init(&p->Stream);
        break;
      }
    }
  };

  return SOX_EOF;
}
Exemplo n.º 24
0
// the following function has been copied from XMMS' mad input plugin
// Copyright (C) 2001-2002 Sam Clegg
void mpgDecoder::scanFile( )
{
#ifdef HAVE_MAD
  mad_stream scanStream;
  mad_header scanHeader;
  int remainder = 0;
  int data_used = 0;
  int pos = 0;
  unsigned char buffer[4096];

  // reset file, so we can read from the beginning
  madFile->reset();
  mad_timer_reset( endPositionTimer );

  mad_stream_init (&scanStream);
  mad_header_init (&scanHeader);
  while (1)
    {
      remainder = scanStream.bufend - scanStream.next_frame;
      memcpy (buffer, scanStream.this_frame, remainder);
	// get some more Byte from File...
	int readCnt = 0;
	unsigned char* readStart;
	readStart = buffer+remainder;
	while( !madFile->atEnd() && readCnt < (4096 - remainder) )
	{
                readStart[readCnt] = madFile->read(1).at(0);
		readCnt++;
	}

      if (madFile->atEnd())
	break;

      mad_stream_buffer (&scanStream, buffer, readCnt + remainder);

      while (1)
        {
	  if (mad_header_decode (&scanHeader, &scanStream) == -1)
	    {
	      if (scanStream.error == MAD_ERROR_BUFLEN)
		{
		  break;
		}
	      if (!MAD_RECOVERABLE (scanStream.error))
		{
		  break;
		}
	      continue;
	    }
	  pos++;
	  data_used += scanStream.next_frame - scanStream.this_frame;
      mad_timer_add( endPositionTimer, scanHeader.duration );
	  if (pos == 1)
	    {
          sampleRate = scanHeader.samplerate;
	      channels = MAD_NCHANNELS(&scanHeader);
	    }
	}
      if (scanStream.error != MAD_ERROR_BUFLEN)
	break;
    }

  mad_header_finish (&scanHeader);
  mad_stream_finish (&scanStream);

  // reset the file again, so we can read from the beginning when playing
  madFile->reset();
#endif
}
Exemplo n.º 25
0
static void 
MP3_getInfo()
{
    int FrameCount = 0;
    struct mad_stream stream;
    struct mad_header header; 
    mad_stream_init (&stream);
    mad_header_init (&header);

    MP3_info.fileSize = size;
    mad_timer_reset(&MP3_info.length);
    mad_stream_buffer (&stream, mp3_data, size);
    while (1){
        if (mad_header_decode (&header, &stream) == -1){
            if (MAD_RECOVERABLE(stream.error)){
                continue;                
            }else{
                break;
            }
        }
        //Informazioni solo dal primo frame:
        if (FrameCount == 0){
            switch (header.layer) {
            case MAD_LAYER_I:
                strcpy(MP3_info.layer,"I");
                break;
            case MAD_LAYER_II:
                strcpy(MP3_info.layer,"II");
                break;
            case MAD_LAYER_III:
                strcpy(MP3_info.layer,"III");
                break;
            default:
                strcpy(MP3_info.layer,"unknown");
                break;
            }

            MP3_info.kbit = header.bitrate / 1000;
            MP3_info.hz = header.samplerate;
            switch (header.mode) {
            case MAD_MODE_SINGLE_CHANNEL:
                strcpy(MP3_info.mode, "single channel");
                break;
            case MAD_MODE_DUAL_CHANNEL:
                strcpy(MP3_info.mode, "dual channel");
                break;
            case MAD_MODE_JOINT_STEREO:
                strcpy(MP3_info.mode, "joint (MS/intensity) stereo");
                break;
            case MAD_MODE_STEREO:
                strcpy(MP3_info.mode, "normal LR stereo");
                break;
            default:
                strcpy(MP3_info.mode, "unknown");
                break;
            }

            switch (header.emphasis) {
            case MAD_EMPHASIS_NONE:
                strcpy(MP3_info.emphasis,"no");
                break;
            case MAD_EMPHASIS_50_15_US:
                strcpy(MP3_info.emphasis,"50/15 us");
                break;
            case MAD_EMPHASIS_CCITT_J_17:
                strcpy(MP3_info.emphasis,"CCITT J.17");
                break;
            case MAD_EMPHASIS_RESERVED:
                strcpy(MP3_info.emphasis,"reserved(!)");
                break;
            default:
                strcpy(MP3_info.emphasis,"unknown");
                break;
            }            
        }
        FrameCount++;
        mad_timer_add (&MP3_info.length, header.duration);
    }
    mad_header_finish (&header);
    mad_stream_finish (&stream);

    MP3_info.frames = FrameCount;
    mad_timer_string(MP3_info.length, MP3_info.strLength, "%02lu:%02u:%02u", MAD_UNITS_HOURS, MAD_UNITS_MILLISECONDS, 0);
}
Exemplo n.º 26
0
Arquivo: mp3.c Projeto: 173210/mvspsp
static void MP3Update(void)
{
	int flip;
	UINT8 *GuardPtr;
	INT16 *OutputPtr, *OutputEnd;
	struct mad_stream Stream;
	struct mad_frame Frame;
	struct mad_synth Synth;
	mad_timer_t Timer;

	mad_stream_init(&Stream);
	mad_frame_init(&Frame);
	mad_synth_init(&Synth);
	mad_timer_reset(&Timer);

	OutputPtr = (INT16 *)mp3_out[0];
	OutputEnd = (INT16 *)(mp3_out[0] + MP3_BUFFER_SIZE);
	GuardPtr = NULL;

	mp3_filepos = 0;
	mp3_frame = 0;
	flip = 0;
	cdda_command_ack = 1;

	while (mp3_active && mp3_status != MP3_STOP)
	{
		if (Stream.buffer == NULL || Stream.error == MAD_ERROR_BUFLEN)
		{
			UINT32 ReadSize, Remaining;
			UINT8 *ReadStart;

			if (Stream.next_frame != NULL)
			{
				Remaining = Stream.bufend - Stream.next_frame;
				ReadStart = mp3_in + Remaining;
				ReadSize  = (2 * MP3_BUFFER_SIZE) - Remaining;
				memmove(mp3_in, Stream.next_frame, Remaining);
			}
			else
			{
				ReadSize  = 2 * MP3_BUFFER_SIZE;
				ReadStart = mp3_in;
				Remaining = 0;
			}

			if (MP3SleepCheck()) break;

			ReadSize = sceIoRead(mp3_fd, ReadStart, ReadSize);
			mp3_filepos += ReadSize;
			if (mp3_filepos == mp3_fsize)
			{
				if (cdda_autoloop)
				{
					mp3_filepos = 0;
					sceIoLseek(mp3_fd, 0, PSP_SEEK_SET);
				}
				else
				{
					cdda_playing = CDDA_STOP;
					mp3_status = MP3_STOP;
				}
			}

			if (mp3_filepos == mp3_fsize)
			{
				GuardPtr = ReadStart + ReadSize;
				memset(GuardPtr, 0, MAD_BUFFER_GUARD);
				ReadSize += MAD_BUFFER_GUARD;
			}

			mad_stream_buffer(&Stream, mp3_in, ReadSize + Remaining);

			Stream.error = 0;
		}

		if (mad_frame_decode(&Frame, &Stream))
		{
			if (MAD_RECOVERABLE(Stream.error))
			{
//				if (Stream.error != MAD_ERROR_LOSTSYNC || Stream.this_frame != GuardPtr)
				continue;
			}
			else if (Stream.error == MAD_ERROR_BUFLEN)
			{
				continue;
			}
			else
			{
				ui_popup(TEXT(MP3_DECODE_ERROR));
				mp3_status = MP3_STOP;
				break;
			}
		}

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

		if (mp3_status == MP3_PLAY)
		{
			int i;

			for (i = 0; i < Synth.pcm.length; i++)
			{
				if (MAD_NCHANNELS(&Frame.header) == 2)
				{
					*OutputPtr++ = MP3Limit(Synth.pcm.samples[0][i]);
					*OutputPtr++ = MP3Limit(Synth.pcm.samples[1][i]);
				}
				else
				{
					INT16 data = MP3Limit(Synth.pcm.samples[0][i]);

					*OutputPtr++ = data;
					*OutputPtr++ = data;
				}

				if (OutputPtr == OutputEnd)
				{
					sceAudioOutputPannedBlocking(mp3_handle, mp3_volume, mp3_volume, mp3_out[flip]);
					flip ^= 1;
					OutputPtr = (INT16 *)mp3_out[flip];
					OutputEnd = (INT16 *)(mp3_out[flip] + MP3_BUFFER_SIZE);
				}
			}
		}
		else if (mp3_status == MP3_SEEK)
		{
			if (mp3_frame >= mp3_start_frame)
			{
				mp3_start_frame = 0;
				mp3_status = MP3_SLEEP;
				sceKernelSleepThread();
			}
		}
	}

	mad_synth_finish(&Synth);
	mad_frame_finish(&Frame);
	mad_stream_finish(&Stream);

	if (mp3_fd >= 0)
	{
		sceIoClose(mp3_fd);
		mp3_fd = -1;
	}
}
Exemplo n.º 27
0
Arquivo: mpg321.c Projeto: e3c/mpg321
int main(int argc, char *argv[])
{
    int fd = 0;
    char *currentfile, old_dir[PATH_MAX];
    playlist *pl = NULL;
    struct id3_file *id3struct = NULL;
    struct id3_tag *id3tag = NULL;

    buffer playbuf;
    
    struct mad_decoder decoder;

    old_dir[0] = '\0';

    playbuf.pl = pl = new_playlist();

    if (!pl)
    {
        fprintf(stderr, "malloc failed at startup!\n");
        exit(1);
    }

    options.volume = MAD_F_ONE;

    status = MPG321_PLAYING;
    
    /* Get the command line options */
    parse_options(argc, argv, pl);

    /* If there were no files and no playlist specified just print the usage */
    if (!playlist_file && optind == argc)
    {
        usage(argv[0]);
        exit(0);
    }

    if (playlist_file)
        load_playlist(pl, playlist_file);
    
    add_cmdline_files(pl, argv);

    if (shuffle_play)
        shuffle_files(pl);

    ao_initialize();

    check_default_play_device();
    
    if (!(options.opt & MPG321_REMOTE_PLAY))
    {
        handle_signals(-1); /* initialize signal handler */
     
        remote_input_buf[0] = '\0';
    }
    
    if (!(options.opt & MPG321_QUIET_PLAY)) 
        mpg123_boilerplate();
    
    if (options.opt & MPG321_REMOTE_PLAY)
    {
        printf ("@R MPG123\n");
    }
    
    /* Play the mpeg files or zip it! */
    while((currentfile = get_next_file(pl, &playbuf)))
    {
        if (quit_now) 
            break;
        
        signal(SIGINT, SIG_DFL);
        
        playbuf.buf = NULL;
        playbuf.fd = -1;
        playbuf.length = 0;
        playbuf.done = 0;
        playbuf.num_frames = 0;
        playbuf.max_frames = -1;
        strncpy(playbuf.filename,currentfile, PATH_MAX);
        playbuf.filename[PATH_MAX-1] = '\0';
        
        if (status == MPG321_PLAYING) 
            file_change = 1;

        mad_timer_reset(&playbuf.duration);
        
        mad_timer_reset(&current_time);

        if (!(options.opt & MPG321_QUIET_PLAY) && file_change)
        {
            id3struct = id3_file_open (currentfile, ID3_FILE_MODE_READONLY);

            if (id3struct)
            {
                id3tag = id3_file_tag (id3struct);
            
                if (id3tag)
                {
                    show_id3 (id3tag);
                }

                id3_file_close (id3struct);
            }
        }

        if (options.opt & MPG321_REMOTE_PLAY && file_change)
        {
            id3struct = id3_file_open (currentfile, ID3_FILE_MODE_READONLY);

            if (id3struct)
            {
                id3tag = id3_file_tag (id3struct);
            
                if (id3tag)
                {
                    if (!show_id3(id3tag))
                    {
                        /* This shouldn't be necessary, but it appears that
                           libid3tag doesn't necessarily know if there are no
                           id3 tags on a given mp3 */
                        char * basec = strdup(currentfile);
                        char * basen = basename(basec);
                        
                        char * dot = strrchr(basen, '.');
                        
                        if (dot)
                            *dot = '\0';
                        
                        printf("@I %s\n", basen);

                        free(basec);
                    }
                }
                
                else
                {
                    fprintf(stderr, "Allocation error");
                    exit(1);
                }

                id3_file_close (id3struct);
            }
            
            else
            {
                char * basec = strdup(currentfile);
                char * basen = basename(basec);
                
                char * dot = strrchr(basen, '.');
                
                if (dot)
                    *dot = '\0';
                
                printf("@I %s\n", basen);

                free(basec);
            }
        }

        /* Create the MPEG stream */
        /* Check if source is on the network */
        if((fd = raw_open(currentfile)) != 0 || (fd = http_open(currentfile)) != 0
            || (fd = ftp_open(currentfile)) != 0)
        {
            playbuf.fd = fd;
            playbuf.buf = malloc(BUF_SIZE);
            playbuf.length = BUF_SIZE;
            
            mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0,
                            output, /*error*/0, /* message */ 0);
        }

        /* Check if we are to use stdin for input */
        else if(strcmp(currentfile, "-") == 0)
        {
            playbuf.fd = fileno(stdin);
            playbuf.buf = malloc(BUF_SIZE);
            playbuf.length = BUF_SIZE;

            mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0,
                            output, /*error*/0, /* message */ 0);
        }
            
        /* currentfile is a local file (presumably.) mmap() it */
        else
        {
            struct stat stat;
            
            if((fd = open(currentfile, O_RDONLY)) == -1)
            {
                mpg321_error(currentfile);

                /* mpg123 stops immediately if it can't open a file */
                break;
            }
            
            if(fstat(fd, &stat) == -1)
            {
                close(fd);
                mpg321_error(currentfile);
                continue;
            }
            
            if (!S_ISREG(stat.st_mode))
            {
                close(fd);
                continue;
            }
            
            calc_length(currentfile, &playbuf);

            if ((options.maxframes != -1) && (options.maxframes <= playbuf.num_frames))
            { 
                playbuf.max_frames = options.maxframes;
            }
            
            playbuf.frames = malloc((playbuf.num_frames + 1) * sizeof(void*));
            playbuf.times = malloc((playbuf.num_frames + 1) * sizeof(mad_timer_t));
    
            if((playbuf.buf = mmap(0, playbuf.length, PROT_READ, MAP_SHARED, fd, 0))
                                == MAP_FAILED)
            {
                close(fd);
                mpg321_error(currentfile);
                continue;
            }
            
            close(fd);
            playbuf.frames[0] = playbuf.buf;
            
            mad_decoder_init(&decoder, &playbuf, read_from_mmap, read_header, /*filter*/0,
                            output, /*error*/0, /* message */ 0);
        }

        if(!(options.opt & MPG321_QUIET_PLAY))/*zip it!!!*/
        {
            /* Because dirname might modify the argument */
            char * dirc = strdup(currentfile);
            char * basec = strdup(currentfile);

            char * basen = basename(basec);
            char * dirn = dirname(dirc);
            
            /* make sure that the file has a pathname; otherwise don't print out
               a Directory: listing */
            if(strchr(currentfile, '/') && strncmp(old_dir, dirn, PATH_MAX) != 0)
            {
                /* Print information about the file */
                fprintf(stderr, "\n");
                fprintf(stderr,"Directory: %s/\n", dirn);
                
                strncpy(old_dir, dirn, PATH_MAX);
                old_dir[PATH_MAX-1] = '\0';
            }
            
            /* print a newline between different songs only, not after
               Directory: listing */
            else
            {
                fprintf(stderr, "\n");
            }

            fprintf(stderr,"Playing MPEG stream from %s ...\n", basen);
    
            free(dirc);
            free(basec);
        }    

        signal(SIGINT, handle_signals);

        /* Every time the user gets us to rewind, we exit decoding,
           reinitialize it, and re-start it */
        while (1)
        {
            mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
            
            /* if we're rewinding on an mmap()ed stream */
            if(status == MPG321_REWINDING && playbuf.fd == -1) 
            {
                mad_decoder_init(&decoder, &playbuf, read_from_mmap, read_header, /*filter*/0,
                    output, /*error*/0, /* message */ 0);
            }    
            else
                break;
        } 

        if (!(options.opt & MPG321_QUIET_PLAY))
        {
            char time_formatted[11];
            mad_timer_string(current_time, time_formatted, "%.1u:%.2u", MAD_UNITS_MINUTES,
                       MAD_UNITS_SECONDS, 0);
            fprintf(stderr, "\n[%s] Decoding of %s finished.\n",time_formatted, basename(currentfile));
        }
        
        if (options.opt & MPG321_REMOTE_PLAY && status == MPG321_STOPPED)
        {
            clear_remote_file(pl);
        }

        mad_decoder_finish(&decoder);

        if (quit_now)
            break;

        if (playbuf.frames)
             free(playbuf.frames);

        if (playbuf.times)
            free(playbuf.times);
            
        if (playbuf.fd == -1)
        {
            munmap(playbuf.buf, playbuf.length);
        }

        else
        {
            free(playbuf.buf);
            if (playbuf.fd != fileno(stdin)) 
                close(playbuf.fd);
        }
    }

    if(playdevice)
        ao_close(playdevice);

    ao_shutdown();

#if defined(RAW_SUPPORT) || defined(HTTP_SUPPORT) || defined(FTP_SUPPORT) 
    if(fd) close(fd);
#endif

    return(0);
}
Exemplo n.º 28
0
int main(int argc, char *argv[])
{
    int fd = 0;
    char *currentfile, old_dir[PATH_MAX];
    playlist *pl = NULL;
    struct id3_file *id3struct = NULL;
    struct id3_tag *id3tag = NULL;
    int retval;

    buffer playbuf;
    
    struct mad_decoder decoder;
    pthread_t keyb_thread;

    key_t sem_key;
    key_t mem_key;
    key_t frames_key;

    union semun sem_ops;
    int shm_id;
    int frames_id;
    mad_decoder_position = 0;
    output_buffer_position = 0;
    
    old_dir[0] = '\0';

    playbuf.pl = pl = new_playlist();

    if (!pl)
    {
        fprintf(stderr, "malloc failed at startup!\n");
        exit(1);
    }

    loop_remaining = 1;

    options.volume = MAD_F_ONE;

    status = MPG321_PLAYING;
    
    /* Get the command line options */
    parse_options(argc, argv, pl);

    if(options.opt & MPG321_PRINT_FFT)
	    if(!(options.opt & MPG321_REMOTE_PLAY))
	    {
		    /* printf("FFT analysis can only be used in Remote mode play.\n\n"); */
		    usage(argv[0]);			
		    exit(0);
	    }


    /* If there were no files and no playlist specified just print the usage */
    if (!playlist_file && optind == argc)
    {
        usage(argv[0]);
        exit(0);
    }

    if (playlist_file)
        load_playlist(pl, playlist_file);

    if(options.opt & MPG321_RECURSIVE_DIR)
	    add_cmdline_files_recursive_dir(pl, argv);
    else
	    add_cmdline_files(pl, argv);

    if (shuffle_play)
        shuffle_files(pl);

    if(options.opt & MPG321_ENABLE_BUFFER)
    {
	    /* Initialize semaphore and shared memeory */
	    if(access(argv[0],X_OK) == 0)
		    sem_key = ftok(argv[0],0);
	    else
		    sem_key = ftok(MPG321_PATH,0);
	    if(sem_key == -1)
	    {
		    perror("Cannot obtain resources for semaphores");
		    exit(EXIT_FAILURE);
	    }
	    semarray = semget(sem_key,3,IPC_CREAT | IPC_EXCL | S_IRWXU);
	    if(semarray == -1)
	    {
		    perror("Cannot initialize semaphores");
		    exit(EXIT_FAILURE);
	    }
	    sem_ops.val = buffer_size-1;
	    if(semctl(semarray,0,SETVAL,sem_ops) == -1)
	    {
		    perror("Error while initializing mad_decoder semaphore");
		    if(semctl(semarray,0,IPC_RMID) == -1)
			    perror("Error while destroying semaphores");
		    goto out;
		    //exit(EXIT_FAILURE);
	    }
	    sem_ops.val = 0;
	    if(semctl(semarray,1,SETVAL,sem_ops) == -1)
	    {
		    perror("Error while initializing mad_decoder semaphore");
		    if(semctl(semarray,0,IPC_RMID) == -1)
			    perror("Error while destroying semaphores");
		    goto out;
		    //exit(EXIT_FAILURE);
	    }
	    sem_ops.val = 0;
	    if(semctl(semarray,2,SETVAL,sem_ops) == -1)
	    {
		    perror("Error while initializing mad_decoder semaphore");
		    if(semctl(semarray,0,IPC_RMID) == -1)
			    perror("Error while destroying semaphores");
		    goto out;
		    //exit(EXIT_FAILURE);
	    }

	    /* Shared Memory */
	    mem_key = ftok(argv[0],1);
	    shm_id = shmget(mem_key,buffer_size * sizeof(output_frame), IPC_CREAT | S_IREAD | S_IWRITE);
	    if(shm_id == -1)
	    {
		    perror("Cannot initialize shared buffer");
		    goto out;
		    //exit(EXIT_FAILURE);
	    }
	    Output_Queue = shmat(shm_id,NULL,0);
	    if(*(int *)Output_Queue == -1)
	    {
		    perror("Error while attaching shared buffer to mad_decoder");
		    if(shmctl(shm_id,IPC_RMID,NULL))
			    perror("Cannot destroy shared buffer");
		    goto out;
		    //exit(EXIT_FAILURE);
	    }
	    static int n;
	    for(n=0;n<buffer_size;n++)
	    {
		    memset((Output_Queue+n)->data,'\0',4608);
		    memset((Output_Queue+n)->time,'\0',80);
		    (Output_Queue+n)->length = 0;
		    (Output_Queue+n)->seconds = 0;
		    (Output_Queue+n)->num_frames = 0;
	    }
	    
	    frames_key = ftok(argv[0],2);
	    frames_id = shmget(frames_key,buffer_size * sizeof(decoded_frames), IPC_CREAT | S_IREAD | S_IWRITE);
	    if(frames_id == -1)
	    {
		    perror("Cannot initialize shared frames counter");
		    goto out;
		    //exit(EXIT_FAILURE);
	    }
	    Decoded_Frames = shmat(frames_id,NULL,0);
	    if(*(int *)Decoded_Frames == -1)
	    {
		    perror("Error while attaching shared frames counter to mad_decoder");
		    if(shmctl(frames_id,IPC_RMID,NULL))
			    perror("Cannot destroy shared frames counter");
		    goto out;
		    //exit(EXIT_FAILURE);
	    }
	    	
	    Decoded_Frames->is_http = 0;
	    Decoded_Frames->is_file = 0;

    }
    else {
	    ao_initialize();
	    check_default_play_device();
    }
    
    if (!(options.opt & MPG321_REMOTE_PLAY))
    {
        handle_signals(-1); /* initialize signal handler */
        remote_input_buf[0] = '\0';
    }
    
    if (!(options.opt & MPG321_QUIET_PLAY)) 
        mpg123_boilerplate();
    
    if (options.opt & MPG321_REMOTE_PLAY)
    {
        printf ("@R MPG123\n");
	if(options.opt & MPG321_ENABLE_BUFFER)
	{
#ifdef HAVE_ALSA
		init_alsa_volume_control("default"); /* For the moment use "default", it works on most of the systems. Tested in Debian,Fedora,Ubuntu,RedHat,CentOS,Gentoo */
		if(options.volume != MAD_F_ONE)
			mpg321_alsa_set_volume((long)options.volume*volume_max/100);
#endif
	}
    }

    /* Fork here. */
    if(options.opt & MPG321_ENABLE_BUFFER)
    {
	    output_pid = fork();
	    if(output_pid == -1)
	    {
		    perror("Error while forking output process");
		    goto out; /* Release shared memeory and semaphores */
		//    exit(EXIT_FAILURE);
	    }

	    if(output_pid == 0)
	    {
		    frame_buffer_p();
		    exit(EXIT_SUCCESS);
	    }
	    signal(SIGUSR1,handle_signals);
	    if(!(options.opt & MPG321_REMOTE_PLAY))
	    {
#ifdef HAVE_ALSA
		    init_alsa_volume_control("default");
		    if(options.volume != MAD_F_ONE)
			    mpg321_alsa_set_volume((long)options.volume*volume_max/100);
#endif
	    }
    }

    if( (options.volume != MAD_F_ONE) && !(options.opt & MPG321_ENABLE_BUFFER))
    {
	    options.volume = mad_f_tofixed((long)options.volume/100.0);
    }
    else{
	    options.volume = MAD_F_ONE; /* When using the buffer options.volume when decoding each frame should be equal to MAD_F_ONE */
//	    options.volume = mad_f_tofixed((long)100.0/100.0);
    }

    if (!(options.opt & MPG321_REMOTE_PLAY))
    {
	     if(options.opt & MPG321_ENABLE_BASIC)
	     {
	 	     /* Now create and detach the basic controls thread */
		     sem_init(&main_lock,0,0);
	 	     pthread_create(&keyb_thread,NULL,read_keyb,NULL);
		     pthread_detach(keyb_thread);
	     }
     }
    if(set_xterm)
    {
	    tty_control();
	    get_term_title(title);
    }else
    {
     	
	    if (!(options.opt & MPG321_REMOTE_PLAY))
	    {
	    	    if (tcgetattr(0, &terminal_settings) < 0)
	    		    perror("tcgetattr()");
	    	    memcpy(&old_terminal_settings, &terminal_settings, sizeof(struct termios));
		    /* Early thread start */
		    sem_post(&main_lock);
	    }
    }
    /* Play the mpeg files or zip it! */
    while((currentfile = get_next_file(pl, &playbuf)))
    {
        //printf("Current File: %s\n",currentfile);
	   if (quit_now) 
            break;
        
        signal(SIGINT, SIG_DFL);
        
        playbuf.buf = NULL;
        playbuf.fd = -1;
        playbuf.length = 0;
        playbuf.done = 0;
        playbuf.num_frames = 0;
        current_frame = 0;
        playbuf.max_frames = -1;
        strncpy(playbuf.filename,currentfile, PATH_MAX);
        playbuf.filename[PATH_MAX-1] = '\0';
        
        if (status == MPG321_PLAYING || status == MPG321_STOPPED) 
            file_change = 1;

        mad_timer_reset(&playbuf.duration);
        
        mad_timer_reset(&current_time);

	id3struct = NULL;

        if (!(options.opt & MPG321_QUIET_PLAY) && file_change)
        {
           /* id3struct = id3_file_open (currentfile, ID3_FILE_MODE_READONLY);*/

            if (id3struct == NULL)
		    get_id3_info(currentfile, &id3struct, &id3tag);
	    if(id3tag)
		    show_id3(id3tag);
	}

	scrobbler_time = -1;
	if(options.opt & MPG321_USE_SCROBBLER)
	{
		if(id3struct == NULL)
			get_id3_info(currentfile,&id3struct,&id3tag);
                
	    if (id3tag)
	    {
		    char emptystring[31], emptyyear[5] = "    ";
		    int i;

		    if(parse_id3(scrobbler_args, id3tag))
		    {
			    memset(emptystring, ' ', 30);
			    emptystring[30] = '\0';
	    		    if((options.opt & MPG321_VERBOSE_PLAY) && (options.opt & MPG321_USE_SCROBBLER))
			    {
				    fprintf(stderr, "\nPreparing for the AudioScrobbler:\n");
				    for(i = 0; i < 6; i++)
				    {
					    if(scrobbler_args[i] == NULL)
						    scrobbler_args[i] =
							    ( i == 3 ? emptyyear: emptystring);
					    fprintf(stderr, "- %s\n", scrobbler_args[i]);
				    }
			    }
		    }
	    }
	}
      

        if (options.opt & MPG321_REMOTE_PLAY && file_change)
        {
		if(id3struct == NULL)
			get_id3_info(currentfile, &id3struct, &id3tag);
		if(id3tag)
                {
                    if (!show_id3(id3tag))
                    {
                        /* This shouldn't be necessary, but it appears that
                           libid3tag doesn't necessarily know if there are no
                           id3 tags on a given mp3 */
                        char * basec = strdup(currentfile);
                        char * basen = basename(basec);
                        
                        char * dot = strrchr(basen, '.');
                        
                        if (dot)
                            *dot = '\0';
                        
                        printf("@I %s\n", basen);

                        free(basec);
                    }
                }
            else
            {
                char * basec = strdup(currentfile);
                char * basen = basename(basec);
                
                char * dot = strrchr(basen, '.');
                
                if (dot)
                    *dot = '\0';
                
                printf("@I %s\n", basen);

                free(basec);
            }
        }

	if(id3struct != NULL)
		id3_file_close(id3struct);

        /* Create the MPEG stream */
        /* Check if source is on the network */
        if((fd = raw_open(currentfile)) != 0 || (fd = http_open(currentfile)) != 0
            || (fd = ftp_open(currentfile)) != 0)
        {
            playbuf.fd = fd;
            playbuf.buf = malloc(BUF_SIZE);
            playbuf.length = BUF_SIZE;
	    if(options.opt & MPG321_ENABLE_BUFFER)
	    {
		    Decoded_Frames->is_http = 1;
		    Decoded_Frames->is_file = 0;
	    }
	    calc_http_length(&playbuf);

            mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0,
                            output, handle_error, /* message */ 0);
        }

        /* Check if we are to use stdin for input */
        else if(strcmp(currentfile, "-") == 0)
        {
            playbuf.fd = fileno(stdin);
            playbuf.buf = malloc(BUF_SIZE);
            playbuf.length = BUF_SIZE;

            mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0,
                            output, handle_error, /* message */ 0);
        }
            
        /* currentfile is a local file (presumably.) mmap() it */
        else
        {
            struct stat stat;
            
            if((fd = open(currentfile, O_RDONLY)) == -1)
            {
	    
                mpg321_error(currentfile);
		/* Restore TTY from keyboard reader thread */
	        if(options.opt & MPG321_ENABLE_BASIC)
			if (tcsetattr(0, TCSANOW, &old_terminal_settings) < 0)
				perror("tcsetattr ICANON");
		if(set_xterm)
	    	{
			set_tty_restore();
	    		osc_print(0,0,title);
	    		if (ctty)
	    			fclose(ctty);
	    	}
		if( options.opt & MPG321_REMOTE_PLAY)
			if(remote_restart)
			{	
				clear_remote_file(pl); /* If restart is enabled, restart remote shell when file doesn't exist*/
				continue;
			}
		if(options.opt & MPG321_ENABLE_BUFFER)
			goto out;
		else
			exit(1);
                /* mpg123 stops immediately if it can't open a file */
		/* If sth goes wrong break!!!*/
                break;
            }

	    if(options.opt & MPG321_ENABLE_BUFFER)
	    {
		    Decoded_Frames->is_http = 0;
		    Decoded_Frames->is_file = 1;
	    }
            
            if(fstat(fd, &stat) == -1)
            {
                mpg321_error(currentfile);
		close(fd);
                continue;
            }
            
            if (!S_ISREG(stat.st_mode))
            {
		    if(S_ISFIFO(stat.st_mode))
		    {
			    fallback = 1;
			    goto fall_back_to_read_from_fd;
		    }

		close(fd);    
                continue;
            }
            
            retval = calc_length(currentfile, &playbuf); //FIXME Check also if it is an mp3 file. If not break and go to the next file possible
	    if(retval < 0)
	    {
		    if(options.opt & MPG321_REMOTE_PLAY)
		    {
			    fprintf(stderr,"@E Corrupted file: %s\n",currentfile);
			    close(fd);
			    if(remote_restart)
			    {
				    clear_remote_file(pl); /* If restart is enabled, restart remote shell when file is corrupted */
				    continue;
			    }
			    break;
		    }
		    mpg321_error(currentfile);
		    close(fd);
//		    break; //FIXME Break and stop OR continue the playlist ????
		    continue;
	    }

	    if((options.opt & MPG321_VERBOSE_PLAY) && (options.opt & MPG321_USE_SCROBBLER))
		    fprintf(stderr, "Track duration: %ld seconds\n",playbuf.duration.seconds);

	    if(options.opt & MPG321_USE_SCROBBLER)
		    scrobbler_set_time(playbuf.duration.seconds);

            if ((options.maxframes != -1) && (options.maxframes <= playbuf.num_frames))
            { 
                playbuf.max_frames = options.maxframes;
            }
            
            playbuf.frames = malloc((playbuf.num_frames + 1) * sizeof(void*));
            playbuf.times = malloc((playbuf.num_frames + 1) * sizeof(mad_timer_t));
#ifdef __uClinux__
	    if((playbuf.buf = mmap(0, playbuf.length, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
#else       
 	    if((playbuf.buf = mmap(0, playbuf.length, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED)
#endif		    
            {
                mpg321_error(currentfile);
                continue;
            }
            
            playbuf.frames[0] = playbuf.buf;
		    
	    mad_decoder_init(&decoder, &playbuf, read_from_mmap, read_header, /*filter*/0,
            
	    		    output, handle_error, /* message */ 0);
fall_back_to_read_from_fd:	//FIXME. Reported that on some embedded systems with low memory, less than 16MB doesn't work properly.
	    if(fallback)
	    {
	    
		    playbuf.fd = fd;
		    playbuf.buf = malloc(BUF_SIZE);
		    playbuf.length = BUF_SIZE;
		    mad_decoder_init(&decoder, &playbuf, read_from_fd, read_header, /*filter*/0,
				    output, handle_error, /* message */ 0);
		    fallback = 1;
	    }
        }

        if(!(options.opt & MPG321_QUIET_PLAY))/*zip it!!!*/
        {
            /* Because dirname might modify the argument */
            char * dirc = strdup(currentfile);
            char * basec = strdup(currentfile);

            char * basen = basename(basec);
            char * dirn = dirname(dirc);
            
            /* make sure that the file has a pathname; otherwise don't print out
               a Directory: listing */
            if(strchr(currentfile, '/') && strncmp(old_dir, dirn, PATH_MAX) != 0)
            {
                /* Print information about the file */
                fprintf(stderr, "\n");
                fprintf(stderr,"Directory: %s\n", dirn);
                
                strncpy(old_dir, dirn, PATH_MAX);
                old_dir[PATH_MAX-1] = '\0';
            }
            
            /* print a newline between different songs only, not after
               Directory: listing */
            else
            {
                fprintf(stderr, "\n");
            }

            fprintf(stderr,"Playing MPEG stream from %s ...\n", basen);
            
	    /* Printing xterm title */
	    if(set_xterm)
	    {
		    osc_print(0,0,basen);
	    }
	    
            free(dirc);
            free(basec);
        }    

        signal(SIGINT, handle_signals);
	signal(SIGCHLD, handle_sigchld);
        /*Give control back so that we can implement SIG's*/
	if(set_xterm)
	{
		set_tty_restore();
		if (tcgetattr(0, &terminal_settings) < 0)
			perror("tcgetattr()");
		memcpy(&old_terminal_settings, &terminal_settings, sizeof(struct termios));
		/* disable canonical mode processing in the line discipline driver */
		terminal_settings.c_lflag &= ~(ICANON | ECHO);
		/* apply our new settings */
		if (tcsetattr(0, TCSANOW, &terminal_settings) < 0)
			perror("tcsetattr ICANON");
		if(options.opt & MPG321_ENABLE_BASIC)
		{
			/* Late thread start */
			sem_post(&main_lock);
		}
	}
        /* Every time the user gets us to rewind, we exit decoding,
           reinitialize it, and re-start it */
	    
	if(options.opt & MPG321_ENABLE_BUFFER)
    	{
		Decoded_Frames->total_decoded_frames = 0;
		Decoded_Frames->done = 0;
	}
      
        while (1)
        {
            decoder.options |= MAD_OPTION_IGNORECRC;
            mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
	    if(options.opt & MPG321_ENABLE_BUFFER)
	    {
		    static struct sembuf start_sops = {2,-1,0};
		    semop(semarray,&start_sops,1);
		    mad_decoder_position = 0;
		    output_buffer_position = 0;
		    union semun sem_ops;
		    sem_ops.val = 0;
		    semctl(semarray,2,SETVAL,sem_ops);
		    Decoded_Frames->total_decoded_frames = 0;
		    Decoded_Frames->done = 0;
		    Decoded_Frames->is_http = 0;
		    Decoded_Frames->is_file = 0;
	    }
            /* if we're rewinding on an mmap()ed stream */
            if(status == MPG321_REWINDING && playbuf.fd == -1) 
            {
                mad_decoder_init(&decoder, &playbuf, read_from_mmap, read_header, /*filter*/0,
                    output, /*error*/0, /* message */ 0);
            }    
            else
                break;
        } 

        if (!(options.opt & MPG321_QUIET_PLAY))
        {
            char time_formatted[11];
            mad_timer_string(current_time, time_formatted, "%.1u:%.2u", MAD_UNITS_MINUTES,
                       MAD_UNITS_SECONDS, 0);
	    fprintf(stderr,"                                                                            \r");
	    fprintf(stderr, "\n[%s] Decoding of %s finished.\n",time_formatted, basename(currentfile)); /* Report total decoded seconds. Maybe for the frame buffer report only total played time?? */
        }
        
        if (options.opt & MPG321_REMOTE_PLAY && status == MPG321_STOPPED)
        {
            clear_remote_file(pl);
        }

        mad_decoder_finish(&decoder);

        if (playbuf.frames)
             free(playbuf.frames);

        if (playbuf.times)
            free(playbuf.times);
            
        if (playbuf.fd == -1)
        {
            munmap(playbuf.buf, playbuf.length);
            close(fd);
        }

        else
        {
            free(playbuf.buf);
            if (playbuf.fd != fileno(stdin)) 
                close(playbuf.fd);
        }
    }

    if(!(options.opt & MPG321_ENABLE_BUFFER))
    {
  	     if(playdevice)
		     ao_close(playdevice);
	     ao_shutdown();
     }

     if (!(options.opt & MPG321_REMOTE_PLAY))
     {
	     if(options.opt & MPG321_ENABLE_BASIC)
	     {
	 	     pflag = 1;
		     /* Restore TTY from keyboard reader thread */
	 	     if (tcsetattr(0, TCSANOW, &old_terminal_settings) < 0)
		 	     perror("tcsetattr ICANON");
	     }
     }
    /*Restoring TTY*/
    if(set_xterm)
    {
	    set_tty_restore();
	    osc_print(0,0,title);
	    if (ctty)
		    fclose(ctty);
    }

out:
    if(options.opt & MPG321_ENABLE_BUFFER)
    {
	    if(kill(output_pid,SIGUSR1) == -1)
		    perror("Error while stopping output process");
	    static int wstatus;
	    wait(&wstatus);
	    if(wstatus == -1)
		    perror("Error while waiting for output process to exit");
	    if(semctl(semarray,0,IPC_RMID) == -1)
		    perror("Error while destroying semaphores");
	    if(shmdt(Output_Queue) == -1)
		    perror("Error while detaching shared buffer");
	    if(shmctl(shm_id,IPC_RMID,NULL))
		    perror("Cannot destroy shared buffer");
	    if(shmctl(frames_id,IPC_RMID,NULL))
		    perror("Cannot destroy shared buffer");
    }
    return(0);
}
Exemplo n.º 29
0
  long madaudiofile::update_duration(FILE *f) {
    bool oldEOF = reachedEOF;
    reachedEOF = false;
    current_pos = 0;
    frame_count = 0;
    outputLength = 0;
    outputPosition = 0;
    //      samplerate = 44100;
    samplerate = 16000;

    //bool firstRun = true;

    if (!f)
      throw "madaudiofile::update_duration(): file is not opened\n";

    fpos_t oldPosition;
    fgetpos(f,&oldPosition);
    fseek(f, 0, SEEK_SET);

    /*
      struct mad_header m_header;
      mad_timer_reset(Timer);

      while(!reachedEOF) {

      if(Stream->buffer==NULL || Stream->error==MAD_ERROR_BUFLEN || 
      firstRun) {
      firstRun = false;
      size_t ReadSize,Remaining;
      unsigned char *ReadStart;
      u_int8_t *GuardPtr = NULL;
      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;
      }

      ReadSize = readData(ReadStart,1,ReadSize,f);
      if(ReadSize <= 0)
      throw "Madaudiofile: could not read from file\n";

      if(reachedEOF) {
      GuardPtr=ReadStart+ReadSize;
      memset(GuardPtr,0,MAD_BUFFER_GUARD);
      ReadSize+=MAD_BUFFER_GUARD;
      }
      mad_stream_buffer(Stream,InputBuffer,ReadSize);
      }

      while(1) {
      if( mad_header_decode(&m_header, Stream) == -1 ) {
      if( MAD_RECOVERABLE(Stream->error) ) {
      continue;
      } else if( Stream->error == MAD_ERROR_BUFLEN ) {
      break; // EOF 
      } else {
      break; // BAD ERROR, oh well 
      }
      }
      mad_timer_add(Timer, m_header.duration);
      }
      }  
    */
    double dur = 0;
    /*while(!eof()) */{
      audiodata ad = getNextAudioSlice(1000, false);
      dur += ad.getDuration();
    }
    duration = (long int) dur;
            
    fsetpos(f,&oldPosition);


    /*
      duration = mad_timer_count(*Timer, MAD_UNITS_MILLISECONDS);
    
      mad_header_finish(&m_header);
    */

#ifdef HAVE_MAD_H
    mad_synth_finish(Synth);
    mad_frame_finish(Frame);
    mad_stream_finish(Stream);
      
    memset(OutputBuffer, 0, OUTPUT_BUFFER_SIZE);
    memset(InputBuffer, 0, INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD);
      
    mad_stream_init(Stream);
    mad_frame_init(Frame);
    mad_synth_init(Synth);
    mad_timer_reset(Timer);

    Stream->error=(mad_error)0;
#endif // HAVE_MAD_H

    reachedEOF = oldEOF;

#ifdef MADAUDIO_PRINT_DEBUG
    printf("Got duration %li\n",duration);
#endif
    return duration;
  }
Exemplo n.º 30
0
static int mp3_startread(snd_stream_t *stream)
{
	mp3_priv_t *p = (mp3_priv_t *) stream->priv;
	size_t ReadSize;

	mad_stream_init(&p->Stream);
	mad_frame_init(&p->Frame);
	mad_synth_init(&p->Synth);
	mad_timer_reset(&p->Timer);

	/* Decode at least one valid frame to find out the input
	 * format.  The decoded frame will be saved off so that it
	 * can be processed later.
	 */
	ReadSize = FS_fread(p->mp3_buffer, 1, MP3_BUFFER_SIZE, &stream->fh);
	if (ReadSize != MP3_BUFFER_SIZE)
	{
		if (FS_feof(&stream->fh) || FS_ferror(&stream->fh))
			return -1;
	}

	mad_stream_buffer(&p->Stream, p->mp3_buffer, ReadSize);

	/* Find a valid frame before starting up.  This makes sure
	 * that we have a valid MP3 and also skips past ID3v2 tags
	 * at the beginning of the audio file.
	 */
	p->Stream.error = MAD_ERROR_NONE;
	while (mad_frame_decode(&p->Frame,&p->Stream))
	{
		/* check whether input buffer needs a refill */
		if (p->Stream.error == MAD_ERROR_BUFLEN)
		{
			if (mp3_inputdata(stream) == -1)
				return -1;

			continue;
		}

		/* Consume any ID3 tags */
		mp3_inputtag(stream);

		/* FIXME: We should probably detect when we've read
		 * a bunch of non-ID3 data and still haven't found a
		 * frame.  In that case we can abort early without
		 * scanning the whole file.
		 */
		p->Stream.error = MAD_ERROR_NONE;
	}

	if (p->Stream.error)
	{
		Con_Printf("MP3: No valid MP3 frame found\n");
		return -1;
	}

	switch(p->Frame.header.mode)
	{
	case MAD_MODE_SINGLE_CHANNEL:
	case MAD_MODE_DUAL_CHANNEL:
	case MAD_MODE_JOINT_STEREO:
	case MAD_MODE_STEREO:
		stream->info.channels = MAD_NCHANNELS(&p->Frame.header);
		break;
	default:
		Con_Printf("MP3: Cannot determine number of channels\n");
		return -1;
	}

	p->FrameCount = 1;

	mad_timer_add(&p->Timer,p->Frame.header.duration);
	mad_synth_frame(&p->Synth,&p->Frame);
	stream->info.width = MP3_MAD_SAMPLEWIDTH;
	stream->info.rate = p->Synth.pcm.samplerate;

	p->cursamp = 0;

	return 0;
}