1 /* Copyright (C) 2019, 2020 Olga Yakovleva <yakovleva.o.v@gmail.com> */ 2 3 /* This program is free software: you can redistribute it and/or modify */ 4 /* it under the terms of the GNU General Public License as published by */ 5 /* the Free Software Foundation, either version 2 of the License, or */ 6 /* (at your option) any later version. */ 7 8 /* This program is distributed in the hope that it will be useful, */ 9 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 10 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ 11 /* GNU General Public License for more details. */ 12 13 /* You should have received a copy of the GNU General Public License */ 14 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #include <iostream> 17 #include <stdint.h> 18 #include "core/io.hpp" 19 #include "file_playback_stream_impl.hpp" 20 21 namespace 22 { 23 const std::size_t unspec_count=0x7ffff000; 24 } 25 26 namespace RHVoice 27 { 28 namespace audio 29 { 30 file_playback_stream_impl::file_playback_stream_impl(const playback_params& params): 31 file_path(params.device), 32 piping(file_path=="-"), 33 stream(piping?std::cout:fstream), 34 header_written(false), 35 num_samples(0) 36 { 37 } 38 39 void file_playback_stream_impl::write(const short* samples,std::size_t count) 40 { 41 stream.write(reinterpret_cast<const char*>(samples),count*sizeof(short)); 42 if(!stream) 43 throw playback_error(); 44 num_samples+=count; 45 } 46 47 void file_playback_stream_impl::open(uint32_t sample_rate) 48 { 49 if(!piping) 50 io::open_ofstream(fstream,file_path,true); 51 stream.write("RIFF",4); 52 write_number<uint32_t>(unspec_count+36); 53 stream.write("WAVE",4); 54 stream.write("fmt ",4); 55 write_number<uint32_t>(16); 56 write_number<uint16_t>(1); 57 write_number<uint16_t>(1); 58 write_number<uint32_t>(sample_rate); 59 write_number<uint32_t>(sample_rate*2); 60 write_number<uint16_t>(2); 61 write_number<uint16_t>(16); 62 stream.write("data",4); 63 write_number<uint32_t>(unspec_count); 64 if(!stream) 65 throw opening_error(); 66 header_written=true; 67 } 68 69 bool file_playback_stream_impl::is_open() const 70 { 71 return header_written; 72 } 73 74 void file_playback_stream_impl::close() 75 { 76 if(piping) 77 return; 78 if(!is_open()) 79 return; 80 stream.seekp(4); 81 std::size_t count=num_samples*sizeof(short); 82 write_number<uint32_t>(count+36); 83 stream.seekp(40); 84 write_number<uint32_t>(count); 85 num_samples=0; 86 fstream.close(); 87 } 88 } 89 } 90 91