示例#1
0
 void Resample(RenderItem item)
 {
     byte[] data = null;
     try {
         uint hash = item.HashParameters();
         data = cache.Get(hash);
         if (data == null)
         {
             CopySourceTemp(item);
             if (!resamplers.TryGetValue(item.ResamplerName, out var driver))
             {
                 driver = this.driver;
             }
             data = driver.DoResampler(DriverModels.CreateInputModel(item, 0), Log.Logger);
             if (data == null || data.Length == 0)
             {
                 throw new Exception("Empty render result.");
             }
             cache.Put(hash, data);
             Log.Information($"Sound {hash:x} {item.Oto.Alias} {item.GetResamplerExeArgs()} resampled.");
             CopyBackMetaFiles(item);
         }
     } catch (Exception e) {
         Log.Error(e, $"Failed to render item {item.SourceFile} {item.Oto.Alias} {item.GetResamplerExeArgs()}.");
     } finally {
         item.Data = data ?? new byte[0];
         item.OnComplete?.Invoke(item.Data);
         item.progress?.CompleteOne($"Resampling \"{item.phonemeName}\"");
     }
 }
示例#2
0
        void CopyBackMetaFiles(RenderItem item)
        {
            string sourceTemp = item.SourceTemp;
            var    metaFiles  = GetMetaFiles(item.SourceFile, item.SourceTemp);

            metaFiles.ForEach(t => CopyOrStamp(t.Item2, t.Item1));
        }
示例#3
0
        private RenderItem BuildRenderItem(UPhoneme phoneme, UVoicePart part, UProject project)
        {
            USinger singer  = project.Tracks[part.TrackNo].Singer;
            string  rawfile = Lib.EncodingUtil.ConvertEncoding(singer.FileEncoding, singer.PathEncoding, phoneme.Oto.File);

            rawfile = Path.Combine(singer.Path, rawfile);

            double strechRatio      = Math.Pow(2, 1.0 - (double)(int)phoneme.Parent.Expressions["velocity"].Data / 100);
            double length           = phoneme.Oto.Preutter * strechRatio + phoneme.Envelope.Points[4].X;
            double requiredLength   = Math.Ceiling(length / 50 + 1) * 50;
            double lengthAdjustment = phoneme.TailIntrude == 0 ? phoneme.Preutter : phoneme.Preutter - phoneme.TailIntrude + phoneme.TailOverlap;

            RenderItem item = new RenderItem()
            {
                // For resampler
                RawFile        = rawfile,
                NoteNum        = phoneme.Parent.NoteNum,
                Velocity       = (int)phoneme.Parent.Expressions["velocity"].Data,
                Volume         = (int)phoneme.Parent.Expressions["volume"].Data,
                StrFlags       = phoneme.Parent.GetResamplerFlags(),
                PitchData      = BuildPitchData(phoneme, part, project),
                RequiredLength = (int)requiredLength,
                Oto            = phoneme.Oto,
                Tempo          = project.BPM,

                // For connector
                SkipOver = phoneme.Oto.Preutter * strechRatio - phoneme.Preutter,
                PosMs    = project.TickToMillisecond(part.PosTick + phoneme.Parent.PosTick + phoneme.PosTick) - phoneme.Preutter,
                DurMs    = project.TickToMillisecond(phoneme.DurTick) + lengthAdjustment,
                Envelope = phoneme.Envelope.Points
            };

            return(item);
        }
示例#4
0
        async Task <SequencingSampleProvider> RenderPartAsync(UVoicePart part, UProject project, string cacheDir)
        {
            var singer = project.Tracks[part.TrackNo].Singer;

            if (singer == null || !singer.Loaded)
            {
                return(null);
            }
            var tasks    = new List <Task <RenderItem> >();
            var progress = new Progress(part.Notes.Sum(note => note.Phonemes.Count));

            progress.Clear();
            foreach (var note in part.Notes)
            {
                foreach (var phoneme in note.Phonemes)
                {
                    if (string.IsNullOrEmpty(phoneme.Oto.File))
                    {
                        Log.Warning($"Cannot find phoneme in note {note.Lyric}");
                        continue;
                    }
                    var item = new RenderItem(phoneme, part, project);
                    item.progress = progress;
                    tasks.Add(Task <RenderItem> .Factory.StartNew(ResamplePhonemeAsync, item, cancellationTokenSource.Token));
                }
            }
            await Task.WhenAll(tasks.ToArray());

            progress.Clear();
            return(new SequencingSampleProvider(tasks.Select(task => new RenderItemSampleProvider(task.Result))));
        }
