Without dynamic

Daniel Levitan <[email protected]> Mon, 06 Jun 2005 15:19:15 -0300
Newsgroups gmane.comp.audio.mad.devel
Message-ID <[email protected]>
Hi everyone,

After many tries I've finally succeed decoding a mp3 file. But now the 
sound seems whitout dynamic, I don't know if the problem is the function 
that I'm using to scale the samples or the routine that I've used to 
save it to a file (using libsndfile). Can anyone help me ?

Thank you !

Daniel

No virus found in this outgoing message.
Checked by AVG Anti-Virus.
Version: 7.0.323 / Virus Database: 267.6.2 - Release Date: 4/6/2005
main.cpp (text/plain, 8.9 KB)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mad.h"
#include "sndfile.h"


#define INPUT_BUFFER_SIZE 65535


struct private_data {
		FILE			*file;
		unsigned char	*inputBuffer;
		int 			numChannels;
		int				samplerate;
		int				len;
		float 			*sample;
		int				icount,
						ocount;
		bool			firstRun;
		void 			*userData; //nao sei pra que vai usar...
};

/* The MAD callbacks */
enum mad_flow input_cb (void *_data, struct mad_stream *stream);
enum mad_flow output_cb(void *_data, struct mad_header const *header, struct mad_pcm *pcm);
enum mad_flow error_cb (void *_data, struct mad_stream *stream, struct mad_frame *frame);


inline float scale(mad_fixed_t sample)
{
   return (float) (sample / (float) (1L << MAD_F_FRACBITS));
}




int main(){
	
	struct private_data mPrivateData;
	mad_decoder mDecoder;	
	int	chn;
	const char 	*filename="saida.wav";
	SF_INFO 	info;
	SNDFILE		*outfile;
	
       /* Prepare decoder data, initialize decoder */
	mPrivateData.len = 0;
	mPrivateData.file = fopen("weapon2.mp3","rb");
	mPrivateData.inputBuffer = new unsigned char [INPUT_BUFFER_SIZE];
    mPrivateData.numChannels = 0;
	mPrivateData.samplerate = 0;
	mPrivateData.icount = mPrivateData.ocount = 0;
	mPrivateData.firstRun = true;

    mad_decoder_init(&mDecoder, &mPrivateData, input_cb, 0, 0, output_cb, error_cb, 0);

	if(mad_decoder_run(&mDecoder, MAD_DECODER_MODE_SYNC) == 0)
	{
		/* success */
		printf("success\n"); 
		//GRAVAR O ARQUIVO COM A SNDFILE
		info.samplerate = mPrivateData.samplerate;
		info.channels   = mPrivateData.numChannels;

		//printf("Sample rate %d\n",info.samplerate);
		//printf("Channels %d\n",info.channels);

		//info.samplerate = 44100;
		//info.channels   = 1;
		info.format	    = 65538;
		info.sections   = 1;
		info.seekable   = 1;
		info.frames 	= 0;
		
		outfile = sf_open(filename , SFM_WRITE , &info);
		sf_write_float( outfile, mPrivateData.sample , mPrivateData.len) ;
		sf_close(outfile);
		
		mad_decoder_finish(&mDecoder);
		
		
		
		/* copy the WaveTrack pointers into the Track pointer list that
		 * we are expected to fill */
	        //*outTracks = new Track* [mPrivateData.numChannels];
	        //for(chn = 0; chn < mPrivateData.numChannels; chn++) {
		//       mPrivateData.channels[chn]->Flush();
		//        (*outTracks)[chn] = mPrivateData.channels[chn];
		//}
		//*outNumTracks = mPrivateData.numChannels;
	        //delete mPrivateData.inputBuffer;
		//delete[] mPrivateData.channels;
                //return true;
        }
	else {

		/* failure */
	       	printf("failure\n"); 

	       	mad_decoder_finish(&mDecoder);

	        /* delete everything */
	        //for(chn = 0; chn < mPrivateData.numChannels; chn++)
		//	delete mPrivateData.channels[chn];
	        //delete[] mPrivateData.channels;
		//delete mPrivateData.inputBuffer;
  	        //return false;
       }


	//mad_decoder_finish(&mDecoder);

	/* delete everything */
    	//for(chn = 0; chn < mPrivateData.numChannels; chn++)
    	//delete mPrivateData.channels[chn];
	printf("Input %d   Output %d\n",mPrivateData.icount, mPrivateData.ocount);
	
       	delete mPrivateData.inputBuffer;
	fclose(mPrivateData.file);
	return(0);
}

//
//   MAD Callbacks
//

/* The input callback is called when the decoder wants more data. */
enum mad_flow input_cb(void *_data, struct mad_stream *stream)
{
   struct private_data *data = (struct private_data *)_data;

    data->icount += 1;

   if(feof(data->file)) 
      return MAD_FLOW_STOP;
  

   /* "Each time you refill your buffer, you need to preserve the data in
    *  your existing buffer from stream.next_frame to the end.
    *
    *  This usually amounts to calling memmove() on this unconsumed portion
    *  of the buffer and appending new data after it, before calling
    *  mad_stream_buffer()"
    *           -- Rob Leslie, on the mad-dev mailing list */

   unsigned int unconsumedBytes;
   if(stream->next_frame) {
      unconsumedBytes = data->inputBuffer + INPUT_BUFFER_SIZE - stream->next_frame;
      memmove(data->inputBuffer, stream->next_frame, unconsumedBytes);
   }
   else
      unconsumedBytes = 0;


