mirror of
				https://github.com/AlexandreRouma/SDRPlusPlus.git
				synced 2025-10-31 00:48:11 +01:00 
			
		
		
		
	final fixes
This commit is contained in:
		| @@ -7,6 +7,7 @@ | ||||
| #include <dsp/sink/handler_sink.h> | ||||
| #include <dsp/routing/splitter.h> | ||||
| #include <dsp/audio/volume.h> | ||||
| #include <dsp/convert/stereo_to_mono.h> | ||||
| #include <thread> | ||||
| #include <ctime> | ||||
| #include <gui/gui.h> | ||||
| @@ -41,15 +42,15 @@ public: | ||||
|         root = (std::string)core::args["root"]; | ||||
|  | ||||
|         // Define option lists | ||||
|         formats.define("WAV", wav::FORMAT_WAV); | ||||
|         // formats.define("RF64", wav::FORMAT_RF64); // Disabled for now | ||||
|         containers.define("WAV", wav::FORMAT_WAV); | ||||
|         // containers.define("RF64", wav::FORMAT_RF64); // Disabled for now | ||||
|         sampleTypes.define(wav::SAMP_TYPE_UINT8, "Uint8", wav::SAMP_TYPE_UINT8); | ||||
|         sampleTypes.define(wav::SAMP_TYPE_INT16, "Int16", wav::SAMP_TYPE_INT16); | ||||
|         sampleTypes.define(wav::SAMP_TYPE_INT32, "Int32", wav::SAMP_TYPE_INT32); | ||||
|         sampleTypes.define(wav::SAMP_TYPE_FLOAT32, "Float32", wav::SAMP_TYPE_FLOAT32); | ||||
|  | ||||
|         // Load default config for option lists | ||||
|         formatId = formats.valueId(wav::FORMAT_WAV); | ||||
|         containerId = containers.valueId(wav::FORMAT_WAV); | ||||
|         sampleTypeId = sampleTypes.valueId(wav::SAMP_TYPE_INT16); | ||||
|  | ||||
|         // Load config | ||||
| @@ -60,8 +61,8 @@ public: | ||||
|         if (config.conf[name].contains("recPath")) { | ||||
|             folderSelect.setPath(config.conf[name]["recPath"]); | ||||
|         } | ||||
|         if (config.conf[name].contains("format") && formats.keyExists(config.conf[name]["format"])) { | ||||
|             formatId = formats.keyId(config.conf[name]["format"]); | ||||
|         if (config.conf[name].contains("format") && containers.keyExists(config.conf[name]["format"])) { | ||||
|             containerId = containers.keyId(config.conf[name]["format"]); | ||||
|         } | ||||
|         if (config.conf[name].contains("sampleType") && sampleTypes.keyExists(config.conf[name]["sampleType"])) { | ||||
|             sampleTypeId = sampleTypes.keyId(config.conf[name]["sampleType"]); | ||||
| @@ -82,11 +83,12 @@ public: | ||||
|         splitter.init(&volume.out); | ||||
|         splitter.bindStream(&meterStream); | ||||
|         meter.init(&meterStream); | ||||
|         s2m.init(NULL); | ||||
|  | ||||
|         // Init sinks | ||||
|         basebandSink.init(NULL, complexHandler, this); | ||||
|         stereoSink.init(NULL, stereoHandler, this); | ||||
|         monoSink.init(NULL, monoHandler, this); | ||||
|         monoSink.init(&s2m.out, monoHandler, this); | ||||
|  | ||||
|         gui::menu.registerEntry(name, menuHandler, this); | ||||
|     } | ||||
| @@ -142,7 +144,7 @@ public: | ||||
|         else { | ||||
|             samplerate = sigpath::iqFrontEnd.getSampleRate(); | ||||
|         } | ||||
|         writer.setFormat(formats[formatId]); | ||||
|         writer.setFormat(containers[containerId]); | ||||
|         writer.setChannels((recMode == RECORDER_MODE_AUDIO && !stereo) ? 1 : 2); | ||||
|         writer.setSampleType(sampleTypes[sampleTypeId]); | ||||
|         writer.setSamplerate(samplerate); | ||||
| @@ -159,8 +161,15 @@ public: | ||||
|         if (recMode == RECORDER_MODE_AUDIO) { | ||||
|             // TODO: Select the stereo to mono converter if needed | ||||
|             stereoStream = sigpath::sinkManager.bindStream(selectedStreamName); | ||||
|             stereoSink.setInput(stereoStream); | ||||
|             stereoSink.start(); | ||||
|             if (stereo) { | ||||
|                 stereoSink.setInput(stereoStream); | ||||
|                 stereoSink.start(); | ||||
|             } | ||||
|             else { | ||||
|                 s2m.setInput(stereoStream); | ||||
|                 s2m.start(); | ||||
|                 monoSink.start(); | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             // Create and bind IQ stream | ||||
| @@ -179,8 +188,10 @@ public: | ||||
|  | ||||
|         // Close audio stream or baseband | ||||
|         if (recMode == RECORDER_MODE_AUDIO) { | ||||
|             // TODO: HAS TO BE DONE PROPERLY | ||||
|             // NOTE: Has to be done before the unbind since the stream is deleted... | ||||
|             monoSink.stop(); | ||||
|             stereoSink.stop(); | ||||
|             s2m.stop(); | ||||
|             sigpath::sinkManager.unbindStream(selectedStreamName, stereoStream); | ||||
|         } | ||||
|         else { | ||||
| @@ -231,11 +242,11 @@ private: | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         ImGui::LeftLabel("WAV Format"); | ||||
|         ImGui::LeftLabel("Container"); | ||||
|         ImGui::FillWidth(); | ||||
|         if (ImGui::Combo(CONCAT("##_recorder_wav_fmt_", _this->name), &_this->formatId, _this->formats.txt)) { | ||||
|         if (ImGui::Combo(CONCAT("##_recorder_container_", _this->name), &_this->containerId, _this->containers.txt)) { | ||||
|             config.acquire(); | ||||
|             config.conf[_this->name]["format"] = _this->formats.key(_this->formatId); | ||||
|             config.conf[_this->name]["container"] = _this->containers.key(_this->containerId); | ||||
|             config.release(true); | ||||
|         } | ||||
|  | ||||
| @@ -431,12 +442,12 @@ private: | ||||
|     bool enabled = true; | ||||
|     std::string root; | ||||
|  | ||||
|     OptionList<std::string, wav::Format> formats; | ||||
|     OptionList<std::string, wav::Format> containers; | ||||
|     OptionList<int, wav::SampleType> sampleTypes; | ||||
|     FolderSelect folderSelect; | ||||
|  | ||||
|     int recMode = RECORDER_MODE_AUDIO; | ||||
|     int formatId; | ||||
|     int containerId; | ||||
|     int sampleTypeId; | ||||
|     bool stereo = true; | ||||
|     std::string selectedStreamName = ""; | ||||
| @@ -460,6 +471,7 @@ private: | ||||
|     dsp::routing::Splitter<dsp::stereo_t> splitter; | ||||
|     dsp::stream<dsp::stereo_t> meterStream; | ||||
|     dsp::bench::PeakLevelMeter<dsp::stereo_t> meter; | ||||
|     dsp::convert::StereoToMono s2m; | ||||
|  | ||||
|     uint64_t samplerate = 48000; | ||||
|  | ||||
|   | ||||
| @@ -2,28 +2,64 @@ | ||||
| #include <stdexcept> | ||||
|  | ||||
| namespace riff { | ||||
|     bool Writer::open(std::string path, char form[4]) { | ||||
|         // TODO:  Open file | ||||
|     const char* RIFF_SIGNATURE      = "RIFF"; | ||||
|     const char* LIST_SIGNATURE      = "LIST"; | ||||
|     const size_t RIFF_LABEL_SIZE    = 4; | ||||
|  | ||||
|     bool Writer::open(std::string path, const char form[4]) { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|  | ||||
|         // Open file | ||||
|         file = std::ofstream(path, std::ios::out | std::ios::binary); | ||||
|         if (!file.is_open()) { return false; } | ||||
|  | ||||
|         // Begin RIFF chunk | ||||
|         beginRIFF(form); | ||||
|  | ||||
|         return false; | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool Writer::isOpen() { | ||||
|          | ||||
|         return false; | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|         return file.is_open(); | ||||
|     } | ||||
|  | ||||
|     void Writer::close() { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|  | ||||
|         if (!isOpen()) { return; } | ||||
|  | ||||
|         // Finalize RIFF chunk | ||||
|         endRIFF(); | ||||
|  | ||||
|         // Close file | ||||
|         file.close(); | ||||
|     } | ||||
|  | ||||
|     void Writer::beginChunk(char id[4]) { | ||||
|     void Writer::beginList(const char id[4]) { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|  | ||||
|         // Create chunk with the LIST ID and write id | ||||
|         beginChunk(LIST_SIGNATURE); | ||||
|         write((uint8_t*)id, RIFF_LABEL_SIZE); | ||||
|     } | ||||
|  | ||||
|     void Writer::endList() { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|  | ||||
|         if (chunks.empty()) { | ||||
|             throw std::runtime_error("No chunk to end"); | ||||
|         } | ||||
|         if (memcmp(chunks.top().hdr.id, LIST_SIGNATURE, RIFF_LABEL_SIZE)) { | ||||
|             throw std::runtime_error("Top chunk not LIST chunk"); | ||||
|         } | ||||
|  | ||||
|         endChunk(); | ||||
|     } | ||||
|  | ||||
|     void Writer::beginChunk(const char id[4]) { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|  | ||||
|         // Create and write header | ||||
|         ChunkDesc desc; | ||||
|         desc.pos = file.tellp(); | ||||
| @@ -36,7 +72,9 @@ namespace riff { | ||||
|     } | ||||
|  | ||||
|     void Writer::endChunk() { | ||||
|         if (!chunks.empty()) { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|  | ||||
|         if (chunks.empty()) { | ||||
|             throw std::runtime_error("No chunk to end"); | ||||
|         } | ||||
|  | ||||
| @@ -46,7 +84,9 @@ namespace riff { | ||||
|  | ||||
|         // Write size | ||||
|         auto pos = file.tellp(); | ||||
|         file.seekp(desc.pos + 4); | ||||
|         auto npos = desc.pos; | ||||
|         npos += 4; | ||||
|         file.seekp(npos); | ||||
|         file.write((char*)&desc.hdr.size, sizeof(desc.hdr.size)); | ||||
|         file.seekp(pos); | ||||
|  | ||||
| @@ -56,31 +96,38 @@ namespace riff { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Writer::write(void* data, size_t len) { | ||||
|         if (!chunks.empty()) { | ||||
|     void Writer::write(const uint8_t* data, size_t len) { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|  | ||||
|         if (chunks.empty()) { | ||||
|             throw std::runtime_error("No chunk to write into"); | ||||
|         } | ||||
|         file.write((char*)data, len); | ||||
|         chunks.top().hdr.size += len; | ||||
|     } | ||||
|  | ||||
|     void Writer::beginRIFF(char form[4]) { | ||||
|     void Writer::beginRIFF(const char form[4]) { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|  | ||||
|         if (!chunks.empty()) { | ||||
|             throw std::runtime_error("Can't create RIFF chunk on an existing RIFF file"); | ||||
|         } | ||||
|  | ||||
|         // Create chunk with RIFF ID and write form | ||||
|         beginChunk("RIFF"); | ||||
|         write(form, sizeof(form)); | ||||
|         beginChunk(RIFF_SIGNATURE); | ||||
|         write((uint8_t*)form, RIFF_LABEL_SIZE); | ||||
|     } | ||||
|  | ||||
|     void Writer::endRIFF() { | ||||
|         if (!chunks.empty()) { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|  | ||||
|         if (chunks.empty()) { | ||||
|             throw std::runtime_error("No chunk to end"); | ||||
|         } | ||||
|         if (memcmp(chunks.top().hdr.id, "RIFF", 4)) { | ||||
|         if (memcmp(chunks.top().hdr.id, RIFF_SIGNATURE, RIFF_LABEL_SIZE)) { | ||||
|             throw std::runtime_error("Top chunk not RIFF chunk"); | ||||
|         } | ||||
|  | ||||
|         endChunk(); | ||||
|     } | ||||
| } | ||||
| @@ -1,4 +1,5 @@ | ||||
| #pragma once | ||||
| #include <mutex> | ||||
| #include <fstream> | ||||
| #include <string> | ||||
| #include <stack> | ||||
| @@ -19,22 +20,23 @@ namespace riff { | ||||
|  | ||||
|     class Writer { | ||||
|     public: | ||||
|         bool open(std::string path, char form[4]); | ||||
|         bool open(std::string path, const char form[4]); | ||||
|         bool isOpen(); | ||||
|         void close(); | ||||
|  | ||||
|         void beginList(); | ||||
|         void beginList(const char id[4]); | ||||
|         void endList(); | ||||
|  | ||||
|         void beginChunk(char id[4]); | ||||
|         void beginChunk(const char id[4]); | ||||
|         void endChunk(); | ||||
|  | ||||
|         void write(void* data, size_t len); | ||||
|         void write(const uint8_t* data, size_t len); | ||||
|  | ||||
|     private: | ||||
|         void beginRIFF(char form[4]); | ||||
|         void beginRIFF(const char form[4]); | ||||
|         void endRIFF(); | ||||
|  | ||||
|         std::recursive_mutex mtx; | ||||
|         std::ofstream file; | ||||
|         std::stack<ChunkDesc> chunks; | ||||
|     }; | ||||
|   | ||||
| @@ -6,7 +6,6 @@ | ||||
| #include <map> | ||||
|  | ||||
| namespace wav { | ||||
|     const char* RIFF_SIGNATURE          = "RIFF"; | ||||
|     const char* WAVE_FILE_TYPE          = "WAVE"; | ||||
|     const char* FORMAT_MARKER           = "fmt "; | ||||
|     const char* DATA_MARKER             = "data"; | ||||
| @@ -30,13 +29,6 @@ namespace wav { | ||||
|         _samplerate = samplerate; | ||||
|         _format = format; | ||||
|         _type = type; | ||||
|  | ||||
|         // Initialize header with constants | ||||
|         memcpy(hdr.signature, RIFF_SIGNATURE, 4); | ||||
|         memcpy(hdr.fileType, WAVE_FILE_TYPE, 4); | ||||
|         memcpy(hdr.formatMarker, FORMAT_MARKER, 4); | ||||
|         hdr.formatHeaderLength = FORMAT_HEADER_LEN; | ||||
|         memcpy(hdr.dataMarker, DATA_MARKER, 4); | ||||
|     } | ||||
|  | ||||
|     Writer::~Writer() { close(); } | ||||
| @@ -44,14 +36,21 @@ namespace wav { | ||||
|     bool Writer::open(std::string path) { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|         // Close previous file | ||||
|         if (_isOpen) { close(); } | ||||
|         if (rw.isOpen()) { close(); } | ||||
|  | ||||
|         // Reset work values | ||||
|         samplesWritten = 0; | ||||
|  | ||||
|         // Fill header | ||||
|         bytesPerSamp = (SAMP_BITS[_type] / 8) * _channels; | ||||
|         hdr.codec = (_type == SAMP_TYPE_FLOAT32) ? CODEC_FLOAT : CODEC_PCM; | ||||
|         hdr.channelCount = _channels; | ||||
|         hdr.sampleRate = _samplerate; | ||||
|         hdr.bitDepth = SAMP_BITS[_type]; | ||||
|         hdr.bytesPerSample = bytesPerSamp; | ||||
|         hdr.bytesPerSecond = bytesPerSamp * _samplerate; | ||||
|  | ||||
|         // Precompute sizes and allocate buffers | ||||
|         // TODO: Get number of bits for each sample type | ||||
|         bytesPerSamp = (SAMP_BITS[_type] / 8) * _channels; // THIS IS WRONG | ||||
|         switch (_type) { | ||||
|         case SAMP_TYPE_UINT8: | ||||
|             bufU8 = dsp::buffer::alloc<uint8_t>(STREAM_BUFFER_SIZE * _channels); | ||||
| @@ -69,36 +68,37 @@ namespace wav { | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         // Open new file | ||||
|         file.open(path, std::ios::out | std::ios::binary); | ||||
|         if (!file.is_open()) { return false; } | ||||
|         // Open file | ||||
|         if (!rw.open(path, WAVE_FILE_TYPE)) { return false; } | ||||
|  | ||||
|         // Skip header, it'll be written when finalizing the file | ||||
|         uint8_t dummy[sizeof(Header)]; | ||||
|         memset(dummy, 0, sizeof(dummy)); | ||||
|         file.write((char*)dummy, sizeof(dummy)); | ||||
|         // Write format chunk | ||||
|         rw.beginChunk(FORMAT_MARKER); | ||||
|         rw.write((uint8_t*)&hdr, sizeof(FormatHeader)); | ||||
|         rw.endChunk(); | ||||
|  | ||||
|         _isOpen = true; | ||||
|         // Begin data chunk | ||||
|         rw.beginChunk(DATA_MARKER); | ||||
|          | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool Writer::isOpen() { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|         return _isOpen; | ||||
|         return rw.isOpen(); | ||||
|     } | ||||
|  | ||||
|     void Writer::close() { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|         // Do nothing if the file is not open | ||||
|         if (!_isOpen) { return; } | ||||
|         if (!rw.isOpen()) { return; } | ||||
|  | ||||
|         // Finilize wav | ||||
|         finalize(); | ||||
|         // Finish data chunk | ||||
|         rw.endChunk(); | ||||
|  | ||||
|         // Close the file | ||||
|         file.close(); | ||||
|         rw.close(); | ||||
|  | ||||
|         // Destroy buffers | ||||
|         // Free buffers | ||||
|         if (bufU8) { | ||||
|             dsp::buffer::free(bufU8); | ||||
|             bufU8 = NULL; | ||||
| @@ -111,15 +111,12 @@ namespace wav { | ||||
|             dsp::buffer::free(bufI32); | ||||
|             bufI32 = NULL; | ||||
|         } | ||||
|  | ||||
|         // Mark as closed | ||||
|         _isOpen = false; | ||||
|     } | ||||
|  | ||||
|     void Writer::setChannels(int channels) { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|         // Do not allow settings to change while open | ||||
|         if (_isOpen) { throw std::runtime_error("Cannot change parameters while file is open"); } | ||||
|         if (rw.isOpen()) { throw std::runtime_error("Cannot change parameters while file is open"); } | ||||
|  | ||||
|         // Validate channel count | ||||
|         if (channels < 1) { throw std::runtime_error("Channel count must be greater or equal to 1"); } | ||||
| @@ -129,7 +126,7 @@ namespace wav { | ||||
|     void Writer::setSamplerate(uint64_t samplerate) { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|         // Do not allow settings to change while open | ||||
|         if (_isOpen) { throw std::runtime_error("Cannot change parameters while file is open"); } | ||||
|         if (rw.isOpen()) { throw std::runtime_error("Cannot change parameters while file is open"); } | ||||
|  | ||||
|         // Validate samplerate | ||||
|         if (!samplerate) { throw std::runtime_error("Samplerate must be non-zero"); } | ||||
| @@ -138,42 +135,42 @@ namespace wav { | ||||
|     void Writer::setFormat(Format format) { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|         // Do not allow settings to change while open | ||||
|         if (_isOpen) { throw std::runtime_error("Cannot change parameters while file is open"); } | ||||
|         if (rw.isOpen()) { throw std::runtime_error("Cannot change parameters while file is open"); } | ||||
|         _format = format; | ||||
|     } | ||||
|  | ||||
|     void Writer::setSampleType(SampleType type) { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|         // Do not allow settings to change while open | ||||
|         if (_isOpen) { throw std::runtime_error("Cannot change parameters while file is open"); } | ||||
|         if (rw.isOpen()) { throw std::runtime_error("Cannot change parameters while file is open"); } | ||||
|         _type = type; | ||||
|     } | ||||
|  | ||||
|     void Writer::write(float* samples, int count) { | ||||
|         std::lock_guard<std::recursive_mutex> lck(mtx); | ||||
|         if (!_isOpen) { return; } | ||||
|         if (!rw.isOpen()) { return; } | ||||
|          | ||||
|         // Select different writer function depending on the chose depth | ||||
|         int tcount; | ||||
|         int tcount = count * _channels; | ||||
|         int tbytes = count * bytesPerSamp; | ||||
|         switch (_type) { | ||||
|         case SAMP_TYPE_UINT8: | ||||
|             tcount = count * _channels; | ||||
|             // Volk doesn't support unsigned ints :/ | ||||
|             // Volk doesn't support unsigned ints yet :/ | ||||
|             for (int i = 0; i < tcount; i++) { | ||||
|                 bufU8[i] = (samples[i] * 127.0f) + 128.0f; | ||||
|             } | ||||
|             file.write((char*)bufU8, count * bytesPerSamp); | ||||
|             rw.write(bufU8, tbytes); | ||||
|             break; | ||||
|         case SAMP_TYPE_INT16: | ||||
|             volk_32f_s32f_convert_16i(bufI16, samples, 32767.0f, count * _channels); | ||||
|             file.write((char*)bufI16, count * bytesPerSamp); | ||||
|             volk_32f_s32f_convert_16i(bufI16, samples, 32767.0f, tcount); | ||||
|             rw.write((uint8_t*)bufI16, tbytes); | ||||
|             break; | ||||
|         case SAMP_TYPE_INT32: | ||||
|             volk_32f_s32f_convert_32i(bufI32, samples, 2147483647.0f, count * _channels); | ||||
|             file.write((char*)bufI32, count * bytesPerSamp); | ||||
|             volk_32f_s32f_convert_32i(bufI32, samples, 2147483647.0f, tcount); | ||||
|             rw.write((uint8_t*)bufI32, tbytes); | ||||
|             break; | ||||
|         case SAMP_TYPE_FLOAT32: | ||||
|             file.write((char*)samples, count * bytesPerSamp); | ||||
|             rw.write((uint8_t*)samples, tbytes); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
| @@ -182,17 +179,4 @@ namespace wav { | ||||
|         // Increment sample counter | ||||
|         samplesWritten += count; | ||||
|     } | ||||
|  | ||||
|     void Writer::finalize() { | ||||
|         file.seekp(file.beg); | ||||
|         hdr.codec = (_type == SAMP_TYPE_FLOAT32) ? CODEC_FLOAT : CODEC_PCM; | ||||
|         hdr.channelCount = _channels; | ||||
|         hdr.sampleRate = _samplerate; | ||||
|         hdr.bitDepth = SAMP_BITS[_type]; | ||||
|         hdr.bytesPerSample = bytesPerSamp; | ||||
|         hdr.bytesPerSecond = bytesPerSamp * _samplerate; | ||||
|         hdr.dataSize = samplesWritten * bytesPerSamp; | ||||
|         hdr.fileSize = hdr.dataSize + sizeof(hdr) - 8; | ||||
|         file.write((char*)&hdr, sizeof(hdr)); | ||||
|     } | ||||
| } | ||||
| @@ -3,23 +3,17 @@ | ||||
| #include <fstream> | ||||
| #include <stdint.h> | ||||
| #include <mutex> | ||||
| #include "riff.h" | ||||
|  | ||||
| namespace wav {     | ||||
|     #pragma pack(push, 1) | ||||
|     struct Header { | ||||
|         char signature[4];              // "RIFF" | ||||
|         uint32_t fileSize;              // data bytes + sizeof(WavHeader_t) - 8 | ||||
|         char fileType[4];               // "WAVE" | ||||
|         char formatMarker[4];           // "fmt " | ||||
|         uint32_t formatHeaderLength;    // Always 16 | ||||
|         uint16_t codec;                 // PCM (1) | ||||
|     struct FormatHeader { | ||||
|         uint16_t codec; | ||||
|         uint16_t channelCount; | ||||
|         uint32_t sampleRate; | ||||
|         uint32_t bytesPerSecond; | ||||
|         uint16_t bytesPerSample; | ||||
|         uint16_t bitDepth; | ||||
|         char dataMarker[4];             // "data" | ||||
|         uint32_t dataSize; | ||||
|     }; | ||||
|     #pragma pack(pop) | ||||
|  | ||||
| @@ -59,12 +53,9 @@ namespace wav { | ||||
|         void write(float* samples, int count); | ||||
|  | ||||
|     private: | ||||
|         void finalize(); | ||||
|          | ||||
|         std::recursive_mutex mtx; | ||||
|         std::ofstream file; | ||||
|         Header hdr; | ||||
|         bool _isOpen = false; | ||||
|         FormatHeader hdr; | ||||
|         riff::Writer rw; | ||||
|  | ||||
|         int _channels; | ||||
|         uint64_t _samplerate; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user