Beispiel #1
0
VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];

    int loop_flag=0;
    int channel_count;
	off_t start_offset;

	uint8_t	testBuffer[0x10];
	off_t	readOffset = 0;
	off_t	loopEnd = 0;

    int i;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("ads",filename_extension(filename)) && 
        strcasecmp("ss2",filename_extension(filename))) goto fail;

    /* check SShd Header */
    if (read_32bitBE(0x00,streamFile) != 0x53536864)
        goto fail;

    /* check SSbd Header */
    if (read_32bitBE(0x20,streamFile) != 0x53536264)
        goto fail;

    /* check if file is not corrupt */
    if (get_streamfile_size(streamFile)<(size_t)(read_32bitLE(0x24,streamFile) + 0x28))
        goto fail;

    /* check loop */
    loop_flag = (read_32bitLE(0x1C,streamFile)!=0xFFFFFFFF);

    channel_count=read_32bitLE(0x10,streamFile);

    /* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

    /* fill in the vital statistics */
    vgmstream->channels = read_32bitLE(0x10,streamFile);
    vgmstream->sample_rate = read_32bitLE(0x0C,streamFile);

    /* Check for Compression Scheme */
    vgmstream->coding_type = coding_PSX;
    vgmstream->num_samples = ((read_32bitLE(0x24,streamFile)-0x40)/16*28)/vgmstream->channels;

	/* SS2 container with RAW Interleaved PCM */
    if (read_32bitLE(0x08,streamFile)!=0x10) {
        vgmstream->coding_type=coding_PCM16LE;
        vgmstream->num_samples = read_32bitLE(0x24,streamFile)/2/vgmstream->channels;
    }

    vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile);
    vgmstream->layout_type = layout_interleave;
    vgmstream->meta_type = meta_PS2_SShd;

    /* Get loop point values */
    if(vgmstream->loop_flag) {
		if((read_32bitLE(0x1C,streamFile)*0x10*vgmstream->channels+0x800)==get_streamfile_size(streamFile)) 
		{
			// Search for Loop Value
			readOffset=(off_t)get_streamfile_size(streamFile)-(4*vgmstream->interleave_block_size); 

			do {
				readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); 
	
				// Loop End ...
				if(testBuffer[0x01]==0x01) {
					if(loopEnd==0) loopEnd = readOffset-0x10;
					break;
				}

			} while (streamFile->get_offset(streamFile)<(int32_t)get_streamfile_size(streamFile));

			vgmstream->loop_start_sample = 0;
			vgmstream->loop_end_sample = (loopEnd/(vgmstream->interleave_block_size)*vgmstream->interleave_block_size)/16*28;
			vgmstream->loop_end_sample += (loopEnd%vgmstream->interleave_block_size)/16*28;
			vgmstream->loop_end_sample /=vgmstream->channels;

		} else {
			if(read_32bitLE(0x1C,streamFile)<=vgmstream->num_samples) {
			vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile);
			vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile);
		} else {
				vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*0x10)/16*28/vgmstream->channels;;
				vgmstream->loop_end_sample = (read_32bitLE(0x1C,streamFile)*0x10)/16*28/vgmstream->channels;
		}
    }
    }

    /* don't know why, but it does happen, in ps2 too :( */
    if (vgmstream->loop_end_sample > vgmstream->num_samples)
        vgmstream->loop_end_sample = vgmstream->num_samples;

	start_offset=0x28;

	// Hack for files with start_offset = 0x800
	if(get_streamfile_size(streamFile)-read_32bitLE(0x24,streamFile)>=0x800)
		start_offset=0x800;

	if((vgmstream->coding_type == coding_PSX) && (start_offset==0x28)) {
		start_offset=0x800;
		for(i=0;i<0x1f6;i+=4) {
			if(read_32bitLE(0x28+(i*4),streamFile)!=0) {
				start_offset=0x28;
				break;
	}
		}
	} 

	/* expect pcm format allways start @ 0x800, don't know if it's true :P */
	/*if(vgmstream->coding_type == coding_PCM16LE)
		start_offset=0x800;*/

    /* open the file for reading by each channel */
    {
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8000);

            if (!vgmstream->ch[i].streamfile) goto fail;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=
                (off_t)(start_offset+vgmstream->interleave_block_size*i);
        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #2
0
/* BO2 (Blood Omen 2 NGC) */
VGMSTREAM * init_vgmstream_ngc_bo2(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[1024];
    int loop_flag;
  	int channels;
    int channel_count;
    off_t start_offset;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("bo2",filename_extension(filename))) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0x0) /* "IDSP" */
        goto fail;

    switch (read_32bitBE(0x10,streamFile))
    {
    	case 0x0:
    	  channels = 1;
    	break;
      case 0x1:
        channels = 2;
      break;
        default:
          goto fail;
    }
    
    if ((get_streamfile_size(streamFile)) < ((read_32bitBE(0x0C,streamFile)/14*8*channels)+0x800))
    {
      goto fail;
    }

    channel_count = channels;
    loop_flag = (read_32bitBE(0x08,streamFile) != 0xFFFFFFFF);

	  /* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	  /* fill in the vital statistics */
    start_offset = 0x800;
	  vgmstream->channels = channel_count;
    vgmstream->sample_rate = read_32bitBE(0x04,streamFile);
    vgmstream->coding_type = coding_NGC_DSP;
    vgmstream->num_samples = read_32bitBE(0x0C,streamFile);
    if (loop_flag) {
        vgmstream->loop_start_sample = read_32bitBE(0x08,streamFile);
        vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile);
    }

    if (channel_count == 1)
    {
      vgmstream->layout_type = layout_none;
    }
    else
    {
      vgmstream->layout_type = layout_interleave;
      vgmstream->interleave_block_size = 0x400;
    }
    
    vgmstream->meta_type = meta_NGC_BO2;

			{
				int i;
				for (i=0;i<16;i++)
					vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x24+i*2,streamFile);
				if (channel_count == 2) {
				for (i=0;i<16;i++)
					vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x52+i*2,streamFile);
				}
      }

    /* open the file for reading */
    {
        int i;
        STREAMFILE * file;
        file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!file) goto fail;
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = file;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=start_offset+
                vgmstream->interleave_block_size*i;

        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #3
0
VGMSTREAM * init_vgmstream_ps2_npsf(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];

    int loop_flag=0;
	int channel_count;
    off_t start_offset;
    int i;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("npsf",filename_extension(filename))) goto fail;

    /* check NPSF Header */
    if (read_32bitBE(0x00,streamFile) != 0x4E505346)
        goto fail;

	/* check loop */
	loop_flag = (read_32bitLE(0x14,streamFile)!=0xFFFFFFFF);
    channel_count=read_32bitLE(0x0C,streamFile);
    
	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	/* fill in the vital statistics */
	vgmstream->channels = read_32bitLE(0x0C,streamFile);
    vgmstream->sample_rate = read_32bitLE(0x18,streamFile);

	/* Check for Compression Scheme */
	vgmstream->coding_type = coding_PSX;
    vgmstream->num_samples = read_32bitLE(0x08,streamFile)*28/16;

	/* Get loop point values */
	if(vgmstream->loop_flag) {
		vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile);
		vgmstream->loop_end_sample = read_32bitLE(0x08,streamFile)*28/16;
	}

	vgmstream->interleave_block_size = read_32bitLE(0x04,streamFile)/2;
    vgmstream->meta_type = meta_PS2_NPSF;
    start_offset = (off_t)read_32bitLE(0x10,streamFile);

    if (vgmstream->channels == 1) {
        vgmstream->layout_type = layout_none;
    } else {
        vgmstream->layout_type = layout_interleave;
    }

    /* open the file for reading by each channel */
    {
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8000);

            if (!vgmstream->ch[i].streamfile) goto fail;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=
                (off_t)(start_offset+vgmstream->interleave_block_size*i);
        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #4