示例#5
0
        RenderItem ResamplePhonemeAsync(object state)
        {
            RenderItem item = state as RenderItem;

            Log.Verbose($"Sound {item.HashParameters():x} resampling {item.GetResamplerExeArgs()}");
            var output = driver.DoResampler(DriverModels.CreateInputModel(item, 0));

            item.Sound = MemorySampleProvider.FromStream(output);
            output.Dispose();
            item.progress.CompleteOne($"Resampling \"{item.phonemeName}\"");
            return(item);
        }
 public RenderItemSampleProvider(RenderItem renderItem)
 {
     this.RenderItem = renderItem;
     var cachedSampleProvider = new CachedSoundSampleProvider(RenderItem.Sound);
     var offsetSampleProvider = new OffsetSampleProvider(new EnvelopeSampleProvider(cachedSampleProvider, RenderItem.Envelope, RenderItem.SkipOver))
     {
         DelayBySamples = (int)(RenderItem.PosMs * cachedSampleProvider.WaveFormat.SampleRate / 1000),
         TakeSamples = (int)(RenderItem.DurMs * cachedSampleProvider.WaveFormat.SampleRate / 1000),
         SkipOverSamples = (int)(RenderItem.SkipOver * cachedSampleProvider.WaveFormat.SampleRate / 1000)
     };
     this.signalChain = offsetSampleProvider;
     this.firstSample = offsetSampleProvider.DelayBySamples + offsetSampleProvider.SkipOverSamples;
     this.lastSample = this.firstSample + offsetSampleProvider.TakeSamples;
 }
        public RenderItemSampleProvider(RenderItem renderItem)
        {
            this.RenderItem = renderItem;
            var cachedSampleProvider = new CachedSoundSampleProvider(RenderItem.Sound);
            var offsetSampleProvider = new OffsetSampleProvider(new EnvelopeSampleProvider(cachedSampleProvider, RenderItem.Envelope, RenderItem.SkipOver))
            {
                DelayBySamples  = (int)(RenderItem.PosMs * cachedSampleProvider.WaveFormat.SampleRate / 1000),
                TakeSamples     = (int)(RenderItem.DurMs * cachedSampleProvider.WaveFormat.SampleRate / 1000),
                SkipOverSamples = (int)(RenderItem.SkipOver * cachedSampleProvider.WaveFormat.SampleRate / 1000)
            };

            this.signalChain = offsetSampleProvider;
            this.firstSample = offsetSampleProvider.DelayBySamples + offsetSampleProvider.SkipOverSamples;
            this.lastSample  = this.firstSample + offsetSampleProvider.TakeSamples;
        }
        private List <RenderItem> RenderAsync(UVoicePart part, UProject project, IResamplerDriver engine, BackgroundWorker worker)
        {
            var renderItems = new List <RenderItem>();
            var watch       = new Stopwatch();

            watch.Start();
            Log.Information("Resampling start.");
            lock (part) {
                var cacheDir = PathManager.Inst.GetCachePath(project.FilePath);
                var cacheFiles = Directory.EnumerateFiles(cacheDir).ToArray();
                int count = 0, i = 0;
                foreach (var note in part.Notes)
                {
                    foreach (var phoneme in note.Phonemes)
                    {
                        count++;
                    }
                }

                foreach (var note in part.Notes)
                {
                    foreach (var phoneme in note.Phonemes)
                    {
                        if (string.IsNullOrEmpty(phoneme.Oto.File))
                        {
                            Log.Warning($"Cannot find phoneme in note {note.Lyric}");
                            continue;
                        }

                        var item = new RenderItem(phoneme, part, project);

                        //System.Diagnostics.Debug.WriteLine("Sound {0:x} resampling {1}", item.HashParameters(), item.GetResamplerExeArgs());
                        var engineArgs = DriverModels.CreateInputModel(item, 0);
                        var output     = engine.DoResampler(engineArgs);
                        item.Sound = MemorySampleProvider.FromStream(output);
                        output.Dispose();
                        renderItems.Add(item);
                        worker.ReportProgress(100 * ++i / count, $"Resampling \"{phoneme.Phoneme}\" {i}/{count}");
                    }
                }
            }
            watch.Stop();
            Log.Information($"Resampling end, total time {watch.Elapsed}");
            return(renderItems);
        }
示例#9
0
        RenderItem ResamplePhonemeAsync(object state)
        {
            RenderItem item = state as RenderItem;
            uint       hash = item.HashParameters();

            byte[] data = cache.Get(hash);
            if (data == null)
            {
                data = driver.DoResampler(DriverModels.CreateInputModel(item, 0));
                cache.Put(hash, data);
                Log.Information($"Sound {hash:x} {item.GetResamplerExeArgs()} resampled.");
            }
            else
            {
                Log.Information($"Sound {hash:x} {item.GetResamplerExeArgs()} cache retrieved.");
            }
            var stream = new MemoryStream(data);

            item.Sound = MemorySampleProvider.FromStream(stream);
            item.progress.CompleteOne($"Resampling \"{item.phonemeName}\"");
            return(item);
        }
