• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 3-Clause Clear License
5  * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6  * License was not distributed with this source code in the LICENSE file, you
7  * can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
8  * Alliance for Open Media Patent License 1.0 was not distributed with this
9  * source code in the PATENTS file, you can obtain it at
10  * www.aomedia.org/license/patent.
11  */
12 
13 #ifndef CLI_WAV_WRITER_H_
14 #define CLI_WAV_WRITER_H_
15 
16 #include <cstddef>
17 #include <cstdint>
18 #include <cstdio>
19 #include <memory>
20 #include <string>
21 #include <vector>
22 
23 #include "absl/functional/any_invocable.h"
24 #include "absl/status/status.h"
25 #include "absl/types/span.h"
26 #include "iamf/cli/sample_processor_base.h"
27 
28 namespace iamf_tools {
29 
30 /*!\brief Write samples to a wav (or pcm) file, then consumes the samples. */
31 class WavWriter : public SampleProcessorBase {
32  public:
33   /*!\brief Factory function to create a `WavWriter`.
34    *
35    * Creates a `WavWriter` that can be used to write a wav file without knowing
36    * the number of samples in advance.
37    *
38    * \param wav_filename Path of the file to write to.
39    * \param num_channels Number of channels in the wav file.
40    * \param sample_rate_hz Sample rate of the wav file in Hz.
41    * \param bit_depth Bit-depth of the wav file, must be 16, 24, or 32.
42    * \param num_samples_per_frame Number of samples per frame. Subsequent writes
43    *        must use at most this number of samples.
44    * \param write_header If true, the wav header is written.
45    * \return Unique pointer to `WavWriter` on success. `nullptr` otherwise.
46    */
47   static std::unique_ptr<WavWriter> Create(const std::string& wav_filename,
48                                            int num_channels, int sample_rate_hz,
49                                            int bit_depth,
50                                            size_t num_samples_per_frame,
51                                            bool write_header = true);
52 
53   /*!\brief Finalizes the wav header and closes the underlying file.*/
54   ~WavWriter();
55 
56   /*!\brief Returns the bit-depth.*/
bit_depth()57   int bit_depth() const { return bit_depth_; }
58 
59   /*!\brief Writes samples to the wav file.
60    *
61    * There must be an integer number of samples and the number of samples %
62    * `num_channels()` must equal 0. The number of samples is implicitly
63    * calculated by `buffer.size()` / (bit_depth / 8).
64    *
65    * \param buffer Buffer of raw input PCM with channels interlaced and no
66    *        padding.
67    * \return `absl::OkStatus()` on success. A specific status on failure.
68    */
69   [[deprecated("Use `SampleProcessorBase::PushFrame` instead.")]]
70   absl::Status WritePcmSamples(const std::vector<uint8_t>& buffer);
71 
72   /*!\brief Aborts the write process and deletes the wav file.*/
73   void Abort();
74 
75  private:
76   typedef absl::AnyInvocable<int(FILE*, size_t, int, int)> WavHeaderWriter;
77 
78   /*!\brief Private Constructor. Used only by the factory function.
79    *
80    * \param filename_to_remove Path of the file; used to clean up the output
81    *        file when aborting.
82    * \param num_channels Number of channels in the wav file, must be 1 or 2.
83    * \param sample_rate_hz Sample rate of the wav file in Hz.
84    *  \param num_samples_per_frame Number of samples per frame. Subsequent
85    *         writes must use at most this number of samples.
86    * \param bit_depth Bit-depth of the wav file, must be 16, 24, or 32.
87    * \param file Pointer to the file to write to.
88    * \param wav_header_writer Function that writes the header if non-empty.
89    */
90   WavWriter(const std::string& filename_to_remove, int num_channels,
91             int sample_rate_hz, int bit_depth, size_t num_samples_per_frame,
92             FILE* file, WavHeaderWriter wav_header_writer);
93 
94   /*!\brief Writes samples to the wav file and consumes them.
95    *
96    * Since the samples are consumed, the
97    * `SampleProcessorBase::GetOutputSamplesAsSpan` method will always return an
98    * empty span.
99    *
100    * There must be the same number of samples for each channel.
101    *
102    * \param time_channel_samples Samples to push arranged in (time, channel).
103    * \return `absl::OkStatus()` on success. A specific status on failure.
104    */
105   absl::Status PushFrameDerived(
106       absl::Span<const std::vector<int32_t>> time_channel_samples) override;
107 
108   /*!\brief Signals that no more samples will be pushed.
109    *
110    * After calling `Flush()`, it is invalid to call `PushFrame()`
111    * or `Flush()` again.
112    *
113    * \return `absl::OkStatus()` on success. A specific status on failure.
114    */
115   absl::Status FlushDerived() override;
116 
117   const size_t sample_rate_hz_;
118   const size_t bit_depth_;
119   size_t total_samples_written_;
120   FILE* file_;
121   const std::string filename_to_remove_;
122   WavHeaderWriter wav_header_writer_;
123 };
124 }  // namespace iamf_tools
125 
126 #endif  // CLI_WAV_WRITER_H_
127