#include "coding.h" #include "g7221_decoder_lib.h" #ifdef VGM_USE_G7221 #define G7221_MAX_FRAME_SIZE 0x78 /* 960/8 */ #define G7221_MAX_FRAME_SAMPLES 640 /* 32000/50 */ struct g7221_codec_data { int channels; int frame_size; struct g7221_channel_data { sample_t buffer[G7221_MAX_FRAME_SAMPLES]; g7221_handle* handle; } *ch; }; g7221_codec_data* init_g7221(int channels, int frame_size) { int i; g7221_codec_data* data = NULL; if (frame_size > G7221_MAX_FRAME_SIZE) goto fail; data = calloc(1, sizeof(g7221_codec_data)); if (!data) goto fail; data->channels = channels; data->frame_size = frame_size; data->ch = calloc(channels, sizeof(struct g7221_channel_data)); if (!data->ch) goto fail; for (i = 0; i < data->channels; i++) { data->ch[i].handle = g7221_init(frame_size); if (!data->ch[i].handle) goto fail; } return data; fail: free_g7221(data); return NULL; } void decode_g7221(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t samples_to_do, int channel) { VGMSTREAMCHANNEL* ch = &vgmstream->ch[channel]; g7221_codec_data* data = vgmstream->codec_data; struct g7221_channel_data* ch_data = &data->ch[channel]; int i; if (0 == vgmstream->samples_into_block) { uint8_t buf[G7221_MAX_FRAME_SIZE]; size_t bytes; size_t read = data->frame_size; bytes = read_streamfile(buf, ch->offset, read, ch->streamfile); if (bytes != read) { //g7221_decode_empty(ch_data->handle, ch_data->buffer); memset(ch_data->buffer, 0, sizeof(ch_data->buffer)); VGM_LOG("S14: EOF read\n"); } else { g7221_decode_frame(ch_data->handle, buf, ch_data->buffer); } } for (i = 0; i < samples_to_do; i++) { outbuf[i*channelspacing] = ch_data->buffer[vgmstream->samples_into_block+i]; } } void reset_g7221(g7221_codec_data* data) { int i; if (!data) return; for (i = 0; i < data->channels; i++) { g7221_reset(data->ch[i].handle); } } void free_g7221(g7221_codec_data* data) { int i; if (!data) return; for (i = 0; i < data->channels; i++) { g7221_free(data->ch[i].handle); } free(data->ch); free(data); } void set_key_g7221(g7221_codec_data* data, const uint8_t* key) { int i; if (!data) return; for (i = 0; i < data->channels; i++) { g7221_set_key(data->ch[i].handle, key); } } /* just in case but very few should be enough */ #define S14_KEY_MIN_TEST_FRAMES 3 #define S14_KEY_MAX_TEST_FRAMES 5 /* Test a number of frames to check if current key decrypts correctly. * Returns score: <0: error/wrong, 0: unknown/silent, >0: good (closer to 1 is better). */ int test_key_g7221(g7221_codec_data* data, off_t start, STREAMFILE* sf) { size_t test_frames = 0, current_frame = 0; int total_score = 0; int max_frames = (get_streamfile_size(sf) - start) / data->frame_size; int cur_ch = 0; /* assumes key was set before this call */ while (test_frames < S14_KEY_MAX_TEST_FRAMES && current_frame < max_frames) { int score, ok; size_t bytes; uint8_t buf[G7221_MAX_FRAME_SIZE]; bytes = read_streamfile(buf, start, data->frame_size, sf); if (bytes != data->frame_size) { total_score = -1; break; } ok = g7221_decode_frame(data->ch[cur_ch].handle, buf, data->ch[cur_ch].buffer); if (!ok) { total_score = -1; break; } /* alternate channels (decode may affect scores otherwise) */ cur_ch = (cur_ch + 1) % data->channels; /* good key if it decodes without error, encryption is easily detectable */ score = 1; test_frames++; total_score += score; start += data->frame_size; } /* signal best possible score (many perfect frames and few blank frames) */ if (test_frames > S14_KEY_MIN_TEST_FRAMES && total_score > 0 && total_score <= test_frames) { total_score = 1; } /* clean up decoders */ reset_g7221(data); return total_score; } #endif