0
VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const char * filename, ov_callbacks *callbacks_p, off_t other_header_bytes, const vgm_vorbis_info_t *vgm_inf) {
    VGMSTREAM * vgmstream = NULL;

    OggVorbis_File temp_ovf;
    ogg_vorbis_streamfile temp_streamfile;

    ogg_vorbis_codec_data * data = NULL;
    OggVorbis_File *ovf;
    int inited_ovf = 0;
    vorbis_info *info;

    int loop_flag = vgm_inf->loop_flag;
    int32_t loop_start = vgm_inf->loop_start;
    int loop_length_found = vgm_inf->loop_length_found;
    int32_t loop_length = vgm_inf->loop_length;
    int loop_end_found = vgm_inf->loop_end_found;
    int32_t loop_end = vgm_inf->loop_end;

    ov_callbacks default_callbacks;

    if (!callbacks_p) {
        default_callbacks.read_func = read_func;
        default_callbacks.seek_func = seek_func;
        default_callbacks.close_func = close_func;
        default_callbacks.tell_func = tell_func;

        if (vgm_inf->scd_xor != 0) {
            default_callbacks.read_func = read_func_scd;
        }

        callbacks_p = &default_callbacks;
    }

    temp_streamfile.streamfile = streamFile;
    temp_streamfile.offset = 0;
    temp_streamfile.size = get_streamfile_size(temp_streamfile.streamfile);
    temp_streamfile.other_header_bytes = other_header_bytes;
    temp_streamfile.scd_xor  = vgm_inf->scd_xor;
    temp_streamfile.scd_xor_len = vgm_inf->scd_xor_len;

    /* can we open this as a proper ogg vorbis file? */
    memset(&temp_ovf, 0, sizeof(temp_ovf));
    if (ov_test_callbacks(&temp_streamfile, &temp_ovf, NULL,
            0, *callbacks_p)) goto fail;

    /* we have to close this as it has the init_vgmstream meta-reading
       STREAMFILE */
    ov_clear(&temp_ovf);

    /* proceed to open a STREAMFILE just for this stream */
    data = calloc(1,sizeof(ogg_vorbis_codec_data));
    if (!data) goto fail;

    data->ov_streamfile.streamfile = streamFile->open(streamFile,filename,
            STREAMFILE_DEFAULT_BUFFER_SIZE);
    if (!data->ov_streamfile.streamfile) goto fail;
    data->ov_streamfile.offset = 0;
    data->ov_streamfile.size = get_streamfile_size(data->ov_streamfile.streamfile);
    data->ov_streamfile.other_header_bytes = other_header_bytes;
    data->ov_streamfile.scd_xor  = vgm_inf->scd_xor;
    data->ov_streamfile.scd_xor_len = vgm_inf->scd_xor_len;

    /* open the ogg vorbis file for real */
    if (ov_open_callbacks(&data->ov_streamfile, &data->ogg_vorbis_file, NULL,
                0, *callbacks_p)) goto fail;
    ovf = &data->ogg_vorbis_file;
    inited_ovf = 1;

    data->bitstream = DEFAULT_BITSTREAM;

    info = ov_info(ovf,DEFAULT_BITSTREAM);

    /* grab the comments */
    {
        int i;
        vorbis_comment *comment;

        comment = ov_comment(ovf,DEFAULT_BITSTREAM);

        /* search for a "loop_start" comment */
        for (i=0;i<comment->comments;i++) {
            if (strstr(comment->user_comments[i],"loop_start=")==
                    comment->user_comments[i] ||
                strstr(comment->user_comments[i],"LOOP_START=")==
                    comment->user_comments[i] ||
                strstr(comment->user_comments[i],"COMMENT=LOOPPOINT=")==
                    comment->user_comments[i] ||
                strstr(comment->user_comments[i],"LOOPSTART=")==
                    comment->user_comments[i] ||
                strstr(comment->user_comments[i],"um3.stream.looppoint.start=")==
                    comment->user_comments[i] ||
                strstr(comment->user_comments[i],"LOOP_BEGIN=")==
                    comment->user_comments[i] ||
                strstr(comment->user_comments[i],"LoopStart=")==
                    comment->user_comments[i]
                    ) {
                loop_start=atol(strrchr(comment->user_comments[i],'=')+1);
                if (loop_start >= 0)
                    loop_flag=1;
            }
            else if (strstr(comment->user_comments[i],"LOOPLENGTH=")==
                    comment->user_comments[i]) {
                loop_length=atol(strrchr(comment->user_comments[i],'=')+1);
                loop_length_found=1;
            }
            else if (strstr(comment->user_comments[i],"title=-lps")==
                    comment->user_comments[i]) {
                loop_start=atol(comment->user_comments[i]+10);
                if (loop_start >= 0)
                    loop_flag=1;
            }
            else if (strstr(comment->user_comments[i],"album=-lpe")==
                    comment->user_comments[i]) {
                loop_end=atol(comment->user_comments[i]+10);
                loop_flag=1;
                loop_end_found=1;
            }
            else if (strstr(comment->user_comments[i],"LoopEnd=")==
                    comment->user_comments[i]) {
						if(loop_flag) {
							loop_length=atol(strrchr(comment->user_comments[i],'=')+1)-loop_start;
							loop_length_found=1;
						}
            }
            else if (strstr(comment->user_comments[i],"LOOP_END=")==
                    comment->user_comments[i]) {
						if(loop_flag) {
							loop_length=atol(strrchr(comment->user_comments[i],'=')+1)-loop_start;
							loop_length_found=1;
						}
            }
            else if (strstr(comment->user_comments[i],"lp=")==
                    comment->user_comments[i]) {
                sscanf(strrchr(comment->user_comments[i],'=')+1,"%d,%d",
                        &loop_start,&loop_end);
                loop_flag=1;
                loop_end_found=1;
            }
            else if (strstr(comment->user_comments[i],"COMMENT=loop(")==
                    comment->user_comments[i]) {
                sscanf(strrchr(comment->user_comments[i],'(')+1,"%d,%d",
                        &loop_start,&loop_end);
                loop_flag=1;
                loop_end_found=1;
            }
        }
    }

    /* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(info->channels,loop_flag);
    if (!vgmstream) goto fail;

    /* store our fun extra datas */
    vgmstream->codec_data = data;

    /* fill in the vital statistics */
    vgmstream->channels = info->channels;
    vgmstream->sample_rate = info->rate;

    /* let's play the whole file */
    vgmstream->num_samples = ov_pcm_total(ovf,-1);

    if (loop_flag) {
        vgmstream->loop_start_sample = loop_start;
        if (loop_length_found)
            vgmstream->loop_end_sample = loop_start+loop_length;
        else if (loop_end_found)
            vgmstream->loop_end_sample = loop_end;
        else
            vgmstream->loop_end_sample = vgmstream->num_samples;
        vgmstream->loop_flag = loop_flag;

        if (vgmstream->loop_end_sample > vgmstream->num_samples)
            vgmstream->loop_end_sample = vgmstream->num_samples;
    }
    vgmstream->coding_type = coding_ogg_vorbis;
    vgmstream->layout_type = vgm_inf->layout_type;
    vgmstream->meta_type = vgm_inf->meta_type;

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (data) {
        if (inited_ovf)
            ov_clear(&data->ogg_vorbis_file);
        if (data->ov_streamfile.streamfile)
            close_streamfile(data->ov_streamfile.streamfile);
        free(data);
    }
    if (vgmstream) {
        vgmstream->codec_data = NULL;
        close_vgmstream(vgmstream);
    }
    return NULL;
}
Beispiel #5
0
Datei: pcm.c Projekt: 1c0n/xbmc
/* PCM (from Ephemeral Fantasia) */
VGMSTREAM * init_vgmstream_pcm(STREAMFILE *streamFile) {

	VGMSTREAM * vgmstream = NULL;
	char filename[260];
	off_t start_offset;

    int loop_flag;
    int channel_count;

	/* check extension, case insensitive */
	streamFile->get_name(streamFile,filename,sizeof(filename));
	if (strcasecmp("pcm",filename_extension(filename))) goto fail;

	/* check header */
    if (read_32bitBE(0x0C,streamFile) ==0x0AA00AA0) {

		loop_flag = (read_32bitLE(0x02,streamFile)!=0);
		channel_count = 1;
	 
		/* build the VGMSTREAM */
		vgmstream = allocate_vgmstream(channel_count,loop_flag);
		if (!vgmstream) goto fail;

		/* fill in the vital statistics */
		start_offset = 0x200;
		vgmstream->channels = channel_count;
		vgmstream->sample_rate = 44100;
		vgmstream->coding_type = coding_PCM8_SB_int;
		vgmstream->num_samples = read_32bitBE(0x06,streamFile)*2;

		if(loop_flag) {
			vgmstream->loop_start_sample = read_32bitBE(0x02,streamFile)*2;
			vgmstream->loop_end_sample = read_32bitBE(0x06,streamFile)*2;
		}
		vgmstream->layout_type = layout_interleave;
		vgmstream->interleave_block_size = 0x2;
		vgmstream->meta_type = meta_PCM;

	} else if (read_32bitBE(0x410,streamFile) ==0x9CDB0740) {

		loop_flag = (read_32bitLE(0x0C,streamFile)!=0);
		channel_count = 2;
 
		/* build the VGMSTREAM */
		vgmstream = allocate_vgmstream(channel_count,loop_flag);
		if (!vgmstream) goto fail;

		/* fill in the vital statistics */
		start_offset = 0x800;
		vgmstream->channels = channel_count;
		vgmstream->sample_rate = 22050;
		vgmstream->coding_type = coding_PCM16LE;
		vgmstream->num_samples = read_32bitLE(0x4,streamFile);

        if(loop_flag == 1) {
			vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile);
			vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile);
		}

		vgmstream->layout_type = layout_interleave;
		vgmstream->interleave_block_size = 0x2;
		vgmstream->meta_type = meta_PCM;
	} else if ((read_32bitBE(0x0,streamFile) ==0x786D6402) || 
				(read_32bitBE(0x0,streamFile) ==0x786D6401)) {
		loop_flag = 0;
		channel_count = read_8bit(0x03,streamFile);
 
		/* build the VGMSTREAM */
		vgmstream = allocate_vgmstream(channel_count,loop_flag);
		if (!vgmstream) goto fail;

		/* fill in the vital statistics */
		start_offset = 0x10;
		vgmstream->channels = channel_count;
		vgmstream->sample_rate = (int32_t)(read_16bitLE(0x4,streamFile) & 0x0000ffff);
		vgmstream->coding_type = coding_PCM8_int;
		vgmstream->num_samples = read_32bitLE(0x6,streamFile);

        if(loop_flag == 1) {
			vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile);
			vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile);
		}

		vgmstream->layout_type = layout_interleave;
		vgmstream->interleave_block_size = 0x8;
		vgmstream->meta_type = meta_PCM;
	} else
		goto fail;

	/* open the file for reading */
	{
		int i;
		STREAMFILE * file;
		file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
		if (!file) goto fail;
		for (i=0;i<channel_count;i++) {
			vgmstream->ch[i].streamfile = file;
			vgmstream->ch[i].channel_start_offset=
              vgmstream->ch[i].offset=start_offset+
              vgmstream->interleave_block_size*i;

		}
	}

	return vgmstream;

  /* clean up anything we may have opened */
fail:
  if (vgmstream) close_vgmstream(vgmstream);
  return NULL;
}
Beispiel #6
0
/* BGW - from Final Fantasy XI (PC) music files */
VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    STREAMFILE *temp_streamFile = NULL;
    uint32_t codec, file_size, block_size, sample_rate, block_align;
    int32_t loop_start;
    off_t start_offset;

    int channel_count, loop_flag = 0;

    /* check extensions */
    if ( !check_extensions(streamFile, "bgw") )
        goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0x42474d53 || /* "BGMS" */
        read_32bitBE(0x04,streamFile) != 0x74726561 || /* "trea" */
        read_32bitBE(0x08,streamFile) != 0x6d000000 )  /* "m\0\0\0" */
        goto fail;

    codec = read_32bitLE(0x0c,streamFile);
    file_size = read_32bitLE(0x10,streamFile);
    /*file_id = read_32bitLE(0x14,streamFile);*/
    block_size = read_32bitLE(0x18,streamFile);
    loop_start = read_32bitLE(0x1c,streamFile);
    sample_rate = (read_32bitLE(0x20,streamFile) + read_32bitLE(0x24,streamFile)) & 0x7FFFFFFF; /* bizarrely obfuscated sample rate */
    start_offset = read_32bitLE(0x28,streamFile);
    /*0x2c: unk (vol?) */
    /*0x2d: unk (0x10?) */
    channel_count = read_8bit(0x2e,streamFile);
    block_align = (uint8_t)read_8bit(0x2f,streamFile);

    if (file_size != get_streamfile_size(streamFile))
        goto fail;

    loop_flag = (loop_start > 0);

    /* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

    vgmstream->meta_type = meta_FFXI_BGW;
    vgmstream->sample_rate = sample_rate;

    switch (codec) {
        case 0: /* PS ADPCM */
            vgmstream->coding_type = coding_PSX_cfg;
            vgmstream->layout_type = layout_interleave;
            vgmstream->interleave_block_size = (block_align / 2) + 1; /* half, even if channels = 1 */

            vgmstream->num_samples = block_size * block_align;
            if (loop_flag) {
                vgmstream->loop_start_sample = (loop_start-1) * block_align;
                vgmstream->loop_end_sample = vgmstream->num_samples;
            }
            
            break;

#ifdef VGM_USE_FFMPEG
        case 3: { /* ATRAC3 (encrypted) */
            uint8_t buf[0x100];
            int bytes, joint_stereo, skip_samples;
            size_t data_size = file_size - start_offset;

            vgmstream->num_samples = block_size; /* atrac3_bytes_to_samples gives the same value */
            if (loop_flag) {
                vgmstream->loop_start_sample = loop_start;
                vgmstream->loop_end_sample = vgmstream->num_samples;
            }

            block_align  = 0xC0 * vgmstream->channels; /* 0x00 in header */
            joint_stereo = 0;
            skip_samples = 0;

            bytes = ffmpeg_make_riff_atrac3(buf, 0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_align, joint_stereo, skip_samples);
            if (bytes <= 0) goto fail;

            temp_streamFile = setup_bgw_atrac3_streamfile(streamFile, start_offset,data_size, 0xC0,channel_count);
            if (!temp_streamFile) goto fail;

            vgmstream->codec_data = init_ffmpeg_header_offset(temp_streamFile, buf,bytes, 0,data_size);
            if (!vgmstream->codec_data) goto fail;
            vgmstream->coding_type = coding_FFmpeg;
            vgmstream->layout_type = layout_none;

            close_streamfile(temp_streamFile);
            break;
        }
#endif

        default:
            goto fail;
    }


    if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
        goto fail;
    return vgmstream;

fail:
    close_streamfile(temp_streamFile);
    close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #7
0
/* Old MUSX format, this one handles "Sphinx and the cursed Mummy", it's different from the other formats */
VGMSTREAM * init_vgmstream_musx_v201(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];
    off_t start_offset;
	//int musx_version; /* 0x08 provides a "version" byte */
	int loop_flag;
	int channel_count;
	int loop_detect;
	int loop_offsets;
	
    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("musx",filename_extension(filename))) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0x4D555358) /* "MUSX" */
		goto fail;
	if (read_32bitBE(0x08,streamFile) != 0xC9000000) /* "0xC9000000" */
		goto fail;

    channel_count = 2;

	loop_detect = read_32bitBE(0x800,streamFile);
	switch (loop_detect) {
		case 0x02000000:
		loop_offsets = 0x8E0;
	break;
		case 0x03000000:
		loop_offsets = 0x880;
	break;
		case 0x04000000:
		loop_offsets = 0x8B4;
	break;
		case 0x05000000:
		loop_offsets = 0x8E8;
	break;
		case 0x06000000:
		loop_offsets = 0x91C;
	break;
		default:
			goto fail;
	}

	loop_flag = (read_32bitLE(loop_offsets+0x04,streamFile) !=0x00000000);

	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	/* fill in the vital statistics */	
		start_offset = read_32bitLE(0x18,streamFile);
		vgmstream->channels = channel_count;
		vgmstream->sample_rate = 32000;
		vgmstream->coding_type = coding_PSX;
		vgmstream->num_samples = read_32bitLE(loop_offsets,streamFile)*28/16/channel_count;
		if (loop_flag) {
			vgmstream->loop_start_sample = read_32bitLE(loop_offsets+0x10,streamFile)*28/16/channel_count;
			vgmstream->loop_end_sample = read_32bitLE(loop_offsets,streamFile)*28/16/channel_count;
		}
		vgmstream->layout_type = layout_interleave;
		vgmstream->interleave_block_size = 0x80;
		vgmstream->meta_type = meta_MUSX_V201;	
	
    /* open the file for reading */
    {
        int i;
        STREAMFILE * file;
        file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!file) goto fail;
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = file;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=start_offset+
                vgmstream->interleave_block_size*i;

        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #8
0
/* IVAG
	- The Idolm@ster: Gravure For You! Vol. 3 (PS3)

	Appears to be two VAGp streams interleaved.
*/
VGMSTREAM * init_vgmstream_ps3_ivag(STREAMFILE *streamFile) 
{
    VGMSTREAM * vgmstream = NULL;
    char filename[260];
    
	size_t fileLength;
	off_t readOffset = 0;
	off_t start_offset;

	int loop_flag = 0;
	int channel_count;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("ivag",filename_extension(filename))) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0x49564147) // "IVAG"
        goto fail;

	// channel count
	channel_count = read_32bitBE(0x08, streamFile);

	// header size
	start_offset = 0x40 + (0x40 * channel_count);
    
	// loop flag
	if ((read_32bitBE(0x14, streamFile) != 0 || 
		(read_32bitBE(0x18, streamFile) != 0)))
	{
		loop_flag = 1;
	}

	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	/* fill in the vital statistics */	
	vgmstream->channels = channel_count;
    vgmstream->sample_rate = read_32bitBE(0x0C,streamFile);
    vgmstream->coding_type = coding_PSX;
	vgmstream->num_samples = read_32bitBE(0x10,streamFile);
 
	if (loop_flag) 
	{
		vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile);
		vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile);
	}

    vgmstream->layout_type = layout_interleave;
    vgmstream->interleave_block_size = read_32bitBE(0x1C,streamFile);
    vgmstream->meta_type = meta_PS3_IVAG;

    /* open the file for reading */
    {
        int i;
        STREAMFILE * file;
        file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!file) goto fail;
        
		for (i=0;i<channel_count;i++) 
		{
            vgmstream->ch[i].streamfile = file;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=start_offset + (vgmstream->interleave_block_size * i);

        }
		
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #9
0
/* manakoAT 28.01.2009 :
	BAKA - found in "Crypt Killer (Saturn)...
    looks like some developers were really bored, every file starts with
    the word "BAKA" which is the japanese word for "IDIOT" :o)
    Files containing "begloop" markers at EOF...
	some files should loop, but i don't know how to get the loopstart here!*/
