Пример #1
0
        public override string GetArguments(EncoderItem encoderItem, IBassStream stream)
        {
            var channelInfo = default(ChannelInfo);

            if (!Bass.ChannelGetInfo(stream.ChannelHandle, out channelInfo))
            {
                throw new NotImplementedException();
            }
            var length    = this.GetLength(encoderItem, stream);
            var arguments = string.Format(
                "--no-seektable --force-raw-format --endian=little --sign=signed --sample-rate={0} --channels={1} --bps={2} - --compression-level-{3} -o \"{4}\"",
                channelInfo.Frequency,
                channelInfo.Channels,
                this.GetDepth(encoderItem, stream),
                this.Compression,
                encoderItem.OutputFileName
                );

            if (this.IgnoreErrors)
            {
                arguments += " --decode-through-errors";
            }
            else
            {
                arguments += string.Format(
                    "--input-size={0}",
                    length
                    );
            }
            return(arguments);
        }
Пример #2
0
 protected virtual void EncodeWithResampler(EncoderItem encoderItem, IBassStream stream, IBassEncoderSettings settings)
 {
     using (var resamplerProcess = this.CreateResamplerProcess(encoderItem, stream, new SoxEncoderSettings(settings)))
     {
         using (var encoderProcess = this.CreateEncoderProcess(encoderItem, stream, settings))
         {
             var success = true;
             this.EncodeWithResampler(encoderItem, stream, resamplerProcess, encoderProcess);
             if (this.WaitForExit(resamplerProcess))
             {
                 if (resamplerProcess.ExitCode != 0)
                 {
                     success = false;
                 }
             }
             if (this.WaitForExit(encoderProcess))
             {
                 if (encoderProcess.ExitCode != 0)
                 {
                     success = false;
                 }
             }
             if (!success)
             {
                 throw new InvalidOperationException("Process does not indicate success.");
             }
         }
     }
 }
Пример #3
0
 public virtual int GetDepth(EncoderItem encoderItem, IBassStream stream)
 {
     if (this.Format.AutoDepth)
     {
         switch (encoderItem.BitsPerSample)
         {
         case DEPTH_16:
         case DEPTH_24:
         case DEPTH_32:
             Logger.Write(this, LogLevel.Debug, "Using meta data suggested bit depth for file \"{0}\": {1} bit", encoderItem.InputFileName, encoderItem.BitsPerSample);
             return(encoderItem.BitsPerSample);
         }
         var channelInfo = default(ChannelInfo);
         if (!Bass.ChannelGetInfo(stream.ChannelHandle, out channelInfo))
         {
             throw new NotImplementedException();
         }
         if (channelInfo.Flags.HasFlag(BassFlags.Float))
         {
             Logger.Write(this, LogLevel.Debug, "Using decoder bit depth for file \"{0}\": 32 bit", encoderItem.InputFileName);
             return(DEPTH_32);
         }
         else
         {
             Logger.Write(this, LogLevel.Debug, "Using decoder bit depth for file \"{0}\": 16 bit", encoderItem.InputFileName);
             return(DEPTH_16);
         }
     }
     Logger.Write(this, LogLevel.Debug, "Using user defined bit depth for file \"{0}\": {1} bit", encoderItem.InputFileName, this.Format.Depth);
     return(this.Format.Depth);
 }
Пример #4
0
        public override string GetArguments(EncoderItem encoderItem, IBassStream stream)
        {
            var channelInfo = default(ChannelInfo);

            if (!Bass.ChannelGetInfo(stream.ChannelHandle, out channelInfo))
            {
                throw new NotImplementedException();
            }
            var depth = this.Settings.GetDepth(encoderItem, stream);

            if (channelInfo.Flags.HasFlag(BassFlags.Float))
            {
                Logger.Write(this.GetType(), LogLevel.Debug, "Resampling file \"{0}\" from 32 bit float to {1} bit integer.", encoderItem.InputFileName, depth);
                return(string.Format(
                           "-t raw -e floating-point --bits 32 -r {0} -c {1} - -t raw -e signed-integer --bits {2} -r {0} -c {1} -",
                           channelInfo.Frequency,
                           channelInfo.Channels,
                           depth
                           ));
            }
            else
            {
                Logger.Write(this.GetType(), LogLevel.Debug, "Resampling file \"{0}\" from 16 bit integer to {1} bit integer.", encoderItem.InputFileName, depth);
                return(string.Format(
                           "-t raw -e signed-integer --bits 16 -r {0} -c {1} - -t raw -e signed-integer --bits {2} -r {0} -c {1} -",
                           channelInfo.Frequency,
                           channelInfo.Channels,
                           depth
                           ));
            }
        }
