Exemplo n.º 1
0
int save_wav(const char * fn, SAMPLE * sp)
{
	PACKFILE * file;

	eof_log("save_wav() entered", 1);

	if(!fn || !sp)
	{
		return 0;
	}
	/* open file */
	file = pack_fopen(fn, "w");
	if(file == NULL)
	{
		(void) snprintf(eof_log_string, sizeof(eof_log_string) - 1, "\tError saving WAV:  \"%s\"", strerror(errno));	//Get the Operating System's reason for the failure
		eof_log(eof_log_string, 1);
		return 0;
	}

	/* save WAV to the file */
	if(!save_wav_fp(sp, file))
	{
		(void) pack_fclose(file);
		return 0;
	}

	/* close the file */
	(void) pack_fclose(file);

	return 1;
}
Exemplo n.º 2
0
void eof_move_text_events(EOF_SONG * sp, unsigned long beat, unsigned long offset, int dir)
{
	unsigned long i;

	eof_log("eof_move_text_events() entered", 1);

	if(!sp)
	{
		return;
	}
	for(i = 0; i < sp->text_events; i++)
	{
		if(sp->text_event[i]->beat >= beat)
		{
			if(sp->text_event[i]->beat >= sp->beats)
				continue;	//Do not allow an out of bound access
			sp->beat[sp->text_event[i]->beat]->flags &= ~(EOF_BEAT_FLAG_EVENTS);	//Clear the event flag
			if(dir < 0)
			{
				if(offset > sp->text_event[i]->beat)
					continue;	//Do not allow an underflow
				sp->text_event[i]->beat -= offset;
			}
			else
			{
				if(sp->text_event[i]->beat + offset >= sp->beats)
					continue;	//Do not allow an overflow
				sp->text_event[i]->beat += offset;
			}
			sp->beat[sp->text_event[i]->beat]->flags |= EOF_BEAT_FLAG_EVENTS;	//Set the event flag
		}
	}
}
Exemplo n.º 3
0
void eof_controller_read_button_names(EOF_CONTROLLER * cp)
{
	int i;

	eof_log("eof_controller_read_button_names() entered", 1);

	if(!cp)
	{
		return;
	}
	for(i = 0; i < EOF_CONTROLLER_MAX_BUTTONS; i++)
	{
		switch(cp->button[i].type)
		{
			case EOF_CONTROLLER_BUTTON_TYPE_KEY:
			{
				(void) ustrcpy(cp->button[i].name, scancode_to_name(cp->button[i].key));
				break;
			}
			case EOF_CONTROLLER_BUTTON_TYPE_JOYBUTTON:
			{
				(void) snprintf(cp->button[i].name, sizeof(cp->button[i].name) - 1, "Joy %d %s", cp->button[i].joy, joy[cp->button[i].joy].button[cp->button[i].key].name);
				break;
			}
			case EOF_CONTROLLER_BUTTON_TYPE_JOYAXIS:
			{
				(void) snprintf(cp->button[i].name, sizeof(cp->button[i].name) - 1, "Joy %d %s Axis (%s)", cp->button[i].joy, joy[cp->button[i].joy].stick[cp->button[i].index].axis[cp->button[i].key].name, cp->button[i].d == 0 ? "-" : "+");
				break;
			}
		}
	}
}
Exemplo n.º 4
0
void eof_undo_reset(void)
{
 	eof_log("eof_undo_reset() entered", 1);

	eof_undo_current_index = 0;
	eof_undo_count = 0;
	eof_redo_count = 0;
}
Exemplo n.º 5
0
void eof_mix_seek(int pos)
{
	int i;

	eof_log("eof_mix_seek() entered", 2);

	eof_mix_next_clap = -1;
	eof_mix_next_metronome = -1;
	eof_mix_next_note = -1;
	eof_mix_next_percussion = -1;

	eof_mix_sample_count = eof_mix_msec_to_sample(pos, alogg_get_wave_freq_ogg(eof_music_track));
	for(i = 0; i < eof_mix_claps; i++)
	{
		if(eof_mix_clap_pos[i] >= eof_mix_sample_count)
		{
			eof_mix_current_clap = i;
			eof_mix_next_clap = eof_mix_clap_pos[i];
			break;
		}
	}
	for(i = 0; i < eof_mix_metronomes; i++)
	{
		if(eof_mix_metronome_pos[i] >= eof_mix_sample_count)
		{
			eof_mix_current_metronome = i;
			eof_mix_next_metronome = eof_mix_metronome_pos[i];
			break;
		}
	}
	for(i = 0; i < eof_mix_notes; i++)
	{
		if(eof_mix_note_pos[i] >= eof_mix_sample_count)
		{
			eof_mix_current_note = i;
			eof_mix_next_note = eof_mix_note_pos[i];
			break;
		}
	}
	for(i = 0; i < eof_mix_percussions; i++)
	{
		if(eof_mix_percussion_pos[i] >= eof_mix_sample_count)
		{
			eof_mix_current_percussion = i;
			eof_mix_next_percussion = eof_mix_percussion_pos[i];
			break;
		}
	}
	for(i = 0; i < eof_mix_guitar_notes; i++)
	{
		if(eof_guitar_notes[i].pos >= eof_mix_sample_count)
		{
			eof_mix_current_guitar_note = i;
			eof_mix_next_guitar_note = eof_guitar_notes[i].pos;
			break;
		}
	}
}
Exemplo n.º 6
0
void eof_window_destroy(EOF_WINDOW * wp)
{
    eof_log("eof_window_destroy() entered", 1);

    if(wp)
    {
        destroy_bitmap(wp->screen);
        free(wp);
    }
}
Exemplo n.º 7
0
static unsigned long msec_to_samples(unsigned long msec)
{
	unsigned long sample;
	double second = (double)msec / (double)1000.0;
	unsigned long freq = alogg_get_wave_freq_ogg(eof_music_track);

	eof_log("msec_to_samples() entered", 1);

	sample = (unsigned long)(second * (double)freq);
	return sample;
}
Exemplo n.º 8
0
int eof_copy_file(const char * src, const char * dest)
{
	PACKFILE * src_fp = NULL;
	PACKFILE * dest_fp = NULL;
	void *ptr = NULL;	//Used to buffer memory
	unsigned long src_size = 0;
	unsigned long i;

 	eof_log("eof_copy_file() entered", 1);

	if((src == NULL) || (dest == NULL))
		return 0;
	if(!ustricmp(src,dest))		//Special case:  The input and output file are the same
		return 0;				//Return success without copying any files

	src_size = (unsigned long)file_size_ex(src);
	if(src_size > LONG_MAX)
		return 0;	//Unable to validate I/O due to Allegro's usage of signed values
	src_fp = pack_fopen(src, "r");
	if(!src_fp)
	{
		return 0;
	}
	dest_fp = pack_fopen(dest, "w");
	if(!dest_fp)
	{
		(void) pack_fclose(src_fp);
		return 0;
	}
//Attempt to buffer the input file into memory for faster read and write
	ptr = malloc((size_t)src_size);
	if(ptr != NULL)
	{	//If a buffer large enough to store the input file was created
		long long_src_size = src_size;
		if((pack_fread(ptr, long_src_size, src_fp) != long_src_size) || (pack_fwrite(ptr, long_src_size, dest_fp) != long_src_size))
		{	//If there was an error reading from file or writing from memory
			free(ptr);	//Release buffer
			return 0;	//Return error
		}
		free(ptr);	//Release buffer
	}
	else
	{	//Otherwise copy the slow way (one byte at a time)
		for(i = 0; i < src_size; i++)
		{
			(void) pack_putc(pack_getc(src_fp), dest_fp);
		}
	}
	(void) pack_fclose(src_fp);
	(void) pack_fclose(dest_fp);
	return 1;
}
Exemplo n.º 9
0
int eof_file_compare(char *file1, char *file2)
{
	uint64_t filesize,ctr;
	int data1,data2;
	PACKFILE *fp1 = NULL,*fp2 = NULL;
	char result = 0;	//The result is assumed to "files identical" until found otherwise

 	eof_log("eof_file_compare() entered", 1);

	if((file1 == NULL) || (file2 == NULL))
	{
		return 2;	//Return error
	}

	filesize = file_size_ex(file1);	//Get length of file1
	if(filesize != file_size_ex(file2))
	{	//If file1 and file2 are different lengths
		return 1;	//Return files don't match
	}

	fp1 = pack_fopen(file1, "r");
	if(fp1 == NULL)
	{
		return 2;	//Return error
	}
	fp2 = pack_fopen(file2, "r");
	if(fp2 == NULL)
	{
		(void) pack_fclose(fp1);
		return 2;	//Return error
	}

	for(ctr = 0;ctr < filesize; ctr++)
	{	//For each byte in the files
		data1 = pack_getc(fp1);	//Read one byte from each
		data2 = pack_getc(fp2);
		if((data1 == EOF) || (data2 == EOF))
		{	//If EOF was reached unexpectedly
			break;	//Exit loop
		}
		if(data1 != data2)
		{
			result = 1;	//Store a "non identical" result
			break;		//Exit loop
		}
	}
	(void) pack_fclose(fp1);
	(void) pack_fclose(fp2);

	return result;
}
Exemplo n.º 10
0
int eof_undo_load_state(const char * fn)
{
	EOF_SONG * sp = NULL;
	PACKFILE * fp = NULL, * rfp = NULL;
	char rheader[16] = {0};
	int old_eof_silence_loaded = eof_silence_loaded;	//Retain this value, since it is destroyed by eof_destroy_song()
	char eof_recover_path[50];

 	eof_log("eof_undo_load_state() entered", 1);

	if(fn == NULL)
	{
		return 0;
	}
	fp = pack_fopen(fn, "r");
	if(!fp)
	{
		return 0;
	}
	if(pack_fread(rheader, 16, fp) != 16)
	{
		return 0;	//Return error if 16 bytes cannot be read
	}
	sp = eof_create_song();		//Initialize an empty chart
	if(sp == NULL)
	{
		return 0;
	}
	sp->tags->accurate_ts = 0;	//For existing projects, this setting must be manually enabled in order to prevent unwanted alteration to beat timings
	(void) snprintf(eof_recover_path, sizeof(eof_recover_path) - 1, "%seof.recover", eof_temp_path);
	rfp = pack_fopen(eof_recover_path, "r");	//Open the recovery file to prevent eof_destroy_song() from deleting it
	if(!eof_load_song_pf(sp, fp))
	{	//If loading the undo state fails
		allegro_message("Failed to perform undo");
		(void) pack_fclose(rfp);	//Close this recovery file handle so that it will be deleted by the following call to eof_destroy_song()
		eof_destroy_song(sp);
		return 0;	//Return failure
	}
	if(eof_song)
	{
		eof_destroy_song(eof_song);	//Destroy the chart that is open
	}
	(void) pack_fclose(rfp);
	eof_song = sp;	//Replacing it with the loaded undo state
	eof_silence_loaded = old_eof_silence_loaded;	//Restore the status of whether chart audio is loaded

	(void) pack_fclose(fp);
	return 1;
}
Exemplo n.º 11
0
void eof_mix_init(void)
{
	int i;
	char fbuffer[1024] = {0};

	eof_log("eof_mix_init() entered", 1);

	eof_sound_clap = load_wav("eof.dat#clap.wav");
	if(!eof_sound_clap)
	{
		allegro_message("Couldn't load clap sound!");
	}
	eof_sound_metronome = load_wav("eof.dat#metronome.wav");
	if(!eof_sound_metronome)
	{
		allegro_message("Couldn't load metronome sound!");
	}
	eof_sound_grid_snap = load_wav("eof.dat#gridsnap.wav");
	if(!eof_sound_grid_snap)
	{
		allegro_message("Couldn't load seek sound!");
	}
	for(i = 0; i < EOF_MAX_VOCAL_TONES; i++)
	{	//Load piano tones
		(void) snprintf(fbuffer, sizeof(fbuffer) - 1, "eof.dat#piano.esp/NOTE_%02d_OGG", i);
		eof_sound_note[i] = eof_mix_load_ogg_sample(fbuffer);
	}
	eof_sound_cowbell = eof_mix_load_ogg_sample("percussion.dat#cowbell.ogg");
	eof_sound_chosen_percussion = eof_sound_cowbell;	//Until the user specifies otherwise, make cowbell the default percussion
	eof_sound_tambourine1 = eof_mix_load_ogg_sample("percussion.dat#tambourine1.ogg");
	eof_sound_tambourine2 = eof_mix_load_ogg_sample("percussion.dat#tambourine2.ogg");
	eof_sound_tambourine3 = eof_mix_load_ogg_sample("percussion.dat#tambourine3.ogg");
	eof_sound_triangle1 = eof_mix_load_ogg_sample("percussion.dat#triangle1.ogg");
	eof_sound_triangle2 = eof_mix_load_ogg_sample("percussion.dat#triangle2.ogg");
	eof_sound_woodblock1 = eof_mix_load_ogg_sample("percussion.dat#woodblock1.ogg");
	eof_sound_woodblock2 = eof_mix_load_ogg_sample("percussion.dat#woodblock2.ogg");
	eof_sound_woodblock3 = eof_mix_load_ogg_sample("percussion.dat#woodblock3.ogg");
	eof_sound_woodblock4 = eof_mix_load_ogg_sample("percussion.dat#woodblock4.ogg");
	eof_sound_woodblock5 = eof_mix_load_ogg_sample("percussion.dat#woodblock5.ogg");
	eof_sound_woodblock6 = eof_mix_load_ogg_sample("percussion.dat#woodblock6.ogg");
	eof_sound_woodblock7 = eof_mix_load_ogg_sample("percussion.dat#woodblock7.ogg");
	eof_sound_woodblock8 = eof_mix_load_ogg_sample("percussion.dat#woodblock8.ogg");
	eof_sound_woodblock9 = eof_mix_load_ogg_sample("percussion.dat#woodblock9.ogg");
	eof_sound_woodblock10 = eof_mix_load_ogg_sample("percussion.dat#woodblock10.ogg");
	eof_sound_clap1 = eof_mix_load_ogg_sample("percussion.dat#clap1.ogg");
	eof_sound_clap2 = eof_mix_load_ogg_sample("percussion.dat#clap2.ogg");
	eof_sound_clap3 = eof_mix_load_ogg_sample("percussion.dat#clap3.ogg");
	eof_sound_clap4 = eof_mix_load_ogg_sample("percussion.dat#clap4.ogg");
}
Exemplo n.º 12
0
SAMPLE * create_silence_sample(unsigned long ms)
{
	SAMPLE * sp = NULL;
	int bits;
	int stereo;
	int freq;
	unsigned long samples, i;
	unsigned channels;

	eof_log("create_silence_sample() entered", 1);

	if(eof_music_track)
	{
		bits = alogg_get_wave_bits_ogg(eof_music_track);
		stereo = alogg_get_wave_is_stereo_ogg(eof_music_track);
		freq = alogg_get_wave_freq_ogg(eof_music_track);
		samples = msec_to_samples(ms);
		channels = stereo ? 2 : 1;
	}
	else
	{
		bits = 16;
		stereo = 1;
		freq = 44100;
		samples = (double)(ms * freq) / 1000.0;
		channels = 2;
	}

	sp = create_sample(bits, stereo, freq, samples);
	if(!sp)
		return NULL;	//Return error

	if(bits == 8)
	{
		for(i = 0; i < samples * channels; i++)
		{
			((unsigned char *)(sp->data))[i] = 0x80;
		}
	}
	else
	{
		for(i = 0; i < samples * channels; i++)
		{
			((unsigned short *)(sp->data))[i] = 0x8000;
		}
	}

	return sp;
}
Exemplo n.º 13
0
void eof_sort_events(EOF_SONG * sp)
{
	unsigned long ctr;

 	eof_log("eof_sort_events() entered", 1);

	if(sp)
	{
		for(ctr = 0; ctr < sp->text_events; ctr++)
		{	//For each text event in the project
			sp->text_event[ctr]->index = ctr;	//Store the native index into the event to prevent qsort() from corrupting the order of events that otherwise have matching sort criteria
		}
		qsort(sp->text_event, (size_t)sp->text_events, sizeof(EOF_TEXT_EVENT *), eof_song_qsort_events);
	}
}
Exemplo n.º 14
0
void eof_destroy_waveform(struct wavestruct *ptr)
{
 	eof_log("eof_destroy_waveform() entered", 1);

	if(ptr)
	{
		if(ptr->oggfilename)
			free(ptr->oggfilename);
		if(ptr->left.slices)
			free(ptr->left.slices);
		if(ptr->right.slices)
			free(ptr->right.slices);
		free(ptr);
	}
}
Exemplo n.º 15
0
void eof_controller_load_config(EOF_CONTROLLER * cp, char * name)
{
	int i;
	char string[256] = {0};

	eof_log("eof_controller_load_config() entered", 1);

	if(!cp || !name)
	{
		return;
	}
	for(i = 0; i < EOF_CONTROLLER_MAX_BUTTONS; i++)
	{
		(void) snprintf(string, sizeof(string) - 1, "button_%d_type", i);
		cp->button[i].type = get_config_int(name, string, 0);
		switch(cp->button[i].type)
		{
			case EOF_CONTROLLER_BUTTON_TYPE_KEY:
			{
				(void) snprintf(string, sizeof(string) - 1, "button_%d_key", i);
				cp->button[i].key = get_config_int(name, string, 0);
				break;
			}
			case EOF_CONTROLLER_BUTTON_TYPE_JOYBUTTON:
			{
				(void) snprintf(string, sizeof(string) - 1, "button_%d_controller", i);
				cp->button[i].joy = get_config_int(name, string, 0);
				(void) snprintf(string, sizeof(string) - 1, "button_%d_key", i);
				cp->button[i].key = get_config_int(name, string, 0);
				break;
			}
			case EOF_CONTROLLER_BUTTON_TYPE_JOYAXIS:
			{
				(void) snprintf(string, sizeof(string) - 1, "button_%d_controller", i);
				cp->button[i].joy = get_config_int(name, string, 0);
				(void) snprintf(string, sizeof(string) - 1, "button_%d_axis", i);
				cp->button[i].index = get_config_int(name, string, 0);
				(void) snprintf(string, sizeof(string) - 1, "button_%d_direction", i);
				cp->button[i].d = get_config_int(name, string, 0);
				(void) snprintf(string, sizeof(string) - 1, "button_%d_key", i);
				cp->button[i].key = get_config_int(name, string, 0);
				break;
			}
		}
	}
	cp->delay = get_config_int(name, "delay", 0);
}
Exemplo n.º 16
0
void eof_song_delete_text_event(EOF_SONG * sp, unsigned long event)
{
	unsigned long i;

 	eof_log("eof_song_delete_text_event() entered", 1);

	if(sp)
	{
		free(sp->text_event[event]);
		for(i = event; i < sp->text_events - 1; i++)
		{
			sp->text_event[i] = sp->text_event[i + 1];
		}
		sp->text_events--;
		eof_cleanup_beat_flags(sp);	//Rebuild event flags for all beats to ensure they're valid
	}
}
Exemplo n.º 17
0
EOF_WINDOW * eof_window_create(int x, int y, int w, int h, BITMAP * bp)
{
    EOF_WINDOW * wp = NULL;
    if(bp == NULL)
        return NULL;

    eof_log("eof_window_create() entered", 1);

    wp = malloc(sizeof(EOF_WINDOW));
    if(wp)
    {
        wp->x = x;
        wp->y = y;
        wp->w = w;
        wp->h = h;
        wp->screen = create_sub_bitmap(bp, x, y, w, h);
    }
    return wp;
}
Exemplo n.º 18
0
int eof_undo_load_state(const char * fn)
{
	EOF_SONG * sp = NULL;
	PACKFILE * fp = NULL;
	char rheader[16] = {0};
	int old_eof_silence_loaded = eof_silence_loaded;	//Retain this value, since it is destroyed by eof_destroy_song()

 	eof_log("eof_undo_load_state() entered", 1);

	if(fn == NULL)
	{
		return 0;
	}
	fp = pack_fopen(fn, "r");
	if(!fp)
	{
		return 0;
	}
	if(pack_fread(rheader, 16, fp) != 16)
	{
		return 0;	//Return error if 16 bytes cannot be read
	}
	sp = eof_create_song();		//Initialize an empty chart
	if(sp == NULL)
	{
		return 0;
	}
	if(!eof_load_song_pf(sp, fp))
	{	//If loading the undo state fails
		allegro_message("Failed to perform undo");
		eof_destroy_song(sp);
		return 0;	//Return failure
	}
	if(eof_song)
	{
		eof_destroy_song(eof_song);	//Destroy the chart that is open
	}
	eof_song = sp;	//Replacing it with the loaded undo state
	eof_silence_loaded = old_eof_silence_loaded;	//Restore the status of whether chart audio is loaded

	(void) pack_fclose(fp);
	return 1;
}
Exemplo n.º 19
0
void eof_mix_start(int speed)
{
	unsigned long i;

	eof_log("eof_mix_start() entered", 1);

	eof_mix_next_clap = -1;
	eof_mix_next_metronome = -1;
	for(i = 0; i < EOF_MIX_MAX_CHANNELS; i++)
	{
		eof_voice[i].sp = NULL;
		eof_voice[i].pos = 0;
		eof_voice[i].fpos = 0.0;
		eof_voice[i].playing = 0;
		eof_voice[i].volume = 100;		//Default to 100% volume
		eof_voice[i].multiplier = 1.0;	//Default to 100% volume
	}
	eof_voice[0].volume = eof_clap_volume;	//Put the clap volume into effect
	eof_voice[0].multiplier = sqrt(eof_clap_volume/100.0);	//Store this math so it only needs to be performed once

	eof_voice[1].volume = eof_tick_volume;	//Put the tick volume into effect
	eof_voice[1].multiplier = sqrt(eof_tick_volume/100.0);	//Store this math so it only needs to be performed once

	eof_voice[2].volume = eof_tone_volume;	//Put the tone volume into effect
	eof_voice[2].multiplier = sqrt(eof_tone_volume/100.0);	//Store this math so it only needs to be performed once

	eof_voice[3].volume = eof_percussion_volume;	//Put the percussion volume into effect
	eof_voice[3].multiplier = sqrt(eof_percussion_volume/100.0);	//Store this math so it only needs to be performed once

	eof_mix_speed = speed;
	eof_mix_speed_ticker = 0;
	eof_mix_sample_count = eof_mix_msec_to_sample(alogg_get_pos_msecs_ogg(eof_music_track), alogg_get_wave_freq_ogg(eof_music_track));
	eof_mix_sample_increment = (1.0) * (44100.0 / (double)alogg_get_wave_freq_ogg(eof_music_track));
	eof_mix_start_helper();

	for(i = 1; i < eof_song->tracks; i++)
	{	//Pre-process all tracks so that switching tracks during playback doesn't cause the playback to lag
		eof_determine_phrase_status(eof_song, i);
	}
}
Exemplo n.º 20
0
int EOF_EXPORT_TO_LC(EOF_VOCAL_TRACK * tp, char *outputfilename, char *string2, int format)
{
	unsigned long linectr = 0, lyrctr = 0, lastlyrtime = 0, linestart = 0, lineend = 0;
	unsigned char pitch = 0;
	FILE *outf = NULL;			//Used to open output file
	FILE *pitchedlyrics = NULL;	//Used to open output pitched lyric fle
	char *vrhythmid = NULL;
	EOF_PHRASE_SECTION temp;	//Used to store the first lyric line in the project, which gets overridden with one covering all lyrics during RS1 export
	unsigned long original_lines;
	char *tempoutputfilename = "lyrics.temp";

	eof_log("EOF_EXPORT_TO_LC() entered", 1);

	if((tp == NULL) || (outputfilename == NULL) || (tp->lyrics == 0))
		return -1;	//Return failure

//Initialize variables
	InitLyrics();	//Initialize all variables in the Lyrics structure
	InitMIDI();		//Initialize all variables in the MIDI structure

	qsort(tp->line, (size_t)tp->lines, sizeof(EOF_PHRASE_SECTION), eof_song_qsort_phrase_sections);	//Sort the lyric lines
	temp = tp->line[0];			//Preserve the original lyric line information
	original_lines = tp->lines;

//Set export-specific settings
	if(format == SCRIPT_FORMAT)
	{
		Lyrics.grouping = 2;	//Enable line grouping for script.txt export
		Lyrics.nohyphens = 3;	//Disable hyphen output
		Lyrics.noplus = 1;	//Disable plus output
		Lyrics.filter = DuplicateString("^=%#/");	//Use default filter list
		Lyrics.defaultfilter = 1;	//Track that the above string will need to be freed
	}
	else if((format == RS_FORMAT) || (format == RS2_FORMAT))
	{
		Lyrics.noplus = 1;	//Disable plus output
		Lyrics.filter = DuplicateString("^=%#/");	//Use default filter list
		Lyrics.defaultfilter = 1;	//Track that the above string will need to be freed
		if((format == RS_FORMAT) || (!tp->lines))
		{	//If exporting to Rocksmith 1 format or if the lyrics don't have any lines defined
			tp->lines = 0;		//Temporarily disregard any existing lyric lines
			(void) eof_vocal_track_add_line(tp, 0, tp->lyric[tp->lyrics - 1]->pos + 1, 0xFF);	//Create a single line encompassing all lyrics
		}
	}
	else if(format == PLAIN_FORMAT)
	{	//This format option is meant to invoke script export with the plain flag set and filtering enabled
		Lyrics.nohyphens = 3;	//Disable hyphen output
		Lyrics.noplus = 1;	//Disable plus output
		Lyrics.filter = DuplicateString("^=%#/");	//Use default filter list
		Lyrics.defaultfilter = 1;	//Track that the above string will need to be freed
		format = SCRIPT_FORMAT;
		Lyrics.plain = 1;
		Lyrics.grouping = 2;	//Enable line grouping for script.txt export
	}

//Import lyrics from EOF structure
	lyrctr = 0;		//Begin indexing into lyrics from the very first
	lastlyrtime = 0;	//First lyric is expected to be greater than or equal to this timestamp
	for(linectr = 0; linectr < (unsigned long)tp->lines; linectr++)
	{	//For each line of lyrics in the EOF structure
		linestart = (tp->line[linectr]).start_pos;
		lineend = (tp->line[linectr]).end_pos;

		if(linestart > lineend)	//If the line starts after it ends
		{
			ReleaseMemory(1);
			return -1;			//Return failure
		}

		if(lyrctr < tp->lyrics)	//If there are lyrics remaining
			CreateLyricLine();	//Initialize new line of lyrics

		if((tp->line[linectr]).flags & EOF_LYRIC_LINE_FLAG_OVERDRIVE)	//If this line is overdrive
			Lyrics.overdrive_on = 1;
		else
			Lyrics.overdrive_on = 0;

		while(lyrctr < tp->lyrics)
		{	//For each lyric
			if((tp->lyric[lyrctr])->text[0] != '\0')
			{	//If this lyric's text isn't an empty string
				if((tp->lyric[lyrctr])->pos < lastlyrtime)	//If this lyric precedes the previous lyric
				{
					(void) snprintf(eof_log_string, sizeof(eof_log_string) - 1, "\tLogic error while preparing lyrics for export to file \"%s\"", tempoutputfilename);
					eof_log(eof_log_string, 1);
					ReleaseMemory(1);
					return -1;				//Return failure
				}
				if((tp->lyric[lyrctr])->pos < linestart)		//If this lyric precedes the beginning of the line
				{
					(void) snprintf(eof_log_string, sizeof(eof_log_string) - 1, "\tWarning:  Lyric \"%s\" at %lums is outside of defined lyric lines", tp->lyric[lyrctr]->text, tp->lyric[lyrctr]->pos);
					eof_log(eof_log_string, 1);
					CreateLyricLine();	//Initialize new line of lyrics
				}
				if((tp->lyric[lyrctr])->pos > lineend)		//If this lyric is placed beyond the end of this line
				{
					break;					//Break from this while loop to have another line created
				}

				pitch = (tp->lyric[lyrctr])->note;			//Store the lyric's pitch
				if((tp->lyric[lyrctr])->note == 0)			//Remap EOF's pitchless value to FLC's pitchless value
					pitch = PITCHLESS;

				if(!Lyrics.line_on)		//If a lyric line is not in progress
					CreateLyricLine();	//Force one to be before adding the next lyric
				AddLyricPiece((tp->lyric[lyrctr])->text, (tp->lyric[lyrctr])->pos, (tp->lyric[lyrctr])->pos+(tp->lyric[lyrctr])->length, pitch, 0);
					//Add the lyric to the Lyrics structure

				if((Lyrics.lastpiece != NULL) && (Lyrics.lastpiece->lyric[strlen(Lyrics.lastpiece->lyric)-1] == '-'))	//If the piece that was just added ended in a hyphen
					Lyrics.lastpiece->groupswithnext = 1;	//Set its grouping status
			}//If this lyric's text isn't an empty string

			lyrctr++;	//Advance to next lyric
		}

		ForceEndLyricLine();	//End the current line of lyrics
	}

	if(Lyrics.piececount == 0)	//No lyrics imported
	{
		ReleaseMemory(1);
		return 0;		//Return no lyrics found
	}

//Load chart tags
	if(eof_song->tags->artist[0] != '\0')
		Lyrics.Artist = DuplicateString(eof_song->tags->artist);
	if(eof_song->tags->title[0] != '\0')
		Lyrics.Title = DuplicateString(eof_song->tags->title);
	if(eof_song->tags->frettist[0] != '\0')
		Lyrics.Editor = DuplicateString(eof_song->tags->frettist);
	if(eof_song->tags->album[0] != '\0')
		Lyrics.Album = DuplicateString(eof_song->tags->album);

	PostProcessLyrics();	//Perform hyphen and grouping validation/handling

	Lyrics.outfilename = tempoutputfilename;
	Lyrics.out_format = format;

	//If the export format is MIDI-based, write a MIDI file header and a MIDI track (track 0) specifying a tempo of 120BPM
	if((Lyrics.out_format == MIDI_FORMAT) || (Lyrics.out_format == VRHYTHM_FORMAT) || (Lyrics.out_format == SKAR_FORMAT) || (Lyrics.out_format == KAR_FORMAT))
	{
		outf = fopen_err(Lyrics.outfilename,"wb");	//These are binary formats
		Write_Default_Track_Zero(outf);
	}

//Export lyrics
	switch(Lyrics.out_format)
	{
		case SCRIPT_FORMAT:	//Export as script.txt format file
			outf = fopen_err(Lyrics.outfilename,"wt");	//Script.txt is a text format
			Export_Script(outf);
		break;

		case VL_FORMAT:	//Export as VL format file
			outf = fopen_err(Lyrics.outfilename,"wb");	//VL is a binary format
			Export_VL(outf);
		break;

		case MIDI_FORMAT:	//Export as MIDI format file.  Default export track is "PART VOCALS"
			if(string2 == NULL)						//If a destination track name wasn't given
				Lyrics.outputtrack = DuplicateString("PART VOCALS");	//Write track name as PART VOCALS by default
			else
				Lyrics.outputtrack = DuplicateString(string2);
			Export_MIDI(outf);
		break;

		case USTAR_FORMAT:	//Export as UltraStar format file
			outf = fopen_err(Lyrics.outfilename,"wt");	//UltraStar is a text format
			Export_UStar(outf);
		break;

		case LRC_FORMAT:	//Export as simple LRC
		case ELRC_FORMAT:	//Export as extended LRC
			outf = fopen_err(Lyrics.outfilename,"wt");	//LRC is a text format
			Export_LRC(outf);
		break;

		case VRHYTHM_FORMAT:	//Export as Vocal Rhythm (MIDI and text file)
			if(string2 == NULL)	//If a pitched lyric file wasn't given
			{
				fclose_err(outf);
				return -1;	//Return failure
			}

			pitchedlyrics = fopen_err(string2,"wt");	//Pitched lyrics is a text format
			vrhythmid = DuplicateString("G4");
			Export_Vrhythm(outf, pitchedlyrics, vrhythmid);
			fflush_err(pitchedlyrics);	//Commit any pending pitched lyric writes to file
			fclose_err(pitchedlyrics);	//Close pitched lyric file
			free(vrhythmid);
		break;

		case SKAR_FORMAT:	//Export as Soft Karaoke.  Default export track is "Words"
			if(string2 == NULL)						//If a destination track name wasn't given
				Lyrics.outputtrack = DuplicateString("Words");	//Write track name as "Words" by default
			else
				Lyrics.outputtrack = DuplicateString(string2);
			Export_SKAR(outf);
		break;

		case KAR_FORMAT:	//Export as unofficial KAR.  Default export track is "Melody"
			if(Lyrics.outputtrack == NULL)
			{
				(void) puts("\aNo ouput track name for KAR file was given.  A track named \"Melody\" will be used by default");
				Lyrics.outputtrack = DuplicateString("Melody");
			}
			Export_MIDI(outf);
		break;

		case RS_FORMAT:	//Export as Rocksmith XML
			outf = fopen_err(Lyrics.outfilename,"wt");	//XML is a text format
			Lyrics.rocksmithver = 1;
			Export_RS(outf);
		break;

		case RS2_FORMAT:	//Export as Rocksmith 2 XML
			outf = fopen_err(Lyrics.outfilename,"wt");	//XML is a text format
			Lyrics.rocksmithver = 2;
			Export_RS(outf);
		break;

		default:
			(void) puts("Unexpected error in export switch\nAborting");
			exit_wrapper(4);
		break;
	}

	if((Lyrics.out_format == MIDI_FORMAT) || (Lyrics.out_format == VRHYTHM_FORMAT) || (Lyrics.out_format == SKAR_FORMAT) || (Lyrics.out_format == KAR_FORMAT))
	{	//Update the MIDI header to reflect the number of MIDI tracks written to file for all applicable export formats
		fseek_err(outf, 10, SEEK_SET);		//The number of tracks is 10 bytes in from the start of the file header
		fputc_err(MIDIstruct.trackswritten>>8, outf);
		fputc_err(MIDIstruct.trackswritten&0xFF, outf);
	}
Exemplo n.º 21
0
int EOF_IMPORT_VIA_LC(EOF_VOCAL_TRACK *tp, struct Lyric_Format **lp, int format, char *inputfilename, char *string2)
{
	char * returnedfn = NULL;	//Return string from dialog window
	FILE *inf;	  //Used to open the input file
	struct Lyric_Format *detectionlist;
	unsigned long i;
	int jumpcode = 0;

	eof_log("EOF_IMPORT_VIA_LC() entered", 1);

//Validate parameters
	if((tp == NULL) || (inputfilename == NULL))
		return 0;	//Return failure

	if((format == 0) && (lp == NULL))
		return 0;	//Return failure

//Perform detection logic
	InitLyrics();	//Initialize all variables in the Lyrics structure
	InitMIDI();		//Initialize all variables in the MIDI structure
	if(format == 0)		//Auto-detect lyric format
	{
		detectionlist=DetectLyricFormat(inputfilename);
		if(detectionlist == NULL)
			return 0;	//Return invalid lyric file

		if(detectionlist->format == PITCHED_LYRIC_FORMAT)
		{	//If the detection format is Pitched Lyrics, the user must specify the corresponding Vocal Rhythm MIDI
			*lp=detectionlist;	//Return the detected lyric information via the lp pointer
			return -1;			//Return prompt for user selection
		}

		if(detectionlist->next != NULL)
		{	//If there was more MIDI track with lyrics, the user must specify which track to import
			*lp=detectionlist;	//Return the detected lyric information via the lp pointer
			return -2;			//Return prompt for user selection
		}

		Lyrics.in_format=detectionlist->format;		//Format to import
		if(detectionlist->track != NULL)
			Lyrics.inputtrack=detectionlist->track;	//Track to import from
		DestroyLyricFormatList(detectionlist);		//Deallocate the linked list returned by DetectLyricFormat()
		detectionlist=NULL;
	}
	else			//Import specific format
	{
		Lyrics.in_format=format;

		if(Lyrics.in_format == KAR_FORMAT)
		{	//If this is a format for which string2 (pitched file or track name) must be specified
			if(string2 == NULL)	//If the track name to import is not given
				return 0;	//Return failure

			Lyrics.inputtrack=DuplicateString(string2);	//Make a duplicate, so its de-allocation won't affect calling function
		}
		else if(Lyrics.in_format == PITCHED_LYRIC_FORMAT)
		{	//If importing Pitched Lyrics, user must provide the Vocal Rhythm MIDI
			returnedfn = ncd_file_select(0, eof_filename, "Select Vocal Rhythm MIDI", eof_filter_midi_files);
			eof_clear_input();
			if(!returnedfn)
				return 0;	//Return error or user canceled
		}
	}

	Lyrics.infilename=DuplicateString(inputfilename);	//Make a duplicate, so it's de-allocation won't affect calling function

	jumpcode=setjmp(jumpbuffer); //Store environment/stack/etc. info in the jmp_buf array
	if(jumpcode!=0) //if program control returned to the setjmp() call above returning any nonzero value
	{
		(void) puts("Assert() handled sucessfully!");
		free(Lyrics.infilename);
		Lyrics.infilename = NULL;
		ReleaseMemory(1);	//Release memory allocated during lyric import
		return 0;	//Return error
	}

//Import lyrics
	switch(Lyrics.in_format)
	{
		case SCRIPT_FORMAT:	//Load script.txt format file as input
			inf=fopen_err(Lyrics.infilename,"rt");	//Script is a text format
			Script_Load(inf);
		break;

		case VL_FORMAT:	//Load VL format file as input
			inf=fopen_err(Lyrics.infilename,"rb");	//VL is a binary format
			VL_Load(inf);
		break;

		case MIDI_FORMAT:	//Load MIDI format file as input
			if(string2 == NULL)	//If no track name was given
				Lyrics.inputtrack=DuplicateString("PART VOCALS");	//Default to PART VOCALS
			else
				Lyrics.inputtrack=DuplicateString(string2);	//Make a duplicate, so its de-allocation won't affect calling function

			inf=fopen_err(Lyrics.infilename,"rb");	//MIDI is a binary format
			Parse_Song_Ini(Lyrics.infilename,1,1);	//Load ALL tags from song.ini first, as the delay tag will affect timestamps
			MIDI_Load(inf,Lyric_handler,0);		//Call MIDI_Load, specifying the new KAR-compatible Lyric Event handler
		break;

		case USTAR_FORMAT:	//Load UltraStar format file as input
			inf=fopen_err(Lyrics.infilename,"rt");	//UltraStar is a text format
			UStar_Load(inf);
		break;

		case LRC_FORMAT:	//Load LRC format file as input
		case ELRC_FORMAT:
			inf=fopen_err(Lyrics.infilename,"rt");	//LRC is a text format
			LRC_Load(inf);
		break;

		case VRHYTHM_FORMAT:	//Load vocal rhythm (MIDI) and pitched lyrics
			inf=fopen_err(returnedfn,"rb");	//Vrhythm is a binary format
			VRhythm_Load(inputfilename,returnedfn,inf);
		break;

		case PITCHED_LYRIC_FORMAT:
			inf=fopen_err(returnedfn,"rb");	//Vrhythm is a binary format
			VRhythm_Load(eof_filename,returnedfn,inf);
		break;

		case KAR_FORMAT:	//Load KAR MIDI file
			inf=fopen_err(Lyrics.infilename,"rb");	//KAR is a binary format
			MIDI_Load(inf,Lyric_handler,0);	//Call MIDI_Load, specifying the new KAR-compatible Lyric Event handler
		break;

		case SKAR_FORMAT:	//Load SKAR MIDI file
			inf=fopen_err(Lyrics.infilename,"rb");	//KAR is a binary format
			Lyrics.inputtrack=DuplicateString("Words");
			MIDI_Load(inf,SKAR_handler,0);	//Call MIDI_Load, specifying the Simple Karaoke Event handler
			EndLyricLine();	//KAR files do not mark the end of the last line of lyrics
		break;

		case ID3_FORMAT:	//Load MP3 ID3 tag
			inf=fopen_err(Lyrics.infilename,"rb");	//MP3 is a binary format
			ID3_Load(inf);
		break;

		case SRT_FORMAT:	//Load SRT file
			inf=fopen_err(Lyrics.infilename,"rt");	//SRT is a text format
			SRT_Load(inf);
		break;

		case XML_FORMAT:	//Load XML file
			inf=fopen_err(Lyrics.infilename,"rt");	//XML is a text format
			XML_Load(inf);
		break;

		case C9C_FORMAT:	//Load JamBand file
			inf=fopen_err(Lyrics.infilename,"rt");	//JamBand is a text format
			JB_Load(inf);
		break;

		case RS_FORMAT:		//Load Rocksmith XML file
		case RS2_FORMAT:
			inf=fopen_err(Lyrics.infilename,"rt");	//Rocksmith XML is a text format
			RS_Load(inf);
		break;

		default:
		return 0;	//Return failure
	}//switch(Lyrics.in_format)

	free(Lyrics.infilename);
	Lyrics.infilename = NULL;

//Validate imported lyrics
	if((Lyrics.piececount == 0) || (MIDI_Lyrics.head != NULL))	//If the imported MIDI track had no valid lyrics or otherwise was incorrectly formatted
	{
		ReleaseMemory(1);	//Release memory allocated during lyric import
		fclose_err(inf);
		return 0;	  //Return no EOF lyric structure
	}

	PostProcessLyrics();	//Perform validation of pointers, counters, etc.

	if(Lyrics.pitch_tracking)
	{	//Only perform input pitch validation and remapping if the import lyrics had pitch information
		RemapPitches();		//Ensure pitches are within the correct range (except for pitchless lyrics)
	}

	//Delete any existing lyrics and lines
	for(i = 0; i < tp->lyrics; i++)
	{
		free(tp->lyric[i]);
	}
	tp->lyrics = 0;
	tp->lines = 0;
	fclose_err(inf);	//Ensure this file gets closed
	inf=NULL;

	if(EOF_TRANSFER_FROM_LC(tp,&Lyrics) != 0)	//Pass the Lyrics global variable by reference
	{
		ReleaseMemory(1);	//Release memory allocated during lyric import
		return 0;		//Return error (failed to import into EOF lyric structure)
	}

	ReleaseMemory(1);	//Release memory allocated during lyric import
	return 1;	 		//Return finished EOF lyric structure
}
Exemplo n.º 22
0
int EOF_TRANSFER_FROM_LC(EOF_VOCAL_TRACK * tp, struct _LYRICSSTRUCT_ * lp)
{
	struct Lyric_Line *curline;	//Conductor of the lyric line linked list
	struct Lyric_Piece *curpiece;	//Conductor of the lyric piece linked list
	EOF_LYRIC *temp;		//Pointer returned by eof_vocal_track_add_lyric()
	unsigned long start=0;	//Used to track the start position of each line
	char startfound=0;		//Used to help skip adding vocal percussion notes to lyric lines
	char overdrive=0;		//Used to track the overdrive status of a lyric line

	eof_log("EOF_TRANSFER_FROM_LC() entered", 1);

	if((tp == NULL) || (lp == NULL))
		return -1;	//Return error (invalid structure pointers)

	curline=lp->lines;	//Point line conductor to first lineof lyrics in the Lyrics structure
	while(curline != NULL)
	{	//For each line of lyrics
		startfound =  0;
		overdrive = 0;

		curpiece=curline->pieces;	//Point lyric conductor to first lyric in this line
		while(curpiece != NULL)
		{	//For each lyric in this line
			if((startfound == 0) && (curpiece->pitch != VOCALPERCUSSION))
			{
				startfound = 1;
				start=curpiece->start;	//Store the timestamp of the first non vocal percussion note in this line
			}

			if(curpiece->overdrive)				//If this lyric is overdrive
				overdrive = 1;

			temp=eof_vocal_track_add_lyric(tp);	//Add a new lyric to EOF structure
			if(temp == NULL)
				return -1;	//Return error (out of memory)

			if((curpiece->pitch == PITCHLESS) || (!lp->pitch_tracking))	//If this lyric has no defined pitch, or all imported lyrics have the same pitch
				temp->note=0;				//Store with EOF's notation of a non defined pitch
			else
				temp->note=(char)curpiece->pitch;	//curpiece->pitch is an unsigned char between the values of 0 and 127

			temp->pos=curpiece->start;
			temp->length=(long)curpiece->duration;	//curpiece->duration is an unsigned long value, hopefully this won't cause problems
			if(ustrlen(curpiece->lyric) > EOF_MAX_LYRIC_LENGTH)
				return -1;	//Return error (lyric too large to store in EOF's array)
			if(curpiece->pitch == VOCALPERCUSSION)
				(void) ustrcpy(temp->text, "");	//Copy an empty string for a vocal percussion note
			else
				(void) ustrcpy(temp->text,curpiece->lyric);

			if((curpiece->next == NULL) && startfound)
			{	//If this was the last lyric for this line, and at least one non vocal percussion note was found
				(void) eof_vocal_track_add_line(tp,start,curpiece->start + curpiece->duration, 0xFF);	//Add the lyric line definition to the EOF structure

				if(overdrive && (tp->lines > 0))	//If this line had any overdriven lyrics
					tp->line[tp->lines-1].flags |= EOF_LYRIC_LINE_FLAG_OVERDRIVE;	//Mark the line for overdrive
			}

			curpiece=curpiece->next;	//Point to next lyric in the line
		}

		curline=curline->next;	//Point to next line of lyrics
	}

	eof_log("\tLyrics imported", 1);

	return 0;	//Return success
}
Exemplo n.º 23
0
int save_wav_with_silence_appended(const char * fn, SAMPLE * sp, unsigned long ms)
{
	unsigned long i, samples, channels, index = 0;
	SAMPLE * silence, * combined;
	int retval;

 	eof_log("save_wav_with_silence_appended() entered", 1);

	if(!fn || !sp)
		return 0;	//Invalid parameters

	if(!ms)
	{	//If the calling function specified writing the WAV with no silence appended
		return save_wav(fn, sp);	//Write the audio normally
	}

	//Generate the silent audio to conform to the input sample's specifications
	samples = (double)ms * (double)sp->freq / 1000.0;
	channels = sp->stereo ? 2 : 1;
	silence = create_sample(sp->bits, sp->stereo, sp->freq, samples);
	if(!silence)
		return 0;	//Return failure
	if(sp->bits == 8)
	{
		for(i = 0; i < samples * channels; i++)
		{
			((unsigned char *)(silence->data))[i] = 0x80;
		}
	}
	else
	{
		for(i = 0; i < samples * channels; i++)
		{
			((unsigned short *)(silence->data))[i] = 0x8000;
		}
	}

	//Combine the input audio and silence
	combined = create_sample(sp->bits, sp->stereo, sp->freq, sp->len + samples);
	if(!combined)
	{
		free(silence);
		return 0;	//Return failure
	}
	if(sp->bits == 8)
	{
		for(i = 0; i < sp->len * channels; i++)
		{	//For each sample in the input audio
			((unsigned char *)(combined->data))[index++] = ((unsigned char *)(sp->data))[i];	//Copy it into the combined audio sample
		}
		for(i = 0; i < silence->len * channels; i++)
		{	//For each sample in the silent audio
			((unsigned char *)(combined->data))[index++] = ((unsigned char *)(silence->data))[i];	//Copy it into the combined audio sample
		}
	}
	else
	{
		for(i = 0; i < sp->len * channels; i++)
		{	//For each sample in the input audio
			((unsigned short *)(combined->data))[index++] = ((unsigned short *)(sp->data))[i];	//Copy it into the combined audio sample
		}
		for(i = 0; i < silence->len * channels; i++)
		{	//For each sample in the silent audio
			((unsigned short *)(combined->data))[index++] = ((unsigned short *)(silence->data))[i];	//Copy it into the combined audio sample
		}
	}

	//Write the combined audio to file and return
	retval = save_wav(fn, combined);	//Write the combined audio
	destroy_sample(combined);
	destroy_sample(silence);
	return retval;
}
Exemplo n.º 24
0
int eof_undo_load_state(const char * fn)
{
	EOF_SONG * sp = NULL;
	PACKFILE * fp = NULL, * rfp = NULL;
	char rheader[16] = {0};
	int old_eof_silence_loaded = eof_silence_loaded;	//Retain this value, since it is destroyed by eof_destroy_song()
	char eof_recover_path[50];

 	eof_log("eof_undo_load_state() entered", 1);

	if(fn == NULL)
	{
		return 0;
	}
	fp = pack_fopen(fn, "r");
	if(!fp)
	{
		return 0;
	}
	if(pack_fread(rheader, 16, fp) != 16)
	{
		(void) pack_fclose(fp);
		return 0;	//Return error if 16 bytes cannot be read
	}
	sp = eof_create_song();		//Initialize an empty chart
	if(sp == NULL)
	{
		(void) pack_fclose(fp);
		return 0;
	}
	sp->tags->accurate_ts = 0;	//For existing projects, this setting must be manually enabled in order to prevent unwanted alteration to beat timings
	(void) snprintf(eof_recover_path, sizeof(eof_recover_path) - 1, "%seof.recover", eof_temp_path_s);
	rfp = pack_fopen(eof_recover_path, "r");	//Open the recovery file to prevent eof_destroy_song() from deleting it
	if(!eof_load_song_pf(sp, fp))
	{	//If loading the undo state fails
		allegro_message("Failed to perform undo");
		(void) pack_fclose(rfp);	//Close this recovery file handle so that it will be deleted by the following call to eof_destroy_song()
		eof_destroy_song(sp);
		(void) pack_fclose(fp);
		return 0;	//Return failure
	}
	(void) pack_fclose(fp);
	if(EOF_TRACK_PRO_GUITAR_B >= sp->tracks)
	{	//If the chart loaded does not contain a bonus pro guitar track (a pre 1.8RC12 chart or a post 1.8RC12 chart with an empty bonus track during save)
		if(eof_song_add_track(sp, &eof_default_tracks[EOF_TRACK_PRO_GUITAR_B]) == 0)	//Add a blank bonus pro guitar track
		{	//If the track failed to be added
			allegro_message("Failed to perform undo");
			(void) pack_fclose(rfp);	//Close this recovery file handle so that it will be deleted by the following call to eof_destroy_song()
			eof_destroy_song(sp);
			return 0;	//Return failure
		}
	}
	if(eof_song)
	{
		eof_undo_in_progress = 1;	//Signal to eof_destroy_song() that the waveform and spectrogram are not to be destroyed along with the active project structure
		eof_destroy_song(eof_song);	//Destroy the chart that is open
		eof_undo_in_progress = 0;
	}
	(void) pack_fclose(rfp);	//Calls to eof_destroy_song() are finished, the recovery file handle can be released now
	eof_song = sp;	//Replacing it with the loaded undo state
	eof_silence_loaded = old_eof_silence_loaded;	//Restore the status of whether chart audio is loaded

	return 1;
}
Exemplo n.º 25
0
void eof_redo_apply(void)
{
	char fn[1024] = {0};
	char title[256] = {0};
	unsigned long ctr;
	EOF_PRO_GUITAR_TRACK *tp = NULL;
	char tech_view_status[EOF_PRO_GUITAR_TRACKS_MAX] = {0};	//Tracks whether or not tech view was in effect for each of the pro guitar tracks, so this view's status can be restored after the redo

 	eof_log("eof_redo_apply() entered", 1);

	if(eof_redo_count > 0)
	{
		if(eof_validate_temp_folder())
		{	//Ensure the correct working directory and presence of the temporary folder
			eof_log("\tCould not validate working directory and temp folder", 1);
			return;
		}

		//Determine whether each pro guitar track was in tech view
		for(ctr = 0; ctr < EOF_PRO_GUITAR_TRACKS_MAX; ctr++)
		{	//For each pro guitar track in the project
			tp = eof_song->pro_guitar_track[ctr];
			if(tp->note == tp->technote)
			{	//If tech view was in effect for this track
				tech_view_status[ctr] = 1;
			}
		}

		strncpy(title, eof_song->tags->title, sizeof(title) - 1);	//Backup the song title field, since if it changes as part of the redo, the Rocksmith WAV file should be deleted

		(void) eof_save_song(eof_song, eof_undo_filename[eof_undo_current_index]);
		eof_undo_current_index++;
		if(eof_undo_current_index >= EOF_MAX_UNDO)
		{
			eof_undo_current_index = 0;
		}
		(void) snprintf(fn, sizeof(fn) - 1, "%seof%03u.redo", eof_temp_path_s, eof_log_id);	//Get the name of this EOF instance's redo file
		(void) eof_undo_load_state(fn);	//And load it
		if(eof_redo_type == EOF_UNDO_TYPE_SILENCE)
		{
			(void) snprintf(fn, sizeof(fn) - 1, "%seof%03u.redo.ogg", eof_temp_path_s, eof_log_id);	//Get the name of this EOF instance's redo OGG
			(void) eof_copy_file(fn, eof_loaded_ogg_name);	//And save the current audio to that filename
			(void) eof_load_ogg(eof_loaded_ogg_name, 0);
			eof_delete_rocksmith_wav();		//Delete the Rocksmith WAV file since changing silence will require a new WAV file to be written
			eof_fix_waveform_graph();
			eof_fix_spectrogram();
		}
		if(strcmp(title, eof_song->tags->title))
		{	//If the song title changed as part of the redo, delete the Rocksmith WAV file, since changing the title will cause a new WAV file to be written
			eof_delete_rocksmith_wav();
		}
		eof_undo_count++;
		if(eof_undo_count >= EOF_MAX_UNDO)
		{
			eof_undo_count = EOF_MAX_UNDO;
		}
		eof_redo_count = 0;
		eof_change_count++;
		if(eof_change_count == 0)
		{
			eof_changes = 0;
		}
		else
		{
			eof_changes = 1;
		}

		eof_init_after_load(1);	//Perform various cleanup
		(void) eof_detect_difficulties(eof_song, eof_selected_track);
		eof_select_beat(eof_selected_beat);
		eof_fix_catalog_selection();
		eof_scale_fretboard(0);	//Recalculate the 2D screen positioning based on the current track

		//Restore tech view for each pro guitar track that had it in use before the redo operation
		for(ctr = 0; ctr < EOF_PRO_GUITAR_TRACKS_MAX; ctr++)
		{	//For each pro guitar track in the project
			tp = eof_song->pro_guitar_track[ctr];
			if(tech_view_status[ctr])
			{	//If tech view was in effect for this track
				eof_menu_pro_guitar_track_enable_tech_view(tp);
			}
		}
		eof_fix_window_title();
	}
}
Exemplo n.º 26
0
/* saves a wave file to file pointer */
static int save_wav_fp(SAMPLE * sp, PACKFILE * fp)
{
	size_t channels, bits, freq;
	size_t data_size;
	size_t samples;
	size_t i, n;
	void * pval = NULL;
	unsigned short *data;

	eof_log("save_wav_fp() entered", 1);

	if(!sp || !fp)
	{
		return 0;
	}
	channels = sp->stereo ? (size_t)2 : (size_t)1;
	bits = (size_t)sp->bits;

	samples = (size_t)sp->len;
	data_size = samples * channels * (bits / 8);
	n = samples * channels;

	freq = (size_t)sp->freq;

	(void) pack_fputs("RIFF", fp);
	(void) pack_iputl(36 + (long)data_size, fp);
	(void) pack_fputs("WAVE", fp);

	(void) pack_fputs("fmt ", fp);
	(void) pack_iputl(16, fp);
	(void) pack_iputw(1, fp);
	(void) pack_iputw((int)channels, fp);
	(void) pack_iputl((long)freq, fp);
	(void) pack_iputl((long)(freq * channels * (bits / 8)), fp);	//ByteRate = SampleRate * NumChannels * BitsPerSample/8
	(void) pack_iputw((int)(channels * (bits / 8)), fp);
	(void) pack_iputw((int)bits, fp);

	(void) pack_fputs("data", fp);
	(void) pack_iputl((long)data_size, fp);

	if(bits == 8)
	{
		pval = sp->data;
		(void) pack_fwrite(pval, (long)(samples * channels), fp);
	}
	else if(bits == 16)
	{
		data = (unsigned short *)sp->data;
		for (i = 0; i < n; i++)
		{
			(void) pack_iputw((short)(data[i] - 0x8000), fp);
		}
	}
	else
	{
		(void) snprintf(eof_log_string, sizeof(eof_log_string) - 1, "Unknown audio depth (%lu) when saving wav ALLEGRO_FILE.", (unsigned long) bits);
		eof_log(eof_log_string, 1);
		return 0;
	}

	return 1;
}
Exemplo n.º 27
0
int eof_undo_add(int type)
{
	char fn[1024] = {0}, temp[1024] = {0};
	unsigned long ctr;

 	eof_log("eof_undo_add() entered", 1);

	if(eof_undo_states_initialized == -1)
	{	//The undo filename array couldn't be initialized previously
		return 0;
	}

	if(eof_validate_temp_folder())
	{	//Ensure the correct working directory and presence of the temporary folder
		eof_log("\tCould not validate working directory and temp folder", 1);
		return 0;
	}

	if(!eof_undo_states_initialized)
	{	//Initialize the undo filename array
		for(ctr = 0; ctr < EOF_MAX_UNDO; ctr++)
		{	//For each undo slot
			(void) snprintf(fn, sizeof(fn) - 1, "%seof%03u-%03lu.undo", eof_temp_path_s, eof_log_id, ctr);	//Build the undo filename in the format of "eof#-#.undo", where the first number is the EOF ID
			eof_undo_filename[ctr] = malloc(sizeof(fn) + 1);
			if(eof_undo_filename[ctr] == NULL)
			{
				allegro_message("Error initializing undo system.  Undo disabled");
				eof_undo_states_initialized = -1;
				return 0;
			}
			strcpy(eof_undo_filename[ctr], fn);	//Save the undo filename to the array
		}
		eof_undo_states_initialized = 1;
	}

	if((type == EOF_UNDO_TYPE_NOTE_LENGTH) && (eof_undo_last_type == EOF_UNDO_TYPE_NOTE_LENGTH))
	{
		return 0;
	}
	if((type == EOF_UNDO_TYPE_LYRIC_NOTE) && (eof_undo_last_type == EOF_UNDO_TYPE_LYRIC_NOTE))
	{
		return 0;
	}
	if((type == EOF_UNDO_TYPE_RECORD) && (eof_undo_last_type == EOF_UNDO_TYPE_RECORD))
	{
		return 0;
	}
	if((type == EOF_UNDO_TYPE_TEMPO_ADJUST) && (eof_undo_last_type == EOF_UNDO_TYPE_TEMPO_ADJUST))
	{
		return 0;
	}
	if(type == EOF_UNDO_TYPE_SILENCE)
	{
		(void) snprintf(fn, sizeof(fn) - 1, "%s%s.ogg", eof_temp_path_s, eof_undo_filename[eof_undo_current_index]);
		(void) eof_copy_file(eof_loaded_ogg_name, fn);
	}
	eof_undo_last_type = type;

	(void) eof_save_song(eof_song, eof_undo_filename[eof_undo_current_index]);
	eof_undo_type[eof_undo_current_index] = type;
	if(eof_recovery)
	{	//If this EOF instance is maintaining auto-recovery files
		PACKFILE *fp;
		(void) snprintf(fn, sizeof(fn) - 1, "%seof.recover", eof_temp_path_s);
		fp = pack_fopen(fn, "w");	//Open the recovery definition file for writing
		if(fp)
		{	//If the file opened
			(void) append_filename(temp, eof_song_path, eof_loaded_song_name, 1024);	//Construct the full path to the project file
			(void) pack_fputs(eof_undo_filename[eof_undo_current_index], fp);			//Write the undo file path
			(void) pack_fputs("\n", fp);												//Write a newline character
			(void) pack_fputs(temp, fp);												//Write the project path
			(void) pack_fclose(fp);
		}
	}
	eof_undo_current_index++;
	if(eof_undo_current_index >= EOF_MAX_UNDO)
	{
		eof_undo_current_index = 0;
	}
	eof_undo_count++;
	if(eof_undo_count >= EOF_MAX_UNDO)
	{
		eof_undo_count = EOF_MAX_UNDO;
	}
	eof_redo_count = 0;
	return 1;
}
Exemplo n.º 28
0
int eof_export_bandfuse(EOF_SONG * sp, char * fn, unsigned short *user_warned)
{
	PACKFILE * fp;
	char buffer[600] = {0}, buffer2[600] = {0};
	EOF_PRO_GUITAR_TRACK *tp;
	char restore_tech_view = 0;			//If tech view is in effect, it is temporarily disabled so that the correct notes are exported
	unsigned long ctr, ctr2, ctr3, ctr4, ctr5, gemcount, bitmask, guitartracknum = 0, basstracknum = 0;

	eof_log("eof_export_bandfuse() entered", 1);

	if(!sp || !fn || !sp->beats || !user_warned)
	{
		eof_log("\tError saving:  Invalid parameters", 1);
		return 0;	//Return failure
	}
	fp = pack_fopen(fn, "w");
	if(!fp)
	{
		eof_log("\tError saving:  Cannot open file for writing", 1);
		return 0;	//Return failure
	}

	//Write the song metadata
	(void) pack_fputs("<?xml version='1.0' encoding='UTF-8'?>\n", fp);
	(void) pack_fputs("<Bandfuse>\n", fp);
	(void) pack_fputs("<!-- " EOF_VERSION_STRING " -->\n", fp);	//Write EOF's version in an XML comment
	expand_xml_text(buffer2, sizeof(buffer2) - 1, sp->tags->title, 64, 0);	//Expand XML special characters into escaped sequences if necessary, and check against the maximum supported length of this field
	(void) snprintf(buffer, sizeof(buffer) - 1, "  <title>%s</title>\n", buffer2);
	(void) pack_fputs(buffer, fp);
	expand_xml_text(buffer2, sizeof(buffer2) - 1, sp->tags->artist, 256, 0);	//Replace any special characters in the artist song property with escape sequences if necessary
	(void) snprintf(buffer, sizeof(buffer) - 1, "  <artistName>%s</artistName>\n", buffer2);
	(void) pack_fputs(buffer, fp);
	expand_xml_text(buffer2, sizeof(buffer2) - 1, sp->tags->album, 256, 0);	//Replace any special characters in the album song property with escape sequences if necessary
	(void) snprintf(buffer, sizeof(buffer) - 1, "  <albumName>%s</albumName>\n", buffer2);
	(void) pack_fputs(buffer, fp);
	expand_xml_text(buffer2, sizeof(buffer2) - 1, sp->tags->year, 32, 0);	//Replace any special characters in the year song property with escape sequences if necessary
	(void) snprintf(buffer, sizeof(buffer) - 1, "  <albumYear>%s</albumYear>\n", buffer2);
	(void) pack_fputs(buffer, fp);

	//Write tempo changes
	(void) pack_fputs("  <tempochanges>\n", fp);
	ctr = 0;	//Begin with the first beat
	while(ctr < sp->beats)
	{	//Until the last beat has been reached
		for(ctr2 = ctr + 1; ctr2 < sp->beats; ctr2++)
		{	//For each beat that follows
			if(sp->beat[ctr]->ppqn != sp->beat[ctr2]->ppqn)
			{	//If the following beat has a different tempo
				break;	//Break from inner for loop
			}
		}
		if(ctr2 < sp->beats)
		{	//If a beat with a different tempo was found, that beat is written as the end position of this tempo change
			(void) snprintf(buffer, sizeof(buffer) - 1, "    <tempo start=\"%lu\" end=\"%lu\" tempo=\"%f\">\n", sp->beat[ctr]->pos, sp->beat[ctr2]->pos, 60000000.0 / (double)sp->beat[ctr]->ppqn);
		}
		else
		{	//No remaining beats had a different tempo, the outer for loop's beat is written as the end position of this tempo change
			(void) snprintf(buffer, sizeof(buffer) - 1, "    <tempo start=\"%lu\" end=\"%lu\" tempo=\"%f\">\n", sp->beat[ctr]->pos, sp->beat[ctr]->pos, 60000000.0 / (double)sp->beat[ctr]->ppqn);
		}
		(void) pack_fputs(buffer, fp);
		ctr = ctr2;	//Advance the beat counter
	}
	(void) pack_fputs("  </tempochanges>\n", fp);

	for(ctr = 1; ctr < sp->tracks; ctr++)
	{	//For each track
		if(ctr >= EOF_TRACKS_MAX)
			break;		//Redundant bounds check to satisfy a false positive with Coverity
		if(sp->track[ctr]->track_format != EOF_PRO_GUITAR_TRACK_FORMAT)
			continue;	//If this isn't a pro guitar/bass track, skip it
		if(ctr == EOF_TRACK_PRO_GUITAR_B)
			continue;	//If this is the bonus Rocksmith arrangement, skip it

		tp = sp->pro_guitar_track[sp->track[ctr]->tracknum];
		restore_tech_view = eof_menu_track_get_tech_view_state(sp, ctr);
		eof_menu_track_set_tech_view_state(sp, ctr, 0);	//Disable tech view if applicable

		if(tp->notes)
		{	//If this track is populated
			eof_determine_phrase_status(sp, ctr);	//Update the trill and tremolo status of each note
			if(tp->arrangement != 4)
			{	//If this isn't a bass track
				guitartracknum++;	//Keep count of how many of this track type there have been
				(void) snprintf(buffer, sizeof(buffer) - 1, "  <arrangement name=\"Guitar %lu (%s)\">\n", guitartracknum, sp->track[ctr]->name);
				(void) pack_fputs(buffer, fp);
			}
			else
			{	//This is a bass track
				basstracknum++;	//Keep count of how many of this track type there have been
				(void) snprintf(buffer, sizeof(buffer) - 1, "  <arrangement name=\"Bass %lu (%s)\">\n", guitartracknum, sp->track[ctr]->name);
				(void) pack_fputs(buffer, fp);
			}
			(void) snprintf(buffer, sizeof(buffer) - 1, "    <tuning string0=\"%d\" string1=\"%d\" string2=\"%d\" string3=\"%d\" string4=\"%d\" string5=\"%d\" />\n", tp->tuning[0], tp->tuning[1], tp->tuning[2], tp->tuning[3], tp->tuning[4], tp->tuning[5]);
			(void) pack_fputs(buffer, fp);

			(void) eof_detect_difficulties(sp, ctr);	//Update eof_track_diff_populated_status[] to reflect all populated difficulties for this track
			for(ctr2 = 0; ctr2 < 6; ctr2++)
			{	//For each of the first 6 difficulties
				unsigned long anchorcount;
				char anchorsgenerated = 0;	//Is set to nonzero if fret hand positions are automatically generated for this difficulty and will have to be deleted

				if(!eof_track_diff_populated_status[ctr2])
					continue;	//If this difficulty is not populated, skip it

				(void) snprintf(buffer, sizeof(buffer) - 1, "    <level difficulty=\"%lu\">\n", ctr2);
				(void) pack_fputs(buffer, fp);

				//Count the number of note gems in this track difficulty
				for(ctr3 = 0, gemcount = 0; ctr3 < tp->notes; ctr3++)
				{	//For each note in the track
					if(eof_get_note_type(sp, ctr, ctr3) == ctr2)
					{	//If the note is in this difficulty
						gemcount += eof_note_count_rs_lanes(sp, ctr, ctr3, 2);	//Add this note's number of non-ghosted gems to a counter
					}
				}
				(void) snprintf(buffer, sizeof(buffer) - 1, "      <notes count=\"%lu\">\n", gemcount);
				(void) pack_fputs(buffer, fp);

				//Generate fret hand positions if there are none for this difficulty
				for(ctr3 = 0, anchorcount = 0; ctr3 < tp->handpositions; ctr3++)
				{	//For each hand position defined in the track
					if(tp->handposition[ctr3].difficulty == ctr2)
					{	//If the hand position is in this difficulty
						anchorcount++;
					}
				}
				if(!anchorcount)
				{	//If there are no anchors in this track difficulty, automatically generate them
					if((tp->arrangement != 4) || eof_warn_missing_bass_fhps)
					{	//Don't warn about missing FHPs in bass arrangements if user disabled that preference
						if((*user_warned & 1) == 0)
						{	//If the user wasn't alerted that one or more track difficulties have no fret hand positions defined
							allegro_message("Warning:  At least one track difficulty has no fret hand positions defined.  They will be created automatically.");
							*user_warned |= 1;
						}
					}
					eof_fret_hand_position_list_dialog_undo_made = 1;	//Ensure no undo state is written during export
					eof_generate_efficient_hand_positions(sp, ctr, ctr2, 0, 0);	//Generate the fret hand positions for the track difficulty being currently written
					anchorsgenerated = 1;
				}
				for(ctr3 = 0, anchorcount = 0; ctr3 < tp->handpositions; ctr3++)	//Re-count the hand positions
				{	//For each hand position defined in the track
					if(tp->handposition[ctr3].difficulty == ctr)
					{	//If the hand position is in this difficulty
						anchorcount++;
					}
				}

				//Write the notes to XML
				for(ctr3 = 0; ctr3 < tp->notes; ctr3++)
				{	//For each note in the track
					if(eof_get_note_type(sp, ctr, ctr3) != ctr2)
						continue;	//If the note is not in this difficulty, skip it

					for(ctr4 = 0, bitmask = 1; ctr4 < tp->numstrings; ctr4++, bitmask <<= 1)
					{	//For each string in this track
						EOF_RS_TECHNIQUES tech = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
						unsigned long notepos;
						unsigned long fret, finger;				//The fret and finger numbers used to play the gem on this string
						unsigned long trill_start, trill_stop;	//The start and stop positions of the note's trill phrase
						int trillwith = -1;						//If the note is in a trill phrase, this is set to the fret value of the next or previous gem on the string
						long next;
						unsigned long stringnum;				//The converted string number (ie. low E string is string 6)
						char *sustainpadding;

						if(!(tp->note[ctr3]->note & bitmask) || (tp->note[ctr3]->ghost & bitmask))
							continue;	//If this string does not have a gem, or if it has one that is ghosted, skip it

						trill_start = trill_stop = tp->note[ctr3]->pos;	//Initialize variables in order to track if the trill phrase can't be properly found
						if(tp->note[ctr3]->flags & EOF_NOTE_FLAG_IS_TRILL)
						{	//If this note is in a trill phrase
							//Find which trill phrase it's in
							for(ctr5 = 0; ctr5 < tp->trills; ctr5++)
							{	//For each trill phrase
								if((tp->trill[ctr5].difficulty == 0xFF) || (tp->trill[ctr5].difficulty == ctr2))
								{	//If this trill phrase applies to all difficulties or if it otherwise applies to this note's difficulty
									if((tp->trill[ctr5].start_pos <= tp->note[ctr3]->pos) && (tp->trill[ctr5].end_pos >= tp->note[ctr3]->pos))
									{	//If the note is inside this trill phrase
										trill_start = tp->trill[ctr5].start_pos;
										trill_stop = tp->trill[ctr5].end_pos;
										break;
									}
								}
							}
							//Determine if this is the first note in the trill phrase, and if so, what note it trills with
							if(trill_start != trill_stop)
							{	//If a trill phrase was identified
								for(ctr5 = 0; ctr5 < tp->notes; ctr5++)
								{	//For each note in the track
									if(eof_get_note_type(sp, ctr, ctr3) != ctr2)
										continue;	//If the note is not in this difficulty, skip it
									if(tp->note[ctr5]->pos > trill_stop)
										break;		//Stop looking at notes if the trill has already been passed
									if(tp->note[ctr5]->pos < trill_start)
										continue;	//If the note is not within the trill phrase

									if(ctr5 != ctr3)
									{	//If the note being written to XML is not this note
										break;	//Don't export it with trill technique
									}
									next = eof_fixup_next_pro_guitar_note(tp, ctr5);
									if((next > 0) && (tp->note[next]->pos <= trill_stop))
									{	//If the next note in the track difficulty is also in this trill phrase
										if((tp->note[next]->note & bitmask) && ((tp->note[next]->frets[next] & 0x7F) > (tp->note[ctr3]->frets[ctr4] & 0x7F)))
										{	//If the next note has a gem on the target string and its fret value is higher than that of the note being currently written to XML
											trillwith = tp->note[next]->frets[ctr4] & 0x7F;	//This is the fret value being trilled with
										}
									}
									break;
								}//For each note in the track
							}//If a trill phrase was identified
						}//If this note is in a trill phrase

						(void) eof_get_rs_techniques(sp, ctr, ctr3, ctr4, &tech, 2, 1);	//Determine techniques used by this note (honoring technotes where applicable)
						notepos = eof_get_note_pos(sp, ctr, ctr3);
						fret = tp->note[ctr3]->frets[ctr4] & 0x7F;	//Get the fret value for this string (mask out the muting bit)
						finger = eof_pro_guitar_note_lookup_string_fingering(tp, ctr3, ctr4, 1);	//Unless a more suitable fingering for this note can be determined, assume 1 (index)
						if(tech.length < 10)
						{	//The sustain is one digit
							sustainpadding = "   ";
						}
						else if(tech.length < 100)
						{	//The sustain is two digits
							sustainpadding = "  ";
						}
						else if(tech.length < 1000)
						{	//The sustain is three digits
							sustainpadding = " ";
						}
						else
						{	//It's four or more digits
							sustainpadding = "";
						}
						fret += tp->capo;							//Compensate for the the capo position if applicable
						stringnum = tp->numstrings - ctr4;			//Convert to tab string numbering (low E is string 6 in a 6 string track, string 4 on a 4 string track, etc)
						(void) snprintf(buffer, sizeof(buffer) - 1, "        <note time=\"%lu\" linkNext=\"%d\" bend=\"%lu\" fret=%s\"%lu\" hammerOn=\"%d\" harmonic=\"%d\" hopo=\"%d\" ignore=\"0\" mute=\"%d\" palmMute=\"%d\" pluck=\"%d\" pullOff=\"%d\" slap=\"%d\" slideTo=\"%ld\" string=\"%lu\" sustain=%s\"%lu\" tremolo=\"%d\" harmonicPinch=\"%d\" slideUnpitchTo=\"%ld\" trillwith=\"%d\" finger=\"%lu\" vibrato=\"%d\"/>\n", notepos, tech.linknext, tech.bendstrength_h, ((fret < 10) ? " " : ""), fret, tech.hammeron, tech.harmonic, tech.hopo, tech.stringmute, tech.palmmute, tech.pop, tech.pulloff, tech.slap, tech.slideto, stringnum, sustainpadding, tech.length, tech.tremolo, tech.pinchharmonic, tech.unpitchedslideto, trillwith, finger, tech.vibrato);
						(void) pack_fputs(buffer, fp);
					}//For each string in this track
				}//For each note in the track

				//Remove any automatically generated fret hand positions
				if(anchorsgenerated)
				{	//If anchors were automatically generated for this track difficulty, remove them now
					for(ctr3 = tp->handpositions; ctr3 > 0; ctr3--)
					{	//For each hand position defined in the track, in reverse order
						if(tp->handposition[ctr3 - 1].difficulty == ctr2)
						{	//If the hand position is in this difficulty
							eof_pro_guitar_track_delete_hand_position(tp, ctr3 - 1);	//Delete the hand position
						}
					}
				}
				(void) pack_fputs("      </notes>\n", fp);
				(void) pack_fputs("    </level>\n", fp);
			}//For each of the first 6 difficulties
			(void) pack_fputs("  </arrangement>\n", fp);
		}//If this track is populated

		eof_menu_track_set_tech_view_state(sp, ctr, restore_tech_view);	//Re-enable tech view if applicable
	}//For each track
	(void) pack_fputs("</Bandfuse>\n", fp);

	//Cleanup
	(void) pack_fclose(fp);

	return 1;	//Return success
}
Exemplo n.º 29
0
int eof_add_silence_recode_mp3(char * oggfn, unsigned long ms)
{
	char sys_command[1024] = {0};
	char backupfn[1024] = {0};
	char wavfn[1024] = {0};
	char soggfn[1024] = {0};
	char mp3fn[1024] = {0};
	SAMPLE * decoded = NULL;
	SAMPLE * combined = NULL;
	int bits;
	int stereo;
	int freq;
	unsigned long samples;
	int channels;
	unsigned long ctr,index;

 	eof_log("eof_add_silence_recode_mp3() entered", 1);

	if(!oggfn || (ms == 0) || eof_silence_loaded)
	{
		return 21;	//Return error:  Invalid parameters
	}
	set_window_title("Adjusting Silence...");

	/* back up original file */
	(void) snprintf(backupfn, sizeof(backupfn) - 1, "%s.backup", oggfn);
	if(!exists(backupfn))
	{
		(void) eof_copy_file(oggfn, backupfn);
	}

	/* decode MP3 */
	(void) replace_filename(wavfn, eof_song_path, "decode.wav", 1024);
	(void) replace_filename(mp3fn, eof_song_path, "original.mp3", 1024);
	(void) uszprintf(sys_command, (int) sizeof(sys_command) - 1, "lame --decode \"%s\" \"%s\"", mp3fn, wavfn);
	(void) eof_system(sys_command);

	/* insert silence */
	decoded = load_sample(wavfn);
	if(!decoded)
	{
		allegro_message("Error opening file.\nMake sure there are no Unicode or extended ASCII characters in this chart's file path.");
		return 22;	//Return failure:  Could not load decoded MP3 file
	}
	bits = decoded->bits;
	stereo = decoded->stereo;
	freq = decoded->freq;
	samples = (decoded->freq * ms) / 1000;	//Calculate this manually instead of using msec_to_samples() because that function assumes the sample rate matches the current chart audio, and this may not be the case with the original MP3 file the user provided
	channels = stereo ? 2 : 1;
	combined = create_sample(bits,stereo,freq,samples+decoded->len);	//Create a sample array long enough for the silence and the OGG file
	if(combined == NULL)
	{
		destroy_sample(decoded);
		return 23;	//Return failure:  Could not create a sample array for the combined audio
	}
	/* Add the PCM data for the silence */
	if(bits == 8)
	{	//Create 8 bit PCM data
		for(ctr=0,index=0;ctr < samples * channels;ctr++)
		{
			((unsigned char *)(combined->data))[index++] = 0x80;
		}
	}
	else
	{	//Create 16 bit PCM data
		for(ctr=0,index=0;ctr < samples * channels;ctr++)
		{
			((unsigned short *)(combined->data))[index++] = 0x8000;
		}
	}
	/* Add the decoded OGG PCM data*/
	if(bits == 8)
	{	//Copy 8 bit PCM data
		for(ctr=0;ctr < decoded->len * channels;ctr++)
		{
			((unsigned char *)(combined->data))[index++] = ((unsigned char *)(decoded->data))[ctr];
		}
	}
	else
	{	//Copy 16 bit PCM data
		for(ctr=0;ctr < decoded->len * channels;ctr++)
		{
			((unsigned short *)(combined->data))[index++] = ((unsigned short *)(decoded->data))[ctr];
		}
	}

	/* save combined WAV */
	(void) replace_filename(wavfn, eof_song_path, "encode.wav", 1024);
	if(!save_wav(wavfn, combined))
	{
		destroy_sample(decoded);	//This is no longer needed
		destroy_sample(combined);	//This is no longer needed
		return 24;	//Return failure:  Could not create the combined audio WAV file
	}

	/* destroy samples */
	destroy_sample(decoded);	//This is no longer needed
	destroy_sample(combined);	//This is no longer needed

	/* encode the audio */
	printf("%s\n%s\n", eof_song_path, wavfn);
	(void) replace_filename(soggfn, eof_song_path, "encode.ogg", 1024);
	#ifdef ALLEGRO_WINDOWS
		(void) uszprintf(sys_command, (int) sizeof(sys_command) - 1, "oggenc2 -o \"%s\" -b %d \"%s\"", soggfn, alogg_get_bitrate_ogg(eof_music_track) / 1000, wavfn);
	#else
		(void) uszprintf(sys_command, (int) sizeof(sys_command) - 1, "oggenc -o \"%s\" -b %d \"%s\"", soggfn, alogg_get_bitrate_ogg(eof_music_track) / 1000, wavfn);
	#endif

	(void) snprintf(eof_log_string, sizeof(eof_log_string) - 1, "\tCalling oggenc as follows:  %s", sys_command);
	eof_log(eof_log_string, 1);
	if(eof_system(sys_command))
	{	//If oggenc failed, retry again by specifying a quality level (specifying bitrate can fail in some circumstances)
		eof_log("\t\toggenc failed.  Retrying by specifying a quality level instead of a target bitrate", 1);
		#ifdef ALLEGRO_WINDOWS
			(void) uszprintf(sys_command, (int) sizeof(sys_command) - 1, "oggenc2 -o \"%s\" -q 9 \"%s\"", soggfn, wavfn);
		#else
			(void) uszprintf(sys_command, (int) sizeof(sys_command) - 1, "oggenc -o \"%s\" -q 9 \"%s\"", soggfn, wavfn);
		#endif
		(void) snprintf(eof_log_string, sizeof(eof_log_string) - 1, "\tCalling oggenc as follows:  %s", sys_command);
		eof_log(eof_log_string, 1);
		if(eof_system(sys_command))
		{	//If oggenc failed again
			char tempfname[30] = {0};
			char redirect[35] = {0};

			if(eof_validate_temp_folder())
			{	//Ensure the correct working directory and presence of the temporary folder
				eof_log("\tCould not validate working directory and temp folder", 1);
				return 25;	//Return failure:  Could not validate cwd and temp folder
			}

			(void) snprintf(tempfname, sizeof(tempfname) - 1, "%soggenc.log", eof_temp_path_s);
			(void) snprintf(redirect, sizeof(redirect) - 1, " 2> %s", tempfname);
			(void) ustrzcat(sys_command, (int) sizeof(sys_command) - 1, redirect);	//Append a redirection to the command to capture the output of oggenc
			if(eof_system(sys_command))
			{	//Run one last time to catch the error output
				(void) snprintf(eof_log_string, sizeof(eof_log_string) - 1, "\tOggenc failed.  Please see %s for any errors it gave.", tempfname);
				eof_log(eof_log_string, 1);
				eof_fix_window_title();
				return 26;	//Return failure:  Could not encode combined audio
			}
		}
	}

	/* replace the current OGG file with the new file */
	(void) eof_copy_file(soggfn, oggfn);	//Copy encode.ogg to the filename of the original OGG

	/* clean up */
	(void) replace_filename(wavfn, eof_song_path, "decode.wav", 1024);
	(void) delete_file(wavfn);		//Delete decode.wav
	(void) replace_filename(wavfn, eof_song_path, "encode.wav", 1024);
	(void) delete_file(wavfn);		//Delete encode.wav
	(void) delete_file(soggfn);	//Delete encode.ogg
	if(eof_load_ogg(oggfn, 0))
	{	//If the combined audio was loaded
		eof_fix_waveform_graph();
		eof_fix_spectrogram();
		eof_fix_window_title();
		eof_chart_length = eof_music_length;
		return 0;	//Return success
	}
	eof_fix_window_title();

	return 27;	//Return error:  Could not load new audio
}
Exemplo n.º 30
0
int eof_undo_apply(void)
{
	char fn[1024] = {0};
	char title[256] = {0};
	unsigned long ctr;
	EOF_PRO_GUITAR_TRACK *tp = NULL;
	char tech_view_status[EOF_PRO_GUITAR_TRACKS_MAX] = {0};	//Tracks whether or not tech view was in effect for each of the pro guitar tracks, so this view's status can be restored after the undo

 	eof_log("eof_undo_apply() entered", 1);

	if(eof_undo_count > 0)
	{
		//Determine whether each pro guitar track was in tech view
		for(ctr = 0; ctr < EOF_PRO_GUITAR_TRACKS_MAX; ctr++)
		{	//For each pro guitar track in the project
			tp = eof_song->pro_guitar_track[ctr];
			if(tp->note == tp->technote)
			{	//If tech view was in effect for this track
				tech_view_status[ctr] = 1;
			}
		}

		strncpy(title, eof_song->tags->title, sizeof(title) - 1);	//Backup the song title field, since if it changes as part of the undo, the Rocksmith WAV file should be deleted

		(void) snprintf(fn, sizeof(fn) - 1, "%seof%03u.redo", eof_temp_path, eof_log_id);	//Include EOF's log ID in the redo name to almost guarantee it is uniquely named
		(void) eof_save_song(eof_song, fn);
		eof_redo_type = 0;
		eof_undo_current_index--;
		if(eof_undo_current_index < 0)
		{
			eof_undo_current_index = EOF_MAX_UNDO - 1;
		}
		(void) eof_undo_load_state(eof_undo_filename[eof_undo_current_index]);
		if(eof_undo_type[eof_undo_current_index] == EOF_UNDO_TYPE_NOTE_SEL)
		{
			(void) eof_menu_edit_deselect_all();
		}
		if(eof_undo_type[eof_undo_current_index] == EOF_UNDO_TYPE_SILENCE)
		{
			(void) snprintf(fn, sizeof(fn) - 1, "%seof%03u.redo.ogg", eof_temp_path, eof_log_id);	//Include EOF's log ID in the redo name to almost guarantee it is uniquely named
			(void) eof_copy_file(eof_loaded_ogg_name, fn);
			(void) snprintf(fn, sizeof(fn) - 1, "%s%s.ogg", eof_temp_path, eof_undo_filename[eof_undo_current_index]);
			(void) eof_copy_file(fn, eof_loaded_ogg_name);
			(void) eof_load_ogg(eof_loaded_ogg_name, 0);
			eof_delete_rocksmith_wav();		//Delete the Rocksmith WAV file since changing silence will require a new WAV file to be written
			eof_fix_waveform_graph();
			eof_fix_spectrogram();
			eof_redo_type = EOF_UNDO_TYPE_SILENCE;
		}
		if(strcmp(title, eof_song->tags->title))
		{	//If the song title changed as part of the undo, delete the Rocksmith WAV file, since changing the title will cause a new WAV file to be written
			eof_delete_rocksmith_wav();
		}
		eof_undo_count--;
		eof_redo_count = 1;
		eof_change_count--;
		if(eof_change_count == 0)
		{
			eof_changes = 0;
		}
		else
		{
			eof_changes = 1;
		}
		eof_undo_last_type = 0;

		eof_init_after_load(1);	//Perform various cleanup
		(void) eof_detect_difficulties(eof_song, eof_selected_track);
		eof_select_beat(eof_selected_beat);
		eof_fix_catalog_selection();
		eof_scale_fretboard(0);	//Recalculate the 2D screen positioning based on the current track

		//Restore tech view for each pro guitar track that had it in use before the undo operation
		for(ctr = 0; ctr < EOF_PRO_GUITAR_TRACKS_MAX; ctr++)
		{	//For each pro guitar track in the project
			tp = eof_song->pro_guitar_track[ctr];
			if(tech_view_status[ctr])
			{	//If tech view was in effect for this track
				eof_menu_pro_guitar_track_enable_tech_view(tp);
			}
		}

		eof_fix_window_title();
		return 1;
	}
	return 0;
}