1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <endian.h>
8 #include <zircon/compiler.h>
9 #include <zircon/types.h>
10 
11 namespace internal {
make_fourcc(uint8_t a,uint8_t b,uint8_t c,uint8_t d)12 static inline constexpr uint32_t make_fourcc(uint8_t a, uint8_t b,
13                                              uint8_t c, uint8_t d) {
14   return (static_cast<uint32_t>(d) << 24) |
15          (static_cast<uint32_t>(c) << 16) |
16          (static_cast<uint32_t>(b) << 8)  |
17           static_cast<uint32_t>(a);
18 }
19 }
20 
21 class WAVCommon {
22 public:
WAVCommon()23     WAVCommon() { }
~WAVCommon()24     virtual ~WAVCommon() { Close(); }
25 
26 protected:
27     struct __PACKED RIFFChunkHeader {
28         uint32_t  four_cc;
29         uint32_t  length;
30 
FixupEndianRIFFChunkHeader31         void FixupEndian() {
32             four_cc = htole32(four_cc);
33             length  = htole32(length);
34         }
35     };
36 
37     struct __PACKED WAVHeader {
38         uint32_t  wave_four_cc;
39         uint32_t  fmt_four_cc;
40         uint32_t  fmt_chunk_len;
41         uint16_t  format;
42         uint16_t  channel_count;
43         uint32_t  frame_rate;
44         uint32_t  average_byte_rate;
45         uint16_t  frame_size;
46         uint16_t  bits_per_sample;
47 
FixupEndianWAVHeader48         void FixupEndian() {
49             wave_four_cc      = htole32(wave_four_cc);
50             fmt_four_cc       = htole32(fmt_four_cc);
51             fmt_chunk_len     = htole32(fmt_chunk_len);
52             format            = htole16(format);
53             channel_count     = htole16(channel_count);
54             frame_rate        = htole32(frame_rate);
55             average_byte_rate = htole32(average_byte_rate);
56             frame_size        = htole16(frame_size);
57             bits_per_sample   = htole16(bits_per_sample);
58         }
59     };
60 
61     enum class InitMode { SOURCE, SINK };
62     zx_status_t Initialize(const char* filename, InitMode mode);
63 
64     static constexpr uint32_t RIFF_FOUR_CC = internal::make_fourcc('R', 'I', 'F', 'F');
65     static constexpr uint32_t WAVE_FOUR_CC = internal::make_fourcc('W', 'A', 'V', 'E');
66     static constexpr uint32_t FMT_FOUR_CC  = internal::make_fourcc('f', 'm', 't', ' ');
67     static constexpr uint32_t DATA_FOUR_CC = internal::make_fourcc('d', 'a', 't', 'a');
68 
69     // WAV/AVI format codes are defined in RFC 2361.  Also, the list goes on for
70     // 55 pages, so we don't list the vast majority of them here.
71     static constexpr uint16_t FORMAT_UNKNOWN    = 0x0000;
72     static constexpr uint16_t FORMAT_LPCM       = 0x0001;
73     static constexpr uint16_t FORMAT_MSFT_ADPCM = 0x0002;
74     static constexpr uint16_t FORMAT_IEEE_FLOAT = 0x0003;
75     static constexpr uint16_t FORMAT_MSFT_ALAW  = 0x0006;
76     static constexpr uint16_t FORMAT_MSFT_MULAW = 0x0007;
77 
78     void Close();
79     zx_status_t Read(void* buf, size_t len);
80     zx_status_t Write(const void* buf, size_t len);
81     zx_status_t Seek(off_t abs_pos);
82 
83     int fd_ = -1;
84 };
85 
86