コード例 #1
0
ファイル: mta2.c プロジェクト: kode54/vgmstream
/* MTA2 in containers */
VGMSTREAM * init_vgmstream_mta2_container(STREAMFILE *streamFile) {
    VGMSTREAM *vgmstream = NULL;
    STREAMFILE *temp_streamFile = NULL;
    off_t subfile_offset;


    /* checks */
    /* .dbm: iPod metadata + mta2 with KCEJ blocks, .bgm: mta2 with KCEJ blocks (fake?) */
    if ( !check_extensions(streamFile,"dbm,bgm,mta2"))
        goto fail;

    if (read_32bitBE(0x00,streamFile) == 0x444C424D) { /* "DLBM" */
        subfile_offset = 0x800;
    }
    else if (read_32bitBE(0x00,streamFile) == 0x00000010) {
        subfile_offset = 0x00;
    }
    else {
        goto fail;
    }
    /* subfile size is implicit in KCEJ blocks */

    temp_streamFile = setup_mta2_streamfile(streamFile, subfile_offset, 1, "mta2");
    if (!temp_streamFile) goto fail;

    vgmstream = init_vgmstream_mta2(temp_streamFile);
    close_streamfile(temp_streamFile);

    return vgmstream;

fail:
    close_streamfile(temp_streamFile);
    close_vgmstream(vgmstream);
    return NULL;
}
コード例 #2
0
/* MIB+MIH - SCEE MultiStream interleaved bank (header+data) [namCollection: Ace Combat 2 (PS2), Rampage: Total Destruction (PS2)] */
VGMSTREAM * init_vgmstream_mib_mih(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    STREAMFILE * streamHeader = NULL;
    off_t start_offset;
    size_t data_size, frame_size, frame_last, frame_count;
    int channel_count, loop_flag;

    /* check extension */
    if (!check_extensions(streamFile, "mib"))
        goto fail;

    streamHeader = open_streamfile_by_ext(streamFile,"mih");
    if (!streamHeader) goto fail;

    if (read_32bitBE(0x00,streamHeader) != 0x40000000) /* header size */
        goto fail;

    loop_flag = 0; /* MIB+MIH don't PS-ADPCM loop flags */
    channel_count = read_32bitLE(0x08,streamHeader);
    start_offset = 0x00;

    /* 0x04: padding (0x20, MIH header must be multiple of 0x40) */
    frame_last  = (uint16_t)read_16bitLE(0x05,streamHeader);
    frame_size  = read_32bitLE(0x10,streamHeader);
    frame_count = read_32bitLE(0x14,streamHeader);
    if (frame_count == 0) { /* rarely [Gladius (PS2)] */
        frame_count = get_streamfile_size(streamFile) / (frame_size * channel_count);
    }

    data_size  = frame_count * frame_size;
    data_size -= frame_last ? (frame_size-frame_last) : 0; /* last frame has less usable data */
    data_size *= channel_count;


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

    vgmstream->sample_rate = read_32bitLE(0x0C,streamHeader);
    vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count);

    vgmstream->meta_type = meta_PS2_MIB_MIH;
    vgmstream->coding_type = coding_PSX;
    vgmstream->layout_type = layout_interleave;
    vgmstream->interleave_block_size = frame_size;

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

fail:
close_streamfile(streamHeader);
    close_vgmstream(vgmstream);
    return NULL;
}
コード例 #3
0
ファイル: pos.c プロジェクト: Sappharad/modizer
VGMSTREAM * init_vgmstream_pos(STREAMFILE *streamFile) {
    
	VGMSTREAM * vgmstream = NULL;
    STREAMFILE * streamFileWAV = NULL;
    char filename[1024];
	char filenameWAV[1024];

	int i;

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

	/* check for .WAV file */
	strcpy(filenameWAV,filename);
	strcpy(filenameWAV+strlen(filenameWAV)-3,"wav");

	streamFileWAV = streamFile->open(streamFile,filenameWAV,STREAMFILE_DEFAULT_BUFFER_SIZE);
	if (!streamFileWAV) {
        /* try again, ucase */
        for (i=strlen(filenameWAV);i>=0&&filenameWAV[i]!=DIRSEP;i--)
            filenameWAV[i]=toupper(filenameWAV[i]);

        streamFileWAV = streamFile->open(streamFile,filenameWAV,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!streamFileWAV) goto fail;
    }

    /* let the real initer do the parsing */
    vgmstream = init_vgmstream_riff(streamFileWAV);
    if (!vgmstream) goto fail;

    close_streamfile(streamFileWAV);
    streamFileWAV = NULL;

    /* install loops */
    if (!vgmstream->loop_flag) {
        vgmstream->loop_flag = 1;
        vgmstream->loop_ch = calloc(vgmstream->channels,
                sizeof(VGMSTREAMCHANNEL));
        if (!vgmstream->loop_ch) goto fail;
    }

    vgmstream->loop_start_sample = read_32bitLE(0,streamFile);
    vgmstream->loop_end_sample = read_32bitLE(4,streamFile);
    vgmstream->meta_type = meta_RIFF_WAVE_POS;

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (streamFileWAV) close_streamfile(streamFileWAV);
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
コード例 #4
0
static STREAMFILE* setup_bgw_atrac3_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, size_t frame_size, int channels) {
    STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL;
    bgw_decryption_data io_data = {0};
    size_t io_data_size = sizeof(bgw_decryption_data);
    int ch;

    /* setup decryption with key (first frame + modified channel header) */
    if (frame_size*channels == 0 || frame_size*channels > BGW_KEY_MAX) goto fail;

    io_data.key_size = read_streamfile(io_data.key, subfile_offset, frame_size*channels, streamFile);
    for (ch = 0; ch < channels; ch++) {
        uint32_t xor = get_32bitBE(io_data.key + frame_size*ch);
        put_32bitBE(io_data.key + frame_size*ch, xor ^ 0xA0024E9F);
    }

    /* setup subfile */
    new_streamFile = open_wrap_streamfile(streamFile);
    if (!new_streamFile) goto fail;
    temp_streamFile = new_streamFile;

    new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size);
    if (!new_streamFile) goto fail;
    temp_streamFile = new_streamFile;

    new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, bgw_decryption_read,NULL);
    if (!new_streamFile) goto fail;
    temp_streamFile = new_streamFile;

    return temp_streamFile;

fail:
    close_streamfile(temp_streamFile);
    return NULL;
}
コード例 #5
0
/* Prepares custom IO for custom Opus, that is converted to Ogg Opus on the fly */
static STREAMFILE* setup_opus_streamfile(STREAMFILE *streamFile, int channels, int skip, int sample_rate, off_t stream_offset, size_t stream_size, opus_type_t type) {
    STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL;
    opus_io_data io_data = {0};
    size_t io_data_size = sizeof(opus_io_data);

    io_data.type = type;
    io_data.stream_offset = stream_offset;
    io_data.stream_size = stream_size;
    io_data.physical_offset = stream_offset;
    io_data.head_size = make_oggs_first(io_data.head_buffer, sizeof(io_data.head_buffer), channels, skip, sample_rate);
    if (!io_data.head_size) goto fail;
    io_data.sequence = 2;
    io_data.logical_size = opus_io_size(streamFile, &io_data); /* force init */

    /* setup subfile */
    new_streamFile = open_wrap_streamfile(streamFile);
    if (!new_streamFile) goto fail;
    temp_streamFile = new_streamFile;

    new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, opus_io_read,opus_io_size);
    if (!new_streamFile) goto fail;
    temp_streamFile = new_streamFile;

    new_streamFile = open_buffer_streamfile(new_streamFile,0);
    if (!new_streamFile) goto fail;
    temp_streamFile = new_streamFile;

    return temp_streamFile;

