@@ -14,49 +14,48 @@ public class OtoFrq {
1414 public int hopSize ;
1515 public bool loaded = false ;
1616
17- public OtoFrq ( UOto oto , Dictionary < string , Frq > dict ) {
18- if ( ! dict . TryGetValue ( oto . File , out var frq ) ) {
19- frq = new Frq ( ) ;
20- if ( frq . Load ( oto . File ) ) {
17+ public OtoFrq ( UOto oto , Dictionary < string , IFrqFiles > dict ) {
18+ if ( ! dict . TryGetValue ( oto . File , out IFrqFiles ? frq ) ) {
19+ Load ( oto . File , out frq ) ;
20+ if ( frq != null ) {
2121 dict . Add ( oto . File , frq ) ;
22- } else {
23- frq = null ;
2422 }
2523 }
26- if ( frq != null && frq . wavSampleLength != - 1 ) {
27- this . hopSize = frq . hopSize ;
28-
29- if ( frq . wavSampleLength == 0 ) {
30- try {
31- using ( var waveStream = Core . Format . Wave . OpenFile ( oto . File ) ) {
32- var sampleProvider = waveStream . ToSampleProvider ( ) ;
33- if ( sampleProvider . WaveFormat . SampleRate == 44100 ) {
34- frq . wavSampleLength = Core . Format . Wave . GetSamples ( sampleProvider ) . Length ;
35- } else {
36- frq . wavSampleLength = - 1 ;
37- }
38- }
39- } catch {
40- frq . wavSampleLength = - 1 ;
41- }
42- }
4324
44- if ( frq . wavSampleLength > 0 ) {
45- int offset = ( int ) Math . Floor ( oto . Offset * 44100 / 1000 / frq . hopSize ) ; // frq samples
46- int consonant = ( int ) Math . Floor ( ( oto . Offset + oto . Consonant ) * 44100 / 1000 / frq . hopSize ) ;
47- int cutoff = oto . Cutoff < 0 ?
48- ( int ) Math . Floor ( ( oto . Offset - oto . Cutoff ) * 44100 / 1000 / frq . hopSize )
49- : frq . wavSampleLength - ( int ) Math . Floor ( oto . Cutoff * 44100 / 1000 / frq . hopSize ) ;
50- var completionF0 = Completion ( frq . f0 ) ;
51- var averageTone = MusicMath . FreqToTone ( frq . averageF0 ) ;
52- toneDiffFix = completionF0 . Skip ( offset ) . Take ( consonant - offset ) . Select ( f => MusicMath . FreqToTone ( f ) - averageTone ) . ToArray ( ) ;
53- toneDiffStretch = completionF0 . Skip ( consonant ) . Take ( cutoff - consonant ) . Select ( f => MusicMath . FreqToTone ( f ) - averageTone ) . ToArray ( ) ;
54-
55- loaded = true ;
56- }
25+ if ( frq != null ) {
26+ hopSize = frq . hopSize ;
27+ int offset = ConvertMsToFrqLength ( frq , oto . Offset ) ;
28+ int consonant = ConvertMsToFrqLength ( frq , oto . Offset + oto . Consonant ) ;
29+ int cutoff = oto . Cutoff < 0 ?
30+ ConvertMsToFrqLength ( frq , oto . Offset - oto . Cutoff )
31+ : frq . f0 . Length - ConvertMsToFrqLength ( frq , oto . Cutoff ) ;
32+ var completionF0 = Completion ( frq . f0 ) ;
33+ var averageTone = MusicMath . FreqToTone ( frq . averageF0 ) ;
34+ toneDiffFix = completionF0 . Skip ( offset ) . Take ( consonant - offset ) . Select ( f => MusicMath . FreqToTone ( f ) - averageTone ) . ToArray ( ) ;
35+ toneDiffStretch = completionF0 . Skip ( consonant ) . Take ( cutoff - consonant ) . Select ( f => MusicMath . FreqToTone ( f ) - averageTone ) . ToArray ( ) ;
36+
37+ loaded = true ;
38+ }
39+ }
40+
41+ private void Load ( string otoPath , out IFrqFiles ? frqFile ) {
42+ var frq = new Frq ( ) ;
43+ if ( frq . Load ( otoPath ) ) {
44+ frqFile = frq ;
45+ return ;
5746 }
47+ // Please write a code to read other frequency files!
48+
49+ frqFile = null ;
5850 }
5951
52+ private int ConvertMsToFrqLength ( IFrqFiles frq , double lengthMs ) {
53+ return ( int ) Math . Floor ( lengthMs * frq . wavSampleRate / 1000 / frq . hopSize ) ;
54+ }
55+
56+ /// <summary>
57+ /// When a pitch is out of tune, it is complemented by the preceding and following pitches.
58+ /// </summary>
6059 private double [ ] Completion ( double [ ] frqs ) {
6160 var list = new List < double > ( ) ;
6261 for ( int i = 0 ; i < frqs . Length ; i ++ ) {
@@ -94,18 +93,39 @@ private double[] Completion(double[] frqs) {
9493 }
9594 }
9695
97- public class Frq {
98- public const int kHopSize = 256 ;
99-
100- public int hopSize ;
101- public double averageF0 ;
102- public double [ ] f0 = new double [ 0 ] ;
103- public double [ ] amp = new double [ 0 ] ;
104- public int wavSampleLength = 0 ;
96+ public interface IFrqFiles {
97+ public int hopSize { get ; }
98+ public double averageF0 { get ; }
99+ public double [ ] f0 { get ; }
100+ public int wavSampleRate { get ; set ; }
105101
106102 /// <summary>
107103 /// If the wav path is null (machine learning voicebank), return false.
108- /// <summary>
104+ /// </summary>
105+ public bool Load ( string wavPath ) ;
106+
107+ /* Might be needed in the future if the frequency files of engines that can handle wav's other than 44100Hz are supported.
108+ if (frq.wavSampleRate == 0) {
109+ try {
110+ using (var waveStream = Core.Format.Wave.OpenFile(oto.File)) {
111+ var sampleProvider = waveStream.ToSampleProvider();
112+ frq.wavSampleRate = sampleProvider.WaveFormat.SampleRate;
113+ }
114+ } catch {
115+ frq.wavSampleRate = 44100;
116+ }
117+ }*/
118+ }
119+
120+ public class Frq : IFrqFiles {
121+ public const int kHopSize = 256 ;
122+
123+ public int hopSize { get ; private set ; }
124+ public double averageF0 { get ; private set ; }
125+ public double [ ] f0 { get ; private set ; } = new double [ 0 ] ;
126+ public double [ ] amp { get ; private set ; } = new double [ 0 ] ;
127+ public int wavSampleRate { get ; set ; } = 44100 ; // Sample rate for .frq files is fixed
128+
109129 public bool Load ( string wavPath ) {
110130 if ( string . IsNullOrEmpty ( wavPath ) ) {
111131 return false ;
0 commit comments