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