fail:
    close_streamfile(temp_streamFile);
    return NULL;
}
コード例 #6
0
static void multifile_close(MULTIFILE_STREAMFILE *streamfile) {
    int i;
    for (i = 0; i < streamfile->inner_sfs_size; i++) {
        for (i = 0; i < streamfile->inner_sfs_size; i++) {
            close_streamfile(streamfile->inner_sfs[i]);
        }
    }
    free(streamfile->inner_sfs);
    free(streamfile->sizes);
    free(streamfile);
}
コード例 #7
0
/* ADS in containers */
VGMSTREAM * init_vgmstream_ps2_ads_container(STREAMFILE *streamFile) {
    VGMSTREAM *vgmstream = NULL;
    STREAMFILE *temp_streamFile = NULL;
    off_t subfile_offset;
    size_t subfile_size;

    /* checks */
    if (!check_extensions(streamFile, "ads"))
        goto fail;

    if (read_32bitBE(0x00,streamFile) == 0x41445343 &&  /* "ADSC" */
        read_32bitBE(0x04,streamFile) == 0x01000000) {
        /* Kenka Bancho 2, Kamen Rider Hibiki/Kabuto, Shinjuku no Okami */
        subfile_offset = 0x08;
    }
    else if (read_32bitBE(0x00,streamFile) == 0x63617669 && /* "cavi" */
             read_32bitBE(0x04,streamFile) == 0x61207374 && /* "a st" */
             read_32bitBE(0x08,streamFile) == 0x7265616D) { /* "ream" */
        /* cavia games: Drakengard 1/2, Dragon Quest Yangus, GITS: Stand Alone Complex */
        subfile_offset = 0x7d8;
    }
    else {
        goto fail;
    }

    subfile_size = get_streamfile_size(streamFile) - subfile_offset;

    temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL);
    if (!temp_streamFile) goto fail;

    vgmstream = init_vgmstream_ps2_ads(temp_streamFile);
    close_streamfile(temp_streamFile);

    return vgmstream;

fail:
    close_streamfile(temp_streamFile);
    close_vgmstream(vgmstream);
    return NULL;
}
コード例 #8
0
ファイル: sab.c プロジェクト: kode54/vgmstream
/* multiple streams may share a name, also sometimes won't a the name */
static void get_stream_name(char * stream_name, STREAMFILE *streamFile, int target_stream) {
    STREAMFILE * streamInfo = NULL;
    int i, j, total_cues, num_cue = -1;
    size_t name_size = 0;
    off_t name_offset = 0x10;

    streamInfo = open_streamfile_by_ext(streamFile, "sob");
    if (!streamInfo) goto end;
    if (read_32bitBE(0x00,streamInfo) != 0x43544632) /* "CTF2" */
        goto end;

    total_cues = read_32bitLE(0x08,streamInfo);

    for (i = 0; i < total_cues; i++) {
        uint32_t flags, num_subsections, subsection_1_size, subsection_2_size;

        flags             = (uint32_t)read_32bitLE(name_offset + 0x00,streamInfo);
        num_subsections   = (uint32_t)read_32bitLE(name_offset + 0x20,streamInfo);
        subsection_1_size = (flags & 0x00000001) ? 0x40 : 0x00;
        subsection_1_size +=(flags & 0x00000040) ? 0x20 : 0x00;
        subsection_2_size = (flags & 0x00000100) ? 0x1c : 0x10;

        for (j = 0; j < num_subsections; j++) {
            int num_stream = read_32bitLE(name_offset + 0x2c + subsection_1_size + j*subsection_2_size + 0x08,streamInfo);
            if (target_stream-1 == num_stream)
                num_cue = i;
        }

        name_offset += 0x2c + subsection_1_size + subsection_2_size * num_subsections;
    }
    if (num_cue < 0)
        goto end;

    for (i = 0; i < total_cues; i++) {
        /* 0x00: id */
        name_size = read_32bitLE(name_offset + 0x04,streamInfo); /* non null-terminated */
        if (i == num_cue) {
            name_offset += 0x08;
            break;
        }
        name_offset += 0x08 + name_size;
    }

    if (name_size > STREAM_NAME_SIZE-1)
        name_size = STREAM_NAME_SIZE-1;

    read_string(stream_name,name_size+1, name_offset,streamInfo);

end:
    if (streamInfo)
        close_streamfile(streamInfo);
}
コード例 #9
0
ファイル: streamfile.c プロジェクト: soneek/vgmstream
/**
 * open file containing looping data and copy to buffer
 *
 * returns true if found and copied
 */