VGMSTREAM * init_vgmstream_sat_baka(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[PATH_LIMIT];
    off_t start_offset;
    int loop_flag = 0;
    int channel_count;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("baka",filename_extension(filename))) goto fail;

    /* check header */
    if ((read_32bitBE(0x00,streamFile) != 0x42414B41 &&  /* "BAKA" */
        read_32bitBE(0x08,streamFile) != 0x2041484F &&  /* " AHO" */
        read_32bitBE(0x0C,streamFile) != 0x50415041 &&  /* "PAPA" */
        read_32bitBE(0x26,streamFile) != 0x4D414D41))   /* "MAMA" */
    goto fail;

    
    channel_count = 2;
    
    /* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

    /* fill in the vital statistics */
    start_offset = 0x2E;
    vgmstream->channels = channel_count;
    vgmstream->sample_rate = 44100;
    vgmstream->coding_type = coding_PCM16BE;
    vgmstream->num_samples = read_32bitBE(0x16,streamFile);
    if (loop_flag) {
        vgmstream->loop_start_sample = 0;
        vgmstream->loop_end_sample = read_32bitBE(0x16,streamFile);
    }

    vgmstream->layout_type = layout_interleave;
    vgmstream->interleave_block_size = 0x2;
    vgmstream->meta_type = meta_SAT_BAKA;

    /* open the file for reading */
    {
        int i;
        STREAMFILE * file;
        file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!file) goto fail;
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = file;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=start_offset+
                vgmstream->interleave_block_size*i;

        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #10
0
Datei: vs.c Projekt: 1c0n/xbmc
/* VS (from Men in Black) */
VGMSTREAM * init_vgmstream_vs(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;

	char filename[260];
    off_t start_offset;
    int loop_flag = 0;
	int channel_count;
    int i;


    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("vs",filename_extension(filename))) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0xC8000000) /* "0xC8000000" */
        goto fail;

    loop_flag = 0;
    channel_count = 2;
    
	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	/* fill in the vital statistics */
    start_offset = 0x08;
	vgmstream->channels = channel_count;
	vgmstream->interleave_block_size=0x10;
    vgmstream->sample_rate = read_32bitLE(0x04,streamFile);
    vgmstream->coding_type = coding_PSX;

#if 0
	if (loop_flag) {
        vgmstream->loop_start_sample = 0;
        vgmstream->loop_end_sample = (read_32bitLE(0x0c,streamFile)-start_offset);
    }
#endif

	vgmstream->layout_type = layout_vs_blocked;
	vgmstream->meta_type = meta_VS;

    
	/* open the file for reading */
	{
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x2000);
            if (!vgmstream->ch[i].streamfile) goto fail;
        }
    }
	
	/* Calc num_samples */
	vs_block_update(start_offset,vgmstream);
	vgmstream->num_samples=0;

	do {
		vgmstream->num_samples += vgmstream->current_block_size*28/16;
		vs_block_update(vgmstream->next_block_offset,vgmstream);
	} while (vgmstream->next_block_offset<get_streamfile_size(streamFile));

	vs_block_update(start_offset,vgmstream);
    	

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #11
0
/* KCES (from Dance Dance Revolution) */
VGMSTREAM * init_vgmstream_ps2_kces(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];
    off_t start_offset;

    int loop_flag = 0;
	int channel_count;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("kces",filename_extension(filename)) &&
        strcasecmp("vig",filename_extension(filename))) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0x01006408)
        goto fail;

    loop_flag = 0; /* (read_32bitLE(0x08,streamFile)!=0); */
    channel_count = read_32bitLE(0x1C,streamFile);
    
	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	/* fill in the vital statistics */
    start_offset = read_32bitLE(0x08,streamFile);
	vgmstream->channels = channel_count;
    vgmstream->sample_rate = read_32bitLE(0x18,streamFile);
    vgmstream->coding_type = coding_PSX;
    vgmstream->num_samples = read_32bitLE(0x0C,streamFile)*28/16/channel_count;
    if (loop_flag) {
        vgmstream->loop_start_sample = 0;
        vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile)*28/16/channel_count;
    }


	if(vgmstream->channels==1) {
		vgmstream->layout_type=layout_none;
	} else {
		vgmstream->layout_type = layout_interleave;
		vgmstream->interleave_block_size = read_32bitLE(0x24,streamFile);
	}
    vgmstream->meta_type = meta_PS2_KCES;

    /* open the file for reading */
    {
        int i;
        STREAMFILE * file;
        file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!file) goto fail;
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = file;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=start_offset+
                vgmstream->interleave_block_size*i;

        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #12
0
/* SCD - Square-Enix games (FF XIII, XIV) */
VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    off_t start_offset, tables_offset, meta_offset, extradata_offset, name_offset = 0;
    int32_t stream_size, extradata_size, loop_start, loop_end;

    int loop_flag = 0, channel_count, codec, sample_rate;
    int version, target_entry, aux_chunk_count;
    int total_subsongs, target_subsong = streamFile->stream_index;

    int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
    int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;


    /* check extension, case insensitive */
    if ( !check_extensions(streamFile, "scd") )
        goto fail;

    /** main header **/
    if (read_32bitBE(0x00,streamFile) != 0x53454442 &&  /* "SEDB" */
        read_32bitBE(0x04,streamFile) != 0x53534346)    /* "SSCF" */
        goto fail;

    if (read_8bit(0x0c,streamFile) == 0x01) { /* big endian flag */
        //size_offset = 0x14;
        read_32bit = read_32bitBE;
        read_16bit = read_16bitBE;
    } else {
        //size_offset = 0x10;
        read_32bit = read_32bitLE;
        read_16bit = read_16bitLE;
    }

    /* SSCF version? (older SSCFs from Crisis Core/FFXI X360 seem to be V3/2) */
    if (read_8bit(0x0d,streamFile) != 0x04)
        goto fail;

    /* v2: FFXIII demo (PS3), FFT0 test files (PC); v3: common; v4: Kingdom Hearts 2.8 (PS4) */
    version = read_32bit(0x08,streamFile);
    if (version != 2 && version != 3 && version != 4)
        goto fail;

    tables_offset = read_16bit(0x0e,streamFile); /* usually 0x30 or 0x20 */

#if 0
    /* never mind, FFXIII music_68tak.ps3.scd is 0x80 shorter */
    /* check file size with header value */
    if (read_32bit(size_offset,streamFile) != get_streamfile_size(streamFile))
        goto fail;
#endif


    /** offset tables **/
    /* 0x00(2): table1/4 (unknown) entries */
    /* 0x02(2): table2 (unknown) entries */
    /* 0x04(2): table3 (headers) entries */
    /* 0x06(2): unknown, varies even for clone files */

    /* (implicit: table1 starts at 0x20) */
    /* 0x08: table2 (unknown) start offset */
    /* 0x0c: table3 (headers) start offset */
    /* 0x10: table4 (unknown) start offset */
    /* 0x14: always null? */
    /* 0x18: table5? (unknown) start offset? */
    /* 0x1c: unknown, often null */
    /* each table entry is an uint32_t offset; after entries there is padding */
    /* if a table isn't present entries is 0 and offset points to next table */

    /* find meta_offset in table3 (headers) and total subsongs */
    {
        int i;
        int headers_entries = read_16bit(tables_offset+0x04,streamFile);
        off_t headers_offset = read_32bit(tables_offset+0x0c,streamFile);

        if (target_subsong == 0) target_subsong = 1;
        total_subsongs = 0;
        meta_offset = 0;

        /* manually find subsongs as entries can be dummy (ex. sfx banks in FF XIV or FF Type-0) */
        for (i = 0; i < headers_entries; i++) {
            off_t entry_offset = read_32bit(headers_offset + i*0x04,streamFile);

            if (read_32bit(entry_offset+0x0c,streamFile) == -1)
                continue; /* codec -1 when dummy */

            total_subsongs++;
            if (!meta_offset && total_subsongs == target_subsong) {
                meta_offset = entry_offset;
                target_entry = i;
            }
        }
        if (meta_offset == 0) goto fail;
        /* SCD can contain 0 entries too */
    }

    /** stream header **/
    stream_size     = read_32bit(meta_offset+0x00,streamFile);
    channel_count   = read_32bit(meta_offset+0x04,streamFile);
    sample_rate     = read_32bit(meta_offset+0x08,streamFile);
    codec           = read_32bit(meta_offset+0x0c,streamFile);

    loop_start      = read_32bit(meta_offset+0x10,streamFile);
    loop_end        = read_32bit(meta_offset+0x14,streamFile);
    extradata_size  = read_32bit(meta_offset+0x18,streamFile);
    aux_chunk_count = read_32bit(meta_offset+0x1c,streamFile);
    /* 0x01e(2): unknown, seen in some FF XIV sfx (MSADPCM) */

    loop_flag       = (loop_end > 0);
    extradata_offset = meta_offset + 0x20;
    start_offset = extradata_offset + extradata_size;

    /* only "MARK" chunk is known (some FF XIV PS3 have "STBL" but it's not counted) */
    if (aux_chunk_count > 1 && aux_chunk_count < 0xFFFF) { /* some FF XIV Heavensward IMA sfx have 0x01000000 */
        VGM_LOG("SCD: unknown aux chunk count %i\n", aux_chunk_count);
        goto fail;
    }

    /* skips aux chunks, sometimes needed (Lightning Returns X360, FF XIV PC) */
    if (aux_chunk_count && read_32bitBE(extradata_offset, streamFile) == 0x4D41524B) { /* "MARK" */
        extradata_offset += read_32bit(extradata_offset+0x04, streamFile);
    }

    /* find name if possible */
    if (version == 4) {
        int info_entries    = read_16bit(tables_offset+0x00,streamFile);
        int headers_entries = read_16bit(tables_offset+0x04,streamFile);
        off_t info_offset   = tables_offset+0x20;

        /* not very exact as table1 and table3 entries may differ in V3, not sure about V4 */
        if (info_entries == headers_entries) {
            off_t entry_offset = read_16bit(info_offset + 0x04*target_entry,streamFile);
            name_offset = entry_offset+0x30;
        }
    }


#ifdef VGM_USE_VORBIS
    /* special case using init_vgmstream_ogg_vorbis */
    if (codec == 0x06) {
        VGMSTREAM *ogg_vgmstream;
        uint8_t ogg_version, ogg_byte;
        ogg_vorbis_meta_info_t ovmi = {0};

        ovmi.meta_type = meta_SQEX_SCD;
        ovmi.total_subsongs = total_subsongs;
        /* loop values are in bytes, let init_vgmstream_ogg_vorbis find loop comments instead */

        ogg_version = read_8bit(extradata_offset + 0x00, streamFile);
        /* 0x01(1): 0x20 in v2/3, this ogg miniheader size? */
        ogg_byte    = read_8bit(extradata_offset + 0x02, streamFile);
        /* 0x03(1): ? in v3 */

        if (ogg_version == 0) { /* 0x10? header, then custom Vorbis header before regular Ogg (FF XIV PC v1) */
            ovmi.stream_size = stream_size;
        }
        else { /* 0x20 header, then seek table */
            size_t seek_table_size  = read_32bit(extradata_offset+0x10, streamFile);
            size_t vorb_header_size = read_32bit(extradata_offset+0x14, streamFile);
            /* 0x18(4): ? (can be 0) */

            if ((extradata_offset-meta_offset) + seek_table_size + vorb_header_size != extradata_size)
                goto fail;

            ovmi.stream_size = vorb_header_size + stream_size;
            start_offset = extradata_offset + 0x20 + seek_table_size; /* extradata_size skips vorb_header */

            if (ogg_version == 2) { /* header is XOR'ed using byte (FF XIV PC) */
                ovmi.decryption_callback = scd_ogg_v2_decryption_callback;
                ovmi.scd_xor = ogg_byte;
                ovmi.scd_xor_length = vorb_header_size;
            }
            else if (ogg_version == 3) { /* file is XOR'ed using table (FF XIV Heavensward PC)  */
                ovmi.decryption_callback = scd_ogg_v3_decryption_callback;
                ovmi.scd_xor = stream_size & 0xFF; /* ogg_byte not used? */
                ovmi.scd_xor_length = vorb_header_size + stream_size;
            }
            else {
                VGM_LOG("SCD: unknown ogg_version 0x%x\n", ogg_version);
            }
        }

        /* actual Ogg init */
        ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
        if (ogg_vgmstream && name_offset)
            read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile);
        return ogg_vgmstream;
    }