Пример #5
0
        public virtual long GetLength(EncoderItem encoderItem, IBassStream stream)
        {
            var source      = default(int);
            var channelInfo = default(ChannelInfo);
            var inputLength = stream.Length;

            if (!Bass.ChannelGetInfo(stream.ChannelHandle, out channelInfo))
            {
                throw new NotImplementedException();
            }
            if (channelInfo.Flags.HasFlag(BassFlags.Float))
            {
                source = DEPTH_32;
            }
            else
            {
                source = DEPTH_16;
            }
            var outputLength = (long)(inputLength / (source / (float)this.GetDepth(encoderItem, stream)));

            if (inputLength != outputLength)
            {
                Logger.Write(this, LogLevel.Debug, "Conversion requires change of data length: {0} bytes => {1} bytes.", inputLength, outputLength);
            }
            return(outputLength);
        }
Пример #6
0
 public override string GetArguments(EncoderItem encoderItem, IBassStream stream)
 {
     return(string.Format(
                "-i -q -y --raw-pcm={0} {1} -x{2} {3} - \"{4}\"",
                this.GetFormat(encoderItem, stream),
                this.GetCompression(),
                this.Processing,
                this.GetHybrid(),
                encoderItem.OutputFileName
                ));
 }
Пример #7
0
        protected virtual bool ScanTrack(ScannerItem scannerItem, IBassStream stream)
        {
            var info = default(ReplayGainInfo);

            if (!BassReplayGain.Process(stream.ChannelHandle, out info))
            {
                return(false);
            }
            scannerItem.ItemPeak = info.peak;
            scannerItem.ItemGain = info.gain;
            return(true);
        }
Пример #8
0
        protected virtual long GetLeadOut(IBassStream stream, int threshold)
        {
            Logger.Write(this, LogLevel.Debug, "Attempting to calculate lead out for channel {0} with window of {1} seconds and threshold of {2}dB.", stream.ChannelHandle, WINDOW, threshold);

            var length = Bass.ChannelSeconds2Bytes(
                stream.ChannelHandle,
                WINDOW
                );

            if (!this.TrySetPosition(stream, stream.Length - (length * 2)))
            {
                Logger.Write(this, LogLevel.Warn, "Failed to synchronize channel {0}, bad plugin? This is very expensive!", stream.ChannelHandle);

                //Track won't synchronize. MOD files seem to have this problem.
                return(-1);
            }
            do
            {
                var levels = new float[1];
                if (!Bass.ChannelGetLevel(stream.ChannelHandle, levels, WINDOW, LevelRetrievalFlags.Mono | LevelRetrievalFlags.RMS))
                {
                    Logger.Write(this, LogLevel.Warn, "Failed to get levels for channel {0}: {1}", stream.ChannelHandle, Enum.GetName(typeof(Errors), Bass.LastError));

                    break;
                }
                var dB = levels[0] > 0 ? 20 * Math.Log10(levels[0]) : -1000;
                if (dB > threshold)
                {
                    //TODO: Sometimes this value is less than zero so clamp it.
                    //TODO: Some problem with BASS/ManagedBass, if you have exactly N bytes available call Bass.ChannelGetLevel with Length = Bass.ChannelBytesToSeconds(N) sometimes results in Errors.Ended.
                    //TODO: Nuts.
                    var leadOut = Math.Max(stream.Length - stream.Position - length, 0);

                    if (leadOut > 0)
                    {
                        Logger.Write(this, LogLevel.Debug, "Successfully calculated lead out for channel {0}: {1} bytes.", stream.ChannelHandle, leadOut);
                    }
                    else
                    {
                        Logger.Write(this, LogLevel.Debug, "Successfully calculated lead out for channel {0}: None.", stream.ChannelHandle);
                    }

                    return(leadOut);
                }
                if (!this.TrySetPosition(stream, stream.Position - (length * 2)))
                {
                    break;
                }
            } while (true);
            //Track was silent?
            return(-1);
        }
Пример #9
0
 protected virtual void Encode(EncoderItem encoderItem, IBassStream stream, IBassEncoderSettings settings)
 {
     using (var encoderProcess = this.CreateEncoderProcess(encoderItem, stream, settings))
     {
         this.Encode(encoderItem, stream, encoderProcess);
         if (this.WaitForExit(encoderProcess))
         {
             if (encoderProcess.ExitCode != 0)
             {
                 throw new InvalidOperationException("Process does not indicate success.");
             }
         }
     }
 }
