FXbool WavOutput::write(const void * data,FXuint nframes) { FXlong duration = (nframes*NANOSECONDS_PER_SECOND) / af.rate; FXThread::sleep(duration); if (!file.isOpen() || file.writeBlock(data,af.framesize()*nframes)!=af.framesize()*nframes) return false; else return true; }
void WavOutput::close() { if (file.isOpen()) { GM_DEBUG_PRINT("[wav] closed output\n"); FXulong end=file.position(); FXulong size; FXuint size32=0xFFFFFFFF; size=end-8; if (end>0xFFFFFFFF) { // RIFF Chunk file.position(0); file.writeBlock("RF64",4); file.writeBlock(&size32,4); // DS64 Chunk file.position(12); file.writeBlock("ds64",4); file.position(20); file.writeBlock(&size,8); // Data Chunk if (data_pos) { size=end-data_pos-4; file.writeBlock(&size,8); size=0; file.writeBlock(&size,8); } } else { /// RIFF chunksize size32=size; file.position(4); file.writeBlock(&size32,4); // Data Chunksize if (data_pos) { file.position(data_pos); size=end-data_pos-4; file.writeBlock(&size,4); } } file.close(); } af.reset(); }
///FIXME perhaps support extensible wav format FXbool WavOutput::configure(const AudioFormat & fmt) { FXushort format; // Can't handle big endian yet, neither does the output thread handle byteorder swaps if (fmt.byteorder() != Format::Little) return false; // Extensible Wav Format not yet supported if (fmt.channels>2) return false; // Determine format switch(fmt.datatype()) { case Format::Unsigned : case Format::Signed : format = WAV_FORMAT_PCM; break; case Format::Float : format = WAV_FORMAT_FLOAT; break; default : return false; break; } FXString path=FXPath::unique("gap.wav"); if (file.open(path,FXIO::Writing)) { GM_DEBUG_PRINT("[wav] opened output file: %s\n",path.text()); af=fmt; FXuint chunksize=0; FXlong ldata=0; /// riff chunk file.writeBlock("RIFF",4); file.writeBlock(&chunksize,4); // empty for now file.writeBlock("WAVE",4); /// junk chunk chunksize=28; file.writeBlock("JUNK",4); file.writeBlock(&chunksize,4); file.writeBlock(&ldata,8); file.writeBlock(&ldata,8); file.writeBlock(&ldata,8); chunksize=0; file.writeBlock(&chunksize,4); /// fmt file.writeBlock("fmt ",4); chunksize=16; file.writeBlock(&chunksize,4); file.writeBlock(&format,2); FXushort channels=fmt.channels; FXuint rate=fmt.rate; FXuint byterate=fmt.rate*fmt.channels*fmt.packing(); FXushort blockalign=fmt.framesize(); FXushort bitspersample=fmt.bps(); file.writeBlock(&channels,2); file.writeBlock(&rate,4); file.writeBlock(&byterate,4); file.writeBlock(&blockalign,2); file.writeBlock(&bitspersample,2); file.writeBlock("data",4); chunksize=0xFFFFFFFF; data_pos=file.position(); file.writeBlock(&chunksize,4); return true; } GM_DEBUG_PRINT("[wav] failed to open output file: %s\n",path.text()); return false; }
// Write string static bool writeString(FXFile& file,const FXchar* string){ register FXint len=(FXint)strlen(string); return file.writeBlock(string,len)==len; }