#include "libwaveformat.h" __inline static void write_int24(t_wav_uint8 * p_output,t_wav_int32 p_value) { p_output[0] = (t_wav_uint8)(p_value); p_output[1] = (t_wav_uint8)(p_value>>8); p_output[2] = (t_wav_uint8)(p_value>>16); } __inline static void write_int32(t_wav_uint8 * p_output,t_wav_int32 p_value) { p_output[0] = (t_wav_uint8)(p_value); p_output[1] = (t_wav_uint8)(p_value>>8); p_output[2] = (t_wav_uint8)(p_value>>16); p_output[3] = (t_wav_uint8)(p_value>>24); } __inline static void write_float(t_wav_uint8 * p_output,t_wav_float32 p_value) { t_wav_conv bah; bah.f = p_value; p_output[0] = (t_wav_uint8)bah.n; p_output[1] = (t_wav_uint8)(bah.n >> 8); p_output[2] = (t_wav_uint8)(bah.n >> 16); p_output[3] = (t_wav_uint8)(bah.n >> 24); } static void g_convert_float32_to_uint8(t_wav_float32 const * p_sample_buffer,t_wav_uint8 * p_output,t_wav_uint32 p_sample_count) { t_wav_uint32 n; for(n=0;n 0x7F) temp = 0x7F; *(p_output++) = (t_wav_uint8)temp ^ 0x80; } } static void g_convert_int16_to_uint8(t_wav_int16 const * p_sample_buffer,t_wav_uint8 * p_output,t_wav_uint32 p_sample_count) { t_wav_uint32 n; for(n=0;n> 8) ^ 0x80; } } static void g_convert_float32_to_int16(t_wav_float32 const * p_sample_buffer,t_wav_uint8 * p_output,t_wav_uint32 p_sample_count) { t_wav_uint32 n; for(n=0;n 0x7FFF) temp = 0x7FFF; *(p_output++) = (t_wav_uint8)((t_wav_uint32)temp); *(p_output++) = (t_wav_uint8)((t_wav_uint32)temp >> 8); } } static void g_convert_int16_to_int16(t_wav_int16 const * p_sample_buffer,t_wav_uint8 * p_output,t_wav_uint32 p_sample_count) { t_wav_uint32 n; for(n=0;n> 8); } } static void g_convert_float32_to_int24(t_wav_float32 const * p_sample_buffer,t_wav_uint8 * p_output,t_wav_uint32 p_sample_count) { t_wav_uint32 n; for(n=0;nm_callback.m_write(p_file->m_callback.m_user_data,p_buffer,p_buffer_size); } static t_wav_uint32 waveformat_seek(t_wav_output_file * p_file,t_wav_uint32 p_position) { return p_file->m_callback.m_seek(p_file->m_callback.m_user_data,p_position); } static t_wav_uint32 waveformat_write_riff(t_wav_output_file * p_file,t_riff_header p_riff) { return waveformat_write(p_file,&p_riff,sizeof(p_riff)) / sizeof(p_riff); } static t_wav_uint32 waveformat_write_uint32(t_wav_output_file * p_file,t_wav_uint32 p_val) { t_wav_uint8 temp[4] = { (t_wav_uint8)(p_val & 0xFF), (t_wav_uint8)((p_val >> 8) & 0xFF), (t_wav_uint8)((p_val >> 16) & 0xFF), (t_wav_uint8)((p_val >> 24) & 0xFF) }; return waveformat_write(p_file,temp,4) / 4; } static t_wav_uint32 waveformat_write_uint16(t_wav_output_file * p_file,t_wav_uint16 p_val) { t_wav_uint8 temp[2] = { (t_wav_uint8)(p_val & 0xFF), (t_wav_uint8)((p_val >> 8) & 0xFF) }; return waveformat_write(p_file,temp,2) / 2; } static t_wav_uint32 calculate_riff_size(t_wav_output_file * p_file,t_wav_uint32 p_samples_written) { t_wav_uint32 bytes_written = p_samples_written * p_file->m_bytes_per_sample, bytes_written_padded = bytes_written; if (bytes_written & 1)//padding bytes_written_padded++; return bytes_written_padded + 4 + 8 + 2+2+4+4+2+2 + 8; } static t_wav_uint32 calculate_data_size(t_wav_output_file * p_file,t_wav_uint32 p_samples_written) { return p_samples_written * p_file->m_bytes_per_sample; } t_wav_uint32 waveformat_output_open(t_wav_output_file * p_file,t_wav_output_file_callback p_callback,t_wav_uint32 p_channels,t_wav_uint32 p_bits_per_sample,t_wav_uint32 p_float,t_wav_uint32 p_sample_rate,t_wav_uint32 p_samples_written_expected) { p_file->m_callback = p_callback; p_file->m_channels = p_channels; p_file->m_bits_per_sample = p_bits_per_sample; p_file->m_float = p_float; p_file->m_sample_rate = p_sample_rate; p_file->m_bytes_per_sample = p_bits_per_sample >> 3; if (p_file->m_bytes_per_sample == 0) return 0; p_file->m_buffer_size = sizeof(p_file->m_workbuffer) / p_file->m_bytes_per_sample; p_file->m_samples_written_expected = p_samples_written_expected; if (p_float) { switch(p_bits_per_sample) { case 32: p_file->m_output_handler = g_wav_output_handler_float32; break; default: return 0; } } else { switch(p_bits_per_sample) { case 8: p_file->m_output_handler = g_wav_output_handler_uint8; break; case 16: p_file->m_output_handler = g_wav_output_handler_int16; break; case 24: p_file->m_output_handler = g_wav_output_handler_int24; break; case 32: p_file->m_output_handler = g_wav_output_handler_int32; break; default: return 0; } } if (waveformat_write_riff(p_file,g_header_riff) != 1) return 0; if (waveformat_write_uint32(p_file,calculate_riff_size(p_file,p_file->m_samples_written_expected)) != 1) return 0; //to be possibly rewritten later, offset : 4 if (waveformat_write_riff(p_file,g_header_wave) != 1) return 0; //offset: 12 if (waveformat_write_riff(p_file,g_header_fmt) != 1) return 0; if (waveformat_write_uint32(p_file,2+2+4+4+2+2) != 1) return 0; //offset: 12 + 8 if (waveformat_write_uint16(p_file,p_float ? waveformat_tag_float : waveformat_tag_int) != 1) return 0; if (waveformat_write_uint16(p_file,(t_wav_uint16) p_channels) != 1) return 0; if (waveformat_write_uint32(p_file,p_sample_rate) != 1) return 0; if (waveformat_write_uint32(p_file,(t_wav_uint32)(p_sample_rate * p_file->m_bytes_per_sample * p_channels)) != 1) return 0; if (waveformat_write_uint16(p_file,(t_wav_uint16)(p_file->m_bytes_per_sample * p_channels)) != 1) return 0; if (waveformat_write_uint16(p_file,(t_wav_uint16)p_bits_per_sample) != 1) return 0; //offset: 12 + 8 + 2+2+4+4+2+2 if (waveformat_write_riff(p_file,g_header_data) != 1) return 0; if (waveformat_write_uint32(p_file,calculate_data_size(p_file,p_file->m_samples_written_expected)) != 1) return 0; //to be possibly rewritten later, offset : 12 + 8 + 2+2+4+4+2+2 + 4 //total header size: 12 + 8 + 2+2+4+4+2+2 + 8 p_file->m_samples_written = 0; return 1; } t_wav_uint32 waveformat_output_process_float32(t_wav_output_file * p_file,t_wav_float32 const * p_sample_buffer,t_wav_uint32 p_sample_count) { t_wav_uint32 samples_done; samples_done = 0; while(samples_done < p_sample_count) { t_wav_uint32 delta = p_sample_count - samples_done, delta_written; if (delta > p_file->m_buffer_size) delta = p_file->m_buffer_size; p_file->m_output_handler.m_convert_float32(p_sample_buffer + samples_done,p_file->m_workbuffer,delta); delta_written = waveformat_write(p_file,p_file->m_workbuffer,delta * p_file->m_bytes_per_sample) / p_file->m_bytes_per_sample; if (delta_written > 0) { samples_done += delta_written; } if (delta_written != delta) break; } p_file->m_samples_written += samples_done; return samples_done; } t_wav_uint32 waveformat_output_process_int16(t_wav_output_file * p_file,t_wav_int16 const * p_sample_buffer,t_wav_uint32 p_sample_count) { t_wav_uint32 samples_done; samples_done = 0; while(samples_done < p_sample_count) { t_wav_uint32 delta = p_sample_count - samples_done, delta_written; if (delta > p_file->m_buffer_size) delta = p_file->m_buffer_size; p_file->m_output_handler.m_convert_int16(p_sample_buffer + samples_done,p_file->m_workbuffer,delta); delta_written = waveformat_write(p_file,p_file->m_workbuffer,delta * p_file->m_bytes_per_sample) / p_file->m_bytes_per_sample; if (delta_written > 0) { samples_done += delta_written; } if (delta_written != delta) break; } p_file->m_samples_written += samples_done; return samples_done; } t_wav_uint32 waveformat_output_close(t_wav_output_file * p_file) { if ((p_file->m_samples_written * p_file->m_bytes_per_sample) & 1)//padding { t_wav_uint8 meh = 0; if (waveformat_write(p_file,&meh,1) != 1) return 0; } if (p_file->m_samples_written != p_file->m_samples_written_expected) { if (!waveformat_seek(p_file,4)) return 0; if (waveformat_write_uint32(p_file,calculate_riff_size(p_file,p_file->m_samples_written)) != 1) return 0; if (!waveformat_seek(p_file,12 + 8 + 2+2+4+4+2+2 + 4)) return 0; if (waveformat_write_uint32(p_file,calculate_data_size(p_file,p_file->m_samples_written)) != 1) return 0; } return 1; }