Пример #10
0
        protected virtual string GetFormat(EncoderItem encoderItem, IBassStream stream)
        {
            var channelInfo = default(ChannelInfo);

            if (!Bass.ChannelGetInfo(stream.ChannelHandle, out channelInfo))
            {
                throw new NotImplementedException();
            }
            return(string.Format(
                       "{0},{1}s,{2},le",
                       channelInfo.Frequency,
                       this.GetDepth(encoderItem, stream),
                       channelInfo.Channels
                       ));
        }
Пример #11
0
        public override int GetDepth(EncoderItem encoderItem, IBassStream stream)
        {
            var depth = base.GetDepth(encoderItem, stream);

            if (depth < DEPTH_16)
            {
                Logger.Write(this.GetType(), LogLevel.Warn, "Requsted bit depth {0} is invalid, using minimum: 16 bit", depth);
                return(DEPTH_16);
            }
            if (depth > DEPTH_32)
            {
                Logger.Write(this.GetType(), LogLevel.Warn, "Requsted bit depth {0} is invalid, using maximum: 32 bit", depth);
                return(DEPTH_32);
            }
            return(depth);
        }
Пример #12
0
        public override string GetArguments(EncoderItem encoderItem, IBassStream stream)
        {
            var channelInfo = default(ChannelInfo);

            if (!Bass.ChannelGetInfo(stream.ChannelHandle, out channelInfo))
            {
                throw new NotImplementedException();
            }
            return(string.Format(
                       "--quiet --raw --raw-rate={0} --raw-chan={1} --raw-bits={2} --raw-endianness=0 - --quality={3} -o \"{4}\"",
                       channelInfo.Frequency,
                       channelInfo.Channels,
                       this.GetDepth(encoderItem, stream),
                       this.Quality,
                       encoderItem.OutputFileName
                       ));
        }
Пример #13
0
        public override string GetArguments(EncoderItem encoderItem, IBassStream stream)
        {
            var channelInfo = default(ChannelInfo);

            if (!Bass.ChannelGetInfo(stream.ChannelHandle, out channelInfo))
            {
                throw new NotImplementedException();
            }
            return(string.Format(
                       "--silent -r --little-endian --signed -s {0} -m {1} --bitwidth {2} - --cbr -b {3} \"{4}\"",
                       channelInfo.Frequency,
                       this.GetStereoMode(channelInfo.Channels),
                       this.GetDepth(encoderItem, stream),
                       this.Bitrate,
                       encoderItem.OutputFileName
                       ));
        }
        public override string GetArguments(EncoderItem encoderItem, IBassStream stream)
        {
            var channelInfo = default(ChannelInfo);

            if (!Bass.ChannelGetInfo(stream.ChannelHandle, out channelInfo))
            {
                throw new NotImplementedException();
            }
            return(string.Format(
                       "--alac --raw --raw-rate {0} --raw-channels {1} --raw-format {2} - --bits-per-sample {3} -o \"{4}\"",
                       channelInfo.Frequency,
                       channelInfo.Channels,
                       this.GetFormat(encoderItem, stream),
                       this.GetDepth(encoderItem, stream),
                       encoderItem.OutputFileName
                       ));
        }
Пример #15
0
        protected virtual Process CreateEncoderProcess(EncoderItem encoderItem, IBassStream stream, IBassEncoderSettings settings)
        {
            Logger.Write(this, LogLevel.Debug, "Creating encoder process for file \"{0}\".", encoderItem.InputFileName);
            var arguments = settings.GetArguments(encoderItem, stream);
            var process   = this.CreateProcess(
                encoderItem,
                stream,
                settings.Executable,
                settings.Directory,
                arguments,
                true,
                false,
                true
                );

            Logger.Write(this, LogLevel.Debug, "Created encoder process for file \"{0}\": \"{1}\" {2}", encoderItem.InputFileName, settings.Executable, arguments);
            return(process);
        }
Пример #16
0
        protected virtual void Encode(EncoderItem encoderItem, IBassStream stream, Process encoderProcess)
        {
            var channelReader = new ChannelReader(encoderItem, stream);
            var encoderWriter = new ProcessWriter(encoderProcess);
            var thread        = new Thread(() =>
            {
                this.Try(() => channelReader.CopyTo(encoderWriter, this.CancellationToken), this.GetErrorHandler(encoderItem));
            })
            {
                Name         = string.Format("ChannelReader(\"{0}\", {1})", encoderItem.InputFileName, stream.ChannelHandle),
                IsBackground = true
            };

            Logger.Write(this, LogLevel.Debug, "Starting background thread for file \"{0}\".", encoderItem.InputFileName);
            thread.Start();
            Logger.Write(this, LogLevel.Debug, "Completing background thread for file \"{0}\".", encoderItem.InputFileName);
            this.Join(thread);
            encoderWriter.Close();
        }