#endif


    /* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

    vgmstream->sample_rate = sample_rate;
    vgmstream->num_streams = total_subsongs;
    vgmstream->stream_size = stream_size;
    vgmstream->meta_type = meta_SQEX_SCD;
    if (name_offset)
        read_string(vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile);

    switch (codec) {
        case 0x01:      /* PCM */
            vgmstream->coding_type = coding_PCM16LE;
            vgmstream->layout_type = layout_interleave;
            vgmstream->interleave_block_size = 0x02;

            vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channel_count, 16);
            if (loop_flag) {
                vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channel_count, 16);
                vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end, channel_count, 16);
            }
            break;

        case 0x03:      /* PS-ADPCM [Final Fantasy Type-0] */
            vgmstream->coding_type = coding_PSX;
            vgmstream->layout_type = layout_interleave;
            vgmstream->interleave_block_size = 0x10;

            vgmstream->num_samples = ps_bytes_to_samples(stream_size, channel_count);
            if (loop_flag) {
                vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channel_count);
                vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end, channel_count);
            }
            break;

        case 0x06:      /* OGG [Final Fantasy XIII-2 (PC), Final Fantasy XIV (PC)] */
            goto fail; /* handled above */

#ifdef VGM_USE_MPEG
        case 0x07: {    /* MPEG [Final Fantasy XIII (PS3)] */
            mpeg_codec_data *mpeg_data = NULL;
            mpeg_custom_config cfg = {0};

            cfg.interleave = 0x800; /* for multistream [Final Fantasy XIII-2 (PS3)], otherwise ignored */
            cfg.data_size = stream_size;

            mpeg_data = init_mpeg_custom(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_SCD, &cfg);
            if (!mpeg_data) goto fail;
            vgmstream->codec_data = mpeg_data;
            vgmstream->layout_type = layout_none;

            /* some Drakengard 3, Kingdom Hearts HD have adjusted sample rate (47999, 44099), for looping? */

            vgmstream->num_samples = mpeg_bytes_to_samples(stream_size, mpeg_data);
            vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, mpeg_data);
            vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, mpeg_data);

            /* somehow loops offsets aren't always frame-aligned, and the code below supposedly helped,
             * but there isn't much difference since MPEG loops are rough (1152-aligned). Seems it
             * would help more loop_start - ~1000, loop_end + ~1000 (ex. FFXIII-2 music_SunMizu.ps3.scd) */
            //vgmstream->num_samples -= vgmstream->num_samples % 576;
            //vgmstream->loop_start_sample -= vgmstream->loop_start_sample % 576;
            //vgmstream->loop_end_sample -= vgmstream->loop_end_sample % 576;
            break;
        }
#endif
        case 0x0C:      /* MS ADPCM [Final Fantasy XIV (PC) sfx] */
            vgmstream->coding_type = coding_MSADPCM;
            vgmstream->layout_type = layout_none;
            vgmstream->interleave_block_size = read_16bit(extradata_offset+0x0c,streamFile);
            /* in extradata_offset is a WAVEFORMATEX (including coefs and all) */

            vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->interleave_block_size, vgmstream->channels);
            if (loop_flag) {
                vgmstream->loop_start_sample = msadpcm_bytes_to_samples(loop_start, vgmstream->interleave_block_size, vgmstream->channels);
                vgmstream->loop_end_sample = msadpcm_bytes_to_samples(loop_end, vgmstream->interleave_block_size, vgmstream->channels);
            }
            break;

        case 0x0A:      /* DSP ADPCM [Dragon Quest X (Wii)] */
        case 0x15: {    /* DSP ADPCM [Dragon Quest X (Wii U)] (no apparent differences except higher sample rate) */
            const off_t interleave_size = 0x800;
            const off_t stride_size = interleave_size * channel_count;
            int i;
            size_t total_size;
            layered_layout_data * data = NULL;

            /* interleaved DSPs including the header (so the first 0x800 is 0x60 header + 0x740 data)
             * so interleave layout can't used; we'll setup de-interleaving streamfiles as layers/channels instead */
            //todo this could be simplified using a block layout or adding interleave_first_block
            vgmstream->coding_type = coding_NGC_DSP;
            vgmstream->layout_type = layout_layered;

            /* read from the first DSP header and verify other channel headers */
            {
                total_size = (read_32bitBE(start_offset+0x04,streamFile)+1)/2; /* rounded nibbles / 2 */
                vgmstream->num_samples = read_32bitBE(start_offset+0x00,streamFile);
                if (loop_flag) {
                    vgmstream->loop_start_sample = loop_start;
                    vgmstream->loop_end_sample = loop_end+1;
                }

                for (i = 1; i < channel_count; i++) {
                    if ((read_32bitBE(start_offset+4,streamFile)+1)/2 != total_size ||
                        read_32bitBE(start_offset+interleave_size*i+0x00,streamFile) != vgmstream->num_samples) {
                        goto fail;
                    }
                }
            }

            /* init layout */
            data = init_layout_layered(channel_count);
            if (!data) goto fail;
            vgmstream->layout_data = data;

            /* open each layer subfile */
            for (i = 0; i < channel_count; i++) {
                STREAMFILE* temp_streamFile = setup_scd_dsp_streamfile(streamFile, start_offset+interleave_size*i, interleave_size, stride_size, total_size);
                if (!temp_streamFile) goto fail;

                data->layers[i] = init_vgmstream_ngc_dsp_std(temp_streamFile);
                close_streamfile(temp_streamFile);
                if (!data->layers[i]) goto fail;
            }

            /* setup layered VGMSTREAMs */
            if (!setup_layout_layered(data))
                goto fail;

            break;
        }

#ifdef VGM_USE_FFMPEG
        case 0x0B: {    /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx, Kingdom Hearts 2.8 (X1)] */
            ffmpeg_codec_data *ffmpeg_data = NULL;
            uint8_t buf[200];
            int32_t bytes;

            /* extradata_offset+0x00: fmt0x166 header (BE),  extradata_offset+0x34: seek table */
            bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, extradata_offset,0x34, stream_size, streamFile, 1);
            ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size);
            if (!ffmpeg_data) goto fail;
            vgmstream->codec_data = ffmpeg_data;
            vgmstream->coding_type = coding_FFmpeg;
            vgmstream->layout_type = layout_none;

            vgmstream->num_samples = ffmpeg_data->totalSamples;
            vgmstream->loop_start_sample = loop_start;
            vgmstream->loop_end_sample = loop_end;

            xma_fix_raw_samples(vgmstream, streamFile, start_offset,stream_size, 0, 0,0); /* samples are ok, loops? */
            break;
        }

        case 0x0E: {    /* ATRAC3/ATRAC3plus [Lord of Arcana (PSP), Final Fantasy Type-0] */
            ffmpeg_codec_data *ffmpeg_data = NULL;

            /* full RIFF header at start_offset/extradata_offset (same) */
            ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size);
            if (!ffmpeg_data) goto fail;
            vgmstream->codec_data = ffmpeg_data;
            vgmstream->coding_type = coding_FFmpeg;
            vgmstream->layout_type = layout_none;

            vgmstream->num_samples = ffmpeg_data->totalSamples; /* fact samples */
            vgmstream->loop_start_sample = loop_start;
            vgmstream->loop_end_sample = loop_end;

            if (ffmpeg_data->skipSamples <= 0) /* in case FFmpeg didn't get them */
                ffmpeg_set_skip_samples(ffmpeg_data, riff_get_fact_skip_samples(streamFile, start_offset));
            /* SCD loop/sample values are relative (without skip samples) vs RIFF (with skip samples), no need to adjust */
            break;
        }
#endif

#ifdef VGM_USE_ATRAC9
        case 0x16: { /* ATRAC9 [Kingdom Hearts 2.8 (PS4)] */
            atrac9_config cfg = {0};

            /* post header has various typical ATRAC9 values */
            cfg.channels = vgmstream->channels;
            cfg.config_data = read_32bit(extradata_offset+0x0c,streamFile);
            cfg.encoder_delay = read_32bit(extradata_offset+0x18,streamFile);

            vgmstream->codec_data = init_atrac9(&cfg);
            if (!vgmstream->codec_data) goto fail;
            vgmstream->coding_type = coding_ATRAC9;
            vgmstream->layout_type = layout_none;

            vgmstream->num_samples = read_32bit(extradata_offset+0x10,streamFile); /* loop values above are also weird and ignored */
            vgmstream->loop_start_sample = read_32bit(extradata_offset+0x20, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_start
            vgmstream->loop_end_sample   = read_32bit(extradata_offset+0x24, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_end
            break;
        }
#endif

        case -1:    /* used for dummy entries */
        default:
            VGM_LOG("SCD: unknown codec 0x%x\n", codec);
            goto fail;
    }


    if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
        goto fail;

    return vgmstream;

fail:
    close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #13
0
VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) {
	VGMSTREAM * vgmstream = NULL;
	char filename[260];

	coding_t coding_type;

	off_t head_offset;
	off_t seek_offset;
	off_t data_offset;
	int codec_number;
	int channel_count;
	int loop_flag;
	int ima = 0;
	off_t start_offset;
	int founddata;
	off_t tempoffset1;

	/* check extension, case insensitive */
	streamFile->get_name(streamFile, filename, sizeof(filename));
	if (strcasecmp("bfstm", filename_extension(filename)))
		goto fail;


	/* check header */
	if ((uint32_t)read_32bitBE(0, streamFile) != 0x4653544D) /* "FSTM" */
		goto fail;
	if ((uint32_t)read_32bitBE(4, streamFile) != 0xFEFF0040 && (uint32_t)read_32bitBE(4, streamFile) != 0xFEFF0060)
		goto fail;

	founddata = 0;
	tempoffset1 = 0x8;
	
	while (!(founddata))
	{
		if ((uint32_t)read_32bitBE(tempoffset1, streamFile) == 0x40020000)
		{
			data_offset = read_32bitBE(tempoffset1 + 4, streamFile);
			founddata++;
			break;
		}
		tempoffset1++;
	}
	
	/* get head offset, check */
	head_offset = read_32bitBE(0x18, streamFile);

	if ((uint32_t)read_32bitBE(head_offset, streamFile) != 0x494E464F) /* "INFO" */
		goto fail;

	seek_offset = read_32bitBE(0x24, streamFile);


	/* check type details */
	codec_number = read_8bit(head_offset + 0x20, streamFile);
	loop_flag = read_8bit(head_offset + 0x21, streamFile);
	channel_count = read_8bit(head_offset + 0x22, streamFile);

	switch (codec_number) {
	case 0:
		coding_type = coding_PCM8;
		break;
	case 1:
		coding_type = coding_PCM16BE;
		break;
	case 2:
		coding_type = coding_NGC_DSP;
		break;
	default:
		goto fail;
	}

	if (channel_count < 1) goto fail;

	/* build the VGMSTREAM */

	vgmstream = allocate_vgmstream(channel_count, loop_flag);
	if (!vgmstream) goto fail;

	/* fill in the vital statistics */
	vgmstream->num_samples = read_32bitBE(head_offset + 0x2c, streamFile);
	vgmstream->sample_rate = (uint16_t)read_16bitBE(head_offset + 0x26, streamFile);
	/* channels and loop flag are set by allocate_vgmstream */
	if (ima) //Shift the loop points back slightly to avoid stupid pops in some IMA streams due to DC offsetting
	{
		vgmstream->loop_start_sample = read_32bitBE(head_offset + 0x28, streamFile);
		if (vgmstream->loop_start_sample > 10000)
		{
			vgmstream->loop_start_sample -= 5000;
			vgmstream->loop_end_sample = vgmstream->num_samples - 5000;
		}
		else
			vgmstream->loop_end_sample = vgmstream->num_samples;
	}
	else
	{
		vgmstream->loop_start_sample = read_32bitBE(head_offset + 0x28, streamFile);
		vgmstream->loop_end_sample = vgmstream->num_samples;
	}

	vgmstream->coding_type = coding_type;
	if (channel_count == 1)
		vgmstream->layout_type = layout_none;
	else
	{
		if (ima)
			vgmstream->layout_type = layout_interleave;
		else
			vgmstream->layout_type = layout_interleave_shortblock;
	}
	vgmstream->meta_type = meta_FSTM;

	if (ima)
		vgmstream->interleave_block_size = 0x200;
	else {
		vgmstream->interleave_block_size = read_32bitBE(head_offset + 0x34, streamFile);
		vgmstream->interleave_smallblock_size = read_32bitBE(head_offset + 0x44, streamFile);
	}

	if (vgmstream->coding_type == coding_NGC_DSP) {
		off_t coef_offset;
		off_t tempoffset2 = head_offset;
		int foundcoef = 0;
		int i, j;
		int coef_spacing = 0x2E;

		while (!(foundcoef))
		{
			if ((uint32_t)read_32bitBE(tempoffset2, streamFile) == 0x41020000)
			{
				coef_offset = read_32bitBE(tempoffset2 + 4, streamFile) + tempoffset2 + (channel_count * 8) - 4 - head_offset;
				foundcoef++;
				break;
			}
			tempoffset2++;
		}

		for (j = 0; j<vgmstream->channels; j++) {
			for (i = 0; i<16; i++) {
				vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(head_offset + coef_offset + j*coef_spacing + i * 2, streamFile);
			}
		}
	}

	if (ima) // No SEEK (ADPC) header, so just start where the SEEK header is supposed to be.
		start_offset = seek_offset;
	else if (vgmstream->coding_type == coding_NGC_DSP)
		start_offset = data_offset + 0x20;
	else // No SEEK header and not IMA, so just start after the DATA header
		start_offset = 0x120;



	/* open the file for reading by each channel */
	{
		int i;
		for (i = 0; i<channel_count; i++) {
			if (vgmstream->layout_type == layout_interleave_shortblock)
				vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
				vgmstream->interleave_block_size);
			else if (vgmstream->layout_type == layout_interleave)
				vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
				STREAMFILE_DEFAULT_BUFFER_SIZE);
			else
				vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
				0x1000);

			if (!vgmstream->ch[i].streamfile) goto fail;

			vgmstream->ch[i].channel_start_offset =
				vgmstream->ch[i].offset =
				start_offset + i*vgmstream->interleave_block_size;
		}
	}

	return vgmstream;

	/* clean up anything we may have opened */
