public static bool IsFlacAvailable() { IntPtr context = IntPtr.Zero; try { context = LibFLAC.FLAC__stream_decoder_new(); return(context != IntPtr.Zero); } catch { return(false); } finally { if (context != IntPtr.Zero) { LibFLAC.FLAC__stream_decoder_finish(context); LibFLAC.FLAC__stream_decoder_delete(context); } } }
private void ParseFlac(string path) { // reference // https://github.com/tgsstdio/BirdNest.Audio/blob/c1474db37be323355f6415cdd9011bc7f2550689/NAudioFLAC/Library/FLACFileReader.cs var context = IntPtr.Zero; try { context = LibFLAC.FLAC__stream_decoder_new(); if (context == IntPtr.Zero) { throw new Exception("FLAC open failed"); } int[] w_buf = null; int sample_index = 0; LibFLAC.StreamDecoderWriteStatus Write(IntPtr _, IntPtr frame_ptr, IntPtr buffer_ptr, IntPtr __) { var frame = (LibFLAC.FlacFrame)Marshal.PtrToStructure(frame_ptr, typeof(LibFLAC.FlacFrame)); if (w_buf == null) { w_buf = new int[frame.Header.BlockSize * ChannelCount]; } for (var c = 0; c < ChannelCount; ++c) { var buf = Marshal.ReadIntPtr(buffer_ptr, c * IntPtr.Size); Marshal.Copy(buf, w_buf, c * frame.Header.BlockSize, frame.Header.BlockSize); } for (int i = 0; i < frame.Header.BlockSize; ++i) { for (int c = 0; c < ChannelCount; c++) { int sample = w_buf[i + c * frame.Header.BlockSize]; switch (BitsPerSample) { case 24: sample = sample >> 8; Samples[c][i + sample_index] = (short)sample; break; case 16: Samples[c][i + sample_index] = (short)sample; break; default: break; } } } sample_index += frame.Header.BlockSize; return(LibFLAC.StreamDecoderWriteStatus.WriteStatusContinue); } void Metadata(IntPtr _, IntPtr metadata_ptr, IntPtr __) { var metadata = (LibFLAC.FLACMetaData)Marshal.PtrToStructure(metadata_ptr, typeof(LibFLAC.FLACMetaData)); if (metadata.MetaDataType == LibFLAC.FLACMetaDataType.StreamInfo) { var stream_info_mem = GCHandle.Alloc(metadata.Data, GCHandleType.Pinned); try { var stream_info = (LibFLAC.FLACStreamInfo)Marshal.PtrToStructure(stream_info_mem.AddrOfPinnedObject(), typeof(LibFLAC.FLACStreamInfo)); Samples = new List <short[]>(); SampleRate = (uint)stream_info.SampleRate; var len = (long)(stream_info.TotalSamplesHi << 32) + stream_info.TotalSamplesLo; for (int c = 0; c < stream_info.Channels; ++c) { Samples.Add(new short[len]); } ChannelCount = (ushort)stream_info.Channels; BitsPerSample = (ushort)stream_info.BitsPerSample; BlockAlign = 4; AudioFormat = 1; } finally { stream_info_mem.Free(); } if (BitsPerSample != 16 && BitsPerSample != 24) { throw new Exception("FLAC currently support 16/24sbit only."); } } } void Error(IntPtr _, LibFLAC.DecodeError status, IntPtr __) { throw new Exception("FLAC decode error"); } var status_code = LibFLAC.FLAC__stream_decoder_init_file(context, path, Write, Metadata, Error, IntPtr.Zero); if (status_code != 0) { throw new Exception($"FLAC open error{status_code}"); } var result = LibFLAC.FLAC__stream_decoder_process_until_end_of_stream(context); if (!result) { throw new Exception($"FLAC decode process failed"); } } finally { LibFLAC.FLAC__stream_decoder_finish(context); LibFLAC.FLAC__stream_decoder_delete(context); } }