   //off_t read = data->file->Read(data->inputBuffer + unconsumedBytes,
    //                             IsNPUT_BUFFER_SIZE - unconsumedBytes);

   //size_t Read(void* buffer, size_t count)
   int read = fread(data->inputBuffer + unconsumedBytes,
					1, 
					INPUT_BUFFER_SIZE - unconsumedBytes,
					data->file);
   
   mad_stream_buffer(stream, data->inputBuffer, read + unconsumedBytes);

   return MAD_FLOW_CONTINUE;
}

/* The output callback is called every time the decoder has finished decoding
 * a frame, allowing us to use the decoded data */

enum mad_flow output_cb(void *_data,
                        struct mad_header const *header,
                        struct mad_pcm *pcm)
{

	int		channels,
			samplerate,
			samples;
	struct	private_data *data = (struct private_data *)_data;
	int		chn,
			smpl,
			cont;

	float	*bufferL,
			*bufferR;


	samplerate= pcm->samplerate;
	channels  = pcm->channels;
	samples   = pcm->length;
	
    if (data->firstRun){
		data->numChannels = channels;
		data->samplerate  = samplerate;	
		data->firstRun = false;
    }

	

    if(data->ocount == 0) 
   		data->sample = (float *) malloc(channels*samples*sizeof(float) );
    else
   		data->sample = (float *) realloc (data->sample , (data->len + samples)*sizeof(float)*channels );
    
	data->ocount += 1;

 	if (!data->sample){
   		printf("NAo alocou memo\n");
		exit(1);
	}
 		
	float *buffer = new float[channels*samples];
	
	if (channels == 1){
		for(smpl = 0; smpl < samples; smpl++)
			 buffer[smpl] = scale(pcm->samples[0][smpl]);
	}

	if (channels == 2){
		bufferL = new float[samples];
		bufferR = new float[samples];
		
		for(smpl = 0; smpl < samples; smpl++){
			 bufferL[smpl] = scale(pcm->samples[0][smpl]);
			 bufferR[smpl] = scale(pcm->samples[1][smpl]);
		}

		//Interleaving
		cont = 0; 
		while (cont < samples){
			buffer[cont] = bufferL[cont];
			cont++;
			buffer[cont] = bufferR[cont];
			cont++;
		}
	}
	
	
	memcpy(data->sample + data->len ,buffer ,channels*samples);
	data->len +=channels*samples;

	
	if (channels == 2){
		delete [] bufferL;	
		delete [] bufferR;
	}
	delete [] buffer;
   
	//Codigo para somente 1 canal
	
	/*if(data->ocount == 0) 
   		data->sample = (float *) malloc(samples*sizeof(float) );
    else
   		data->sample = (float *) realloc (data->sample , (data->len + samples)*sizeof(float) );
    data->ocount += 1;

 	if (!data->sample){
   		printf("NAo alocou memo\n");
		exit(1);
	}
 		
	float *buffer = new float[samples];
	for(smpl = 0; smpl < samples; smpl++)
			 buffer[smpl] = scale(pcm->samples[0][smpl]);
   
	memcpy(data->sample + data->len ,buffer ,samples);
	data->len +=samples;*/





   /* If this is the first run, we need to create the WaveTracks that
    * will hold the data.  We do this now because now is the first
    * moment when we know how many channels there are. */

   /*
   if(!data->channels) {
      data->channels = new WaveTrack* [channels];

      for(chn = 0; chn < channels; chn++) {
         data->channels[chn] = data->trackFactory->NewWaveTrack(floatSample);
         data->channels[chn]->SetRate(samplerate);
         data->channels[chn]->SetChannel(Track::MonoChannel);
      }

      /* special case: 2 channels is understood to be stereo 
      if(channels == 2) {
         data->channels[0]->SetChannel(Track::LeftChannel);
         data->channels[1]->SetChannel(Track::RightChannel);
         data->channels[0]->SetLinked(true);
      }
      data->numChannels = channels;
   }
   else {  
      // This is not the first run, protect us from libmad glitching
      // on the number of channels
      channels = data->numChannels;
   }
*/
   /* TODO: get rid of this by adding fixed-point support to SampleFormat.
    * For now, we allocate temporary float buffers to convert the fixed
    * point samples into something we can feed to the WaveTrack.  Allocating
    * big blocks of data like this isn't a great idea, but it's temporary.*/
 	/*   
   float **channelBuffers = new float* [channels];
   for(chn = 0; chn < channels; chn++)
      channelBuffers[chn] = new float [samples];

   for(smpl = 0; smpl < samples; smpl++)
      for(chn = 0; chn < channels; chn++)
         channelBuffers[chn][smpl] = scale(pcm->samples[chn][smpl]);

   for(chn = 0; chn < channels; chn++)
      data->channels[chn]->Append((samplePtr)channelBuffers[chn],
                                  floatSample,
                                  samples);

   for(chn = 0; chn < channels; chn++)
      delete[] channelBuffers[chn];
   delete[] channelBuffers;
*/
   return MAD_FLOW_CONTINUE;
}


enum mad_flow error_cb(void *_data, struct mad_stream *stream, 
                       struct mad_frame *frame)
{
/* enum mad_flow {
     MAD_FLOW_CONTINUE = 0x0000,
     MAD_FLOW_STOP     = 0x0010,
     MAD_FLOW_BREAK    = 0x0011,
     MAD_FLOW_IGNORE   = 0x0020
   }; */
   /*
   printf("decoding error 0x%04x (%s)\n",
      stream->error, mad_stream_errorstr(stream));
   */

   return MAD_FLOW_CONTINUE;

   /* return MAD_FLOW_BREAK; */
}