fail:
	if (vgmstream) close_vgmstream(vgmstream);
	return NULL;
}
Beispiel #14
0
VGMSTREAM * init_vgmstream_ps2_str(STREAMFILE *streamFile) {
    
	VGMSTREAM * vgmstream = NULL;
	STREAMFILE * infileSTH = NULL;
	char filename[260];

	char * filenameSTH = NULL;

	int i, channel_count, loop_flag;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("str",filename_extension(filename))) goto fail;

	/* check for .MIH file */
	filenameSTH=(char *)malloc(strlen(filename)+1);

	if (!filenameSTH) goto fail;

	strcpy(filenameSTH,filename);
	strcpy(filenameSTH+strlen(filenameSTH)-3,"STH");

	infileSTH = streamFile->open(streamFile,filenameSTH,STREAMFILE_DEFAULT_BUFFER_SIZE);

	/* STH File is necessary, so we can't confuse those file */
	/* with others .STR file as it is a very common extension */
	if (!infileSTH) goto fail;

	if((read_32bitLE(0x2C,infileSTH)==0x07) ||
	   (read_32bitLE(0x2C,infileSTH)==0x06))
		channel_count=2;
	if(read_32bitLE(0x2C,infileSTH)==0x05)
		channel_count=1;

	loop_flag = read_32bitLE(0x2C,infileSTH) & 0x01;

    /* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

    /* fill in the vital statistics */
	vgmstream->channels = channel_count;
	vgmstream->sample_rate = read_32bitLE(0x24,infileSTH);

	vgmstream->interleave_block_size=0x4000;

	if(read_32bitLE(0x40,infileSTH)==0x01) 
		vgmstream->interleave_block_size = 0x8000; 

	vgmstream->num_samples=read_32bitLE(0x20,infileSTH);

	vgmstream->coding_type = coding_PSX;
    vgmstream->layout_type = layout_interleave;
    
	vgmstream->meta_type = meta_PS2_STR;

	if(loop_flag) {
		vgmstream->loop_start_sample = 0;
		vgmstream->loop_end_sample = read_32bitLE(0x20,infileSTH);
	}

	close_streamfile(infileSTH); infileSTH=NULL;

    /* open the file for reading by each channel */
    {
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size);

            if (!vgmstream->ch[i].streamfile) goto fail;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset+=(off_t)(vgmstream->interleave_block_size*i);
        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (infileSTH) close_streamfile(infileSTH);
    if (filenameSTH) {free(filenameSTH); filenameSTH=NULL;}
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #15
0
VGMSTREAM * init_vgmstream_Cstr(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[PATH_LIMIT];

    int loop_flag;
    off_t start_offset;
    off_t first_data;
    off_t loop_offset;
    size_t interleave;
    int loop_adjust;
    int double_loop_end = 0;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("dsp",filename_extension(filename))) goto fail;

    /* check header */
    if ((uint32_t)read_32bitBE(0,streamFile)!=0x43737472)   /* "Cstr" */
        goto fail;
#ifdef DEBUG
    fprintf(stderr,"header ok\n");
#endif

    if (read_8bit(0x1b,streamFile)==1) {
        /* mono version, much simpler to handle */
        /* Only seen in R Racing Evolution radio sfx */

        start_offset = 0x80;
        loop_flag = read_16bitBE(0x2c,streamFile);

        /* check initial predictor/scale */
        if (read_16bitBE(0x5e,streamFile) != (uint8_t)read_8bit(start_offset,streamFile))
            goto fail;

        /* check type==0 and gain==0 */
        if (read_16bitBE(0x2e,streamFile) || read_16bitBE(0x5c,streamFile))
            goto fail;

        loop_offset = start_offset+read_32bitBE(0x10,streamFile);
        if (loop_flag) {
            if (read_16bitBE(0x64,streamFile) != (uint8_t)read_8bit(loop_offset,streamFile)) goto fail;
        }

        /* build the VGMSTREAM */

        vgmstream = allocate_vgmstream(1,loop_flag);
        if (!vgmstream) goto fail;

        /* fill in the vital statistics */
        vgmstream->sample_rate = read_32bitBE(0x28,streamFile);
        vgmstream->num_samples = read_32bitBE(0x20,streamFile);

        if (loop_flag) {
            vgmstream->loop_start_sample = dsp_nibbles_to_samples(
                                               read_32bitBE(0x30,streamFile));
            vgmstream->loop_end_sample =  dsp_nibbles_to_samples(
                                              read_32bitBE(0x34,streamFile))+1;
        }

        vgmstream->coding_type = coding_NGC_DSP;
        vgmstream->layout_type = layout_none;
        vgmstream->meta_type = meta_DSP_CSTR;

        {
            int i;
            for (i=0; i<16; i++)
                vgmstream->ch[0].adpcm_coef[i]=read_16bitBE(0x3c+i*2,streamFile);
        }

        /* open the file for reading by each channel */
        vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);

        if (!vgmstream->ch[0].streamfile) goto fail;

        vgmstream->ch[0].channel_start_offset=
            vgmstream->ch[0].offset=
                start_offset;

        return vgmstream;
    }   /* end mono */

    interleave = read_16bitBE(0x06,streamFile);
    start_offset = 0xe0;
    first_data = start_offset+read_32bitBE(0x0c,streamFile);
    loop_flag = read_16bitBE(0x2c,streamFile);

    if (!loop_flag) {
        /* Nonlooped tracks seem to follow no discernable pattern
         * with where they actually start.
         * But! with the magic of initial p/s redundancy, we can guess.
         */
        while (first_data<start_offset+0x800 &&
                (read_16bitBE(0x5e,streamFile) != (uint8_t)read_8bit(first_data,streamFile) ||
                 read_16bitBE(0xbe,streamFile) != (uint8_t)read_8bit(first_data+interleave,streamFile)))
            first_data+=8;
#ifdef DEBUG
        fprintf(stderr,"guessed first_data at %#x\n",first_data);
#endif
    }

    /* check initial predictor/scale */
    if (read_16bitBE(0x5e,streamFile) != (uint8_t)read_8bit(first_data,streamFile))
        goto fail;
    if (read_16bitBE(0xbe,streamFile) != (uint8_t)read_8bit(first_data+interleave,streamFile))
        goto fail;

#ifdef DEBUG
    fprintf(stderr,"p/s ok\n");
#endif

    /* check type==0 and gain==0 */
    if (read_16bitBE(0x2e,streamFile) || read_16bitBE(0x5c,streamFile))
        goto fail;
    if (read_16bitBE(0x8e,streamFile) || read_16bitBE(0xbc,streamFile))
        goto fail;

#ifdef DEBUG
    fprintf(stderr,"type & gain ok\n");
#endif

    /* check for loop flag agreement */
    if (read_16bitBE(0x2c,streamFile) != read_16bitBE(0x8c,streamFile))
        goto fail;

#ifdef DEBUG
    fprintf(stderr,"loop flags agree\n");
#endif

    loop_offset = start_offset+read_32bitBE(0x10,streamFile)*2;
    if (loop_flag) {
        int loops_ok=0;
        /* check loop predictor/scale */
        /* some fuzz allowed */
        for (loop_adjust=0; loop_adjust>=-0x10; loop_adjust-=8) {
#ifdef DEBUG
            fprintf(stderr,"looking for loop p/s at %#x,%#x\n",loop_offset-interleave+loop_adjust,loop_offset+loop_adjust);
#endif
            if (read_16bitBE(0x64,streamFile) == (uint8_t)read_8bit(loop_offset-interleave+loop_adjust,streamFile) &&
                    read_16bitBE(0xc4,streamFile) == (uint8_t)read_8bit(loop_offset+loop_adjust,streamFile)) {
                loops_ok=1;
                break;
            }
        }
        if (!loops_ok)
            for (loop_adjust=interleave; loop_adjust<=interleave+0x10; loop_adjust+=8) {
#ifdef DEBUG
                fprintf(stderr,"looking for loop p/s at %#x,%#x\n",loop_offset-interleave+loop_adjust,loop_offset+loop_adjust);
#endif
                if (read_16bitBE(0x64,streamFile) == (uint8_t)read_8bit(loop_offset-interleave+loop_adjust,streamFile) &&
                        read_16bitBE(0xc4,streamFile) == (uint8_t)read_8bit(loop_offset+loop_adjust,streamFile)) {
                    loops_ok=1;
                    break;
                }
            }

        if (!loops_ok) goto fail;
#ifdef DEBUG
        fprintf(stderr,"loop p/s ok (with %#4x adjust)\n",loop_adjust);
#endif

        /* check for agreement */
        /* loop end (channel 1 & 2 headers) */
        if (read_32bitBE(0x34,streamFile) != read_32bitBE(0x94,streamFile))
            goto fail;

        /* Mr. Driller oddity */
        if (dsp_nibbles_to_samples(read_32bitBE(0x34,streamFile)*2)+1 <= read_32bitBE(0x20,streamFile)) {
#ifdef DEBUG
            fprintf(stderr,"loop end <= half total samples, should be doubled\n");
#endif
            double_loop_end = 1;
        }

        /* loop start (Cstr header and channel 1 header) */
        if (read_32bitBE(0x30,streamFile) != read_32bitBE(0x10,streamFile)
#if 0
                /* this particular glitch only true for SFA, though it
                 * seems like something similar happens in Donkey Konga */
                /* loop start (Cstr, channel 1 & 2 headers) */
                || (read_32bitBE(0x0c,streamFile)+read_32bitLE(0x30,streamFile)) !=
                read_32bitBE(0x90,streamFile)
#endif
           )
            /* alternatively (Donkey Konga) the header loop is 0x0c+0x10 */
            if (
                /* loop start (Cstr header and channel 1 header) */
                read_32bitBE(0x30,streamFile) != read_32bitBE(0x10,streamFile)+
                read_32bitBE(0x0c,streamFile))
                /* further alternatively (Donkey Konga), if we loop back to
                 * the very first frame 0x30 might be 0x00000002 (which
                 * is a *valid* std dsp loop start, imagine that) while 0x10
                 * is 0x00000000 */
                if (!(read_32bitBE(0x30,streamFile) == 2 &&
                        read_32bitBE(0x10,streamFile) == 0))
                    /* lest there be too few alternatives, in Mr. Driller we
                     * find that [0x30] + [0x0c] + 8 = [0x10]*2 */
                    if (!(double_loop_end &&
                            read_32bitBE(0x30,streamFile) +
                            read_32bitBE(0x0c,streamFile) + 8 ==
                            read_32bitBE(0x10,streamFile)*2))
                        goto fail;

#ifdef DEBUG
        fprintf(stderr,"loop points agree\n");
#endif
    }

    /* assure that sample counts, sample rates agree */
    if (
        /* sample count (channel 1 & 2 headers) */
        read_32bitBE(0x20,streamFile) != read_32bitBE(0x80,streamFile) ||
        /* sample rate (channel 1 & 2 headers) */
        read_32bitBE(0x28,streamFile) != read_32bitBE(0x88,streamFile) ||
        /* sample count (Cstr header and channel 1 header) */
        read_32bitLE(0x14,streamFile) != read_32bitBE(0x20,streamFile) ||
        /* sample rate (Cstr header and channel 1 header) */
        (uint16_t)read_16bitLE(0x18,streamFile) != read_32bitBE(0x28,streamFile))
        goto fail;

    /* build the VGMSTREAM */

    vgmstream = allocate_vgmstream(2,loop_flag);
    if (!vgmstream) goto fail;

    /* fill in the vital statistics */
    vgmstream->sample_rate = read_32bitBE(0x28,streamFile);
    /* This is a slight hack to counteract their hack.
     * All the data is ofset by first_data so that the loop
     * point occurs at a block boundary. However, I always begin decoding
     * right after the header, as that is the start of the first block and
     * my interleave code relies on starting at the beginning of a block.
     * So we decode a few silent samples at the beginning, and here we make up
     * for it by lengthening the track by that much.
     */
    vgmstream->num_samples = read_32bitBE(0x20,streamFile) +
                             (first_data-start_offset)/8*14;

    if (loop_flag) {
        off_t loop_start_bytes = loop_offset-start_offset-interleave;
        vgmstream->loop_start_sample = dsp_nibbles_to_samples((loop_start_bytes/(2*interleave)*interleave+loop_start_bytes%(interleave*2))*2);
        /*dsp_nibbles_to_samples(loop_start_bytes);*/
        /*dsp_nibbles_to_samples(read_32bitBE(0x30,streamFile)*2-inter);*/
        vgmstream->loop_end_sample =  dsp_nibbles_to_samples(
                                          read_32bitBE(0x34,streamFile))+1;

        if (double_loop_end)
            vgmstream->loop_end_sample =
                dsp_nibbles_to_samples(read_32bitBE(0x34,streamFile)*2)+1;

        if (vgmstream->loop_end_sample > vgmstream->num_samples) {
#ifdef DEBUG
            fprintf(stderr,"loop_end_sample > num_samples, adjusting\n");
#endif
            vgmstream->loop_end_sample = vgmstream->num_samples;
        }
    }

    vgmstream->coding_type = coding_NGC_DSP;
    vgmstream->layout_type = layout_interleave;
    vgmstream->interleave_block_size = interleave;
    vgmstream->meta_type = meta_DSP_CSTR;

    {
        int i;
        for (i=0; i<16; i++)
            vgmstream->ch[0].adpcm_coef[i]=read_16bitBE(0x3c+i*2,streamFile);
        for (i=0; i<16; i++)
            vgmstream->ch[1].adpcm_coef[i]=read_16bitBE(0x9c+i*2,streamFile);
    }
