public static void BalanceVolumes(List <SamplePackage> packages, VolumeBalancingArgs args)
        {
            foreach (SamplePackage package in packages)
            {
                double maxVolume = package.Samples.Max(o => o.SampleArgs.Volume);
                if (Math.Abs(maxVolume - -0.01) < Precision.DOUBLE_EPSILON)
                {
                    maxVolume = 1;
                }

                foreach (Sample sample in package.Samples)
                {
                    if (Math.Abs(sample.SampleArgs.Volume - -0.01) < Precision.DOUBLE_EPSILON)
                    {
                        sample.SampleArgs.Volume = 1;
                    }

                    // I pick the new volume such that the samples have a volume as high as possible and the greenline brings the volume down.
                    // With this equation the final amplitude stays the same while the greenline has the volume of the loudest sample at this time.
                    double newVolume = SampleImporter.AmplitudeToVolume(
                        SampleImporter.VolumeToAmplitude(package.Volume) *
                        SampleImporter.VolumeToAmplitude(sample.SampleArgs.Volume) /
                        SampleImporter.VolumeToAmplitude(maxVolume));


                    if (Math.Abs(newVolume - 1) > args.Roughness && !args.AlwaysFullVolume)
                    {
                        // If roughness is not 0 it will quantize the new volume in order to reduce the number of different volumes
                        sample.SampleArgs.Volume = Math.Abs(args.Roughness) > Precision.DOUBLE_EPSILON ?
                                                   args.Roughness * Math.Round(newVolume / args.Roughness) :
                                                   newVolume;
                    }
                    else
                    {
                        sample.SampleArgs.Volume = 1;
                    }
                }

                if (args.AlwaysFullVolume)
                {
                    // Assuming the volume of the sample is always maximum, this equation makes sure that
                    // the loudest sample at this time has the wanted amplitude using the volume change from the greenline.
                    package.Volume = SampleImporter.AmplitudeToVolume(
                        SampleImporter.VolumeToAmplitude(package.Volume) *
                        SampleImporter.VolumeToAmplitude(maxVolume));
                }
                else
                {
                    package.Volume = maxVolume;
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Balances the volume of <see cref="SamplePackage"/> such that volume is mostly handled by osu!'s volume controllers rather than
        /// in-sample amplitude changes.
        /// </summary>
        /// <param name="packages"></param>
        /// <param name="roughness">Quantizing level in the new volumes of samples. Can be used to decrease the number of distinct volume levels.</param>
        /// <param name="alwaysFullVolume">Forces to always use maximum amplitude in the samples.</param>
        /// <param name="individualVolume">Allows for multiple distinct volume levels within a single <see cref="SamplePackage"/>.</param>
        public static void BalanceVolumes(IEnumerable <SamplePackage> packages, double roughness, bool alwaysFullVolume, bool individualVolume = false)
        {
            foreach (SamplePackage package in packages)
            {
                if (individualVolume)
                {
                    // Simply mix the volume in the sample to the outside volume
                    foreach (Sample sample in package.Samples)
                    {
                        sample.OutsideVolume = SampleImporter.AmplitudeToVolume(
                            SampleImporter.VolumeToAmplitude(sample.OutsideVolume) *
                            SampleImporter.VolumeToAmplitude(sample.SampleArgs.Volume));
                        sample.SampleArgs.Volume = 1;
                    }
                    continue;
                }

                double maxVolume = package.Samples.Max(o => o.SampleArgs.Volume);
                if (Math.Abs(maxVolume - -0.01) < Precision.DOUBLE_EPSILON)
                {
                    maxVolume = 1;
                }

                foreach (Sample sample in package.Samples)
                {
                    if (Math.Abs(sample.SampleArgs.Volume - -0.01) < Precision.DOUBLE_EPSILON)
                    {
                        sample.SampleArgs.Volume = 1;
                    }

                    // Pick the new volume such that the samples have a volume as high as possible and the greenline brings the volume down.
                    // With this equation the final amplitude stays the same while the greenline has the volume of the loudest sample at this time.
                    double newVolume = SampleImporter.AmplitudeToVolume(
                        SampleImporter.VolumeToAmplitude(sample.OutsideVolume) *
                        SampleImporter.VolumeToAmplitude(sample.SampleArgs.Volume) /
                        SampleImporter.VolumeToAmplitude(maxVolume));


                    if (Math.Abs(newVolume - 1) > roughness && !alwaysFullVolume)
                    {
                        // If roughness is not 0 it will quantize the new volume in order to reduce the number of different volumes
                        sample.SampleArgs.Volume = Math.Abs(roughness) > Precision.DOUBLE_EPSILON ?
                                                   roughness * Math.Round(newVolume / roughness) :
                                                   newVolume;
                    }
                    else
                    {
                        sample.SampleArgs.Volume = 1;
                    }
                }

                if (alwaysFullVolume)
                {
                    // Assuming the volume of the sample is always maximum, this equation makes sure that
                    // the loudest sample at this time has the wanted amplitude using the volume change from the greenline.
                    package.SetAllOutsideVolume(SampleImporter.AmplitudeToVolume(
                                                    SampleImporter.VolumeToAmplitude(package.MaxOutsideVolume) *
                                                    SampleImporter.VolumeToAmplitude(maxVolume)));
                }
                else
                {
                    package.SetAllOutsideVolume(maxVolume);
                }
            }
        }