public static char[] Encode(int bitsPerChar, EncodeCallback encodeCallback, byte[] value) { Helper.CheckNull("value", value); Helper.CheckRange("value", value, 0, int.MaxValue / 8); return(Encode(bitsPerChar, encodeCallback, value, value.Length * 8)); }
public static char[] Encode(int bitsPerChar, EncodeCallback encodeCallback, byte[] value, int bitsToEncode) { Helper.CheckRange("bitsPerChar", bitsPerChar, 1, 8); Helper.CheckNull("encodeCallback", encodeCallback); Helper.CheckNull("value", value); Helper.CheckRange("bitsToEncode", bitsToEncode, 0, int.MaxValue - (bitsPerChar - 1)); char[] chars = new char[(bitsToEncode + bitsPerChar - 1) / bitsPerChar]; int i = 0, j = 0, bits = 0, buffer = 0; while (bitsToEncode > 0) { if (bits < 6 && i < value.Length) { bits += 8; buffer <<= 8; buffer |= value[i++]; } int chunk = Math.Min(bitsPerChar, Math.Min(bits, bitsToEncode)); bits -= chunk; bitsToEncode -= bitsPerChar; int pow2Bits = buffer >> bits; buffer ^= pow2Bits << bits; chars[j++] = encodeCallback(pow2Bits << (bitsPerChar - chunk)); } Debug.Assert(j == chars.Length); return(chars); }
public static char[] Encode(int bitsPerChar, EncodeCallback encodeCallback, byte[] value, int bitsToEncode) { Helper.CheckRange("bitsPerChar", bitsPerChar, 1, 8); Helper.CheckNull("encodeCallback", encodeCallback); Helper.CheckNull("value", value); Helper.CheckRange("bitsToEncode", bitsToEncode, 0, int.MaxValue - (bitsPerChar - 1)); char[] chars = new char[(bitsToEncode + bitsPerChar - 1)/bitsPerChar]; int i = 0, j = 0, bits = 0, buffer = 0; while (bitsToEncode > 0) { if (bits < 6 && i < value.Length) { bits += 8; buffer <<= 8; buffer |= value[i++]; } int chunk = Math.Min(bitsPerChar, Math.Min(bits, bitsToEncode)); bits -= chunk; bitsToEncode -= bitsPerChar; int pow2Bits = buffer >> bits; buffer ^= pow2Bits << bits; chars[j++] = encodeCallback(pow2Bits << (bitsPerChar - chunk)); } Debug.Assert(j == chars.Length); return chars; }
public static char[] Encode(int bitsPerChar, EncodeCallback encodeCallback, byte[] value) { Helper.CheckNull("value", value); Helper.CheckRange("value", value, 0, int.MaxValue/8); return Encode(bitsPerChar, encodeCallback, value, value.Length*8); }
private void GenerateAudio(List <string> sourceFiles, uint audioId, int bitRate, bool useVbr, string prefixLocation = null, EncodeCallback cbr = null) { int channels = 2; int samplingRate = 48000; List <uint> chapters = new List <uint>(); var outFormat = new WaveFormat(samplingRate, 2); if (cbr == null) { cbr = new EncodeCallback(); } OpusEncoder encoder = OpusEncoder.Create(48000, 2, OpusApplication.OPUS_APPLICATION_AUDIO); encoder.Bitrate = bitRate; encoder.UseVBR = useVbr; if (audioId == 0) { audioId = (uint)((DateTimeOffset)DateTime.UtcNow).ToUnixTimeSeconds(); } string tempName = Path.GetTempFileName(); using (Stream outputData = new FileStream(tempName, FileMode.OpenOrCreate)) { byte[] buffer = new byte[2880 * channels * 2]; OpusTags tags = new OpusTags(); tags.Comment = "Lavf56.40.101"; tags.Fields["encoder"] = "opusenc from opus-tools 0.1.9"; tags.Fields["encoder_options"] = "--quiet --bitrate 96 --vbr"; tags.Fields["pad"] = new string('0', 0x138); OpusOggWriteStream oggOut = new OpusOggWriteStream(encoder, outputData, tags, samplingRate, (int)audioId); uint lastIndex = 0; int track = 0; bool warned = false; long maxSize = 0x77359400; foreach (var sourceFile in sourceFiles) { if ((outputData.Length + 0x1000) >= maxSize) { cbr.Warning("Close to 2 GiB, stopping"); break; } try { int bytesReturned = 1; int totalBytesRead = 0; track++; chapters.Add(lastIndex); int lastPct = 0; cbr.FileStart(track, sourceFile); /* prepend a audio file for e.g. chapter number */ if (prefixLocation != null) { string prefixFile = Path.Combine(prefixLocation, track.ToString("0000") + ".mp3"); if (!File.Exists(prefixFile)) { throw new FileNotFoundException("Missing prefix file '" + prefixFile + "'"); } try { var prefixStream = new Mp3FileReader(prefixFile); var prefixResampled = new MediaFoundationResampler(prefixStream, outFormat); while (true) { bytesReturned = prefixResampled.Read(buffer, 0, buffer.Length); if (bytesReturned <= 0) { break; } bool isEmpty = (buffer.Where(v => v != 0).Count() == 0); if (!isEmpty) { float[] sampleBuffer = ConvertToFloat(buffer, bytesReturned, channels); if ((outputData.Length + 0x1000 + sampleBuffer.Length) >= maxSize) { break; } oggOut.WriteSamples(sampleBuffer, 0, sampleBuffer.Length); } lastIndex = (uint)oggOut.PageCounter; } } catch (Exception ex) { throw new Exception("Failed processing prefix file '" + prefixFile + "'"); } } /* then the real audio file */ var stream = new Mp3FileReader(sourceFile); var streamResampled = new MediaFoundationResampler(stream, outFormat); while (true) { bytesReturned = streamResampled.Read(buffer, 0, buffer.Length); if (bytesReturned <= 0) { break; } totalBytesRead += bytesReturned; decimal progress = (decimal)stream.Position / stream.Length; if ((int)(progress * 20) != lastPct) { lastPct = (int)(progress * 20); cbr.Progress(progress); } bool isEmpty = (buffer.Where(v => v != 0).Count() == 0); if (!isEmpty) { float[] sampleBuffer = ConvertToFloat(buffer, bytesReturned, channels); oggOut.WriteSamples(sampleBuffer, 0, sampleBuffer.Length); } lastIndex = (uint)oggOut.PageCounter; } cbr.FileDone(); stream.Close(); } catch (OpusOggWriteStream.PaddingException e) { string msg = "Failed to pad opus data properly. Please try CBR with bitrates a multiple of 24 kbps"; cbr.Failed(msg); throw new EncodingException(msg); } catch (FileNotFoundException e) { cbr.Failed(e.Message); throw new FileNotFoundException(e.Message); } catch (InvalidDataException e) { string msg = "Failed processing " + sourceFile; cbr.Failed(msg); throw new Exception(msg); } catch (Exception e) { string msg = "Failed processing " + sourceFile; cbr.Failed(msg); throw new Exception(msg); } if (!warned && outputData.Length >= maxSize / 2) { cbr.Warning("Approaching 2 GiB, please reduce the bitrate"); warned = true; } } oggOut.Finish(); Header.AudioId = oggOut.LogicalStreamId; } Audio = File.ReadAllBytes(tempName); var prov = new SHA1CryptoServiceProvider(); Header.Hash = prov.ComputeHash(Audio); Header.AudioChapters = chapters.ToArray(); Header.AudioLength = Audio.Length; Header.Padding = new byte[0]; File.Delete(tempName); }
private void BuildFromFiles(List <string> sourceFiles, uint audioId, int bitRate, bool useVbr, string prefixLocation, EncodeCallback cbr) { GenerateAudio(sourceFiles, audioId, bitRate, useVbr, prefixLocation, cbr); FileContent = new byte[Audio.Length + 0x1000]; Array.Copy(Audio, 0, FileContent, 0x1000, Audio.Length); WriteHeader(); }
public TonieAudio(string[] sources, uint audioId, int bitRate = 96000, bool useVbr = false, string prefixLocation = null, EncodeCallback cbr = null) { BuildFileList(sources); BuildFromFiles(FileList, audioId, bitRate, useVbr, prefixLocation, cbr); }