AudioStreamSample can now be saved to a WAV file
8 and 16 bit sample saving has been implemented.
This commit is contained in:
parent
cd2070c684
commit
adb43b6976
1 changed files with 71 additions and 1 deletions
|
@ -29,6 +29,8 @@
|
|||
/*************************************************************************/
|
||||
|
||||
#include "audio_stream_sample.h"
|
||||
#include "io/marshalls.h"
|
||||
#include "os/file_access.h"
|
||||
|
||||
void AudioStreamPlaybackSample::start(float p_from_pos) {
|
||||
|
||||
|
@ -510,7 +512,73 @@ PoolVector<uint8_t> AudioStreamSample::get_data() const {
|
|||
}
|
||||
|
||||
void AudioStreamSample::save_to_wav(String p_path) {
|
||||
// TODO! Implement saving to wav file
|
||||
if (format == AudioStreamSample::FORMAT_IMA_ADPCM) {
|
||||
WARN_PRINTS("Saving IMA_ADPC samples are not supported yet");
|
||||
return;
|
||||
}
|
||||
|
||||
int sub_chunk_2_size = data_bytes; //Subchunk2Size = Size of data in bytes
|
||||
|
||||
// Format code
|
||||
// 1:PCM format (for 8 or 16 bit)
|
||||
// 3:IEEE float format
|
||||
int format_code = (format == FORMAT_IMA_ADPCM) ? 3 : 1;
|
||||
|
||||
int n_channels = stereo ? 2 : 1;
|
||||
|
||||
long sample_rate = mix_rate;
|
||||
|
||||
int byte_pr_sample = 0;
|
||||
switch (format) {
|
||||
case AudioStreamSample::FORMAT_8_BITS: byte_pr_sample = 1; break;
|
||||
case AudioStreamSample::FORMAT_16_BITS: byte_pr_sample = 2; break;
|
||||
case AudioStreamSample::FORMAT_IMA_ADPCM: byte_pr_sample = 4; break;
|
||||
}
|
||||
|
||||
String file_path = p_path;
|
||||
if (!(file_path.substr(file_path.length() - 4, 4) == ".wav")) {
|
||||
file_path += ".wav";
|
||||
}
|
||||
|
||||
Error err;
|
||||
FileAccess *file = FileAccess::open(file_path, FileAccess::WRITE, &err); //Overrides existing file if present
|
||||
|
||||
// Create WAV Header
|
||||
file->store_string("RIFF"); //ChunkID
|
||||
file->store_32(sub_chunk_2_size + 36); //ChunkSize = 36 + SubChunk2Size (size of entire file minus the 8 bits for this and previous header)
|
||||
file->store_string("WAVE"); //Format
|
||||
file->store_string("fmt "); //Subchunk1ID
|
||||
file->store_32(16); //Subchunk1Size = 16
|
||||
file->store_16(format_code); //AudioFormat
|
||||
file->store_16(n_channels); //Number of Channels
|
||||
file->store_32(sample_rate); //SampleRate
|
||||
file->store_32(sample_rate * n_channels * byte_pr_sample); //ByteRate
|
||||
file->store_16(n_channels * byte_pr_sample); //BlockAlign = NumChannels * BytePrSample
|
||||
file->store_16(byte_pr_sample * 8); //BitsPerSample
|
||||
file->store_string("data"); //Subchunk2ID
|
||||
file->store_32(sub_chunk_2_size); //Subchunk2Size
|
||||
|
||||
// Add data
|
||||
PoolVector<uint8_t>::Read read_data = get_data().read();
|
||||
switch (format) {
|
||||
case AudioStreamSample::FORMAT_8_BITS:
|
||||
for (int i = 0; i < data_bytes; i++) {
|
||||
uint8_t data_point = (read_data[i] + 128);
|
||||
file->store_8(data_point);
|
||||
}
|
||||
break;
|
||||
case AudioStreamSample::FORMAT_16_BITS:
|
||||
for (int i = 0; i < data_bytes / 2; i++) {
|
||||
uint16_t data_point = decode_uint16(&read_data[i * 2]);
|
||||
file->store_16(data_point);
|
||||
}
|
||||
break;
|
||||
case AudioStreamSample::FORMAT_IMA_ADPCM:
|
||||
//Unimplemented
|
||||
break;
|
||||
}
|
||||
|
||||
file->close();
|
||||
}
|
||||
|
||||
Ref<AudioStreamPlayback> AudioStreamSample::instance_playback() {
|
||||
|
@ -549,6 +617,8 @@ void AudioStreamSample::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_stereo", "stereo"), &AudioStreamSample::set_stereo);
|
||||
ClassDB::bind_method(D_METHOD("is_stereo"), &AudioStreamSample::is_stereo);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("save_to_wav", "path"), &AudioStreamSample::save_to_wav);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_data", "get_data");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA-ADPCM"), "set_format", "get_format");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "Disabled,Forward,Ping-Pong"), "set_loop_mode", "get_loop_mode");
|
||||
|
|
Loading…
Reference in a new issue