Ejemplo n.º 1
0
 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));
 }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        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;
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
 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();
 }
Ejemplo n.º 7
0
 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);
 }