1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     flac.h
6 
7     FLAC compression wrappers
8 
9 ***************************************************************************/
10 
11 #ifndef MAME_UTIL_FLAC_H
12 #define MAME_UTIL_FLAC_H
13 
14 #pragma once
15 
16 #include "osdcore.h"
17 #include "corefile.h"
18 
19 #include <FLAC/all.h>
20 
21 
22 //**************************************************************************
23 //  TYPE DEFINITIONS
24 //**************************************************************************
25 
26 // ======================> flac_encoder
27 
28 class flac_encoder
29 {
30 public:
31 	// construction/destruction
32 	flac_encoder();
33 	flac_encoder(void *buffer, uint32_t buflength);
34 	flac_encoder(util::core_file &file);
35 	~flac_encoder();
36 
37 	// configuration
set_sample_rate(uint32_t sample_rate)38 	void set_sample_rate(uint32_t sample_rate) { m_sample_rate = sample_rate; }
set_num_channels(uint8_t num_channels)39 	void set_num_channels(uint8_t num_channels) { m_channels = num_channels; }
set_block_size(uint32_t block_size)40 	void set_block_size(uint32_t block_size) { m_block_size = block_size; }
set_strip_metadata(bool strip)41 	void set_strip_metadata(bool strip) { m_strip_metadata = strip; }
42 
43 	// getters (valid after reset)
state()44 	FLAC__StreamEncoderState state() const { return FLAC__stream_encoder_get_state(m_encoder); }
state_string()45 	const char *state_string() const { return FLAC__stream_encoder_get_resolved_state_string(m_encoder); }
46 
47 	// reset
48 	bool reset();
49 	bool reset(void *buffer, uint32_t buflength);
50 	bool reset(util::core_file &file);
51 
52 	// encode a buffer
53 	bool encode_interleaved(const int16_t *samples, uint32_t samples_per_channel, bool swap_endian = false);
54 	bool encode(int16_t *const *samples, uint32_t samples_per_channel, bool swap_endian = false);
55 
56 	// finish up
57 	uint32_t finish();
58 
59 private:
60 	// internal helpers
61 	void init_common();
62 	static FLAC__StreamEncoderWriteStatus write_callback_static(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data);
63 	FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame);
64 
65 	// internal state
66 	FLAC__StreamEncoder *   m_encoder;              // actual encoder
67 	util::core_file *       m_file;                 // output file
68 	uint32_t                  m_compressed_offset;    // current offset with the compressed stream
69 	FLAC__byte *            m_compressed_start;     // start of compressed data
70 	uint32_t                  m_compressed_length;    // length of the compressed stream
71 
72 	// parameters
73 	uint32_t                  m_sample_rate;          // sample rate
74 	uint8_t                   m_channels;             // number of channels
75 	uint32_t                  m_block_size;           // block size
76 
77 	// header stripping
78 	bool                    m_strip_metadata;       // strip the metadata?
79 	uint32_t                  m_ignore_bytes;         // how many bytes to ignore when writing
80 	bool                    m_found_audio;          // have we hit the audio yet?
81 };
82 
83 
84 // ======================> flac_decoder
85 
86 class flac_decoder
87 {
88 public:
89 	// construction/destruction
90 	flac_decoder();
91 	flac_decoder(const void *buffer, uint32_t length, const void *buffer2 = nullptr, uint32_t length2 = 0);
92 	flac_decoder(util::core_file &file);
93 	~flac_decoder();
94 
95 	// getters (valid after reset)
sample_rate()96 	uint32_t sample_rate() const { return m_sample_rate; }
channels()97 	uint8_t channels() const { return m_channels; }
bits_per_sample()98 	uint8_t bits_per_sample() const { return m_bits_per_sample; }
total_samples()99 	uint32_t total_samples() const { return FLAC__stream_decoder_get_total_samples(m_decoder); }
state()100 	FLAC__StreamDecoderState state() const { return FLAC__stream_decoder_get_state(m_decoder); }
state_string()101 	const char *state_string() const { return FLAC__stream_decoder_get_resolved_state_string(m_decoder); }
102 
103 	// reset
104 	bool reset();
105 	bool reset(const void *buffer, uint32_t length, const void *buffer2 = nullptr, uint32_t length2 = 0);
106 	bool reset(uint32_t sample_rate, uint8_t num_channels, uint32_t block_size, const void *buffer, uint32_t length);
107 	bool reset(util::core_file &file);
108 
109 	// decode to a buffer; num_samples must be a multiple of the block size
110 	bool decode_interleaved(int16_t *samples, uint32_t num_samples, bool swap_endian = false);
111 	bool decode(int16_t **samples, uint32_t num_samples, bool swap_endian = false);
112 
113 	// finish up
114 	uint32_t finish();
115 
116 private:
117 	// internal helpers
118 	static FLAC__StreamDecoderReadStatus read_callback_static(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
119 	FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes);
120 	static void metadata_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
121 	static FLAC__StreamDecoderTellStatus tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
122 	static FLAC__StreamDecoderWriteStatus write_callback_static(const FLAC__StreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
123 	FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
124 	static void error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
125 
126 	// output state
127 	FLAC__StreamDecoder *   m_decoder;              // actual encoder
128 	util::core_file *       m_file;                 // output file
129 	uint32_t                m_sample_rate;          // decoded sample rate
130 	uint8_t                 m_channels;             // decoded number of channels
131 	uint8_t                 m_bits_per_sample;      // decoded bits per sample
132 	uint32_t                m_compressed_offset;    // current offset in compressed data
133 	const FLAC__byte *      m_compressed_start;     // start of compressed data
134 	uint32_t                m_compressed_length;    // length of compressed data
135 	const FLAC__byte *      m_compressed2_start;    // start of compressed data
136 	uint32_t                m_compressed2_length;   // length of compressed data
137 	int16_t *               m_uncompressed_start[8];// pointer to start of uncompressed data (up to 8 streams)
138 	uint32_t                m_uncompressed_offset;  // current position in uncompressed data
139 	uint32_t                m_uncompressed_length;  // length of uncompressed data
140 	bool                    m_uncompressed_swap;    // swap uncompressed sample data
141 	uint8_t                 m_custom_header[0x2a];  // custom header
142 };
143 
144 #endif // MAME_UTIL_FLAC_H
145