summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/flac.h
blob: 20e3f1b93789eee69308054afb0c3b8301c36cd8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    flac.h

    FLAC compression wrappers

***************************************************************************/

#ifndef MAME_UTIL_FLAC_H
#define MAME_UTIL_FLAC_H

#pragma once

#include "osdcore.h"
#include "corefile.h"

#include <FLAC/all.h>


//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

// ======================> flac_encoder

class flac_encoder
{
public:
	// construction/destruction
	flac_encoder();
	flac_encoder(void *buffer, uint32_t buflength);
	flac_encoder(util::core_file &file);
	~flac_encoder();

	// configuration
	void set_sample_rate(uint32_t sample_rate) { m_sample_rate = sample_rate; }
	void set_num_channels(uint8_t num_channels) { m_channels = num_channels; }
	void set_block_size(uint32_t block_size) { m_block_size = block_size; }
	void set_strip_metadata(bool strip) { m_strip_metadata = strip; }

	// getters (valid after reset)
	FLAC__StreamEncoderState state() const { return FLAC__stream_encoder_get_state(m_encoder); }
	const char *state_string() const { return FLAC__stream_encoder_get_resolved_state_string(m_encoder); }

	// reset
	bool reset();
	bool reset(void *buffer, uint32_t buflength);
	bool reset(util::core_file &file);

	// encode a buffer
	bool encode_interleaved(const int16_t *samples, uint32_t samples_per_channel, bool swap_endian = false);
	bool encode(int16_t *const *samples, uint32_t samples_per_channel, bool swap_endian = false);

	// finish up
	uint32_t finish();

private:
	// internal helpers
	void init_common();
	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);
	FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame);

	// internal state
	FLAC__StreamEncoder *   m_encoder;              // actual encoder
	util::core_file *       m_file;                 // output file
	uint32_t                  m_compressed_offset;    // current offset with the compressed stream
	FLAC__byte *            m_compressed_start;     // start of compressed data
	uint32_t                  m_compressed_length;    // length of the compressed stream

	// parameters
	uint32_t                  m_sample_rate;          // sample rate
	uint8_t                   m_channels;             // number of channels
	uint32_t                  m_block_size;           // block size

	// header stripping
	bool                    m_strip_metadata;       // strip the metadata?
	uint32_t                  m_ignore_bytes;         // how many bytes to ignore when writing
	bool                    m_found_audio;          // have we hit the audio yet?
};


// ======================> flac_decoder

class flac_decoder
{
public:
	// construction/destruction
	flac_decoder();
	flac_decoder(const void *buffer, uint32_t length, const void *buffer2 = nullptr, uint32_t length2 = 0);
	flac_decoder(util::core_file &file);
	~flac_decoder();

	// getters (valid after reset)
	uint32_t sample_rate() const { return m_sample_rate; }
	uint8_t channels() const { return m_channels; }
	uint8_t bits_per_sample() const { return m_bits_per_sample; }
	uint32_t total_samples() const { return FLAC__stream_decoder_get_total_samples(m_decoder); }
	FLAC__StreamDecoderState state() const { return FLAC__stream_decoder_get_state(m_decoder); }
	const char *state_string() const { return FLAC__stream_decoder_get_resolved_state_string(m_decoder); }

	// reset
	bool reset();
	bool reset(const void *buffer, uint32_t length, const void *buffer2 = nullptr, uint32_t length2 = 0);
	bool reset(uint32_t sample_rate, uint8_t num_channels, uint32_t block_size, const void *buffer, uint32_t length);
	bool reset(util::core_file &file);

	// decode to a buffer; num_samples must be a multiple of the block size
	bool decode_interleaved(int16_t *samples, uint32_t num_samples, bool swap_endian = false);
	bool decode(int16_t **samples, uint32_t num_samples, bool swap_endian = false);

	// finish up
	uint32_t finish();

private:
	// internal helpers
	static FLAC__StreamDecoderReadStatus read_callback_static(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
	FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes);
	static void metadata_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
	static FLAC__StreamDecoderTellStatus tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
	static FLAC__StreamDecoderWriteStatus write_callback_static(const FLAC__StreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
	FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
	static void error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);

	// output state
	FLAC__StreamDecoder *   m_decoder;              // actual encoder
	util::core_file *       m_file;                 // output file
	uint32_t                m_sample_rate;          // decoded sample rate
	uint8_t                 m_channels;             // decoded number of channels
	uint8_t                 m_bits_per_sample;      // decoded bits per sample
	uint32_t                m_compressed_offset;    // current offset in compressed data
	const FLAC__byte *      m_compressed_start;     // start of compressed data
	uint32_t                m_compressed_length;    // length of compressed data
	const FLAC__byte *      m_compressed2_start;    // start of compressed data
	uint32_t                m_compressed2_length;   // length of compressed data
	int16_t *               m_uncompressed_start[8];// pointer to start of uncompressed data (up to 8 streams)
	uint32_t                m_uncompressed_offset;  // current position in uncompressed data
	uint32_t                m_uncompressed_length;  // length of uncompressed data
	bool                    m_uncompressed_swap;    // swap uncompressed sample data
	uint8_t                 m_custom_header[0x2a];  // custom header
};

#endif // MAME_UTIL_FLAC_H