From 6f241eeeaa4785e5a4f46e113c2eb47129d28ee6 Mon Sep 17 00:00:00 2001 From: fastelbja Date: Sun, 6 Jul 2008 11:24:14 +0000 Subject: [PATCH] git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@290 51a99a44-fe44-0410-b1ba-c3e57ba2b86b --- src/meta/meta.h | 2 + src/meta/ngc_dsp_std.c | 117 +++++++++++++++++++++++++++++++++++++++++ src/vgmstream.c | 1 + src/vgmstream.h | 1 + winamp/in_vgmstream.c | 1 + 5 files changed, 122 insertions(+) diff --git a/src/meta/meta.h b/src/meta/meta.h index 289ad7be..46c3f328 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -81,6 +81,8 @@ VGMSTREAM * init_vgmstream_ps2_vpk(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_amts(STREAMFILE *streamFile); + #ifdef VGM_USE_VORBIS VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile); #endif diff --git a/src/meta/ngc_dsp_std.c b/src/meta/ngc_dsp_std.c index 54a09df5..addfc7fa 100644 --- a/src/meta/ngc_dsp_std.c +++ b/src/meta/ngc_dsp_std.c @@ -493,6 +493,7 @@ VGMSTREAM * init_vgmstream_ngc_dsp_std_int(STREAMFILE *streamFile) { int meta_type; struct dsp_header ch0_header,ch1_header; + int i; /* check extension, case insensitive */ @@ -702,6 +703,122 @@ fail: return NULL; } +/* AMTS - .amts files */ +VGMSTREAM * init_vgmstream_amts(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[260]; + + off_t start_offset; + off_t interleave; + int channel_count; + + struct dsp_header ch0_header,ch1_header; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("amts",filename_extension(filename))) goto fail; + + /* check header magic */ + if (read_32bitBE(0x0,streamFile) != 0x414D5453) goto fail; /* "sadb" */ + + channel_count=read_32bitBE(0x14,streamFile); + start_offset = 0x800; + interleave = read_32bitBE(0x08,streamFile); + + if (read_dsp_header(&ch0_header, 0x20, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(start_offset,streamFile)) + goto fail; + + if(channel_count==2) { + if (read_dsp_header(&ch1_header, 0x80, streamFile)) goto fail; + + if (ch1_header.initial_ps != (uint8_t)read_8bit(start_offset+interleave,streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain || + ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + if (ch0_header.loop_flag) { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + loop_off = (loop_off/interleave*interleave*2) + (loop_off%interleave); + if (ch0_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off+interleave,streamFile)) + goto fail; + } + + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + /* TODO: adjust for interleave? */ + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + vgmstream->meta_type = meta_DSP_AMTS; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if(channel_count==2) { + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + vgmstream->ch[1].streamfile = vgmstream->ch[0].streamfile; + } + + if (!vgmstream->ch[0].streamfile) goto fail; + /* open the file for reading */ + for (i=0;ich[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+i*interleave; + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + /* .wsi as found in Alone in the Dark for Wii */ /* These appear to be standard .dsp, but interleaved in a blocked format */ diff --git a/src/vgmstream.c b/src/vgmstream.c index 530b745b..04d5f8fb 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -67,6 +67,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_ahx, #endif init_vgmstream_ivb, + init_vgmstream_amts, }; #define INIT_VGMSTREAM_FCNS (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0])) diff --git a/src/vgmstream.h b/src/vgmstream.h index 6feee658..1f619e64 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -100,6 +100,7 @@ typedef enum { meta_DSP_STR, /* Conan .str files */ meta_DSP_SADB, /* .sad */ meta_DSP_WSI, /* .wsi */ + meta_DSP_AMTS, /* .amts */ /* Nintendo */ meta_STRM, /* STRM */ diff --git a/winamp/in_vgmstream.c b/winamp/in_vgmstream.c index dfd3b455..1d835022 100644 --- a/winamp/in_vgmstream.c +++ b/winamp/in_vgmstream.c @@ -123,6 +123,7 @@ char * extension_list[] = { "aud\0AUD Audio File (*.AUD)\0", "ahx\0AHX Audio File (*.AHX)\0", "ivb\0IVB Audio File (*.IVB)\0", + "amts\0AMTS Audio File (*.AMTS)\0", }; void about(HWND hwndParent) {