#ifdef DEBUG
    vgmstream->ch[0].loop_history1 = read_16bitBE(0x66,streamFile);
    vgmstream->ch[0].loop_history2 = read_16bitBE(0x68,streamFile);
    vgmstream->ch[1].loop_history1 = read_16bitBE(0xc6,streamFile);
    vgmstream->ch[1].loop_history2 = read_16bitBE(0xc8,streamFile);
#endif

    /* open the file for reading by each channel */
    {
        int i;
        for (i=0; i<2; i++) {
            vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,interleave);

            if (!vgmstream->ch[i].streamfile) goto fail;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=
                    start_offset+interleave*i;
        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #16
0
/* PDT - Custom Generated File (Mario Party) */
VGMSTREAM * init_vgmstream_ngc_pdt(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];
    int loop_flag;
    int channel_count;
    off_t start_offset;
    int second_channel_start = -1;
    
    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("pdt",filename_extension(filename))) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0x50445420) /* "PDT " */
        goto fail;
    if (read_32bitBE(0x04,streamFile) != 0x44535020) /* "DSP " */
        goto fail;
    if (read_32bitBE(0x08,streamFile) != 0x48454144) /* "HEAD " */
        goto fail;
    if (read_16bitBE(0x0C,streamFile) != 0x4552) /* "ER " */
        goto fail;

    loop_flag = (read_32bitBE(0x1C,streamFile)!=2);
    channel_count = (uint16_t)(read_16bitLE(0x0E,streamFile));

	  /* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	  /* fill in the vital statistics */
    start_offset = 0x800;
	  vgmstream->channels = channel_count;
    vgmstream->sample_rate = read_32bitBE(0x14,streamFile);
    vgmstream->coding_type = coding_NGC_DSP;

    if (channel_count == 1)
    {
      vgmstream->num_samples = read_32bitBE(0x18,streamFile)*14/8/channel_count/2;
        if (loop_flag) {
            vgmstream->loop_start_sample = read_32bitBE(0x1C,streamFile)*14/8/channel_count/2;
            vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile)*14/8/channel_count/2;
        }
    }
    else if (channel_count == 2)
    {
      vgmstream->num_samples = read_32bitBE(0x18,streamFile)*14/8/channel_count;
        if (loop_flag) {
            vgmstream->loop_start_sample = read_32bitBE(0x1C,streamFile)*14/8/channel_count;
            vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile)*14/8/channel_count;
        }
        second_channel_start = (get_streamfile_size(streamFile)+start_offset)/2;
    }
    else
    {
      goto fail;
    }

    vgmstream->layout_type = layout_none;
    vgmstream->meta_type = meta_NGC_PDT;

    if (vgmstream->coding_type == coding_NGC_DSP) {
        int i;
        for (i=0;i<16;i++) {
            vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x50+i*2,streamFile);
        }
        if (vgmstream->channels == 2) {
            for (i=0;i<16;i++) {
                vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x70+i*2,streamFile);
            }
        }
    }

    /* open the file for reading */
    {
        int i;
        STREAMFILE * file;
        file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!file) goto fail;
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = file;

                vgmstream->ch[0].channel_start_offset=start_offset;
            if (channel_count == 2) {
                if (second_channel_start == -1) goto fail;
                vgmstream->ch[1].channel_start_offset=second_channel_start;
            }
        vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset;
        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #17
0
/* SPW (SEWave) - from  PlayOnline viewer for Final Fantasy XI (PC) */
VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    uint32_t codec, file_size, block_size, sample_rate, block_align;
    int32_t loop_start;
    off_t start_offset;

    int channel_count, loop_flag = 0;

    /* check extensions */
    if ( !check_extensions(streamFile, "spw") )
        goto fail;

    /* check header */
    if (read_32bitBE(0,streamFile) != 0x53655761 || /* "SeWa" */
        read_32bitBE(4,streamFile) != 0x76650000)   /* "ve\0\0" */
        goto fail;

    file_size = read_32bitLE(0x08,streamFile);
    codec = read_32bitLE(0x0c,streamFile);
    /*file_id = read_32bitLE(0x10,streamFile);*/
    block_size = read_32bitLE(0x14,streamFile);
    loop_start = read_32bitLE(0x18,streamFile);
    sample_rate = (read_32bitLE(0x1c,streamFile) + read_32bitLE(0x20,streamFile)) & 0x7FFFFFFF; /* bizarrely obfuscated sample rate */
    start_offset = read_32bitLE(0x24,streamFile);
    /*0x2c: unk (0x00?) */
    /*0x2d: unk (0x00/01?) */
    channel_count = read_8bit(0x2a,streamFile);
    block_align = read_8bit(0x2b,streamFile);
    /*0x2c: unk (0x01 when PCM, 0x10 when VAG?) */

    if (file_size != get_streamfile_size(streamFile))
        goto fail;

    loop_flag = (loop_start > 0);

    /* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

    vgmstream->meta_type = meta_FFXI_SPW;
    vgmstream->sample_rate = sample_rate;

    switch (codec) {
        case 0: /* PS ADPCM */
            vgmstream->coding_type = coding_PSX_cfg;
            vgmstream->layout_type = layout_interleave;
            vgmstream->interleave_block_size = (block_align / 2) + 1; /* half, even if channels = 1 */
            
            vgmstream->num_samples = block_size * block_align;
            if (loop_flag) {
                vgmstream->loop_start_sample = (loop_start-1) * block_align;;
                vgmstream->loop_end_sample = vgmstream->num_samples;
            }
            
            break;

        case 1: /* PCM */
            vgmstream->coding_type = coding_PCM16LE;
            vgmstream->layout_type = layout_interleave;
            vgmstream->interleave_block_size = 0x02;
            
            vgmstream->num_samples = block_size;
            if (loop_flag) {
                vgmstream->loop_start_sample = (loop_start-1);
                vgmstream->loop_end_sample = vgmstream->num_samples;
            }

            break;

        default:
            goto fail;
    }


    /* open the file for reading */
    if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
        goto fail;

    return vgmstream;

fail:
    close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #18
0
VGMSTREAM * init_vgmstream_ps2_p2bt(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];

    int loop_flag=0;
	int channel_count;
    off_t start_offset;
    int i;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("p2bt",filename_extension(filename))) goto fail;

	if((read_32bitBE(0x00,streamFile)!=0x4d4F5645) && // MOVE 
	   (read_32bitBE(0x00,streamFile)!=0x50324254))   // P2BT
		goto fail;

	/* check loop */
	loop_flag = (read_32bitLE(0x0C,streamFile)!=0);
    channel_count=read_32bitLE(0x20,streamFile);
    
	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	/* fill in the vital statistics */
	vgmstream->channels = channel_count;
    vgmstream->sample_rate = read_32bitLE(0x08,streamFile);;

	/* Check for Compression Scheme */
	vgmstream->coding_type = coding_PSX;
    vgmstream->num_samples = read_32bitLE(0x10,streamFile)/16*28/vgmstream->channels;

	/* Get loop point values */
	if(vgmstream->loop_flag) {
		vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile)/16*28/vgmstream->channels;
		vgmstream->loop_end_sample = vgmstream->num_samples;
	}

	vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile);;
    vgmstream->layout_type = layout_interleave;
    vgmstream->meta_type = meta_PS2_P2BT;

	start_offset = (off_t)0x800;

    /* open the file for reading by each channel */
    {
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size);

            if (!vgmstream->ch[i].streamfile) goto fail;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=
                (off_t)(start_offset+vgmstream->interleave_block_size*i);
        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #19
0
/* New MUSX formats, found in Quantum of Solace, The Mummy 3, possibly more */
VGMSTREAM * init_vgmstream_musx_v010(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];
    off_t start_offset;
	int musx_type; /* determining the decoder by strings like "PS2_", "GC__" and so on */
	//int musx_version; /* 0x08 provides a "version" byte */
	int loop_flag = 0;
	int channel_count;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("musx",filename_extension(filename))) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0x4D555358) /* "MUSX" */
		goto fail;
	if (read_32bitBE(0x08,streamFile) != 0x0A000000) /* "0x0A000000" */
		goto fail;

	loop_flag = (read_32bitLE(0x34,streamFile)!=0x00000000);
    channel_count = 2;
    
	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;
	
	/* fill in the vital statistics */	
	musx_type=(read_32bitBE(0x10,streamFile));

	switch (musx_type) {
	case 0x5053325F: /* PS2_ */
			start_offset = 0x800;
			vgmstream->channels = channel_count;
			vgmstream->sample_rate = 32000;
			vgmstream->coding_type = coding_PSX;
			vgmstream->num_samples = read_32bitLE(0x40,streamFile);
			vgmstream->layout_type = layout_interleave;
			vgmstream->interleave_block_size = 0x80;
			vgmstream->meta_type = meta_MUSX_V010;
		if (loop_flag) {
			vgmstream->loop_start_sample = read_32bitLE(0x44,streamFile);
			vgmstream->loop_end_sample = read_32bitLE(0x40,streamFile);
		}
	break;
		default:
			goto fail;

	}

    /* open the file for reading */
    {
        int i;
        STREAMFILE * file;
        file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!file) goto fail;
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = file;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=start_offset+
                vgmstream->interleave_block_size*i;

        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #20
0
Datei: zwdsp.c Projekt: 1c0n/xbmc
/* ZWDSP (hcs' custom DSP files from Zack & Wiki) */
VGMSTREAM * init_vgmstream_zwdsp(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];
    off_t start_offset;

    int loop_flag;
    int channel_count;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("zwdsp",filename_extension(filename))) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0x00000000) /* 0x0 */
        goto fail;

    /* Retrieve the loop flag, some files have 0x0 and some 0x02 as "no loop" */

    switch (read_32bitBE(0x10, streamFile)) {
        case 0:
        case 2:
            loop_flag = 0;
            break;
        default:
            loop_flag = 1;
    }

    channel_count = read_32bitBE(0x1C,streamFile);

    /* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

    /* fill in the vital statistics */
    start_offset = 0x90;
    vgmstream->channels = channel_count;
    vgmstream->sample_rate = read_32bitBE(0x08,streamFile);
    vgmstream->coding_type = coding_NGC_DSP;
    vgmstream->num_samples = read_32bitBE(0x18,streamFile)*14/8/channel_count;
    if (loop_flag) {
        vgmstream->loop_start_sample = read_32bitBE(0x10,streamFile)*14/8/channel_count;
        vgmstream->loop_end_sample = read_32bitBE(0x14,streamFile)*14/8/channel_count;
    }


    vgmstream->layout_type = layout_none;
    vgmstream->meta_type = meta_ZWDSP;


    if (vgmstream->coding_type == coding_NGC_DSP) {
        int i;
        for (i=0;i<16;i++) {
            vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x20+i*2,streamFile);
        }
        if (vgmstream->channels == 2) {
            for (i=0;i<16;i++) {
                vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x60+i*2,streamFile);
            }
        }
    }

    /* open the file for reading */
    {
        int i;
        STREAMFILE * file;
        file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!file) goto fail;
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = file;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=start_offset+
                ((get_streamfile_size(streamFile)-start_offset)/2)*i;

        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #21
