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
11namespace internal {
12static 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
21class WAVCommon {
22public:
23    WAVCommon() { }
24    virtual ~WAVCommon() { Close(); }
25
26protected:
27    struct __PACKED RIFFChunkHeader {
28        uint32_t  four_cc;
29        uint32_t  length;
30
31        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
48        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