int read_pos_file(uint8_t * buf, size_t bufsize, STREAMFILE *streamFile) {
    char posname[PATH_LIMIT];
    char filename[PATH_LIMIT];
    /*size_t bytes_read;*/
    STREAMFILE * streamFilePos= NULL;

    streamFile->get_name(streamFile,filename,sizeof(filename));

    if (strlen(filename)+4 > sizeof(posname)) goto fail;

    /* try to open a posfile using variations: "(name.ext).pos" */
    {
        strcpy(posname, filename);
        strcat(posname, ".pos");
        streamFilePos = streamFile->open(streamFile,posname,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (streamFilePos) goto found;

        goto fail;
    }

found:
    //if (get_streamfile_size(streamFilePos) != bufsize) goto fail;

    /* allow pos files to be of different sizes in case of new features, just fill all we can */
    memset(buf, 0, bufsize);
    read_streamfile(buf, 0, bufsize, streamFilePos);

    close_streamfile(streamFilePos);

    return 1;

fail:
    if (streamFilePos) close_streamfile(streamFilePos);

    return 0;
}
コード例 #10
0
static STREAMFILE *multifile_open(MULTIFILE_STREAMFILE *streamfile, const char * const filename, size_t buffersize) {
    char original_filename[PATH_LIMIT];
    STREAMFILE *new_sf = NULL;
    STREAMFILE **new_inner_sfs = NULL;
    int i;

    streamfile->inner_sfs[0]->get_name(streamfile->inner_sfs[0], original_filename, PATH_LIMIT);

    /* detect re-opening the file */
    if (strcmp(filename, original_filename) == 0) { /* same multifile */
        new_inner_sfs = calloc(streamfile->inner_sfs_size, sizeof(STREAMFILE*));
        if (!new_inner_sfs) goto fail;

        for (i = 0; i < streamfile->inner_sfs_size; i++) {
            streamfile->inner_sfs[i]->get_name(streamfile->inner_sfs[i], original_filename, PATH_LIMIT);
            new_inner_sfs[i] = streamfile->inner_sfs[i]->open(streamfile->inner_sfs[i], original_filename, buffersize);
            if (!new_inner_sfs[i]) goto fail;
        }

        new_sf = open_multifile_streamfile(new_inner_sfs, streamfile->inner_sfs_size);
        if (!new_sf) goto fail;

        return new_sf;
    }
    else {
        return streamfile->inner_sfs[0]->open(streamfile->inner_sfs[0], filename, buffersize); /* regular file */
    }

fail:
    if (new_inner_sfs) {
        for (i = 0; i < streamfile->inner_sfs_size; i++)
            close_streamfile(new_inner_sfs[i]);
    }
    free(new_inner_sfs);
    return NULL;
}
コード例 #11
0
/* SXD - Sony/SCE's SNDX lib format (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */
VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    STREAMFILE * streamHeader = NULL, *streamData = NULL;
    off_t start_offset, chunk_offset, first_offset = 0x60, name_offset = 0;
    size_t chunk_size, stream_size = 0;

    int is_dual = 0, is_external = 0;
    int loop_flag, channels, codec, flags;
    int sample_rate, num_samples, loop_start_sample, loop_end_sample;
    uint32_t at9_config_data = 0;
    int total_subsongs, target_subsong = streamFile->stream_index;


    /* check extension, case insensitive */
    /* .sxd: header+data (SXDF), .sxd1: header (SXDF) + .sxd2 = data (SXDS) */
    if (!check_extensions(streamFile,"sxd,sxd2")) goto fail;
    is_dual = !check_extensions(streamFile,"sxd");

    /* sxd1+sxd2: use sxd1 as header; otherwise use the current file as header */
    if (is_dual) {
        if (read_32bitBE(0x00,streamFile) != 0x53584453) /* "SXDS" */
            goto fail;
        streamHeader = open_streamfile_by_ext(streamFile, "sxd1");
        if (!streamHeader) goto fail;
    } else {
        streamHeader = streamFile;
    }
    if (read_32bitBE(0x00,streamHeader) != 0x53584446) /* "SXDF" */
        goto fail;


    /* typical chunks: NAME, WAVE and many control chunks (SXDs don't need to contain any sound data) */
    if (!find_chunk_le(streamHeader, 0x57415645,first_offset,0, &chunk_offset,&chunk_size)) /* "WAVE" */
        goto fail;

    /* check multi-streams (usually only in SFX containers) */
    total_subsongs = read_32bitLE(chunk_offset+0x04,streamHeader);
    if (target_subsong == 0) target_subsong = 1;
    if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
    // todo rarely a WAVE subsong may point to a repeated data offset, with different tags only
    

    /* read stream header */
    {
        off_t table_offset, header_offset, stream_offset;

        /* get target offset using table of relative offsets within WAVE */
        table_offset  = chunk_offset + 0x08 + 4*(target_subsong-1);
        header_offset = table_offset + read_32bitLE(table_offset,streamHeader);

        flags       = read_32bitLE(header_offset+0x00,streamHeader);
        codec       = read_8bit   (header_offset+0x04,streamHeader);
        channels    = read_8bit   (header_offset+0x05,streamHeader);
        /* 0x06(2): unknown, rarely 0xFF */
        sample_rate = read_32bitLE(header_offset+0x08,streamHeader);
        /* 0x0c(4): unknown size? (0x4000/0x3999/0x3333/etc, not related to extra data) */
        /* 0x10(4): ? + volume? + pan? (can be 0 for music) */
        num_samples       = read_32bitLE(header_offset+0x14,streamHeader);
        loop_start_sample = read_32bitLE(header_offset+0x18,streamHeader);
        loop_end_sample   = read_32bitLE(header_offset+0x1c,streamHeader);
        stream_size       = read_32bitLE(header_offset+0x20,streamHeader);
        stream_offset     = read_32bitLE(header_offset+0x24,streamHeader);

        loop_flag = loop_start_sample != -1 && loop_end_sample != -1;

        /* known flag combos:
         *  0x00: Chaos Rings 2 sfx (RAM + no tags)
         *  0x01: common (RAM + tags)
         *  0x02: Chaos Rings 3 sfx (stream + no tags)
         *  0x03: common (stream + tags)
         *  0x05: Gravity Rush 2 sfx (RAM + tags) */
        //has_tags = flags & 1;
        is_external = flags & 2;
        //unknown = flags & 4; /* no apparent differences with/without it? */

        /* flag 1 signals TLV-like extra data. Format appears to be 0x00(1)=tag?, 0x01(1)=extra size*32b?, 0x02(2)=config?
         * but not always (ex. size=0x07 but actually=0), perhaps only some bits are used or varies with tag, or are subflags.
         * A tag may appear with or without extra data (even 0x0a), 0x01/03/04/06 are common at the beginnig (imply number of tags?),
         * 0x64/7F are common at the end (but not always), 0x0A=ATRAC9 config, 0x0B/0C appear with RAM preloading data
         * (most variable in Soul Sacrifice; total TLVs size isn't plainly found in the SXD header AFAIK). */

        /* manually try to find ATRAC9 tag */
        if (codec == 0x42) {
            off_t extra_offset = header_offset+0x28;
            off_t max_offset = chunk_offset + chunk_size;

            if (!(flags & 1))
                goto fail;

            while (extra_offset < max_offset) {
                uint32_t tag = read_32bitBE(extra_offset, streamHeader);
                if (tag == 0x0A010000 || tag == 0x0A010600) {
                    at9_config_data = read_32bitLE(extra_offset+0x04,streamHeader); /* yes, LE */
                    break;
                }

                extra_offset += 0x04;
            }
            if (!at9_config_data)
                goto fail;
        }

        /* usually .sxd=header+data and .sxd1=header + .sxd2=data, but rarely sxd1 may contain data [The Last Guardian (PS4)] */
        if (is_external) {
            start_offset = stream_offset; /* absolute if external */
        } else {
            start_offset = header_offset+0x24 + stream_offset; /* from current entry offset if internal */
        }
    }

    /* get stream name (NAME is tied to REQD/cues, and SFX cues repeat WAVEs, but should work ok for streams) */
    if (is_dual && find_chunk_le(streamHeader, 0x4E414D45,first_offset,0, &chunk_offset,NULL)) { /* "NAME" */
        /* table: relative offset (32b) + hash? (32b) + cue index (32b) */
        int i;
        int num_entries = read_16bitLE(chunk_offset+0x04,streamHeader); /* can be bigger than streams */
        for (i = 0; i < num_entries; i++) {
            uint32_t index = (uint32_t)read_32bitLE(chunk_offset+0x08 + 0x08 + i*0x0c,streamHeader);
            if (index+1 == target_subsong) {
                name_offset = chunk_offset+0x08 + 0x00 + i*0x0c + read_32bitLE(chunk_offset+0x08 + 0x00 + i*0x0c,streamHeader);
                break;
            }
        }
    }

    if (is_external && !is_dual) {
        VGM_LOG("SXD: found single sxd with external data\n");
        goto fail;
    }

    if (is_external) {
        streamData = streamFile;
    } else {
        streamData = streamHeader;
    }

    if (start_offset > get_streamfile_size(streamData)) {
        VGM_LOG("SXD: wrong location?\n");
        goto fail;
    }


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

    vgmstream->sample_rate = sample_rate;
    vgmstream->num_samples = num_samples;
    vgmstream->loop_start_sample = loop_start_sample;
    vgmstream->loop_end_sample = loop_end_sample;
    vgmstream->num_streams = total_subsongs;
    vgmstream->stream_size = stream_size;
    vgmstream->meta_type = meta_SXD;
    if (name_offset)
        read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamHeader);

    switch (codec) {
        case 0x20:      /* PS-ADPCM [Hot Shots Golf: World Invitational (Vita) sfx] */
            vgmstream->coding_type = coding_PSX;
            vgmstream->layout_type = layout_interleave;
            vgmstream->interleave_block_size = 0x10;
            break;

        case 0x21:      /* HEVAG [Gravity Rush (Vita) sfx] */
            vgmstream->coding_type = coding_HEVAG;
            vgmstream->layout_type = layout_interleave;
            vgmstream->interleave_block_size = 0x10;
            break;

#ifdef VGM_USE_ATRAC9
        case 0x42: {    /* ATRAC9 [Soul Sacrifice (Vita), Freedom Wars (Vita), Gravity Rush 2 (PS4)] */
            atrac9_config cfg = {0};

            cfg.channels = vgmstream->channels;
            cfg.config_data = at9_config_data;

            vgmstream->codec_data = init_atrac9(&cfg);
            if (!vgmstream->codec_data) goto fail;
            vgmstream->coding_type = coding_ATRAC9;
            vgmstream->layout_type = layout_none;
            break;
        }
#endif
      //case 0x28:      /* dummy codec? (found with 0 samples) [Hot Shots Golf: World Invitational (Vita) sfx] */
        default:
            VGM_LOG("SXD: unknown codec 0x%x\n", codec);
            goto fail;
    }


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

    if (is_dual) close_streamfile(streamHeader);
    return vgmstream;