0
/* Old MUSX formats, found in Spyro, Ty and other games */
VGMSTREAM * init_vgmstream_musx_v004(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];
    off_t start_offset;
	int musx_type; /* determining the decoder by strings like "PS2_", "GC__" and so on */
	//int musx_version; /* 0x08 provides a "version" byte */
	int loop_flag = 0;
	int channel_count;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("musx",filename_extension(filename))) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0x4D555358) /* "MUSX" */
		goto fail;
	if (read_32bitBE(0x08,streamFile) != 0x04000000) /* "0x04000000" */
		goto fail;
        
	/* This is tricky, the header changes it's layout if the file is unlooped */
    loop_flag = (read_32bitLE(0x840,streamFile)!=0xFFFFFFFF);
    channel_count = 2;

	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;


	/* fill in the vital statistics */	
	musx_type=(read_32bitBE(0x10,streamFile));

	switch (musx_type) {
	case 0x5053325F: /* PS2_ */
			start_offset = read_32bitLE(0x28,streamFile);
			vgmstream->channels = channel_count;
			vgmstream->sample_rate = 32000;
			vgmstream->coding_type = coding_PSX;
			vgmstream->num_samples = (read_32bitLE(0x0C,streamFile))*28/16/channel_count;
			vgmstream->layout_type = layout_interleave;
			vgmstream->interleave_block_size = 0x80;
			vgmstream->meta_type = meta_MUSX_V004;
		if (loop_flag) {
			vgmstream->loop_start_sample = (read_32bitLE(0x890,streamFile))*28/16/channel_count;
			vgmstream->loop_end_sample = (read_32bitLE(0x89C,streamFile))*28/16/channel_count;
		}
	break;
	/* seems to not work for Spyro, maybe i find other games for testing
	case 0x58425F5F: XB__
			start_offset = read_32bitLE(0x28,streamFile);
			vgmstream->channels = channel_count;
			vgmstream->sample_rate = 32000;
			vgmstream->coding_type = coding_XBOX;
			vgmstream->num_samples = (read_32bitLE(0x0C,streamFile))*64/36/channel_count;
			vgmstream->layout_type = layout_none;
			vgmstream->meta_type = meta_MUSX_V004;
		if (loop_flag) {
			vgmstream->loop_start_sample = (read_32bitLE(0x890,streamFile))*64/36/channel_count;
			vgmstream->loop_end_sample = (read_32bitLE(0x89C,streamFile))*64/36/channel_count;
		}
	break;
	*/
		default:
			goto fail;

	}

    /* open the file for reading */
    {
        int i;
        STREAMFILE * file;
        file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!file) goto fail;
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = file;

            
            if (vgmstream->coding_type == coding_XBOX) {
                /* xbox interleaving is a little odd */
                vgmstream->ch[i].channel_start_offset=start_offset;
            } else {
                vgmstream->ch[i].channel_start_offset=
                    start_offset+vgmstream->interleave_block_size*i;
            }
            vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset;

        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #22
0
/* Actual AAX init fcn */
VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) {
    
	VGMSTREAM * vgmstream = NULL;
    STREAMFILE * streamFileAAX = NULL;
    STREAMFILE * streamFileADX = NULL;
    char filename[PATH_LIMIT];
    off_t *segment_offset = NULL;
    off_t *segment_size = NULL;
    int32_t sample_count;
    int table_error = 0;

    int loop_flag = 0;
    int32_t loop_start_sample=0;
    int32_t loop_end_sample=0;
    int loop_segment = 0;

    aax_codec_data *data = NULL;

    const long AAX_offset = 0;

    int channel_count = 0, segment_count;
    int sample_rate = 0;

	int i;


    long aax_data_offset;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("aax",filename_extension(filename))) goto fail;
    
    /* get AAX entry count, data offset */
    {
        struct utf_query_result result;
        long aax_string_table_offset;
        long aax_string_table_size;
       
        result = query_utf_nofail(streamFile, AAX_offset, NULL, &table_error);
        if (table_error) goto fail;
        segment_count = result.rows;
        aax_string_table_offset = AAX_offset + 8 + result.string_table_offset;
        aax_data_offset = AAX_offset + 8 + result.data_offset;
        aax_string_table_size = aax_data_offset - aax_string_table_offset;

        if (result.name_offset+4 > aax_string_table_size) goto fail;
        if (read_32bitBE(aax_string_table_offset + result.name_offset,
                    streamFile) != 0x41415800) /* "AAX\0" */
            goto fail;
    }

    segment_offset = calloc(segment_count,sizeof(off_t));
    if (!segment_offset)
        goto fail;
    segment_size = calloc(segment_count,sizeof(off_t));
    if (!segment_size)
        goto fail;

    /* get offsets of constituent ADXs */
    for (i = 0; i < segment_count; i++)
    {
        struct offset_size_pair offset_size;
        offset_size = query_utf_data(streamFile, AAX_offset, i, "data", &table_error);
        if (table_error) goto fail;
        segment_offset[i] = aax_data_offset + offset_size.offset;
        segment_size[i] = offset_size.size;
    }

    streamFileAAX = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
    if (!streamFileAAX) goto fail;

    data = malloc(sizeof(aax_codec_data));
    if (!data) goto fail;
    data->segment_count = segment_count;
    data->adxs = malloc(sizeof(STREAMFILE *)*segment_count);
    if (!data->adxs) goto fail;
    for (i=0;i<segment_count;i++) {
        data->adxs[i] = NULL;
    }
    data->sample_counts = calloc(segment_count,sizeof(int32_t));
    if (!data->sample_counts) goto fail;

    /* for each segment */
    for (i = 0; i < segment_count; i++)
    {
        VGMSTREAM *adx;
        /*printf("try opening segment %d/%d %x\n",i,segment_count,segment_offset[i]);*/
        streamFileADX = open_aax_with_STREAMFILE(streamFileAAX,segment_offset[i],segment_size[i]);
        if (!streamFileADX) goto fail;
        adx = data->adxs[i] = init_vgmstream_adx(streamFileADX);
        if (!adx)
            goto fail;
        data->sample_counts[i] = adx->num_samples;
        close_streamfile(streamFileADX); streamFileADX = NULL;

        if (i == 0)
        {
            channel_count = adx->channels;
            sample_rate = adx->sample_rate;
        }
        else
        {
            if (channel_count != adx->channels)
                goto fail;
            if (sample_rate != adx->sample_rate)
                goto fail;
        }

        if (adx->loop_flag != 0)
            goto fail;

        /* save start things so we can restart for seeking/looping */
        /* copy the channels */
        memcpy(adx->start_ch,adx->ch,sizeof(VGMSTREAMCHANNEL)*adx->channels);
        /* copy the whole VGMSTREAM */
        memcpy(adx->start_vgmstream,adx,sizeof(VGMSTREAM));

    }

    sample_count = 0;
    loop_flag = 0;
    for (i = 0; i < segment_count; i++)
    {
        int segment_loop_flag = query_utf_1byte(streamFile, AAX_offset, i,
                "lpflg", &table_error);
        if (table_error) segment_loop_flag = 0;

        if (!loop_flag && segment_loop_flag)
        {
            loop_start_sample = sample_count;
            loop_segment = i;
        }

        sample_count += data->sample_counts[i];

        if (!loop_flag && segment_loop_flag)
        {
            loop_end_sample = sample_count;
            loop_flag = 1;
        }
    }

    vgmstream = allocate_vgmstream(channel_count,loop_flag);

    vgmstream->num_samples = sample_count;
    vgmstream->sample_rate = sample_rate;

    vgmstream->loop_start_sample = loop_start_sample;
    vgmstream->loop_end_sample = loop_end_sample;

    vgmstream->coding_type = data->adxs[0]->coding_type;
    vgmstream->layout_type = layout_aax;
    vgmstream->meta_type = meta_AAX;

    vgmstream->ch[0].streamfile = streamFileAAX;
    data->current_segment = 0;
    data->loop_segment = loop_segment;

    vgmstream->codec_data = data;
    free(segment_offset);
    free(segment_size);

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (streamFileAAX) close_streamfile(streamFileAAX);
    if (streamFileADX) close_streamfile(streamFileADX);
    if (vgmstream) close_vgmstream(vgmstream);
    if (segment_offset) free(segment_offset);
    if (segment_size) free(segment_size);
    if (data) {
        if (data->adxs)
        {
            int i;
            for (i=0;i<data->segment_count;i++)
                if (data->adxs)
                    close_vgmstream(data->adxs[i]);
            free(data->adxs);
        }
        if (data->sample_counts)
        {
            free(data->sample_counts);
        }
        free(data);
    }
    return NULL;
}
Beispiel #23
0
VGMSTREAM * init_vgmstream_bnsf(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];

    off_t file_size = -1;
    uint32_t riff_size;
    uint32_t bnsf_form;
    enum {
        form_IS14 = UINT32_C(0x49533134),  /* IS14 */
    };

    int channel_count = 0;
    int sample_count = 0;
    int sample_rate = 0;
    int coding_type = -1;
    off_t start_offset = -1;

    int loop_flag = 0;
    off_t loop_start = -1;
    off_t loop_end = -1;
    uint32_t data_size = 0;
    uint32_t block_size = 0;
    uint32_t block_samples = 0;

    int FormatChunkFound = 0;
    int DataChunkFound = 0;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("bnsf",filename_extension(filename)))
    {
        goto fail;
    }

    /* check header */
    if ((uint32_t)read_32bitBE(0,streamFile)!=0x424E5346) /* BNSF */
        goto fail;

    /* check form */
    bnsf_form = read_32bitBE(8,streamFile);
    switch (bnsf_form)
    {
#ifdef VGM_USE_G7221
        case form_IS14:
            break;
#endif
        default:
            goto fail;
    }

    riff_size = read_32bitBE(4,streamFile);
    file_size = get_streamfile_size(streamFile);

    /* check for tructated RIFF */
    if (file_size < riff_size+8) goto fail;

    /* read through chunks to verify format and find metadata */
    {
        off_t current_chunk = 0xc; /* start with first chunk */

        while (current_chunk < file_size && current_chunk < riff_size+8) {
            uint32_t chunk_type = read_32bitBE(current_chunk,streamFile);
            off_t chunk_size = read_32bitBE(current_chunk+4,streamFile);

            if (current_chunk+8+chunk_size > file_size) goto fail;

            switch(chunk_type) {
                case 0x73666d74:    /* "sfmt" */
                    /* only one per file */
                    if (FormatChunkFound) goto fail;
                    FormatChunkFound = 1;

                    sample_rate = read_32bitBE(current_chunk+0x0c,streamFile);
                    channel_count = read_16bitBE(current_chunk+0x0a,streamFile);
                    // read_32bitBE(current_chunk+0x10,streamFile); // ?
                    // read_32bitBE(current_chunk+0x14,streamFile); // ?
                    block_size = read_16bitBE(current_chunk+0x18,streamFile);
                    block_samples = read_16bitBE(current_chunk+0x1a,streamFile);

                    /* I assume this is still the codec id, but as the codec is
                       specified by the BNSF "form" I've only seen this zero */
                    switch ((uint16_t)read_16bitBE(current_chunk+0x8,streamFile)) {
                        case 0:
                            break;
                        default:
                            goto fail;
                    }
                    break;
                case 0x73646174:    /* sdat */
                    /* at most one per file */
                    if (DataChunkFound) goto fail;
                    DataChunkFound = 1;

                    start_offset = current_chunk + 8;
                    data_size = chunk_size;
                    break;
                case 0x6C6F6F70:    /* loop */
                    loop_flag = 1;
                    loop_start =
                        read_32bitBE(current_chunk+8, streamFile);
                    loop_end =
                        read_32bitBE(current_chunk+0xc,streamFile);
                    break;
                default:
                    /* ignorance is bliss */
                    break;
            }

            current_chunk += 8+chunk_size;
        }
    }

    if (!FormatChunkFound || !DataChunkFound) goto fail;

    switch (bnsf_form) {
#ifdef VGM_USE_G7221
        case form_IS14:
            coding_type = coding_G7221C;
            sample_count = data_size/block_size*block_samples;

            break;
#endif
        default:
            goto fail;
    }

    /* build the VGMSTREAM */

    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

    /* fill in the vital statistics */
    vgmstream->num_samples = sample_count;
    vgmstream->sample_rate = sample_rate;

    vgmstream->coding_type = coding_type;
    vgmstream->layout_type = layout_interleave;
    vgmstream->interleave_block_size = block_size/channel_count;

    if (loop_flag) {
        vgmstream->loop_start_sample = loop_start;
        vgmstream->loop_end_sample = loop_end;
    }
    vgmstream->meta_type = meta_BNSF;

#ifdef VGM_USE_G7221
    if (coding_G7221C == coding_type)
    {
        int i;
        g7221_codec_data *data;

        /* one data structure per channel */
        data = malloc(sizeof(g7221_codec_data) * channel_count);
        if (!data)
        {
            goto fail;
        }
        memset(data,0,sizeof(g7221_codec_data) * channel_count);
        vgmstream->codec_data = data;

        for (i = 0; i < channel_count; i++)
        {
            /* Siren 14 == 14khz bandwidth */
            data[i].handle = g7221_init(vgmstream->interleave_block_size, 14000);
            if (!data[i].handle)
            {
                goto fail; /* close_vgmstream is able to clean up */
            }
        }
    }
#endif

    /* open the file, set up each channel */
    {
        int i;

        vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,
                STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!vgmstream->ch[0].streamfile) goto fail;

        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = vgmstream->ch[0].streamfile;
            vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset =
                start_offset+i*vgmstream->interleave_block_size;
        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #24