Пример #17
0
        protected virtual Process CreateProcess(EncoderItem encoderItem, IBassStream stream, string executable, string directory, string arguments, bool redirectStandardInput, bool redirectStandardOutput, bool redirectStandardError)
        {
            if (!File.Exists(executable))
            {
                throw new InvalidOperationException(string.Format("A required utility was not found: {0}", executable));
            }
            var processStartInfo = new ProcessStartInfo()
            {
                FileName               = executable,
                WorkingDirectory       = directory,
                Arguments              = arguments,
                RedirectStandardInput  = redirectStandardInput,
                RedirectStandardOutput = redirectStandardOutput,
                RedirectStandardError  = redirectStandardError,
                UseShellExecute        = false,
                CreateNoWindow         = true
            };
            var process = Process.Start(processStartInfo);

            try
            {
                process.PriorityClass = ProcessPriorityClass.BelowNormal;
            }
            catch
            {
                //Nothing can be done, probably access denied.
            }
            process.ErrorDataReceived += (sender, e) =>
            {
                if (string.IsNullOrEmpty(e.Data))
                {
                    return;
                }
                Logger.Write(this, LogLevel.Trace, "{0}: {1}", executable, e.Data);
                encoderItem.AddError(e.Data);
            };
            process.BeginErrorReadLine();
            return(process);
        }
Пример #18
0
 public BassOutputStream(IBassOutput output, IBassStreamPipelineManager manager, IBassStream stream, PlaylistItem playlistItem)
     : base(playlistItem)
 {
     this.Output  = output;
     this.Manager = manager;
     this.Stream  = stream;
     if (!BassOutputStreams.Add(this))
     {
         //TODO: Warn.
     }
 }
 protected virtual string GetFormat(EncoderItem encoderItem, IBassStream stream)
 {
     return(string.Format("S{0}L", this.GetDepth(encoderItem, stream)));
 }
Пример #20
0
 protected virtual bool TrySetPosition(IBassStream stream, long position)
 {
     return((stream.Position = position) == position);
 }
Пример #21
0
 public abstract string GetArguments(EncoderItem encoderItem, IBassStream stream);
Пример #22
0
 public ChannelReader(EncoderItem encoderItem, IBassStream stream)
 {
     this.EncoderItem = encoderItem;
     this.Stream      = stream;
 }
Пример #23
0
 public override int GetDepth(EncoderItem encoderItem, IBassStream stream)
 {
     return(DEPTH_16);
 }
Пример #24
0
        public override bool Wrap(IBassStreamProvider provider, int channelHandle, IEnumerable <IBassStreamAdvice> advice, BassFlags flags, out IBassStream stream)
        {
            var offset = default(long);
            var length = default(long);

            if (this.Offset != TimeSpan.Zero)
            {
                offset = Bass.ChannelSeconds2Bytes(channelHandle, this.Offset.TotalSeconds);
            }
            if (this.Length != TimeSpan.Zero)
            {
                length = Bass.ChannelSeconds2Bytes(channelHandle, this.Length.TotalSeconds);
            }
            if (offset != 0 || length != 0)
            {
                if (length == 0)
                {
                    length = Bass.ChannelGetLength(channelHandle, PositionFlags.Bytes) - offset;
                }
                stream = new BassStream(
                    provider,
                    BassSubstream.CreateStream(channelHandle, offset, length, flags),
                    length,
                    advice,
                    flags
                    );
                return(true);
            }
            stream = null;
            return(false);
        }
Пример #25
0
 public BassOutputStream(IBassOutput output, IBassStreamPipelineManager manager, IBassStream stream, PlaylistItem playlistItem)
     : base(playlistItem)
 {
     this.Output  = output;
     this.Manager = manager;
     this.Stream  = stream;
 }
Пример #26
0
 public abstract bool Wrap(IBassStreamProvider provider, int channelHandle, IEnumerable <IBassStreamAdvice> advice, BassFlags flags, out IBassStream stream);
Пример #27
0
 public ChannelMonitor(ScannerItem scannerItem, IBassStream stream)
 {
     this.ScannerItem = scannerItem;
     this.Stream      = stream;
 }