fail:
    if (is_dual) close_streamfile(streamHeader);
    close_vgmstream(vgmstream);
    return NULL;
}
コード例 #12
0
ファイル: ish_isd.c プロジェクト: 9a3eedi/Droidsound
VGMSTREAM * init_vgmstream_ish_isd(STREAMFILE *streamFile) {

    VGMSTREAM * vgmstream = NULL;
    STREAMFILE * streamFileISH = NULL;
    char filename[260];
    char filenameISH[260];
    int i;
    int channel_count;
    int loop_flag;

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

    strcpy(filenameISH,filename);
    strcpy(filenameISH+strlen(filenameISH)-3,"ish");

    streamFileISH = streamFile->open(streamFile,filenameISH,STREAMFILE_DEFAULT_BUFFER_SIZE);
    if (!streamFileISH) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFileISH) != 0x495F5346) /* "I_SF" */
        goto fail;
    
    channel_count = read_32bitBE(0x14,streamFileISH);
    loop_flag = (read_32bitBE(0x1C,streamFileISH) !=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(0x08,streamFileISH);
    vgmstream->num_samples=read_32bitBE(0x0C,streamFileISH);
    vgmstream->coding_type = coding_NGC_DSP;
    if(loop_flag) {
        vgmstream->loop_start_sample = read_32bitBE(0x20,streamFileISH)*14/8/channel_count;
        vgmstream->loop_end_sample = read_32bitBE(0x24,streamFileISH)*14/8/channel_count;
    }	

    if (channel_count == 1) {
        vgmstream->layout_type = layout_none;
    } else if (channel_count == 2) {
        vgmstream->layout_type = layout_interleave;
        vgmstream->interleave_block_size = read_32bitBE(0x18,streamFileISH);
    }

    vgmstream->meta_type = meta_ISH_ISD;
    
    /* 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(0x40+i*2,streamFileISH);
        }
        if (vgmstream->channels == 2) {
            for (i=0;i<16;i++) {
                vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x80+i*2,streamFileISH);
            }
        }
    }

    close_streamfile(streamFileISH); streamFileISH=NULL;
    
    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (streamFileISH) close_streamfile(streamFileISH);
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
コード例 #13
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)==0)
		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;
}
コード例 #14
0
ファイル: streamfile.c プロジェクト: soneek/vgmstream
/**
 * open file containing decryption keys and copy to buffer
 * tries combinations of keynames based on the original filename
 *
 * returns true if found and copied
 */
int read_key_file(uint8_t * buf, size_t bufsize, STREAMFILE *streamFile) {
    char keyname[PATH_LIMIT];
    char filename[PATH_LIMIT];
    const char *path, *ext;
    STREAMFILE * streamFileKey = NULL;

    streamFile->get_name(streamFile,filename,sizeof(filename));

    if (strlen(filename)+4 > sizeof(keyname)) goto fail;

    /* try to open a keyfile using variations:
     *  "(name.ext)key" (per song), "(.ext)key" (per folder) */
    {
        ext = strrchr(filename,'.');
        if (ext!=NULL) ext = ext+1;

        path = strrchr(filename,DIR_SEPARATOR);
        if (path!=NULL) path = path+1;

        /* "(name.ext)key" */
        strcpy(keyname, filename);
        strcat(keyname, "key");
        streamFileKey = streamFile->open(streamFile,keyname,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (streamFileKey) goto found;

        /* "(name.ext)KEY" */
        /*
        strcpy(keyname+strlen(keyname)-3,"KEY");
        streamFileKey = streamFile->open(streamFile,keyname,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (streamFileKey) goto found;
        */


        /* "(.ext)key" */
        if (path) {
            strcpy(keyname, filename);
            keyname[path-filename] = '\0';
            strcat(keyname, ".");
        } else {
            strcpy(keyname, ".");
        }
        if (ext) strcat(keyname, ext);
        strcat(keyname, "key");
        streamFileKey = streamFile->open(streamFile,keyname,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (streamFileKey) goto found;

        /* "(.ext)KEY" */
        /*
        strcpy(keyname+strlen(keyname)-3,"KEY");
        streamFileKey = streamFile->open(streamFile,keyname,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (streamFileKey) goto found;
        */

        goto fail;
    }

found:
    if (get_streamfile_size(streamFileKey) != bufsize) goto fail;

    if (read_streamfile(buf, 0, bufsize, streamFileKey)!=bufsize) goto fail;

    close_streamfile(streamFileKey);

    return 1;

fail:
    if (streamFileKey) close_streamfile(streamFileKey);

    return 0;
}
コード例 #15
0
ファイル: sqex_scd.c プロジェクト: kode54/vgmstream
/* 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;
}
コード例 #16
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;
}
コード例 #17
0
ファイル: ogg_vorbis_file.c プロジェクト: 9a3eedi/Droidsound
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;
            }
        }
    }

    /* 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;
}
コード例 #18
0
ファイル: gsp_gsb.c プロジェクト: jpmac26/PGE-Project
/* GSP+GSB - 2008-11-28 - manakoAT
Super Swing Golf 1 & 2 (WII) */
VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {

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


    strcpy(filenameGSP,filename);
    strcpy(filenameGSP+strlen(filenameGSP)-3,"gsp");

    streamFileGSP = streamFile->open(streamFile,filenameGSP,STREAMFILE_DEFAULT_BUFFER_SIZE);
    if (!streamFileGSP) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFileGSP) != 0x47534E44)	/* "GSND" */
        goto fail;

    channel_count = (uint16_t)read_16bitBE(0x3A,streamFileGSP);
    loop_flag = (read_32bitBE(0x64,streamFileGSP) != 0xFFFFFFFF);
    header_len = read_32bitBE(0x1C,streamFileGSP);
    
    coef1_start = header_len-0x4C;
    coef2_start = header_len-0x1C;
    
    /* 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(0x34,streamFileGSP);
    vgmstream->coding_type = coding_NGC_DSP;
    if(loop_flag) {
        vgmstream->loop_start_sample = read_32bitBE(0x64,streamFileGSP);
        vgmstream->loop_end_sample = read_32bitBE(0x68,streamFileGSP);
    }	

    if (channel_count == 1) {
        vgmstream->layout_type = layout_gsb_blocked;
    } else if (channel_count > 1) {
        vgmstream->layout_type = layout_gsb_blocked;
        vgmstream->interleave_block_size = read_32bitBE(header_len-0x64,streamFileGSP);
    }

    vgmstream->meta_type = meta_GSP_GSB;
    
    /* 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(coef1_start+i*2,streamFileGSP);
        }
        if (vgmstream->channels == 2) {
            for (i=0;i<16;i++) {
                vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(coef2_start+i*2,streamFileGSP);
            }
        }
    }

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

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

    gsb_block_update(start_offset,vgmstream);

    close_streamfile(streamFileGSP); streamFileGSP=NULL;

    return vgmstream;


    /* clean up anything we may have opened */
fail:
    if (streamFileGSP) close_streamfile(streamFileGSP);
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
コード例 #19
0
ファイル: pc_sob.c プロジェクト: Sappharad/modizer
VGMSTREAM * init_vgmstream_sab(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
	STREAMFILE* sob = NULL;
    char filename[1024];
	int i;
	int loop_flag, channel_count, numSounds;

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

	/* read information from sob file*/
	filename[strlen(filename)-2]='o'; //change extension in sob of file
	sob = open_stdio_streamfile(filename);
	if(!sob) goto fail;
	filename[strlen(filename)-2]='a';//change back to original file

	if (read_32bitBE(0,streamFile)!=0x43535732)//CSW2 header sab file
	{
		goto fail;
	}
	if (read_32bitBE(0,sob)!=0x43544632)//CTF2 header sob file
	{
		goto fail;
	}
	numSounds = read_32bitLE(8,sob);
	if(numSounds==1)
	{//it means it's a single stream and not a voice bank
		loop_flag = 1;
	}else
	{
		loop_flag = 0;
	}
    
	/* Read channels */
	channel_count = read_32bitLE(0x30,sob);
	if( (channel_count>2)||(numSounds>1))/* dirty hack for number of channels*/
		channel_count = 1;

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

    /* fill in the vital statistics */
	//is offset OK. sab files can contain more audio files, but without the sob it's just a long stream of sound effects
	vgmstream->current_block_offset=8+32*numSounds;
    vgmstream->channels = channel_count;
	vgmstream->sample_rate = read_32bitLE(0x20,streamFile);
    vgmstream->coding_type = coding_PCM16LE_int;
    vgmstream->num_samples = (int32_t)((get_streamfile_size(streamFile)-vgmstream->current_block_offset)/2/channel_count);
	if(loop_flag)
	{
		vgmstream->loop_start_sample = 0;
		vgmstream->loop_end_sample = vgmstream->num_samples;
	}
    vgmstream->layout_type = layout_none;
    vgmstream->meta_type = meta_PC_SOB_SAB;
	
    {
        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=vgmstream->current_block_offset+2*i;
        }
    }
	close_streamfile(sob);
    return vgmstream;

    /* clean up anything we may have opened */
fail:
	if (sob) close_streamfile(sob);
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
コード例 #20
0
ファイル: vsv.c プロジェクト: kode54/vgmstream
/* .VSV - from Square Enix games [Dawn of Mana: Seiken Densetsu 4 (PS2), Kingdom Hearts Re:Chain of Memories (PS2)] */
VGMSTREAM * init_vgmstream_vsv(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    STREAMFILE *temp_streamFile = NULL;
    off_t start_offset;
    int loop_flag, channel_count, flags, sample_rate, is_rs;
    size_t loop_start, adjust, data_size, interleave;


    /* checks */
    /* .vsv: extension from internal filenames [KH Re:CoM (PS2), DoM (PS2), KH HD I.5 + II.5 ReMIX (PS4)]
     * .psh: fake */
    if (!check_extensions(streamFile, "vsv,psh"))
        goto fail;

    /* 0x00(1x4): flags/config? */
    if ((uint8_t)read_8bit(0x03,streamFile) > 0x64) /* possibly volume */
        goto fail;
    if ((uint8_t)read_8bit(0x0a,streamFile) != 0) /* not seen */
        goto fail;

    /* Romancing SaGa (PS2) uses an earlier? version, this seems to work */
    is_rs = ((uint16_t)read_16bitLE(0x00,streamFile) == 0);

    start_offset = 0x00; /* correct, but needs some tricks to fix sound (see below) */
    interleave = 0x800;

    adjust      = (uint16_t)read_16bitLE(0x04,streamFile);
    loop_start = ((uint16_t)read_16bitLE(0x06,streamFile) & 0x7FFF) * interleave;
    loop_flag   = (uint16_t)read_16bitLE(0x06,streamFile) & 0x8000; /* loop_start != 0 works too, no files loop from beginning to end */
    sample_rate = (uint16_t)read_16bitLE(0x08,streamFile);
    flags       =  (uint8_t)read_8bit   (0x0b,streamFile); /* values: 0x01=stereo, 0x10=mono */
    data_size   = (uint16_t)read_16bitLE(0x0c,streamFile) * interleave;
    /* 0x0e: ? (may be a low-ish value) */

    channel_count = (flags & 1) ? 2 : 1;

    /* must discard to avoid wrong loops and unwanted data (easier to see in voices) */
    if (!is_rs) { /* RS doesn't do this */
        /* adjust & 0xF800 is unknown (values=0x0000|0x0800|0xF800, can be mono/stereo, loop/no, adjust/no) */
        size_t discard = adjust & 0x07FF;
        /* at (file_end - 0x800 + discard) is a 0x03 PS flag to check this (adjust 0 does discard full block) */
        data_size -= (0x800 - discard) * channel_count;
    }


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

    vgmstream->meta_type = meta_VSV;
    vgmstream->sample_rate = sample_rate;
    vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count);
    vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channel_count);
    vgmstream->loop_end_sample = vgmstream->num_samples;

    /* these loops are odd, but comparing the audio wave with the OSTs values seem correct */
    if (is_rs) {
        vgmstream->loop_start_sample -= ps_bytes_to_samples(channel_count*interleave,channel_count); /* maybe *before* loop block? */
        vgmstream->loop_start_sample -= ps_bytes_to_samples(0x200*channel_count,channel_count); /* maybe default adjust? */
    }

    vgmstream->coding_type = coding_PSX;
    vgmstream->layout_type = layout_interleave;
    vgmstream->interleave_block_size = interleave;

    temp_streamFile = setup_vsv_streamfile(streamFile, start_offset, data_size);
    if (!temp_streamFile) goto fail;

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

    close_streamfile(temp_streamFile);
    return vgmstream;

fail:
    close_streamfile(temp_streamFile);
    close_vgmstream(vgmstream);
    return NULL;
}
コード例 #21
0
ファイル: sgxd.c プロジェクト: benladen/vgmstream
/* SGXD - Sony/SCEI's format (SGB+SGH / SGD / SGX) */
VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    STREAMFILE * streamHeader = NULL;
    off_t start_offset, data_offset, chunk_offset, name_offset = 0;
    size_t stream_size;

    int is_sgx, is_sgb = 0;
    int loop_flag, channels, type;
    int sample_rate, num_samples, loop_start_sample, loop_end_sample;
    int total_subsongs, target_subsong = streamFile->stream_index;


    /* check extension, case insensitive */
    /* .sgx: header+data (Genji), .sgd: header+data, .sgh/sgd: header/data */
    if (!check_extensions(streamFile,"sgx,sgd,sgb"))
        goto fail;
    is_sgx = check_extensions(streamFile,"sgx");
    is_sgb = check_extensions(streamFile,"sgb");

    /* SGB+SGH: use SGH as header; otherwise use the current file as header */
    if (is_sgb) {
        streamHeader = open_stream_ext(streamFile, "sgh");
        if (!streamHeader) goto fail;
    } else {
        streamHeader = streamFile;
    }


    /* SGXD base (size 0x10) */
    if (read_32bitBE(0x00,streamHeader) != 0x53475844) /* "SGXD" */
        goto fail;
    /* 0x04  SGX: full header_size; SGD/SGH: unknown header_size (counting from 0x0/0x8/0x10, varies) */
    /* 0x08  SGX: first chunk offset? (0x10); SGD/SGH: full header_size */
    /* 0x0c  SGX/SGH: full data size with padding; SGD: full data size + 0x80000000 with padding */
    if (is_sgb) {
        data_offset = 0x00;
    } else if ( is_sgx ) {
        data_offset = read_32bitLE(0x04,streamHeader);
    } else {
        data_offset = read_32bitLE(0x08,streamHeader);
    }


    /* typical chunks: WAVE, RGND, NAME (strings for WAVE or RGND), SEQD (related to SFX), WSUR, WMKR, BUSS */
    /* WAVE chunk (size 0x10 + files * 0x38 + optional padding) */
    if (is_sgx) { /* position after chunk+size */
        if (read_32bitBE(0x10,streamHeader) != 0x57415645) goto fail;  /* "WAVE" */
        chunk_offset = 0x18;
    } else {
        if (!find_chunk_le(streamHeader, 0x57415645,0x10,0, &chunk_offset,NULL)) goto fail; /* "WAVE" */
    }
    /* 0x04  SGX: unknown; SGD/SGH: chunk length,  0x08  null */

    /* check multi-streams (usually only SE containers; Puppeteer) */
    total_subsongs = read_32bitLE(chunk_offset+0x04,streamHeader);
    if (target_subsong == 0) target_subsong = 1;
    if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;

    /* read stream header */
    {
        off_t stream_offset;
        chunk_offset += 0x08 + 0x38 * (target_subsong-1); /* position in target header*/

        /* 0x00  ? (00/01/02) */
        if (!is_sgx) /* meaning unknown in .sgx; offset 0 = not a stream (a RGND sample) */
            name_offset = read_32bitLE(chunk_offset+0x04,streamHeader);
        type = read_8bit(chunk_offset+0x08,streamHeader);
        channels = read_8bit(chunk_offset+0x09,streamHeader);
        /* 0x0a  null */
        sample_rate = read_32bitLE(chunk_offset+0x0c,streamHeader);

        /* 0x10  info_type: meaning of the next value
         *  (00=null, 30/40=data size without padding (ADPCM, ATRAC3plus), 80/A0=block size (AC3) */
        /* 0x14  info_value (see above) */
        /* 0x18  unknown (ex. 0x0008/0010/3307/CC02/etc)x2 */
        /* 0x1c  null */

        num_samples = read_32bitLE(chunk_offset+0x20,streamHeader);
        loop_start_sample = read_32bitLE(chunk_offset+0x24,streamHeader);
        loop_end_sample = read_32bitLE(chunk_offset+0x28,streamHeader);
        stream_size = read_32bitLE(chunk_offset+0x2c,streamHeader); /* stream size (without padding) / interleave (for type3) */

        if (is_sgx) {
            stream_offset = 0x0;
        } else{
            stream_offset = read_32bitLE(chunk_offset+0x30,streamHeader);
        }
        /* 0x34 SGX: unknown; SGD/SGH: stream size (with padding) / interleave */

        loop_flag = loop_start_sample!=0xffffffff && loop_end_sample!=0xffffffff;
        start_offset = data_offset + stream_offset;
    }


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

    vgmstream->sample_rate = sample_rate;
    vgmstream->num_samples = num_samples;
    vgmstream->loop_start_sample = loop_start_sample;
    vgmstream->loop_end_sample = loop_end_sample;
    vgmstream->num_streams = total_subsongs;
    vgmstream->stream_size = stream_size;
    vgmstream->meta_type = meta_SGXD;
    if (name_offset)
        read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamHeader);

    /* needs -1 to match RIFF AT3's loop chunk
     * (maybe SGXD = "loop before this sample" rather than "loop after this sample" as expected by vgmstream) */
    if (vgmstream->loop_end_sample > 0)
        vgmstream->loop_end_sample -= 1;

    switch (type) {
        case 0x03:      /* PS-ADPCM [Genji (PS3), Ape Escape Move (PS3)]*/
            vgmstream->coding_type = coding_PSX;
            vgmstream->layout_type = layout_interleave;
            if (is_sgx || is_sgb) {
                vgmstream->interleave_block_size = 0x10;
            } else { /* this only seems to happen with SFX */
                vgmstream->interleave_block_size = stream_size;
            }

            break;

#ifdef VGM_USE_FFMPEG
        case 0x04: {    /* ATRAC3plus [Kurohyo 1/2 (PSP), BraveStory (PSP)] */
            ffmpeg_codec_data *ffmpeg_data;

            /* internally has a RIFF header; but the SGXD  header / sample rate has priority over it (may not match) */
            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;

            /* manually read skip_samples if FFmpeg didn't do it */
            if (ffmpeg_data->skipSamples <= 0) {
                off_t chunk_offset;
                size_t chunk_size, fact_skip_samples = 0;
                if (!find_chunk_le(streamFile, 0x66616374,start_offset+0xc,0, &chunk_offset,&chunk_size)) /* find "fact" */
                    goto fail;
                if (chunk_size == 0x8) {
                    fact_skip_samples  = read_32bitLE(chunk_offset+0x4, streamFile);
                } else if (chunk_size == 0xc) {
                    fact_skip_samples  = read_32bitLE(chunk_offset+0x8, streamFile);
                }
                ffmpeg_set_skip_samples(ffmpeg_data, fact_skip_samples);
            }
            /* SGXD loop/sample values are relative (without skip samples) vs RIFF (with skip samples), no need to adjust */

            break;
        }
#endif
        case 0x05:      /* Short PS-ADPCM [Afrika (PS3)] */
            vgmstream->coding_type = coding_PSX_cfg;
            vgmstream->layout_type = layout_interleave;
            vgmstream->interleave_block_size = 0x4;

            break;

#ifdef VGM_USE_FFMPEG
        case 0x06: {    /* AC3 [Tokyo Jungle (PS3), Afrika (PS3)] */
            ffmpeg_codec_data *ffmpeg_data;

            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;

            /* manually set skip_samples if FFmpeg didn't do it */
            if (ffmpeg_data->skipSamples <= 0) {
                /* PS3 AC3 consistently has 256 encoder delay samples, and there are ~1000-2000 samples after num_samples.
                 * Skipping them marginally improves full loops in some Tokyo Jungle tracks (ex. a_1.sgd). */
                ffmpeg_set_skip_samples(ffmpeg_data, 256);
            }
            /* SGXD loop/sample values are relative (without skip samples), no need to adjust */

            break;
        }
#endif

        default:
            goto fail;
    }

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

    if (is_sgb && streamHeader) close_streamfile(streamHeader);
    return vgmstream;