0
/* CRI's UTF wrapper around DSP */
VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) {
    
	VGMSTREAM * vgmstream = NULL;
    char filename[PATH_LIMIT];
    int table_error = 0;

    int loop_flag = 0;

    const long top_offset = 0;

    int channel_count;
    int sample_rate;
    long sample_count;

    long top_data_offset, segment_count;
    long body_offset, body_size;
    long header_offset, header_size;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    //if (strcasecmp("aax",filename_extension(filename))) goto fail;

    /* get entry count, data offset */
    {
        struct utf_query_result result;
        long top_string_table_offset;
        long top_string_table_size;
        long name_offset;
       
        result = query_utf_nofail(streamFile, top_offset, NULL, &table_error);
        if (table_error) goto fail;
        segment_count = result.rows;
        if (segment_count != 1) goto fail; // only simple stuff for now
        top_string_table_offset = top_offset + 8 + result.string_table_offset;
        top_data_offset = top_offset + 8 + result.data_offset;
        top_string_table_size = top_data_offset - top_string_table_offset;

        if (result.name_offset+10 > top_string_table_size) goto fail;

        name_offset = top_string_table_offset + result.name_offset;
        if (read_32bitBE(name_offset, streamFile) != 0x41445043   ||// "ADPC"
            read_32bitBE(name_offset+4, streamFile) != 0x4D5F5749 ||// "M_WI"
            read_16bitBE(name_offset+8, streamFile) != 0x4900)      // "I\0"
            goto fail;
    }

    {
        struct offset_size_pair offset_size;

        offset_size = query_utf_data(streamFile, top_offset, 0, "data", &table_error);
        if (table_error) goto fail;
        body_offset = top_data_offset + offset_size.offset;
        body_size = offset_size.size;

        offset_size = query_utf_data(streamFile, top_offset, 0, "header", &table_error);
        if (table_error) goto fail;
        header_offset = top_data_offset + offset_size.offset;
        header_size = offset_size.size;
    }

    channel_count = query_utf_1byte(streamFile, top_offset, 0, "nch", &table_error);
    sample_count = query_utf_4byte(streamFile, top_offset, 0, "nsmpl", &table_error);
    sample_rate = query_utf_4byte(streamFile, top_offset, 0, "sfreq", &table_error);
    if (table_error) goto fail;
    if (channel_count != 1 && channel_count != 2) goto fail;
    if (header_size != channel_count * 0x60) goto fail;

    vgmstream = allocate_vgmstream(channel_count,loop_flag);

    vgmstream->num_samples = sample_count;
    vgmstream->sample_rate = sample_rate;

    vgmstream->coding_type = coding_NGC_DSP;
    vgmstream->layout_type = layout_none;
    vgmstream->meta_type = meta_UTF_DSP;

    {
        int i,j;
        long channel_size = (body_size+7)/8*8/channel_count;
        for (i = 0; i < channel_count; i++)
        {
            vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
            if (!vgmstream->ch[i].streamfile) goto fail;
            vgmstream->ch[i].channel_start_offset =
                vgmstream->ch[i].offset = body_offset + i * channel_size;
            for (j=0;j<16;j++)
            {
                vgmstream->ch[i].adpcm_coef[j] =
                    read_16bitBE(header_offset + 0x60*i + 0x1c + j*2, streamFile);
            }
        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #25
0
VGMSTREAM * init_vgmstream_xbox_xvas(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];

    int loop_flag=0;
	int channel_count;
    int i;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("xvas",filename_extension(filename))) goto fail;

	if((read_32bitLE(0x00,streamFile)!=0x69) && 
	   (read_32bitLE(0x08,streamFile)!=0x48))
		goto fail;

    /* No Loop found atm */
	loop_flag = (read_32bitLE(0x14,streamFile)==read_32bitLE(0x24,streamFile));
    
	/* Always stereo files */
	channel_count=read_32bitLE(0x04,streamFile);
    
	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	/* fill in the vital statistics */
	vgmstream->channels = channel_count;
    vgmstream->sample_rate = read_32bitLE(0x0c,streamFile);

	vgmstream->coding_type = coding_XBOX;
    vgmstream->num_samples = read_32bitLE(0x24,streamFile);
	vgmstream->num_samples -= ((vgmstream->num_samples/0x20000)*0x20);
	vgmstream->num_samples = vgmstream->num_samples / 36 * 64 / vgmstream->channels;

    vgmstream->layout_type = layout_xvas_blocked;
    vgmstream->meta_type = meta_XBOX_XVAS;

	if(loop_flag) {
		vgmstream->loop_start_sample = read_32bitLE(0x10,streamFile);
		vgmstream->loop_start_sample -= ((vgmstream->loop_start_sample/0x20000)*0x20);
		vgmstream->loop_start_sample = vgmstream->loop_start_sample / 36 * 64 / vgmstream->channels;
		vgmstream->loop_end_sample=vgmstream->num_samples;
	}
	
	/* open the file for reading by each channel */
    {
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
            vgmstream->ch[i].offset = 0x800;

            if (!vgmstream->ch[i].streamfile) goto fail;
        }
    }

	xvas_block_update(0x800,vgmstream);
    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #26
0
/* IAB: Ueki no Housoku - Taosu ze Robert Juudan!! (PS2) */
VGMSTREAM * init_vgmstream_ps2_iab(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[PATH_LIMIT];
    int loop_flag = 0;
	int channel_count;
    int i;
	off_t start_offset;
	
    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("iab",filename_extension(filename))) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0x10000000)
        goto fail;
    
    /* check file size */
    if (read_32bitLE(0x1C,streamFile) != get_streamfile_size(streamFile))
        goto fail;

    loop_flag = 0;
    channel_count = 2;
    
	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	/* fill in the vital statistics */
    start_offset = 0x40;
	vgmstream->channels = channel_count;
    vgmstream->sample_rate = read_32bitLE(0x4,streamFile);
    vgmstream->coding_type = coding_PSX;

    vgmstream->layout_type = layout_ps2_iab_blocked;
    vgmstream->interleave_block_size = read_32bitLE(0xC, streamFile);
    vgmstream->meta_type = meta_PS2_IAB;
    
    /* open the file for reading by each channel */
    {
        for (i=0;i<channel_count;i++) 
		{
            vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename, vgmstream->interleave_block_size);            
			if (!vgmstream->ch[i].streamfile) goto fail;
        }
    }

    /* Calc num_samples */
    ps2_iab_block_update(start_offset, vgmstream);
    vgmstream->num_samples=0;

    do 
	{    
		vgmstream->num_samples += 0x4000 * 14 / 16;
        ps2_iab_block_update(vgmstream->next_block_offset, vgmstream);
    } while (vgmstream->next_block_offset < get_streamfile_size(streamFile));

    ps2_iab_block_update(start_offset, vgmstream);

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #27
0
/* BH2PCM (from Bio Hazard 2) */
VGMSTREAM * init_vgmstream_ngc_bh2pcm(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];
    off_t start_offset;
	int channel_count;
	int format_detect;
    int loop_flag;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("bh2pcm",filename_extension(filename))) goto fail;

#if 0
    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0x00000000)
        goto fail;
#endif

    loop_flag = 0;
	channel_count = 2;

	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	/* fill in the vital statistics */
    format_detect=read_32bitLE(0x00,streamFile);
		switch (format_detect) {
			case 1:
				start_offset = 0x20;
				channel_count = 2;
				vgmstream->channels = channel_count;
				vgmstream->sample_rate = 32000;
				vgmstream->num_samples = read_32bitLE(0x04,streamFile)/2;
				vgmstream->layout_type = layout_interleave;
				vgmstream->interleave_block_size = read_32bitLE(0x04,streamFile);
				if (loop_flag) {
					vgmstream->loop_start_sample = 0;
					vgmstream->loop_end_sample = read_32bitLE(0x14,streamFile);
				}
			break;
			case 0:
				start_offset = 0x20;
				channel_count = 1;
				vgmstream->channels = channel_count;
				vgmstream->sample_rate = 32000;
				vgmstream->num_samples = read_32bitLE(0x0C,streamFile);
				vgmstream->layout_type = layout_none;
				if (loop_flag) {
					vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile);
					vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile);
				}
			break;
				default:
					goto fail;
			}

		vgmstream->coding_type = coding_PCM16BE;
		vgmstream->meta_type = meta_NGC_BH2PCM;

    /* open the file for reading */
    {
        int i;
        STREAMFILE * file;
        file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!file) goto fail;
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = file;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=start_offset+
                vgmstream->interleave_block_size*i;

        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #28
0
VGMSTREAM * init_vgmstream_dsp_bdsp(STREAMFILE *streamFile) {

    VGMSTREAM * vgmstream = NULL;
    char filename[PATH_LIMIT];
    int channel_count;
    int loop_flag;
    int i;
    off_t start_offset;
    
    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("bdsp",filename_extension(filename))) goto fail;

    channel_count = 2;
    loop_flag = 0;

    /* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

    /* fill in the vital statistics */
    vgmstream->channels = channel_count;
    vgmstream->sample_rate = read_32bitBE(0x8,streamFile);
    vgmstream->coding_type = coding_NGC_DSP;

#if 0
    if(loop_flag) {
        vgmstream->loop_start_sample = read_32bitBE(0x64,streamFile);
        vgmstream->loop_end_sample = read_32bitBE(0x68,streamFile);
    }	
#endif


        vgmstream->layout_type = layout_dsp_bdsp_blocked;
        vgmstream->interleave_block_size = 0x8;
        vgmstream->meta_type = meta_DSP_BDSP;
    
    /* open the file for reading by each channel */
    {
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size);
            
        if (!vgmstream->ch[i].streamfile) goto fail;
            vgmstream->ch[i].channel_start_offset=
            vgmstream->ch[i].offset=i*vgmstream->interleave_block_size;
        }
    }

    if (vgmstream->coding_type == coding_NGC_DSP) {
        int i;
        for (i=0;i<16;i++) {
            vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x1C+i*2,streamFile);
        }
        if (vgmstream->channels == 2) {
            for (i=0;i<16;i++) {
                vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x7C+i*2,streamFile);
            }
        }
    }

    /* Calc num_samples */
    start_offset = 0x0;
    dsp_bdsp_block_update(start_offset,vgmstream);
    vgmstream->num_samples=0;

    do
    {
      vgmstream->num_samples += vgmstream->current_block_size*14/8;
      dsp_bdsp_block_update(vgmstream->next_block_offset,vgmstream);
    }
    while (vgmstream->next_block_offset<get_streamfile_size(streamFile));

    dsp_bdsp_block_update(start_offset,vgmstream);


    return vgmstream;


    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #29
0
/* Guerrilla's MSS - Found in ShellShock Nam '67 (PS2/Xbox), Killzone (PS2) */
VGMSTREAM * init_vgmstream_mss(STREAMFILE *streamFile) {
	VGMSTREAM * vgmstream = NULL;
	off_t start_offset;
	size_t data_size;
	int loop_flag = 0, channel_count;

    /* checks */
    if (!check_extensions(streamFile, "mss"))
        goto fail;
    if (read_32bitBE(0x00,streamFile) != 0x4D435353) /* "MCSS" */
        goto fail;

    loop_flag = 0;
    channel_count = read_16bitLE(0x16,streamFile);

    /* 0x04: version? (always 0x00000100 LE) */
    start_offset = read_32bitLE(0x08,streamFile);
    data_size = read_32bitLE(0x0c,streamFile);


	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
	/* 0x14(1): 1/2/3/4 if 2/4/6/8ch,  0x15(1): 0/1?,  0x16: ch */
    vgmstream->layout_type = layout_interleave;
    vgmstream->interleave_block_size = read_32bitLE(0x18,streamFile);
    vgmstream->num_samples = read_32bitLE(0x1C,streamFile);
    vgmstream->meta_type = meta_MSS;

    /* no other way to know */
    if (vgmstream->interleave_block_size == 0x4800) {
        vgmstream->coding_type = coding_XBOX_IMA;

        /* in stereo multichannel this value is distance between 2ch pair, but we need
         * interleave*ch = full block (2ch 0x4800 + 2ch 0x4800 = 4ch, 0x4800+4800 / 4 = 0x2400) */
        vgmstream->interleave_block_size = vgmstream->interleave_block_size / 2;
        if (vgmstream->channels > 2 && vgmstream->channels % 2 != 0)
            goto fail; /* only 2ch+..+2ch layout is known */

        /* header values are somehow off? */
        data_size = get_streamfile_size(streamFile) - start_offset;
        vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
    }
    else {
        /* 0x800 interleave */
        vgmstream->coding_type = coding_PSX;

        if (vgmstream->num_samples * vgmstream->channels <= data_size)
            vgmstream->num_samples = vgmstream->num_samples / 16 * 28;
    }

    /* open the file for reading */
    if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
        goto fail;

    return vgmstream;

fail:
    close_vgmstream(vgmstream);
    return NULL;
}
Beispiel #30
0
/* IDVI (Eldorado Gate Volume 1-7) */
VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];
    off_t start_offset;

    int loop_flag;
	int channel_count;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("idvi",filename_extension(filename))) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0x49445649) /* "IDVI." */
        goto fail;

    loop_flag = read_32bitLE(0x0C,streamFile);
    channel_count = read_32bitLE(0x04,streamFile);
    
	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	/* fill in the vital statistics */
	vgmstream->channels = channel_count;
    start_offset = 0x800;
    vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
    vgmstream->coding_type = coding_INT_DVI_IMA;
    vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset);
	if (loop_flag) {
        vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile);
        vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset);
    }
    vgmstream->meta_type = meta_DC_IDVI;

	/* Calculating the short block... */
	if (channel_count > 1) {
		vgmstream->interleave_block_size = 0x400;
		vgmstream->interleave_smallblock_size = ((get_streamfile_size(streamFile)-start_offset)%(vgmstream->channels*vgmstream->interleave_block_size))/vgmstream->channels;
        vgmstream->layout_type = layout_interleave_shortblock;
    } else {
        vgmstream->layout_type = layout_none;
    }

    /* open the file for reading */
    {
        int i;
        STREAMFILE * file;
        file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!file) goto fail;
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = file;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=start_offset+
                vgmstream->interleave_block_size*i;

        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}