예제 #1
0
snd_sequence_struct *snd_decode_mp3(uint8 *buffer,int32 bytes){

mp3_decoder_t mp3;
mp3_info_t info;
memset(&info,0,sizeof(mp3_info_t));

unsigned char *stream_pos;
int bytes_left;
int bytes_read;

int sample_buffer_allocated_bytes=2000000;
int16* sample_buffer=(int16*)malloc(2000000);
int16* sample_buffer_offset;

bytes_left=bytes;
stream_pos=(unsigned char*)buffer;

mp3 = mp3_create();

int bytes_out=0;

int firstTry=1;

sample_buffer_offset=sample_buffer;
mp3getmore:
bytes_read = mp3_decode((void**)mp3, stream_pos, bytes_left, sample_buffer_offset, &info);
if (firstTry==1 && info.audio_bytes<=0){
	free(sample_buffer);
	return NULL;
}
firstTry=0;
bytes_left-=bytes_read;
stream_pos+=bytes_read;
sample_buffer_offset=(int16*)(((uint8*)sample_buffer_offset)+info.audio_bytes);
bytes_out+=info.audio_bytes;

if (bytes_out+1000000>sample_buffer_allocated_bytes){
	sample_buffer_allocated_bytes+=1000000;
	sample_buffer=(int16*)realloc(sample_buffer,sample_buffer_allocated_bytes);
	sample_buffer_offset=(int16*)(((uint8*)sample_buffer)+bytes_out);
}

if (bytes_left>0 && bytes_read!=0) goto mp3getmore;

//attach bufout to new sequence
static int32 seq_handle; seq_handle=list_add(snd_sequences);
static snd_sequence_struct *seq; seq=(snd_sequence_struct*)list_get(snd_sequences,seq_handle);
memset(seq,0,sizeof(snd_sequence_struct));
seq->references=1;
seq->data=(uint8*)sample_buffer;
seq->data_size=bytes_out;
seq->channels=info.channels;
seq->endian=0;//native
seq->is_unsigned=0;
seq->sample_rate=info.sample_rate;
seq->bits_per_sample=16;

return seq;

}
예제 #2
0
파일: getmp3.c 프로젝트: LasDesu/np2debug
static UINT mp3_dec(GETSND snd, short *dst) {

	UINT8	*src;
	MPEGL3	*mp3;
	int		r;

	src = snd->datptr;
	mp3 = (MPEGL3 *)snd->snd;
	if (snd->datsize < 4) {
		goto mp3dec_err;
	}
	r = mp3_predecode(mp3, src);
	if (r) {
		if ((r != MPEGHEAD_RENEWAL) ||
			(snd->samplingrate != mp3->c.samplingrate) ||
			(snd->channels != mp3->c.channels)) {
			TRACEOUT(("mp3 decord err"));
			goto mp3dec_err;
		}
	}

	if (snd->datsize < mp3->c.insize) {
		goto mp3dec_err;
	}
	snd->datptr += mp3->c.insize;
	snd->datsize -= mp3->c.insize;
	mp3_decode(mp3, dst, src, mp3->c.insize);
	return(mp3->c.outsamples);

mp3dec_err:
	return(0);
}
예제 #3
0
/* Read some data from the mp3 file stream */
static adv_error mp3_read_stream(unsigned channel)
{
	if (mixer_map[channel].pos == mixer_map[channel].start) {
		return mp3_first_read_stream(channel);
	} else {
		unsigned char data[MIXER_PAGE_SIZE];
		unsigned run = mp3_read_data(channel, data, MIXER_PAGE_SIZE);

		if (!run) {
			return -1;
		}

		mp3_decode(&mixer_map[channel].mp3, data, run, 0, 0, 0);

		return 0;
	}
}
예제 #4
0
void *loom_asset_soundDeserializer( void *buffer, size_t bufferLen, LoomAssetCleanupCallback *dtor )
{
    loom_asset_sound_t *sound = (loom_asset_sound_t*)lmAlloc(gAssetAllocator, sizeof(loom_asset_sound_t));
    memset(sound, 0, sizeof(loom_asset_sound_t));
    unsigned char *charBuff = (unsigned char *)buffer;

    // Look for magic header in buffer.
    if(charBuff[0] == 0x4f 
        && charBuff[1] == 0x67
        && charBuff[2] == 0x67
        && charBuff[3] == 0x53)
    {
        // It's an Ogg, assume vorbis and throw it to stb_vorbis.
        int channels = 0;
        short *outputBuffer = NULL;
        int sampleCount = stb_vorbis_decode_memory(charBuff, (int)bufferLen, &channels, &outputBuffer);
        if(sampleCount < 0)
        {
            lmLogError(gSoundAssetGroup, "Failed to decode Ogg Vorbis");
            loom_asset_soundDtor(&sound);
            return NULL;
        }

        sound->channels = channels;
        sound->bytesPerSample = 2;
        sound->sampleCount = sampleCount;
        sound->bufferSize = sampleCount * channels * 2;
        sound->sampleRate = 44100; // TODO: This should be variable

        // We can skip this if we get clever about allocations in stbv.
        sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize);
        memcpy(sound->buffer, outputBuffer, sound->bufferSize);

        free(outputBuffer);
    }
    else if((charBuff[0] == 0x49 // ID3
        &&   charBuff[1] == 0x44
        &&   charBuff[2] == 0x33)
        ||  (charBuff[0] == 0xff // Missing ID3 Tag
        &&   charBuff[1] == 0xfb))
    {
        // It's an MP3, y'all!
        short *outBuffer = (short*)lmAlloc(gAssetAllocator, MP3_MAX_SAMPLES_PER_FRAME * 2);
        mp3_info_t mp3Info;

        // Decode once to get total size.
        size_t totalBytes = 0;
        size_t bytesRead = 0, bytesLeft = bufferLen;

        mp3_decoder_t decmp3 = mp3_create();
        for(;;)
        {
            int bytesDecoded = mp3_decode(decmp3, charBuff + bytesRead, (int)bytesLeft, outBuffer, &mp3Info);
            bytesRead += bytesDecoded;
            bytesLeft -= bytesDecoded;
            totalBytes += mp3Info.audio_bytes;
            if(bytesDecoded > 0)
                continue;

            // Clean up.
            mp3_done(decmp3);
            break;
        }

        // Great, set up the sound asset.
        // TODO: Warn about non 44.1khz mp3s.
        sound->channels = mp3Info.channels;
        sound->bytesPerSample = 2;
        sound->sampleCount = (int)totalBytes / sound->bytesPerSample;
        sound->bufferSize = sound->channels * sound->bytesPerSample * sound->sampleCount;
        sound->sampleRate = 44100; // TODO: This should be variable
        sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize);

        // Decode again to get real samples.        
        decmp3 = mp3_create();
        bytesRead = 0; bytesLeft = bufferLen;
        int curBufferOffset = 0;
        for(;;)
        {
            int bytesDecoded = mp3_decode(decmp3, charBuff + bytesRead, (int)bytesLeft, outBuffer, &mp3Info);
            bytesRead += bytesDecoded;
            bytesLeft -= bytesDecoded;

            memcpy(((unsigned char*)sound->buffer) + curBufferOffset, outBuffer, mp3Info.audio_bytes);
            curBufferOffset += mp3Info.audio_bytes;

            if(bytesDecoded > 0)
                continue;

            // Clean up.
            mp3_done(decmp3);
            break;
        }

        // Awesome, all set!
        lmFree(gAssetAllocator, outBuffer);
    }
    else if(charBuff[0] == 0x52 // 'RIFF'
         && charBuff[1] == 0x49
         && charBuff[2] == 0x46
         && charBuff[3] == 0x46)
    {
        // We've got a wav file
        wav_info wav;
        bool wavLoadSuccess = load_wav(charBuff, bufferLen, NULL, &wav);
        if (!wavLoadSuccess)
        {
            lmLogError(gSoundAssetGroup, "Failed to load wav format info");
            loom_asset_soundDtor(sound);
            return 0;
        }
        
        sound->channels = wav.numChannels;
        sound->bytesPerSample = wav.sampleSize / 8; // wav sample size is in bits
        if (sound->bytesPerSample != 1 && sound->bytesPerSample != 2)
        {
            lmLogError(gSoundAssetGroup, "Unsupported wav format. Currently only 8-bit or 16-bit PCM are supported");
            loom_asset_soundDtor(sound);
            return 0;
        }
        sound->bufferSize = wav.sampleDataSize;
        sound->sampleCount = sound->bufferSize / sound->bytesPerSample;
        sound->sampleRate = wav.samplesPerSecond;
        
        sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize);
        bool dataCopySuccess = load_wav(charBuff, bufferLen, (uint8_t*)sound->buffer, NULL);
        if (!dataCopySuccess)
        {
            lmLogError(gSoundAssetGroup, "Failed to copy wav data");
            loom_asset_soundDtor(sound);
            return 0;
        }
    }
    else
    {
        lmLogError(gSoundAssetGroup, "Failed to identify sound buffer by magic number!");
        loom_asset_soundDtor(sound);
        return 0;
    }

   *dtor = loom_asset_soundDtor;
   if(!sound->buffer)
   {
      lmLogError(gSoundAssetGroup, "Sound load failed due to this cryptic reason: %s", "(unknown)");
      lmFree(gAssetAllocator, sound);
      return 0;
   }

    lmLogDebug(gSoundAssetGroup, "Sound allocation: %d bytes", sound->bufferSize);
    return sound;
}
예제 #5
0
void *loom_asset_soundDeserializer( void *buffer, size_t bufferLen, LoomAssetCleanupCallback *dtor )
{
   loom_asset_sound_t *sound = (loom_asset_sound_t*)lmAlloc(gAssetAllocator, sizeof(loom_asset_sound_t));
   unsigned char *charBuff = (unsigned char *)buffer;

    // Look for magic header in buffer.
    if(charBuff[0] == 0x4f 
        && charBuff[1] == 0x67
        && charBuff[2] == 0x67
        && charBuff[3] == 0x53)
    {
        // It's an Ogg, assume vorbis and throw it to stb_vorbis.
        int channels = 0;
        short *outputBuffer = NULL;
        int sampleCount = stb_vorbis_decode_memory(charBuff, bufferLen, &channels, &outputBuffer);
        if(sampleCount < 0)
        {
            lmLogError(gSoundAssetGroup, "Failed to decode Ogg Vorbis!");
            return NULL;
        }

        sound->channels = channels;
        sound->bytesPerSample = 2;
        sound->sampleCount = sampleCount;
        sound->bufferSize = sampleCount * channels * 2;

        // We can skip this if we get clever about allocations in stbv.
        sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize);
        memcpy(sound->buffer, outputBuffer, sound->bufferSize);

        free(outputBuffer);
    }
    else if((charBuff[0] == 0x49 // ID3
        &&   charBuff[1] == 0x44
        &&   charBuff[2] == 0x33)
        ||  (charBuff[0] == 0xff // Missing ID3 Tag
        &&   charBuff[1] == 0xfb))
    {
        // It's an MP3, y'all!
        short *outBuffer = (short*)lmAlloc(gAssetAllocator, MP3_MAX_SAMPLES_PER_FRAME * 2);
        mp3_info_t mp3Info;

        // Decode once to get total size.
        int totalBytes = 0;
        int bytesRead = 0, bytesLeft = bufferLen;

        mp3_decoder_t decmp3 = mp3_create();
        for(;;)
        {
            int bytesDecoded = mp3_decode(decmp3, charBuff + bytesRead, bytesLeft, outBuffer, &mp3Info);
            bytesRead += bytesDecoded;
            bytesLeft -= bytesDecoded;
            totalBytes += mp3Info.audio_bytes;
            if(bytesDecoded > 0)
                continue;

            // Clean up.
            mp3_done(decmp3);
            break;
        }

        // Great, set up the sound asset.
        // TODO: Warn about non 44.1khz mp3s.
        sound->channels = mp3Info.channels;
        sound->bytesPerSample = 2;
        sound->sampleCount = totalBytes / sound->bytesPerSample;
        sound->bufferSize = sound->channels * sound->bytesPerSample * sound->sampleCount;
        sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize);

        // Decode again to get real samples.        
        decmp3 = mp3_create();
        bytesRead = 0; bytesLeft = bufferLen;
        int curBufferOffset = 0;
        for(;;)
        {
            int bytesDecoded = mp3_decode(decmp3, charBuff + bytesRead, bytesLeft, outBuffer, &mp3Info);
            bytesRead += bytesDecoded;
            bytesLeft -= bytesDecoded;

            memcpy(((unsigned char*)sound->buffer) + curBufferOffset, outBuffer, mp3Info.audio_bytes);
            curBufferOffset += mp3Info.audio_bytes;

            if(bytesDecoded > 0)
                continue;

            // Clean up.
            mp3_done(decmp3);
            break;
        }

        // Awesome, all set!
        lmFree(gAssetAllocator, outBuffer);
    }
    else
    {
        lmLogError(gSoundAssetGroup, "Failed to identify sound buffer by magic number!");
        return 0;
    }

   *dtor = loom_asset_soundDtor;
   if(!sound->buffer)
   {
      lmLogError(gSoundAssetGroup, "Sound load failed due to this cryptic reason: %s", "(unknown)");
      lmFree(gAssetAllocator, sound);
      return 0;
   }

   lmLogError(gSoundAssetGroup, "Allocated %d bytes for a sound!", sound->bufferSize);
   return sound;
}
예제 #6
0
static adv_error mixer_mp3_pump(unsigned channel)
{
	unsigned char buffer[2304*4]; /* 2304 samples for MP3 frame */
	unsigned nmin;
	unsigned nmax;
	int bytes_done;
	int err;

	if (mixer_channel_input_is_empty(channel))
		return -1;

	if (mixer_map[channel].rate) {
		/* check for avaiable space */
		mixer_channel_need(channel, &nmin, &nmax);

		/* no space */
		if (nmax < 2304)
			return -1;

		/* no need */
		if (nmin == 0)
			return -1;
	}

	bytes_done = 0;
	err = mp3_decode(&mixer_map[channel].mp3, 0, 0, buffer, sizeof(buffer)/2, &bytes_done);

	/* insert data until it's required */
	while (err == MP3_NEED_MORE && mp3_read_stream(channel)==0) {
		err = mp3_decode(&mixer_map[channel].mp3, 0, 0, buffer, sizeof(buffer)/2, &bytes_done);
	}

	if (err == MP3_NEED_MORE) {
		/* end of the stream */
		mixer_map[channel].empty = 1;
		return -1;
	}

	if (err != MP3_OK) {
		/* generic error */
		mixer_channel_abort(channel);
		return -1;
	}

	if (!bytes_done)
		/* no data ? exit */
		return 0;

	/* delayed set of the channel */
	if (!mixer_map[channel].rate) {
		unsigned rate;
		unsigned nchannel;
		unsigned bit;

		rate = mp3_freqs[mixer_map[channel].mp3.fr.sampling_frequency];
		nchannel = mixer_map[channel].mp3.fr.stereo; /* this is correct, stereo is the number of channel */
		bit = 16;

		mixer_channel_set(channel, rate, nchannel, bit);
	}

	/* override the nchannel value */
	if (mixer_map[channel].mp3.fr.stereo == 1) {
		mixer_channel_mix_mono16(channel, buffer, bytes_done / 2);
	} else {
		mixer_channel_mix_stereo16(channel, buffer, bytes_done / 4);
	}

	return 0;
}
예제 #7
0
static adv_error mp3_first_read_stream(unsigned channel)
{
	unsigned char data[MIXER_PAGE_SIZE];
	unsigned pos = 0;
	unsigned run = mp3_read_data(channel, data, MIXER_PAGE_SIZE);
	if (!run) {
		return -1;
	}

	if (run>=12
		&& data[0]=='R' && data[1]=='I' && data[2]=='F' && data[3]=='F'
		&& data[8]=='W' && data[9]=='A' && data[10]=='V' && data[11]=='E') {
		/* RIFF header */
		unsigned char id[4];

		log_std(("mixer: skip RIFF header\n"));

		if (mp3_skip(channel, 12, data, &pos, &run) != 0)
			return -1;

		if (mp3_read_id(id, channel, data, &pos, &run) != 0)
			return -1;

		while (memcmp(id, "data", 4)!=0) {
			unsigned size;
			if (mp3_read_le32(&size, channel, data, &pos, &run) != 0)
				return -1;
			if (size % 2)
				size += 1;

			if (mp3_skip(channel, size, data, &pos, &run) != 0)
				return -1;

			if (mp3_read_id(id, channel, data, &pos, &run) != 0)
				return -1;
		}

		if (mp3_skip(channel, 4, data, &pos, &run) != 0)
			return -1;

	} else if (run>=10 && data[0]=='I' && data[1]=='D' && data[2]=='3'
		&& data[3]!=0xFF && data[4]!=0xFF
		&& (data[6] & 0x80) == 0 && (data[7] & 0x80) == 0
		&& (data[8] & 0x80) == 0 && (data[9] & 0x80) == 0) {

		/* ID3 tag header */
		unsigned size = (unsigned)data[9] | (((unsigned)data[8]) << 7) | (((unsigned)data[7]) << 14) | (((unsigned)data[6]) << 21);
		size += 10;

		log_std(("mixer: skip ID3 header %d\n", size));

		if (mp3_skip(channel, size, data, &pos, &run) != 0)
			return -1;
	}

	if (run>=4 && !mp3_is_valid(data + pos))
		return -1;

	/* insert the data */
	if (run)
		mp3_decode(&mixer_map[channel].mp3, data + pos, run, 0, 0, 0);

	return 0;
}