fail:
    if (is_sgb && streamHeader) close_streamfile(streamHeader);
    close_vgmstream(vgmstream);
    return NULL;
}
コード例 #22
0
/* SGH+SGB (from Folklore) */
VGMSTREAM * init_vgmstream_ps3_sgh_sgb(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    off_t start_offset = 0;
    STREAMFILE * streamFileSGH = NULL;
    char filename[260];
    char filenameSGH[260];
    int channel_count;
    int loop_flag;

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

	strcpy(filenameSGH,filename);
    strcpy(filenameSGH+strlen(filenameSGH)-3,"sgh");

    streamFileSGH = streamFile->open(streamFile,filenameSGH,STREAMFILE_DEFAULT_BUFFER_SIZE);
    if (!streamFileSGH) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFileSGH) != 0x53475844) /* "SGXD" */
        goto fail;

    channel_count = read_8bit(0x29,streamFileSGH);
 	if (read_32bitBE(0x44,streamFileSGH)==0xFFFFFFFF)
        loop_flag = 0;
	else
		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_32bitLE(0x2C,streamFileSGH);
    vgmstream->num_samples = read_32bitLE(0xC,streamFileSGH)*28/32;
    vgmstream->coding_type = coding_PSX;
    if(loop_flag) {
        vgmstream->loop_start_sample = read_32bitLE(0x44,streamFileSGH);
        vgmstream->loop_end_sample = read_32bitLE(0x48,streamFileSGH);
    }	


    vgmstream->layout_type = layout_interleave;
    vgmstream->interleave_block_size = 0x10;
    vgmstream->meta_type = meta_PS3_SGH_SGB;

    /* 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 (streamFileSGH) close_streamfile(streamFileSGH);
	if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
コード例 #23
0
ファイル: vgmstream123.c プロジェクト: kode54/vgmstream
static int play_vgmstream(const char *filename, struct params *par) {
    int ret = 0;
    STREAMFILE *sf;
    VGMSTREAM *vgms;
    FILE *save_fps[4];
    int loop_count;
    int64_t total_samples;
    size_t buffer_size;
    int64_t buffer_samples;
    int64_t fade_time_samples, fade_start;
    int time_total_min;
    double time_total_sec;
    int64_t s;
    int i;

    sf = open_stdio_streamfile(filename);
    if (!sf) {
        fprintf(stderr, "%s: cannot open file\n", filename);
        return -1;
    }

    sf->stream_index = par->stream_index;
    vgms = init_vgmstream_from_STREAMFILE(sf);
    close_streamfile(sf);

    if (!vgms) {
        fprintf(stderr, "%s: error opening stream\n", filename);
        return -1;
    }

    printf("Playing stream: %s\n", filename);

    /* Print metadata in verbose mode
     */
    if (verbose) {
        char description[4096] = { '\0' };
        describe_vgmstream(vgms, description, sizeof(description));
        puts(description);
        putchar('\n');
    }

    /* If the audio device hasn't been opened yet, then describe it
     */
    if (!device) {
        ao_info *info = ao_driver_info(driver_id);
        printf("Audio device: %s\n", info->name);
        printf("Comment: %s\n", info->comment);
        putchar('\n');
    }

    /* Stupid hack to hang onto a few low-numbered file descriptors
     * so that play_compressed_file() doesn't break, due to POSIX
     * wackiness like https://bugs.debian.org/590920
     */
    for (i = 0; i < 4; i++)
        save_fps[i] = fopen("/dev/null", "r");

    ret = set_sample_format(vgms);
    if (ret) goto fail;

    loop_count = par->loop_count;

    if (vgms->loop_flag && loop_count < 0) {
        /*
         * Calculate how many loops are needed to achieve a minimum
         * playback time. Note: This calculation is derived from the
         * logic in get_vgmstream_play_samples().
         */
        double intro = (double)vgms->loop_start_sample / vgms->sample_rate;
        double loop = (double)(vgms->loop_end_sample - vgms->loop_start_sample) / vgms->sample_rate;
        double end = par->fade_time + par->fade_delay;
        if (loop < 1.0) loop = 1.0;
        loop_count = (int)((par->min_time - intro - end) / loop + 0.99);
        if (loop_count < 1) loop_count = 1;
    }

    total_samples = get_vgmstream_play_samples(loop_count, par->fade_time, par->fade_delay, vgms);

    {
        double total = (double)total_samples / vgms->sample_rate;
        time_total_min = (int)total / 60;
        time_total_sec = total - 60 * time_total_min;
    }

    /* Buffer size in bytes
     */
    buffer_size = 1024 * buffer_size_kb;

    if (!buffer) {
        if (buffer_size_kb < 1) {
            fprintf(stderr, "Invalid buffer size '%d'\n", buffer_size_kb);
            return -1;
        }

        buffer = malloc(buffer_size);
        if (!buffer) goto fail;
    }

    buffer_samples = buffer_size / (vgms->channels * sizeof(sample));

    fade_time_samples = (int64_t)(par->fade_time * vgms->sample_rate);
    fade_start = total_samples - fade_time_samples;
    if (fade_start < 0)
        fade_start = total_samples;

    for (s = 0; s < total_samples && !interrupted; s += buffer_samples) {
        int64_t buffer_used_samples = MIN(buffer_samples, total_samples - s);
        char *suffix = "";

        render_vgmstream(buffer, buffer_used_samples, vgms);

#ifdef LITTLE_ENDIAN_OUTPUT
        swap_samples_le(buffer, vgms->channels * buffer_used_samples);
#endif

        if (vgms->loop_flag && fade_time_samples > 0 && s >= fade_start) {
            /* Got to do the fade-out ourselves :p */
            int64_t b;
            for (b = 0; b < buffer_used_samples; b++) {
                double factor = 1.0 - (double)(s + b - fade_start) / fade_time_samples;
                int c;
                for (c = 0; c < vgms->channels; c++)
                    buffer[vgms->channels * b + c] *= factor;
            }
            suffix = " (fading)";
        }

        if (verbose && !out_filename) {
            double played = (double)s / vgms->sample_rate;
            double remain = (double)(total_samples - s) / vgms->sample_rate;

            int time_played_min = (int)played / 60;
            double time_played_sec = played - 60 * time_played_min;
            int time_remain_min = (int)remain / 60;
            double time_remain_sec = remain - 60 * time_remain_min;

            /* Time: 01:02.34 [08:57.66] of 10:00.00 */
            printf("\rTime: %02d:%05.2f [%02d:%05.2f] of %02d:%05.2f%s ",
                time_played_min, time_played_sec,
                time_remain_min, time_remain_sec,
                time_total_min,  time_total_sec,
                suffix);

            fflush(stdout);
        }

        if (!ao_play(device, (char *)buffer, buffer_used_samples * vgms->channels * sizeof(sample))) {
            fputs("\nAudio playback error\n", stderr);
            ao_close(device);
            device = NULL;
            ret = -1;
            break;
        }
    }

    if (verbose && !ret) {
        /* Clear time status line */
        putchar('\r');
        for (i = 0; i < 64; i++)
            putchar(' ');
        putchar('\r');
        fflush(stdout);
    }

    if (out_filename && !ret)
        printf("Wrote %02d:%05.2f of audio to %s\n\n",
            time_total_min, time_total_sec, out_filename);

    if (interrupted) {
        fputs("Playback terminated.\n\n", stdout);
        ret = record_interrupt();
        if (ret) fputs("Exiting...\n", stdout);
    }

    fail:

    close_vgmstream(vgms);

    for (i = 0; i < 4; i++)
        fclose(save_fps[i]);

    return ret;
}
コード例 #24
0
ファイル: ngc_sck_dsp.c プロジェクト: Sappharad/modizer
VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) {

	VGMSTREAM * vgmstream = NULL;
    STREAMFILE * streamFileDSP = NULL;
    char filename[1024];
	char filenameDSP[1024];
	
	int i;
	int channel_count;
	int loop_flag;

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


	strcpy(filenameDSP,filename);
	strcpy(filenameDSP+strlen(filenameDSP)-3,"dsp");

	streamFileDSP = streamFile->open(streamFile,filenameDSP,STREAMFILE_DEFAULT_BUFFER_SIZE);
	
    if (read_32bitBE(0x5C,streamFile) != 0x60A94000)
        goto fail;

	if (!streamFile) 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(0x18,streamFile);
	vgmstream->num_samples=read_32bitBE(0x14,streamFile)/8/channel_count*14;
	vgmstream->coding_type = coding_NGC_DSP;
	
	if(loop_flag) {
		vgmstream->loop_start_sample = 0;
		vgmstream->loop_end_sample = read_32bitBE(0x10,streamFile)/8/channel_count*14;
	}	

	if (channel_count == 1) {
		vgmstream->layout_type = layout_none;
	} else if (channel_count == 2) {
		vgmstream->layout_type = layout_interleave;
		vgmstream->interleave_block_size=read_32bitBE(0xC,streamFile);
	}



    vgmstream->meta_type = meta_NGC_SCK_DSP;
	
    /* open the file for reading */
    {
        for (i=0;i<channel_count;i++) {
			/* Not sure, i'll put a fake value here for now */
            vgmstream->ch[i].streamfile = streamFile->open(streamFileDSP,filenameDSP,0x8000);
            vgmstream->ch[i].offset = 0;

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


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


	close_streamfile(streamFileDSP); streamFileDSP=NULL;
    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (streamFileDSP) close_streamfile(streamFileDSP);
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
コード例 #25
0
ファイル: dsp_sth_str.c プロジェクト: 9a3eedi/Droidsound
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str1(STREAMFILE *streamFile) {
  	VGMSTREAM * vgmstream = NULL;
    STREAMFILE * streamFileSTR = NULL;
    char filename[260];
	  char filenameSTR[260];
  	int i, j;
	  int channel_count;
	  int loop_flag;
    off_t coef_table[8] = {0x12C,0x18C,0x1EC,0x24C,0x2AC,0x30C,0x36C,0x3CC};

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

	  strcpy(filenameSTR,filename);
	  strcpy(filenameSTR+strlen(filenameSTR)-3,"str");
	  streamFileSTR = streamFile->open(streamFile,filenameSTR,STREAMFILE_DEFAULT_BUFFER_SIZE);
	    if (!streamFileSTR) goto fail;

    if (read_32bitBE(0x0,streamFile) != 0x0)
    {
      goto fail;
    }

    if (read_32bitBE(0x4,streamFile) != 0x800)
    {
      goto fail;
    }

    /* Not really channel_count, just 'included tracks * channels per track */
	  loop_flag = (read_32bitBE(0xD8,streamFile) != 0xFFFFFFFF);
    channel_count = (read_32bitBE(0x70,streamFile)) * (read_32bitBE(0x88,streamFile));
    
    if (channel_count > 8)
    {
      goto fail;
    }

    /* 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(0x24,streamFile);
	  vgmstream->num_samples=get_streamfile_size(streamFileSTR)/8/channel_count*14;
	  vgmstream->coding_type = coding_NGC_DSP;
	
	  if(loop_flag)
    {
		  vgmstream->loop_start_sample = read_32bitBE(0xD8,streamFile);
		  vgmstream->loop_end_sample = read_32bitBE(0xDC,streamFile);
    }

	if (channel_count == 1)
  {
		vgmstream->layout_type = layout_none;
	}
  else
  {
		vgmstream->layout_type = layout_interleave;
		if (channel_count == 2)
    {
      vgmstream->interleave_block_size=0x10000;
    }
    else
    {
      vgmstream->interleave_block_size=0x8000;
    }
  }

  vgmstream->meta_type = meta_NGC_DSP_STH_STR;

    /* open the file for reading */
    for (i=0;i<channel_count;i++)
    {
      vgmstream->ch[i].streamfile = streamFileSTR->open(streamFileSTR,filenameSTR,0x8000);
        if (!vgmstream->ch[i].streamfile) goto fail;
      vgmstream->ch[i].channel_start_offset=vgmstream->ch[i].offset=i*vgmstream->interleave_block_size;
    }

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

  	close_streamfile(streamFileSTR); streamFileSTR=NULL;
    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (streamFileSTR) close_streamfile(streamFileSTR);
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
コード例 #26
0
ファイル: ps2_wmus.c プロジェクト: 9a3eedi/Droidsound
VGMSTREAM * init_vgmstream_ps2_wmus(STREAMFILE *streamFile) 
{
    VGMSTREAM * vgmstream = NULL;
    char filename[260];

    int loop_flag = 1;
	int channel_count;
    off_t start_offset;
    int i;
	
	int blockCount;
	int shortBlockSize;
	int lastBlockLocation;

	char	filenameWHED[260];
	STREAMFILE * streamFileWHED = NULL;

	//_TCHAR szBuffer[100];

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    
	if (strcasecmp("wmus",filename_extension(filename))) 
	{
		goto fail;
	}
	
	/* check for .WHED file */
	strcpy(filenameWHED, filename);
	strcpy(filenameWHED + strlen(filenameWHED) - 4, "WHED");

	streamFileWHED = streamFile->open(streamFile, filenameWHED, STREAMFILE_DEFAULT_BUFFER_SIZE);
	if (!streamFileWHED)
	{
		goto fail;
	}

	/* check loopand channel */
	loop_flag = 1;
    channel_count = read_32bitLE(0x14, streamFileWHED);
    
	/* 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(0x04, streamFileWHED);

	vgmstream->coding_type = coding_PSX;
    
	vgmstream->interleave_block_size = read_32bitLE(0x18, streamFileWHED);
	blockCount = read_32bitLE(0x1C, streamFileWHED) * channel_count;
	shortBlockSize = read_32bitLE(0x20, streamFileWHED);

	vgmstream->num_samples = (vgmstream->interleave_block_size * blockCount) / 16 / channel_count * 28;
	vgmstream->loop_start_sample = 0;
	
	lastBlockLocation = (vgmstream->interleave_block_size * blockCount) - (vgmstream->interleave_block_size - shortBlockSize);
	vgmstream->loop_end_sample = lastBlockLocation / 16 / channel_count * 28;

	//_stprintf(szBuffer, _T("%x"), lastBlockLocation);
	//MessageBox(NULL, szBuffer, _T("Foo"), MB_OK);


    vgmstream->layout_type = layout_interleave;
    vgmstream->meta_type = meta_PS2_WMUS;

	start_offset = 0;

    /* 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 (streamFileWHED) close_streamfile(streamFileWHED);
	if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
コード例 #27
0
ファイル: aax.c プロジェクト: Sappharad/modizer
/* Actual AAX init fcn */
VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) {
    
	VGMSTREAM * vgmstream = NULL;
    STREAMFILE * streamFileAAX = NULL;
    STREAMFILE * streamFileADX = NULL;
    char filename[1024];
    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;
}
コード例 #28
0
ファイル: wii_str.c プロジェクト: jpmac26/PGE-Project
VGMSTREAM * init_vgmstream_wii_str(STREAMFILE *streamFile) {
    
	VGMSTREAM * vgmstream = NULL;
	STREAMFILE * infileSTH = NULL;
	char filename[PATH_LIMIT];

	char * filenameSTH = NULL;

	int i, j, 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)!=0) 
		goto fail;

	channel_count = read_32bitBE(0x70,infileSTH);

	if(channel_count==1)
		loop_flag = (read_32bitBE(0xD4,infileSTH)==0x00740000);
	else
		loop_flag = (read_32bitBE(0x124,infileSTH)==0x00740000);

    /* 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(0x38,infileSTH);

	vgmstream->interleave_block_size=0x8000;
	vgmstream->num_samples=read_32bitBE(0x34,infileSTH);

	vgmstream->coding_type = coding_NGC_DSP;
    vgmstream->layout_type = layout_interleave;
    
	vgmstream->meta_type = meta_WII_STR;

	if(loop_flag) {
		vgmstream->loop_start_sample = 0;
		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,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);

			for(j=0; j<16; j++) {
				vgmstream->ch[i].adpcm_coef[j]=read_16bitBE(0xAC+(j*2)+(i*0x50),infileSTH);
			}
        }
    }

	close_streamfile(infileSTH); infileSTH=NULL;

    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;
}
コード例 #29
0
ファイル: sli.c プロジェクト: jpmac26/PGE-Project
VGMSTREAM * init_vgmstream_sli_ogg(STREAMFILE *streamFile) {
    
	VGMSTREAM * vgmstream = NULL;
    STREAMFILE * streamFileOGG = NULL;
    char filename[PATH_LIMIT];
	char filenameOGG[PATH_LIMIT];
    char linebuffer[PATH_LIMIT];
    off_t bytes_read;
    off_t sli_offset;
    int done;
    int32_t loop_start = -1;
    int32_t loop_length = -1;
    int32_t loop_from = -1;
    int32_t loop_to = -1;

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

	/* check for .OGG file */
	strcpy(filenameOGG,filename);
    /* strip off .sli */
    filenameOGG[strlen(filenameOGG)-4]='\0';

	streamFileOGG = streamFile->open(streamFile,filenameOGG,STREAMFILE_DEFAULT_BUFFER_SIZE);
	if (!streamFileOGG) {
        goto fail;
    }

    /* let the real initer do the parsing */
    vgmstream = init_vgmstream_ogg_vorbis(streamFileOGG);
    if (!vgmstream) goto fail;

    close_streamfile(streamFileOGG);
    streamFileOGG = NULL;

    sli_offset = 0;
    while ((loop_start == -1 || loop_length == -1) && sli_offset < get_streamfile_size(streamFile)) {
        char *endptr;
        char *foundptr;
        bytes_read=get_streamfile_dos_line(sizeof(linebuffer),linebuffer,sli_offset,streamFile,&done);
        if (!done) goto fail;

        if (!memcmp("LoopStart=",linebuffer,10) && linebuffer[10]!='\0') {
            loop_start = strtol(linebuffer+10,&endptr,10);
            if (*endptr != '\0') {
                /* if it didn't parse cleanly */
                loop_start = -1;
            }
        }
        else if (!memcmp("LoopLength=",linebuffer,11) && linebuffer[11]!='\0') {
            loop_length = strtol(linebuffer+11,&endptr,10);
            if (*endptr != '\0') {
                /* if it didn't parse cleanly */
                loop_length = -1;
            }
        }

        /* a completely different format, also with .sli extension and can be handled similarly */
        if ((foundptr=strstr(linebuffer,"To="))!=NULL && isdigit(foundptr[3])) {
            loop_to = strtol(foundptr+3,&endptr,10);
            if (*endptr != ';') {
                loop_to = -1;
            }
        }
        if ((foundptr=strstr(linebuffer,"From="))!=NULL && isdigit(foundptr[5])) {
            loop_from = strtol(foundptr+5,&endptr,10);
            if (*endptr != ';') {
                loop_from = -1;
            }
        }

        sli_offset += bytes_read;
    }

    if ((loop_start != -1 && loop_length != -1) ||
        (loop_to != -1 && loop_from != -1)) {
        /* install loops */
        if (!vgmstream->loop_flag) {
            vgmstream->loop_flag = 1;
            vgmstream->loop_ch = calloc(vgmstream->channels,
                    sizeof(VGMSTREAMCHANNEL));
            if (!vgmstream->loop_ch) goto fail;
        }

        if (loop_to != -1 && loop_from != -1) {
            vgmstream->loop_start_sample = loop_to;
            vgmstream->loop_end_sample = loop_from;
            vgmstream->meta_type = meta_OGG_SLI2;
        } else {
            vgmstream->loop_start_sample = loop_start;
            vgmstream->loop_end_sample = loop_start+loop_length;
            vgmstream->meta_type = meta_OGG_SLI;
        }
    } else goto fail; /* if there's no loop points the .sli wasn't valid */

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (streamFileOGG) close_streamfile(streamFileOGG);
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
コード例 #30
0
ファイル: aix.c プロジェクト: 9a3eedi/Droidsound
VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) {
    
	VGMSTREAM * vgmstream = NULL;
    STREAMFILE * streamFileAIX = NULL;
    STREAMFILE * streamFileADX = NULL;
    char filename[260];
    off_t *segment_offset = NULL;
    int32_t *samples_in_segment = NULL;
    int32_t sample_count;

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

    aix_codec_data *data = NULL;

    off_t first_AIXP;
    off_t stream_list_offset;
    off_t stream_list_end;
    const int segment_list_entry_size = 0x10;
    const off_t segment_list_offset = 0x20;

    int stream_count,channel_count,segment_count;
    int sample_rate;

	int i;

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

    if (read_32bitBE(0x0,streamFile) != 0x41495846 ||   /* "AIXF" */
            read_32bitBE(0x08,streamFile) != 0x01000014 ||
            read_32bitBE(0x0c,streamFile) != 0x00000800)
        goto fail;

    first_AIXP = read_32bitBE(0x4,streamFile)+8;
    segment_count = (uint16_t)read_16bitBE(0x18,streamFile);
    stream_list_offset = segment_list_offset+segment_list_entry_size*segment_count+0x10;

    if (stream_list_offset >= first_AIXP)
        goto fail;
    if (segment_count < 1)
        goto fail;

    sample_rate = read_32bitBE(stream_list_offset+8,streamFile);
    if (!check_sample_rate(sample_rate))
        goto fail;

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

    for (i = 0; i < segment_count; i++)
    {
        segment_offset[i] = read_32bitBE(segment_list_offset+segment_list_entry_size*i+0,streamFile);
        samples_in_segment[i] = read_32bitBE(segment_list_offset+segment_list_entry_size*i+0x08,streamFile);
        /*printf("samples_in_segment[%d]=%d\n",i,samples_in_segment[i]);*/
        /* all segments must have equal sample rate */
        if (read_32bitBE(segment_list_offset+segment_list_entry_size*i+0x0c,streamFile) != sample_rate)
        {
            /* segments > 0 can have 0 sample rate (Ryu ga gotoku: Kenzan! tenkei_sng1.aix),
               seems to indicate same sample rate as first */
            if (!(i > 0 && read_32bitBE(segment_list_offset+segment_list_entry_size*i+0x0c,streamFile) == 0))
                goto fail;
        }
    }

    if (segment_offset[0] != first_AIXP)
        goto fail;

    stream_count = (uint8_t)read_8bit(stream_list_offset,streamFile);
    if (stream_count < 1)
        goto fail;
    stream_list_end = stream_list_offset + 0x8 + stream_count * 8;

    if (stream_list_end >= first_AIXP)
        goto fail;

    channel_count = 0;
    for (i = 0; i < stream_count; i++)
    {
        /* all streams must have same samplerate as segments */
        if (read_32bitBE(stream_list_offset+8+i*8,streamFile)!=sample_rate)
            goto fail;
        channel_count += read_8bit(stream_list_offset+8+i*8+4,streamFile);
    }

    /* check for existence of segments */
    for (i = 0; i < segment_count; i++)
    {
        int j;
        off_t AIXP_offset = segment_offset[i];
        for (j = 0; j < stream_count; j++)
        {
            if (read_32bitBE(AIXP_offset,streamFile)!=0x41495850) /* "AIXP" */
                goto fail;
            if (read_8bit(AIXP_offset+8,streamFile)!=j)
                goto fail;
            AIXP_offset += read_32bitBE(AIXP_offset+4,streamFile)+8;
        }
    }

    /*streamFileAIX = streamFile->open(streamFile,filename,sample_rate*0.0375*2/32*18segment_count);*/
    streamFileAIX = streamFile->open(streamFile,filename,sample_rate*0.1*segment_count);
    if (!streamFileAIX) goto fail;

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

    /* for each segment */
    for (i = 0; i < segment_count; i++)
    {
        int j;
        /* for each stream */
        for (j = 0; j < stream_count; j++)
        {
            VGMSTREAM *adx;
            /*printf("try opening segment %d/%d stream %d/%d %x\n",i,segment_count,j,stream_count,segment_offset[i]);*/
            streamFileADX = open_aix_with_STREAMFILE(streamFileAIX,segment_offset[i],j);
            if (!streamFileADX) goto fail;
            adx = data->adxs[i*stream_count+j] = init_vgmstream_adx(streamFileADX);
            if (!adx)
                goto fail;
            close_streamfile(streamFileADX); streamFileADX = NULL;

            if (adx->num_samples != data->sample_counts[i] ||
                    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));

        }
    }

    if (segment_count > 1)
    {
        loop_flag = 1;
    }

    sample_count = 0;
    for (i = 0; i < segment_count; i++)
    {
        sample_count += data->sample_counts[i];

        if (i == 0)
            loop_start_sample = sample_count;
        if (i == 1)
            loop_end_sample = sample_count;
    }

    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_aix;
    vgmstream->meta_type = meta_AIX;

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

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

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (streamFileAIX) close_streamfile(streamFileAIX);
    if (streamFileADX) close_streamfile(streamFileADX);
    if (vgmstream) close_vgmstream(vgmstream);
    if (samples_in_segment) free(samples_in_segment);
    if (segment_offset) free(segment_offset);
    if (data) {
        if (data->adxs)
        {
            int i;
            for (i=0;i<data->segment_count*data->stream_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;
}