Beispiel #1
0
void CompressionTool::extractAndEncodeWAV(const char *outName, Common::File &input, AudioFormat compMode) {
	unsigned int length;
	char fbuf[2048];
	size_t size;

	input.seek(-4, SEEK_CUR);
	length = input.readUint32LE();
	length += 8;
	input.seek(-8, SEEK_CUR);

	/* Copy the WAV data to a temporary file */
	Common::File f(outName, "wb");
	while (length > 0) {
		size = input.read_noThrow(fbuf, length > sizeof(fbuf) ? sizeof(fbuf) : length);
		if (size <= 0)
			break;
		length -= (int)size;
		f.write(fbuf, size);
	}
	f.close();

	/* Convert the WAV temp file to OGG/MP3 */
	encodeAudio(outName, false, -1, tempEncoded, compMode);
}
int main(int argc, char *argv[]) {
	GtkWidget *main_window, *scroll;
	GtkWidget *treeview;
	GtkTreeViewColumn *column;
	GtkCellRenderer *name_renderer, *size_renderer;
	GtkTreeStore *store;
	GtkTreeIter categories[14];
	GValue value = { 0, };
	gint offset;
	uint32 res_counts[14];
	uint32 res_sizes[14];
	int i;

	Common::File in;
	uint32 index_pos;
	uint32 pos, len;

	gtk_init(&argc, &argv);

	if (argc != 2) {
		printf("Usage: %s filename\n", argv[0]);
		return EXIT_FAILURE;
	}

	in.open(argv[1], "rb");
	if (!in.isOpen()) {
		printf("Couldn't open %s for reading\n", argv[1]);
		return EXIT_FAILURE;
	}

	/* Create the main window, scrollable in both directions */

	main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title(GTK_WINDOW(main_window), "CLUster Explorer");
	gtk_window_set_default_size(GTK_WINDOW(main_window), 400, 400);

	g_signal_connect(G_OBJECT(main_window), "destroy", G_CALLBACK(main_window_destroy_cb), NULL);

	scroll = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_ETCHED_IN);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

	/* Create the tree view */

	for (i = 0; i < ARRAYSIZE(res_counts); i++) {
		res_counts[i] = 0;
		res_sizes[i] = 0;
	}

	store = gtk_tree_store_new(N_COLUMNS,
		G_TYPE_STRING,
		G_TYPE_STRING,
		G_TYPE_INT,
		G_TYPE_INT,
		G_TYPE_INT);

	gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(store), compare_items, NULL, NULL);
	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);

	index_pos = in.readUint32LE();
	in.seek(index_pos, SEEK_SET);

	for (;;) {
		GtkTreeIter iter;
		byte type;
		gchar *utf8_name;
		gchar name[34];
		gchar *size;

		try {
			pos = in.readUint32LE();
			len = in.readUint32LE();
		} catch (...) {
			break;
		}

		size = make_size(len);

		index_pos = in.pos();

		in.seek(pos, SEEK_SET);

		type = in.readByte();
		in.readByte();				/* compType	*/
		in.readUint32LE();			/* compSize	*/
		in.readUint32LE();			/* decompSize	*/
		in.read_noThrow(name, sizeof(name));

		/*
		 * We need to convert from Latin-1 to UTF-8. Otherwise the text
		 * "CAFÉ" won't be displayed properly.
		 */

		utf8_name = g_convert(name, -1, "UTF-8", "ISO-8859-1", NULL, NULL, NULL);

		if (!res_counts[type]) {
			gtk_tree_store_append(store, &categories[type], NULL);
			gtk_tree_store_set(store, &categories[type],
				NAME_COLUMN, getType(type),
				SIZE_COLUMN, "",
				TYPE_COLUMN, -1,
				POSITION_COLUMN, -1,
				LENGTH_COLUMN, -1,
				-1);
		}

		res_counts[type]++;
		res_sizes[type] += len;
		gtk_tree_store_append(store, &iter, &categories[type]);
		gtk_tree_store_set(store, &iter,
			NAME_COLUMN, utf8_name,
			SIZE_COLUMN, size,
			TYPE_COLUMN, type,
			POSITION_COLUMN, pos,
			LENGTH_COLUMN, len);

		in.seek(index_pos, SEEK_SET);
	}

	in.close();

	for (i = 0; i < ARRAYSIZE(res_counts); i++) {
		if (res_counts[i]) {
			gchar size[80];

			sprintf(size, "%s [%d]", make_size(res_sizes[i]), res_counts[i]);
			gtk_tree_store_set(store, &categories[i],
				SIZE_COLUMN, size,
				-1);
		}
	}

	treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), TRUE);

	g_signal_connect(G_OBJECT(treeview), "button-press-event", G_CALLBACK(tree_view_button_cb), argv[1]);

	/* The view now holds a reference. We can get rid of our own. */
	g_object_unref(G_OBJECT(store));

	name_renderer = gtk_cell_renderer_text_new();
	size_renderer = gtk_cell_renderer_text_new();

	g_value_init(&value, G_TYPE_FLOAT);
	g_value_set_float(&value, 1.0);
	g_object_set_property(G_OBJECT(size_renderer), "xalign", &value);

	gtk_tree_view_insert_column_with_attributes(
		GTK_TREE_VIEW(treeview), -1, "Name", name_renderer,
		"text", NAME_COLUMN,
		NULL);

	offset = gtk_tree_view_insert_column_with_attributes(
		GTK_TREE_VIEW(treeview), -1, "Size", size_renderer,
		"text", SIZE_COLUMN,
		NULL);
	column = gtk_tree_view_get_column(GTK_TREE_VIEW(treeview), offset - 1);
	gtk_tree_view_column_set_alignment(column, 1.0);

	gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(treeview));
	gtk_container_add(GTK_CONTAINER(main_window), scroll);
	gtk_widget_show_all(GTK_WIDGET(main_window));
	gtk_main();

	return EXIT_SUCCESS;
}
Beispiel #3
0
bool loadWAVFromStream(Common::File &stream, int &size, int &rate, byte &flags, uint16 *wavType, int *blockAlign_) {
    const uint32 initialPos = stream.pos();
    byte buf[4+1];

    buf[4] = 0;

    stream.read_noThrow(buf, 4);
    if (memcmp(buf, "RIFF", 4) != 0) {
        warning("getWavInfo: No 'RIFF' header");
        return false;
    }

    uint32 wavLength = stream.readUint32LE();

    stream.read_noThrow(buf, 4);
    if (memcmp(buf, "WAVE", 4) != 0) {
        warning("getWavInfo: No 'WAVE' header");
        return false;
    }

    stream.read_noThrow(buf, 4);
    if (memcmp(buf, "fmt ", 4) != 0) {
        warning("getWavInfo: No 'fmt' header");
        return false;
    }

    uint32 fmtLength = stream.readUint32LE();
    if (fmtLength < 16) {
        // A valid fmt chunk always contains at least 16 bytes
        warning("getWavInfo: 'fmt' header is too short");
        return false;
    }

    // Next comes the "type" field of the fmt header. Some typical
    // values for it:
    // 1  -> uncompressed PCM
    // 17 -> IMA ADPCM compressed WAVE
    // See <http://www.saettler.com/RIFFNEW/RIFFNEW.htm> for a more complete
    // list of common WAVE compression formats...
    uint16 type = stream.readUint16LE();	// == 1 for PCM data
    uint16 numChannels = stream.readUint16LE();	// 1 for mono, 2 for stereo
    uint32 samplesPerSec = stream.readUint32LE();	// in Hz
    uint32 avgBytesPerSec = stream.readUint32LE();	// == SampleRate * NumChannels * BitsPerSample/8

    uint16 blockAlign = stream.readUint16LE();	// == NumChannels * BitsPerSample/8
    uint16 bitsPerSample = stream.readUint16LE();	// 8, 16 ...
    // 8 bit data is unsigned, 16 bit data signed


    if (wavType != 0)
        *wavType = type;

    if (blockAlign_ != 0)
        *blockAlign_ = blockAlign;
#if 0
    printf("WAVE information:\n");
    printf("  total size: %d\n", wavLength);
    printf("  fmt size: %d\n", fmtLength);
    printf("  type: %d\n", type);
    printf("  numChannels: %d\n", numChannels);
    printf("  samplesPerSec: %d\n", samplesPerSec);
    printf("  avgBytesPerSec: %d\n", avgBytesPerSec);
    printf("  blockAlign: %d\n", blockAlign);
    printf("  bitsPerSample: %d\n", bitsPerSample);
#endif

    if (type != 1 && type != 2 && type != 17) {
        warning("getWavInfo: only PCM, MS ADPCM or IMA ADPCM data is supported (type %d)", type);
        return false;
    }

    if (blockAlign != numChannels * bitsPerSample / 8 && type != 2) {
        debug(0, "getWavInfo: blockAlign is invalid");
    }

    if (avgBytesPerSec != samplesPerSec * blockAlign && type != 2) {
        debug(0, "getWavInfo: avgBytesPerSec is invalid");
    }

    // Prepare the return values.
    rate = samplesPerSec;

    flags = 0;
    if (bitsPerSample == 8)		// 8 bit data is unsigned
        flags |= Audio::Mixer::FLAG_UNSIGNED;
    else if (bitsPerSample == 16)	// 16 bit data is signed little endian
        flags |= (Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_LITTLE_ENDIAN);
    else if (bitsPerSample == 4 && type == 17)	// MS IMA ADPCM compressed. We decompress it
        flags |= (Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_LITTLE_ENDIAN);
    else if (bitsPerSample == 4 && type == 2)	// MS ADPCM compressed. We decompress it
        flags |= (Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_LITTLE_ENDIAN);
    else {
        warning("getWavInfo: unsupported bitsPerSample %d", bitsPerSample);
        return false;
    }

    if (numChannels == 2)
        flags |= Audio::Mixer::FLAG_STEREO;
    else if (numChannels != 1) {
        warning("getWavInfo: unsupported number of channels %d", numChannels);
        return false;
    }

    // It's almost certainly a WAV file, but we still need to find its
    // 'data' chunk.

    // Skip over the rest of the fmt chunk.
    int offset = fmtLength - 16;

    do {
        stream.seek(offset, SEEK_CUR);
        if (stream.pos() >= int(initialPos + wavLength + 8)) {
            warning("getWavInfo: Cannot find 'data' chunk");
            return false;
        }
        stream.read_noThrow(buf, 4);
        offset = stream.readUint32LE();

#if 0
        printf("  found a '%s' tag of size %d\n", buf, offset);
#endif
    } while (memcmp(buf, "data", 4) != 0);

    // Stream now points at 'offset' bytes of sample data...
    size = offset;

    return true;
}