示例#10
0
        private List <RenderItem> RenderAsync(UVoicePart part, UProject project, IResamplerDriver engine, BackgroundWorker worker)
        {
            List <RenderItem> renderItems = new List <RenderItem>();

            System.Diagnostics.Stopwatch watch = new Stopwatch();
            watch.Start();
            System.Diagnostics.Debug.WriteLine("Resampling start");
            lock (part)
            {
                string   cacheDir = PathManager.Inst.GetCachePath(project.FilePath);
                string[] cacheFiles = Directory.EnumerateFiles(cacheDir).ToArray();
                int      count = 0, i = 0;
                foreach (UNote note in part.Notes)
                {
                    foreach (UPhoneme phoneme in note.Phonemes)
                    {
                        count++;
                    }
                }

                foreach (UNote note in part.Notes)
                {
                    foreach (UPhoneme phoneme in note.Phonemes)
                    {
                        RenderItem item  = BuildRenderItem(phoneme, part, project);
                        var        sound = RenderCache.Inst.Get(item.HashParameters());

                        if (sound == null)
                        {
                            string cachefile = Path.Combine(cacheDir, string.Format("{0:x}.wav", item.HashParameters()));
                            if (!cacheFiles.Contains(cachefile))
                            {
                                System.Diagnostics.Debug.WriteLine("Sound {0:x} resampling {1}", item.HashParameters(), item.GetResamplerExeArgs());
                                DriverModels.EngineInput engineArgs = DriverModels.CreateInputModel(item, 0);
                                System.IO.Stream         output     = engine.DoResampler(engineArgs);
                                sound = new CachedSound(output);
                            }
                            else
                            {
                                System.Diagnostics.Debug.WriteLine("Sound {0:x} found on disk {1}", item.HashParameters(), item.GetResamplerExeArgs());
                                sound = new CachedSound(cachefile);
                            }
                            RenderCache.Inst.Put(item.HashParameters(), sound, engine.GetInfo().ToString());
                        }
                        else
                        {
                            System.Diagnostics.Debug.WriteLine("Sound {0} found in cache {1}", item.HashParameters(), item.GetResamplerExeArgs());
                        }

                        item.Sound = sound;
                        renderItems.Add(item);
                        worker.ReportProgress(100 * ++i / count, string.Format("Resampling \"{0}\" {1}/{2}", phoneme.Phoneme, i, count));
                    }
                }
            }
            watch.Stop();
            System.Diagnostics.Debug.WriteLine("Resampling end");
            System.Diagnostics.Debug.WriteLine("Total cache size {0:n0} bytes", RenderCache.Inst.TotalMemSize);
            System.Diagnostics.Debug.WriteLine("Total time {0} ms", watch.Elapsed.TotalMilliseconds);
            return(renderItems);
        }
示例#11
0
 /// <summary>
 /// 从RenderItem初始化过程
 /// </summary>
 /// <returns></returns>
 internal static EngineInput CreateInputModel(RenderItem renderItem,double Modulation)
 {
     EngineInput Ret = new EngineInput();
     Ret.inputWaveFile = renderItem.RawFile;
     Ret.NoteString = MusicMath.GetNoteString(renderItem.NoteNum);
     Ret.Velocity = renderItem.Velocity;
     Ret.StrFlags = renderItem.StrFlags;
     Ret.Offset = renderItem.Oto.Offset;
     Ret.RequiredLength = renderItem.RequiredLength;
     Ret.Consonant = renderItem.Oto.Consonant;
     Ret.Cutoff = renderItem.Oto.Cutoff;
     Ret.Volume = renderItem.Volume;
     Ret.Modulation = Modulation;
     Ret.pitchBend = renderItem.PitchData.ToArray();
     Ret.nPitchBend = renderItem.PitchData.Count;
     Ret.Tempo =  renderItem.Tempo;
     return Ret;
 }
        private RenderItem BuildRenderItem(UPhoneme phoneme, UVoicePart part, UProject project)
        {
            USinger singer = project.Tracks[part.TrackNo].Singer;
            string rawfile = Lib.EncodingUtil.ConvertEncoding(singer.FileEncoding, singer.PathEncoding, phoneme.Oto.File);
            rawfile = Path.Combine(singer.Path, rawfile);

            double strechRatio = Math.Pow(2, 1.0 - (double)(int)phoneme.Parent.Expressions["velocity"].Data / 100);
            double length = phoneme.Oto.Preutter * strechRatio + phoneme.Envelope.Points[4].X;
            double requiredLength = Math.Ceiling(length / 50 + 1) * 50;
            double lengthAdjustment = phoneme.TailIntrude == 0 ? phoneme.Preutter : phoneme.Preutter - phoneme.TailIntrude + phoneme.TailOverlap;

            RenderItem item = new RenderItem()
            {
                // For resampler
                RawFile = rawfile,
                NoteNum = phoneme.Parent.NoteNum,
                Velocity = (int)phoneme.Parent.Expressions["velocity"].Data,
                Volume = (int)phoneme.Parent.Expressions["volume"].Data,
                StrFlags = phoneme.Parent.GetResamplerFlags(),
                PitchData = BuildPitchData(phoneme, part, project),
                RequiredLength = (int)requiredLength,
                Oto = phoneme.Oto,
                Tempo = project.BPM,

                // For connector
                SkipOver = phoneme.Oto.Preutter * strechRatio - phoneme.Preutter,
                PosMs = project.TickToMillisecond(part.PosTick + phoneme.Parent.PosTick + phoneme.PosTick) - phoneme.Preutter,
                DurMs = project.TickToMillisecond(phoneme.DurTick) + lengthAdjustment,
                Envelope = phoneme.Envelope.Points
            };

            return item;
        }