Je crois que le plus simple reste encore de vous donner le code original, de cette façon vous serez peut-être en mesure d'identifier une erreur qui m'aurait échappée.
Voici "FLACFileReader.cs" :
Code:
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384 using System; using System.IO; using System.Collections.Generic; using System.Diagnostics; using NAudio.Wave; using System.Runtime.InteropServices; namespace NAudio.Wave { /// <summary> /// NAudio reader for FLAC files /// </summary> /// <remarks> /// Written By Yuval Naveh, based a .NET/C# Interop wrapper by Stanimir Stoyanov - http://stoyanoff.info/blog/2010/07/26/decoding-flac-audio-files-in-c/ /// using libFlac - http://flac.sourceforge.net /// </remarks> public class FLACFileReader : WaveStream { #region Constructors /// <summary>Constructor - Supports opening a FLAC file</summary> public FLACFileReader(string flacFileName) { Console.WriteLine("FLACFileReader: " + flacFileName); // Open the flac file for reading through a binary reader m_stream = File.OpenRead(flacFileName); m_reader = new BinaryReader(m_stream); // Create the FLAC decoder m_decoderContext = LibFLACSharp.FLAC__stream_decoder_new(); if (m_decoderContext == IntPtr.Zero) throw new ApplicationException("FLAC: Could not initialize stream decoder!"); // Create call back delegates m_writeCallback = new LibFLACSharp.Decoder_WriteCallback(FLAC_WriteCallback); m_metadataCallback = new LibFLACSharp.Decoder_MetadataCallback(FLAC_MetadataCallback); m_errorCallback = new LibFLACSharp.Decoder_ErrorCallback(FLAC_ErrorCallback); // Initialize the FLAC decoder if (LibFLACSharp.FLAC__stream_decoder_init_file(m_decoderContext, flacFileName, m_writeCallback, m_metadataCallback, m_errorCallback, IntPtr.Zero) != 0) throw new ApplicationException("FLAC: Could not open stream for reading!"); // Process the meta-data (but not the audio frames) so we can prepare the NAudio wave format FLACCheck( LibFLACSharp.FLAC__stream_decoder_process_until_end_of_metadata(m_decoderContext), "Could not process until end of metadata"); // Initialize NAudio wave format m_waveFormat = new WaveFormat(m_flacStreamInfo.SampleRate, m_flacStreamInfo.BitsPerSample, m_flacStreamInfo.Channels); Console.WriteLine("Total FLAC Samples: {0}", LibFLACSharp.FLAC__stream_decoder_get_total_samples(m_decoderContext)); } #endregion #region Overrides - Implement logic which is specific to FLAC /// <summary> /// This is the length in bytes of data available to be read out from the Read method /// (i.e. the decompressed FLAC length) /// n.b. this may return 0 for files whose length is unknown /// </summary> public override long Length { get { // Note: Workaround to fix NAudio calculation of position (which takes channels into account) and FLAC (which ignores channels for sample position) return (long)m_totalSamples * m_waveFormat.BlockAlign; } } /// <summary> /// <see cref="WaveStream.WaveFormat"/> /// </summary> public override WaveFormat WaveFormat { get { return m_waveFormat; } } /// <summary> /// <see cref="Stream.Position"/> /// </summary> public override long Position { get { long lastSampleNumber; lock (m_repositionLock) { // NOTE: FLAC__stream_decoder_get_decode_position() function returns byte index which is useless as it returns the position of the *uncompressed* decoded stream, not the compressed sample source position! // Instead the last sample number of frame from write_callback is being used // See also: http://comments.gmane.org/gmane.comp.audio.compression.flac.devel/2252 lastSampleNumber = m_lastSampleNumber; } // Note: Adjust FLAW raw sample number to NAudio position (which takes block align into account) return lastSampleNumber * m_waveFormat.BlockAlign; } set { lock (m_repositionLock) { m_flacSampleIndex = 0; // Note: Adjust NAudio position to FLAC sample number (which is raw and ignores takes block align) m_repositionRequested = true; m_flacReposition = value / (m_waveFormat.BlockAlign); m_lastSampleNumber = m_flacReposition; } } } /// <summary> /// Reads decompressed PCM data from our FLAC file into the NAudio playback sample buffer /// </summary> /// <remarks> /// 1. The original code did not stop on end of stream. tomislavtustonic applied a fix using FLAC__stream_decoder_get_state. <seealso cref="https://code.google.com/p/practicesharp/issues/detail?id=14"/> /// </remarks> public override int Read(byte[] playbackSampleBuffer, int offset, int numBytes) { int flacBytesCopied = 0; m_NAudioSampleBuffer = playbackSampleBuffer; m_playbackBufferOffset = offset; lock (m_repositionLock) { // If there are still samples in the flac buffer, use them first before reading the next FLAC frame if (m_flacSampleIndex > 0) { flacBytesCopied = CopyFlacBufferToNAudioBuffer(); } } var decoderState = LibFLACSharp.FLAC__stream_decoder_get_state(m_decoderContext); // Keep reading flac packets until enough bytes have been copied while (flacBytesCopied < numBytes) { // Read the next PCM bytes from the FLAC File into the sample buffer FLACCheck( LibFLACSharp.FLAC__stream_decoder_process_single(m_decoderContext), "process single"); decoderState = LibFLACSharp.FLAC__stream_decoder_get_state(m_decoderContext); if (decoderState == LibFLACSharp.StreamDecoderState.EndOfStream) break; else flacBytesCopied += CopyFlacBufferToNAudioBuffer(); } return flacBytesCopied; } #endregion #region Private Methods /// <summary> /// Helper utility function - Checks the result of a libFlac function by throwing an exception if the result was false /// </summary> /// <param name="result"></param> /// <param name="operation"></param> private void FLACCheck(bool result, string operation) { if (!result) throw new ApplicationException(string.Format("FLAC: Could not {0}!", operation)); } /// <summary> /// Copies the Flac buffer samples to the NAudio buffer /// This method is an "Adapter" between the two different buffers and is the key functionality /// that enables NAudio to play FLAC frames /// The Flac buffer has a different length and structure (i.e. all samples from channel 0, all samples from channel 1) /// than the NAudio samples buffer which has a interleaved structure (e.g sample 1 from channel 0, then sample 1 from channel 1 then sample 2 channel from Channel 1 etc.) /// </summary> /// <returns></returns> private int CopyFlacBufferToNAudioBuffer() { int startPlaybackBufferOffset = m_playbackBufferOffset; bool nAudioBufferFull = m_playbackBufferOffset >= m_NAudioSampleBuffer.Length; // For each channel, there are BlockSize number of samples, so let's process these. for (; m_flacSampleIndex < m_samplesPerChannel && !nAudioBufferFull; m_flacSampleIndex++) { for (int channel = 0; channel < m_flacStreamInfo.Channels && !nAudioBufferFull; channel++) { int sample = m_flacSamples[m_flacSampleIndex + channel * m_samplesPerChannel]; switch (m_flacStreamInfo.BitsPerSample) { case 16: // 16-bit m_NAudioSampleBuffer[m_playbackBufferOffset++] = (byte)(sample); m_NAudioSampleBuffer[m_playbackBufferOffset++] = (byte)(sample >> 8); nAudioBufferFull = m_playbackBufferOffset >= m_NAudioSampleBuffer.Length; break; case 24: // 24-bit // Note: Code contributed by Mathew1800, https://code.google.com/p/practicesharp/issues/detail?id=16#c2 m_NAudioSampleBuffer[m_playbackBufferOffset++] = (byte)((sample >> 0) & 0xFF); m_NAudioSampleBuffer[m_playbackBufferOffset++] = (byte)((sample >> 8) & 0xFF); m_NAudioSampleBuffer[m_playbackBufferOffset++] = (byte)((sample >> 16) & 0xFF); nAudioBufferFull = m_playbackBufferOffset >= m_NAudioSampleBuffer.Length; break; default: throw new NotSupportedException("Input FLAC bit depth is not supported!"); } } } // Flac buffer has been exhausted, reset the buffer sample index so it starts from the beginning if (m_flacSampleIndex >= m_samplesPerChannel) { m_flacSampleIndex = 0; } // Return number of actual bytes copied int bytesCopied = m_playbackBufferOffset - startPlaybackBufferOffset; return bytesCopied; } #endregion #region libFlac Callbacks /// <summary> /// FLAC Write Call Back - libFlac notifies back on a frame that was read from the source file and written as a frame /// </summary> /// <param name="context"></param> /// <param name="frame"></param> /// <param name="buffer"></param> /// <param name="clientData"></param> private void FLAC_WriteCallback(IntPtr context, IntPtr frame, IntPtr buffer, IntPtr clientData) { // Read the FLAC Frame into a memory samples buffer (m_flacSamples) LibFLACSharp.FlacFrame flacFrame = (LibFLACSharp.FlacFrame)Marshal.PtrToStructure(frame, typeof(LibFLACSharp.FlacFrame)); if (m_flacSamples == null) { // First time - Create Flac sample buffer m_samplesPerChannel = flacFrame.Header.BlockSize; m_flacSamples = new int[m_samplesPerChannel * m_flacStreamInfo.Channels]; m_flacSampleIndex = 0; } // Iterate on all channels, copy the unmanaged channel bits (samples) to the a managed samples array for (int inputChannel = 0; inputChannel < m_flacStreamInfo.Channels; inputChannel++) { // Get pointer to channel bits, for the current channel IntPtr pChannelBits = Marshal.ReadIntPtr(buffer, inputChannel * IntPtr.Size); // Copy the unmanaged bits to managed memory Marshal.Copy(pChannelBits, m_flacSamples, inputChannel * m_samplesPerChannel, m_samplesPerChannel); } lock (m_repositionLock) { // Keep the current sample number for reporting purposes (See: Position property of FlacFileReader) m_lastSampleNumber = flacFrame.Header.FrameOrSampleNumber; if (m_repositionRequested) { m_repositionRequested = false; FLACCheck(LibFLACSharp.FLAC__stream_decoder_seek_absolute(m_decoderContext, m_flacReposition), "Could not seek absolute: " + m_flacReposition); } } } /// <summary> /// FLAC Meta Call Back - libFlac notifies about one (or more) Meta frames. /// Note that there could be many types of Meta Frames but by default only the StreamInfo meta frame is returned /// </summary> /// <param name="context"></param> /// <param name="metadata"></param> /// <param name="userData"></param> private void FLAC_MetadataCallback(IntPtr context, IntPtr metadata, IntPtr userData) { LibFLACSharp.FLACMetaData flacMetaData = (LibFLACSharp.FLACMetaData)Marshal.PtrToStructure(metadata, typeof(LibFLACSharp.FLACMetaData)); if (flacMetaData.MetaDataType == LibFLACSharp.FLACMetaDataType.StreamInfo) { GCHandle pinnedStreamInfo = GCHandle.Alloc(flacMetaData.Data, GCHandleType.Pinned); try { m_flacStreamInfo = (LibFLACSharp.FLACStreamInfo)Marshal.PtrToStructure( pinnedStreamInfo.AddrOfPinnedObject(), typeof(LibFLACSharp.FLACStreamInfo)); m_totalSamples = (long)(m_flacStreamInfo.TotalSamplesHi << 32) + (long)m_flacStreamInfo.TotalSamplesLo; } finally { pinnedStreamInfo.Free(); } } } /// <summary> /// FLAC Error Call Back - libFlac notifies about a decoding error /// </summary> /// <param name="context"></param> /// <param name="status"></param> /// <param name="userData"></param> private void FLAC_ErrorCallback(IntPtr context, LibFLACSharp.DecodeError status, IntPtr userData) { throw new ApplicationException(string.Format("FLAC: Could not decode frame: {0}!", status)); } #endregion #region Dispose /// <summary> /// Disposes this WaveStream /// </summary> protected override void Dispose(bool disposing) { if (disposing) { if (m_decoderContext != IntPtr.Zero) { FLACCheck( LibFLACSharp.FLAC__stream_decoder_finish(m_decoderContext), "finalize stream decoder"); FLACCheck( LibFLACSharp.FLAC__stream_decoder_delete(m_decoderContext), "dispose of stream decoder instance"); m_decoderContext = IntPtr.Zero; } if (m_stream != null) { m_stream.Close(); m_stream.Dispose(); m_stream = null; } if (m_reader != null) { m_reader.Close(); m_reader = null; } } base.Dispose(disposing); } #endregion #region Private Members private WaveFormat m_waveFormat; private object m_repositionLock = new object(); private IntPtr m_decoderContext; private Stream m_stream; private BinaryReader m_reader; private LibFLACSharp.FLACStreamInfo m_flacStreamInfo; private int m_samplesPerChannel; private long m_totalSamples = 0; private long m_lastSampleNumber = 0; private int[] m_flacSamples; private int m_flacSampleIndex; private byte[] m_NAudioSampleBuffer; private int m_playbackBufferOffset; private bool m_repositionRequested = false; private long m_flacReposition = 0; private LibFLACSharp.Decoder_WriteCallback m_writeCallback; private LibFLACSharp.Decoder_MetadataCallback m_metadataCallback; private LibFLACSharp.Decoder_ErrorCallback m_errorCallback; #endregion } }
Et "LibFLACSharp.cs" :
Code:
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271 using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace NAudio.Wave { /// <summary> /// C# (.NET) Wrapper for the libFlac library (Written in C++) /// </summary> /// <remarks> /// Based a .NET/C# Interop wrapper by Stanimir Stoyanov - /// http://stoyanoff.info/blog/2010/07/26/decoding-flac-audio-files-in-c/ /// and /// http://stoyanoff.info/blog/2010/01/08/encoding-uncompressed-audio-with-flac-in-c/ /// using libFlac - http://flac.sourceforge.net /// For a full description of libFlac Decoder API: http://flac.sourceforge.net/api/group__flac__stream__decoder.html /// For a full description of libFlac Encoder API: http://flac.sourceforge.net/api/group__flac__stream__encoder.html /// </remarks> public class LibFLACSharp { #region Constants const string DLLName = @"LibFlac.dll"; public enum StreamDecoderState { SearchForMetadata = 0, ReadMetadata, SearchForFrameSync, ReadFrame, EndOfStream, OggError, SeekError, Aborted, MemoryAllocationError, Uninitialized } #endregion #region Decoder API [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr FLAC__stream_decoder_new(); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_decoder_finish(IntPtr context); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_decoder_delete(IntPtr context); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern int FLAC__stream_decoder_init_file(IntPtr context, string filename, Decoder_WriteCallback write, Decoder_MetadataCallback metadata, Decoder_ErrorCallback error, IntPtr userData); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_decoder_process_single(IntPtr context); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_decoder_process_until_end_of_metadata(IntPtr context); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_decoder_process_until_end_of_stream(IntPtr context); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_decoder_seek_absolute(IntPtr context, long newSamplePosition); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_decoder_get_decode_position(IntPtr context, ref long position); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern long FLAC__stream_decoder_get_total_samples(IntPtr context); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern int FLAC__stream_decoder_get_channels(IntPtr context); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern int FLAC__stream_decoder_get_bits_per_sample(IntPtr context); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern int FLAC__stream_decoder_get_sample_rate(IntPtr context); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern StreamDecoderState FLAC__stream_decoder_get_state(IntPtr context); // Callbacks [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void Decoder_WriteCallback(IntPtr context, IntPtr frame, IntPtr buffer, IntPtr userData); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void Decoder_ErrorCallback(IntPtr context, DecodeError status, IntPtr userData); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void Decoder_MetadataCallback(IntPtr context, IntPtr metadata, IntPtr userData); private const int FlacMaxChannels = 8; public struct FlacFrame { public FrameHeader Header; [MarshalAs(UnmanagedType.ByValArray, SizeConst = FlacMaxChannels)] public FlacSubFrame[] Subframes; public FrameFooter Footer; } public struct FrameHeader { public int BlockSize; public int SampleRate; public int Channels; public int ChannelAssignment; public int BitsPerSample; public FrameNumberType NumberType; public long FrameOrSampleNumber; public byte Crc; } public struct FlacSubFrame { public SubframeType Type; public IntPtr Data; public int WastedBits; } public struct FrameFooter { public ushort Crc; } public enum FrameNumberType { Frame, Sample } public enum SubframeType { Constant, Verbatim, Fixed, LPC } public enum DecodeError { LostSync, BadHeader, FrameCrcMismatch, UnparsableStream } public enum FLACMetaDataType { StreamInfo, Padding, Application, Seekable, VorbisComment, CueSheet, Picture, Undefined } public struct FLACMetaData { // The type of the metadata block; used determine which member of the data union to dereference. If type >= FLAC__METADATA_TYPE_UNDEFINED then data.unknown must be used. public FLACMetaDataType MetaDataType; // true if this metadata block is the last, else false public bool IsLast; // Length, in bytes, of the block data as it appears in the stream. public int Length; // Polymorphic block data; use the type value to determine which to use. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)] public byte[] Data; } [StructLayout(LayoutKind.Explicit,Pack = 1,Size = 40)] public struct FLACStreamInfo { // Note Offsets 0..3 are the byte array length (header) - we just ingore these bytes and start with Offset 4 [FieldOffset(4)] public Int32 MinBlocksize; [FieldOffset(8)] public Int32 MaxBlocksize; [FieldOffset(12)] public Int32 min_framesize; [FieldOffset(16)] public Int32 max_framesize; [FieldOffset(20)] public Int32 SampleRate; [FieldOffset(24)] public Int32 Channels; [FieldOffset(28)] public Int32 BitsPerSample; [FieldOffset(32)] public Int32 TotalSamplesHi; [FieldOffset(36)] public Int32 TotalSamplesLo; // [FieldOffset(40)] // public byte[] md5sum; } #endregion #region Encoder API [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr FLAC__stream_encoder_new(); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_encoder_finish(IntPtr context); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_encoder_delete(IntPtr context); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_encoder_set_channels(IntPtr context, int value); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_encoder_set_bits_per_sample(IntPtr context, int value); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_encoder_set_sample_rate(IntPtr context, int value); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_encoder_set_compression_level(IntPtr context, int value); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_encoder_set_blocksize(IntPtr context, int value); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern int FLAC__stream_encoder_init_stream(IntPtr context, Encoder_WriteCallback write, Encoder_SeekCallback seek, Encoder_TellCallback tell, Encoder_MetadataCallback metadata, IntPtr userData); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern int FLAC__stream_encoder_init_file(IntPtr context, string filename, IntPtr progress, IntPtr userData); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_encoder_process_interleaved(IntPtr context, IntPtr buffer, int samples); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_encoder_process(IntPtr context, IntPtr buffer, int samples); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_encoder_set_verify(IntPtr context, bool value); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_encoder_set_streamable_subset(IntPtr context, bool value); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_encoder_set_do_mid_side_stereo(IntPtr context, bool value); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern bool FLAC__stream_encoder_set_loose_mid_side_stereo(IntPtr context, bool value); [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl)] public static extern int FLAC__stream_encoder_get_state(IntPtr context); // Callbacks [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int Encoder_WriteCallback(IntPtr context, IntPtr buffer, int bytes, uint samples, uint current_frame, IntPtr userData); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int Encoder_SeekCallback(IntPtr context, long absoluteOffset, IntPtr userData); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int Encoder_TellCallback(IntPtr context, out long absoluteOffset, IntPtr userData); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void Encoder_MetadataCallback(IntPtr context, IntPtr metadata, IntPtr userData); #endregion } }