/** * audio_sdl_init(): Initialize the SDL audio subsystem. * @return 0 on success; non-zero on error. */ static int audio_sdl_init(void) { if (audio_initialized) return -1; // Make sure sound is shut down first. audio_sdl_end(); // Attempt to initialize SDL audio. if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) return -1; // Set up the SDL audio specification. SDL_AudioSpec spec; spec.freq = audio_get_sound_rate(); spec.format = AUDIO_S16SYS; spec.channels = !(audio_get_stereo()) ? 1 : 2; // TODO: Initializing 1 channel seems to double-free if it's later changed... spec.samples = 1024; spec.callback = audio_sdl_callback; spec.userdata = NULL; // Initialize the audio buffer. audio_sdl_audiobuf = (unsigned char*)(calloc(1, (spec.samples * spec.channels * 2 * 4) * sizeof(short))); if (SDL_OpenAudio(&spec, 0) != 0) { // Could not open audio. free(audio_sdl_audiobuf); audio_sdl_audiobuf = NULL; return -2; } SDL_PauseAudio(0); // Sound is initialized. audio_initialized = TRUE; return 0; }
/** * wav_dump_start(): Start dumping a WAV file. * @return 0 on success; non-zero on error. */ int wav_dump_start(void) { #ifdef GENS_OS_WIN32 // Make sure relative pathnames are handled correctly on Win32. pSetCurrentDirectoryU(PathNames.Gens_Save_Path); #endif /* A game must be loaded in order to dump a WAV. */ if (!Game) return 0; if (WAV_Dumping) { vdraw_text_write("WAV sound is already dumping.", 1000); return 0; } /* Build the filename. */ char filename[GENS_PATH_MAX]; int num = -1; do { num++; szprintf(filename, sizeof(filename), "%s%s_%03d.wav", PathNames.Dump_WAV_Dir, ROM_Filename, num); } while (!access(filename, F_OK)); /* Open the file. */ WAV_File = fopen(filename, "wb"); if (!WAV_File) { vdraw_text_write("Error opening WAV file.", 1000); return 1; } /* Create the WAV header. */ memset(&WAV_Header, 0x00, sizeof(WAV_Header)); /* "RIFF" header. */ static const char ChunkID_RIFF[4] = {'R', 'I', 'F', 'F'}; static const char FormatID_WAV[4] = {'W', 'A', 'V', 'E'}; memcpy(WAV_Header.riff.ChunkID, ChunkID_RIFF, sizeof(WAV_Header.riff.ChunkID)); memcpy(WAV_Header.riff.Format, FormatID_WAV, sizeof(WAV_Header.riff.Format)); /* "fmt " header. */ static const char SubchunkID_fmt[4] = {'f', 'm', 't', ' '}; memcpy(WAV_Header.fmt.SubchunkID, SubchunkID_fmt, sizeof(WAV_Header.fmt.SubchunkID)); WAV_Header.fmt.SubchunkSize = cpu_to_le32(sizeof(WAV_Header.fmt) - 8); WAV_Header.fmt.AudioFormat = cpu_to_le16(1); /* PCM */ WAV_Header.fmt.NumChannels = cpu_to_le16((audio_get_stereo() ? 2 : 1)); WAV_Header.fmt.SampleRate = cpu_to_le32(audio_get_sound_rate()); WAV_Header.fmt.BitsPerSample = cpu_to_le16(16); /* Gens is currently hard-coded to 16-bit audio. */ /* Calculated fields. */ WAV_Header.fmt.BlockAlign = cpu_to_le16(WAV_Header.fmt.NumChannels * (WAV_Header.fmt.BitsPerSample / 8)); WAV_Header.fmt.ByteRate = cpu_to_le32(WAV_Header.fmt.BlockAlign * WAV_Header.fmt.SampleRate); /* "data" header. */ static const char SubchunkID_data[4] = {'d', 'a', 't', 'a'}; memcpy(WAV_Header.data.SubchunkID, SubchunkID_data, sizeof(WAV_Header.data.SubchunkID)); /* Write the initial header to the file. */ fwrite(&WAV_Header, sizeof(WAV_Header), 1, WAV_File); /* WAV dump started. */ vdraw_text_write("Starting to dump WAV sound.", 1000); WAV_Dumping = 1; Sync_Gens_Window_SoundMenu(); return 0; }