1 /*
2  * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
3  *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
4  *
5  * This file is part of lsp-plugins
6  * Created on: 6 нояб. 2018 г.
7  *
8  * lsp-plugins is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * any later version.
12  *
13  * lsp-plugins is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef CORE_FILES_LSPC_LSPCAUDIOREADER_H_
23 #define CORE_FILES_LSPC_LSPCAUDIOREADER_H_
24 
25 #include <core/files/lspc/lspc.h>
26 #include <core/files/LSPCFile.h>
27 
28 namespace lsp
29 {
30     /**
31      * This is helper class for reading audio content from LSPC files.
32      */
33     class LSPCAudioReader
34     {
35         private:
36             LSPCAudioReader & operator = (const LSPCAudioReader &);
37 
38         private:
39             enum flags_t
40             {
41                 F_OPENED        = 1 << 0,
42                 F_CLOSE_READER  = 1 << 1,
43                 F_CLOSE_FILE    = 1 << 2,
44                 F_REV_BYTES     = 1 << 3,
45                 F_DROP_READER   = 1 << 4
46             };
47 
48             typedef struct buffer_t
49             {
50                 uint8_t                    *vData;      // Pointer to the data
51                 size_t                      nSize;      // Size of data stored in buffer
52                 size_t                      nOff;       // Offset to the beginning of non-read data
53             } buffer_t;
54 
55             typedef void (*decode_func_t)(float *vp, const void *src, size_t ns);
56 
57         private:
58             lspc_audio_parameters_t     sParams;
59             LSPCFile                   *pFD;
60             LSPCChunkReader            *pRD;
61             size_t                      nFlags;
62             size_t                      nBPS;           // Bytes per sample
63             size_t                      nFrameSize;     // Size of frame
64             size_t                      nBytesLeft;
65             buffer_t                    sBuf;
66             decode_func_t               pDecode;
67             float                      *pFBuffer;       // frame buffer
68 
69         protected:
70             static void     decode_u8(float *vp, const void *src, size_t ns);
71             static void     decode_s8(float *vp, const void *src, size_t ns);
72             static void     decode_u16(float *vp, const void *src, size_t ns);
73             static void     decode_s16(float *vp, const void *src, size_t ns);
74             static void     decode_u24le(float *vp, const void *src, size_t ns);
75             static void     decode_u24be(float *vp, const void *src, size_t ns);
76             static void     decode_s24le(float *vp, const void *src, size_t ns);
77             static void     decode_s24be(float *vp, const void *src, size_t ns);
78             static void     decode_u32(float *vp, const void *src, size_t ns);
79             static void     decode_s32(float *vp, const void *src, size_t ns);
80             static void     decode_f32(float *vp, const void *src, size_t ns);
81             static void     decode_f64(float *vp, const void *src, size_t ns);
82 
83         protected:
84             status_t    read_audio_header(LSPCChunkReader *rd);
85             status_t    apply_params(const lspc_audio_parameters_t *p);
86             status_t    fill_buffer();
87 
88         public:
89             explicit LSPCAudioReader();
90             ~LSPCAudioReader();
91 
92         public:
93             /**
94              * Find first audio chunk and open it for reading
95              * @param lspc opened LSPC file
96              * @param auto_close automatically close reader on close()
97              * @return status of operation
98              */
99             status_t open(LSPCFile *lspc, bool auto_close = false);
100 
101             /**
102              * Find audio chunk by ID and read it
103              * @param lspc opened LSPC file
104              * @param uid unique chunk identifier
105              * @param auto_close automatically close reader on close()
106              * @return status of operation
107              */
108             status_t open(LSPCFile *lspc, uint32_t uid, bool auto_close = false);
109 
110             /**
111              * Find first audio chunk by magic and open it as audio stream with specified parameters
112              * @param lspc opened LSPC file
113              * @param magic chunk magic identifier
114              * @param params audio parameters
115              * @param auto_close automatically close reader on close()
116              * @return status of operation
117              */
118             status_t open_raw_magic(LSPCFile *lspc, const lspc_audio_parameters_t *params, uint32_t magic, bool auto_close = false);
119 
120             /**
121              * Open audio chunk by UID as audio stream with specified parameters
122              * @param lspc opened LSPC file
123              * @param uid unique chunk identifier
124              * @param params audio parameters
125              * @param auto_close automatically close reader on close()
126              * @return status of operation
127              */
128             status_t open_raw_uid(LSPCFile *lspc, const lspc_audio_parameters_t *params, uint32_t uid, bool auto_close = false);
129 
130             /**
131              * Open audio chunk as sub-stream of audio stream with specified parameters
132              * @param rd chunk reader
133              * @param params audio parameers
134              * @param auto_close automatically close reader on close()
135              * @return status of operation
136              */
137             status_t open_raw(LSPCChunkReader *rd, const lspc_audio_parameters_t *params, bool auto_close = false);
138 
139             /**
140              * Close audio reader
141              * @return status of operation
142              */
143             status_t close();
144 
145             /**
146              * Read sample data from chunk
147              *
148              * @param data array of pointers to store data, must match number of channels in the stream
149              * @param frames number of frames to read
150              * @return number of frames actually read or error code as a negative value (0 or STATUS_EOF if there is no data)
151              */
152             ssize_t read_samples(float **data, size_t frames);
153 
154             /**
155              * Read frames from chunk
156              * @param data buffer to store data
157              * @param frames number of frames to read
158              * @return actual number of frames read or error code as a negative value (0 or STATUS_EOF if there is no data)
159              */
160             ssize_t read_frames(float *data, size_t frames);
161 
162             /**
163              * Skip number of frames
164              * @param frames number of frames to skip
165              * @return number of frames actually skipped
166              */
167             ssize_t skip_frames(size_t frames);
168 
169             /**
170              * Obtain current audio parameters of the stream
171              * @param dst pointer to store audio parameters
172              * @return status of operation
173              */
174             status_t get_parameters(lspc_audio_parameters_t *dst) const;
175 
176             /**
177              * Get current chunk identifier
178              * @return current chunk identifier
179              */
180             uint32_t unique_id() const;
181 
182             /**
183              * Get current chunk magic
184              * @return current chunk magic
185              */
186             uint32_t magic() const;
187     };
188 
189 } /* namespace lsp */
190 
191 #endif /* CORE_FILES_LSPC_LSPCAUDIOREADER_H_ */
192