22 if (this->m_bpsValid != this->m_bps)
return true;
43 m_bpsValid = bpsValid;
54 m_bpsValid = p_bpsValid;
65 unsigned bpsValid = p_bps;
66 unsigned bps = (p_bps + 7) & ~7;
67 initialize2(p_chunk, bps, bpsValid, p_float, p_dither, p_wave64);
72 p_wfx.wFormatTag = m_float ? WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM;
73 p_wfx.nChannels = m_channels;
74 p_wfx.nSamplesPerSec = m_samplerate;
75 p_wfx.nAvgBytesPerSec = (m_bps >> 3) * m_channels * m_samplerate;
76 p_wfx.nBlockAlign = (m_bps>>3) * m_channels;
77 p_wfx.wBitsPerSample = m_bps;
83 setup_wfx(p_wfxe.Format);
84 p_wfxe.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
85 p_wfxe.Format.cbSize=22;
86 p_wfxe.Samples.wValidBitsPerSample = this->m_bpsValid;
88 p_wfxe.SubFormat = m_float ? KSDATAFORMAT_SUBTYPE_IEEE_FLOAT : KSDATAFORMAT_SUBTYPE_PCM;
94 m_file->write_object_t(
id, abort);
96 for(
t_size walk = 0; walk < PFC_TABSIZE(RIFF_chunks); ++walk) {
97 if (
id == RIFF_chunks[walk].
m_guid) {
98 m_file->write(RIFF_chunks[walk].
m_name, 4, abort);
return;
107 if (size != ~0) size += 24;
108 m_file->write_lendian_t(size, abort);
111 if (size > 0xFFFFFFFF) clipped = 0xFFFFFFFF;
113 m_file->write_lendian_t(clipped, abort);
119 const t_uint32 val = is64() ? 8 : 2;
121 t_size delta = (val - (pos%val)) % val;
122 if (delta > 0) m_file->write(dummy, delta, abort);
129 filesystem::g_open_write_new(l_file,p_path,p_abort);
130 open(l_file,p_setup,p_abort);
141 if (m_setup.m_channels == 0 || m_setup.m_channels > 18 || m_setup.m_channels !=
audio_chunk::g_count_channels(m_setup.m_channel_mask))
throw exception_io_data();
145 if (m_setup.m_bpsValid > m_setup.m_bps)
throw exceptionBadBitDepth();
149 if (m_setup.m_bps != 32 && m_setup.m_bps != 64)
throw exceptionBadBitDepth();
150 if (m_setup.m_bpsValid != m_setup.m_bps)
throw exceptionBadBitDepth();
154 if (m_setup.m_bps != 8 && m_setup.m_bps != 16 && m_setup.m_bps != 24 && m_setup.m_bps != 32)
throw exceptionBadBitDepth();
155 if (m_setup.m_bpsValid < 1)
throw exceptionBadBitDepth();
158 m_wfxe = m_setup.needWFXE();
160 writeID(guid_RIFF, p_abort);
161 m_offset_fix1 = m_file->get_position(p_abort);
162 writeSize(~0, p_abort);
164 writeID(guid_WAVE, p_abort);
166 writeID(guid_FMT, p_abort);
168 writeSize(
sizeof(WAVEFORMATEXTENSIBLE),p_abort);
170 WAVEFORMATEXTENSIBLE wfxe;
171 m_setup.setup_wfxe(wfxe);
172 m_file->write_object(&wfxe,
sizeof(wfxe),p_abort);
174 writeSize(
sizeof(PCMWAVEFORMAT),p_abort);
177 m_setup.setup_wfx(wfx);
178 m_file->write_object(&wfx,
sizeof(PCMWAVEFORMAT),p_abort);
182 writeID(guid_DATA, p_abort);
183 m_offset_fix2 = m_file->get_position(p_abort);
184 writeSize(~0, p_abort);
185 m_offset_fix1_delta = m_file->get_position(p_abort) - chunkOverhead();
190 if (!m_setup.m_float)
192 m_postprocessor = standard_api_create_t<audio_postprocessor>();
200 || p_chunk.
get_srate() != m_setup.m_samplerate
201 )
throw exception_unexpected_audio_format_change();
206 switch(m_setup.m_bps)
210 #if audio_sample_size == 32 212 m_file->write_object(p_chunk.
get_data(),bytes,p_abort);
213 m_bytes_written += bytes;
215 enum {tempsize = 256};
216 float temp[tempsize];
221 unsigned n,delta = todo;
222 if (delta > tempsize) delta = tempsize;
224 temp[n] = (
float)(*(readptr++));
225 unsigned bytes = delta *
sizeof(float);
226 m_file->write_object_e(temp,bytes,p_abort);
227 m_bytes_written += bytes;
237 m_file->write_object_e(p_chunk.
get_data(),bytes,p_abort);
238 m_bytes_written += bytes;
243 throw exception_io_data();
248 m_postprocessor->run(p_chunk,m_postprocessor_output,m_setup.m_bpsValid,m_setup.m_bps,m_setup.m_dither,1.0f);
249 m_file->write_object(m_postprocessor_output.get_ptr(),m_postprocessor_output.get_size(),p_abort);
250 m_bytes_written += m_postprocessor_output.get_size();
256 if (m_file.is_valid())
258 const size_t alignG = align(p_abort);
260 if (m_file->can_seek()) {
261 m_file->seek(m_offset_fix1,p_abort);
262 writeSize(m_bytes_written + alignG + m_offset_fix1_delta, p_abort);
263 m_file->seek(m_offset_fix2,p_abort);
264 writeSize(m_bytes_written, p_abort);
268 m_postprocessor.release();
274 m_postprocessor.release();
281 spec.
chanMask = m_setup.m_channel_mask;
void writeID(const GUID &id, abort_callback &abort)
void setup_wfx(WAVEFORMATEX &p_wfx)
void setup_wfxe(WAVEFORMATEXTENSIBLE &p_wfx)
static const GUID guid_WAVE
Interface to container of a chunk of audio data. See audio_chunk_impl for an implementation.
GUID GUID_from_text(const char *text)
virtual unsigned get_channels() const =0
Retrieves channel count of contained audio data.
void write(const audio_chunk &p_chunk, abort_callback &p_abort)
static const GUID guid_FMT
void initialize(const audio_chunk &p_chunk, unsigned p_bps, bool p_float, bool p_dither, bool p_wave64=false)
virtual unsigned get_srate() const =0
Retrieves sample rate of contained audio data.
virtual unsigned get_channel_config() const =0
Retrieves channel map of contained audio data. Conditions where number of channels specified by chann...
static unsigned g_count_channels(unsigned p_config)
Counts channels specified by channel map.
size_t align(abort_callback &abort)
void open(const char *p_path, const wavWriterSetup_t &p_setup, abort_callback &p_abort)
virtual audio_sample * get_data()=0
Retrieves audio data buffer pointer (non-const version). Returned pointer is for temporary use only; ...
audio_chunk::spec_t get_spec() const
static const GUID guid_DATA
PFC_DECLARE_EXCEPTION(exception_bad_cuesheet, exception_io_data,"Invalid cuesheet")
static const GUID guid_RIFF
void initialize2(const audio_chunk &p_chunk, unsigned p_bps, unsigned p_bpsValid, bool p_float, bool p_dither, bool p_wave64=false)
void finalize(abort_callback &p_abort)
t_uint64 t_filesize
Type used for file size related variables.
void initialize3(const audio_chunk::spec_t &spec, unsigned bps, unsigned bpsValid, bool bFloat, bool bDither, bool bWave64=false)
void writeSize(t_uint64 size, abort_callback &abort)
static bool g_is_valid_sample_rate(t_uint32 p_val)
PFC_NORETURN void SHARED_EXPORT uBugCheck()
static const RIFF_chunk_desc RIFF_chunks[]
virtual t_size get_sample_count() const =0
Retrieves number of valid samples in the buffer. Note that a "sample" means a unit of interleaved PC...
static uint32_t g_channel_config_to_wfx(unsigned p_config)
Helper function; translates audio_chunk channel map to WAVEFORMATEXTENSIBLE channel map...