@@ -14,49 +14,61 @@ public class OtoFrq {
14
14
public int hopSize ;
15
15
public bool loaded = false ;
16
16
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 ) ) {
21
- dict . Add ( oto . File , frq ) ;
22
- } else {
23
- frq = null ;
17
+ public OtoFrq ( UOto oto , Dictionary < string , IFrqFiles > dict ) {
18
+ if ( ! dict . TryGetValue ( oto . File , out IFrqFiles ? frq ) ) {
19
+ var result = Load ( oto . File , out frq ) ;
20
+ if ( result ) {
21
+ dict . Add ( oto . File , frq ! ) ;
24
22
}
25
23
}
26
- if ( frq != null && frq . wavSampleLength != - 1 ) {
27
- this . hopSize = frq . hopSize ;
28
24
29
- if ( frq . wavSampleLength == 0 ) {
25
+ if ( frq != null ) {
26
+ hopSize = frq . hopSize ;
27
+ /* Might be needed in the future if the frequency files of engines that can handle wav's other than 44100Hz are supported.
28
+ if (frq.wavSampleRate == 0) {
30
29
try {
31
30
using (var waveStream = Core.Format.Wave.OpenFile(oto.File)) {
32
31
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
- }
32
+ frq.wavSampleRate = sampleProvider.WaveFormat.SampleRate;
38
33
}
39
34
} catch {
40
- frq . wavSampleLength = - 1 ;
35
+ frq.wavSampleRate = 44100 ;
41
36
}
42
- }
37
+ }*/
43
38
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
- }
39
+ int offset = ConvertMsToFrqLength ( frq , oto . Offset ) ;
40
+ int consonant = ConvertMsToFrqLength ( frq , oto . Offset + oto . Consonant ) ;
41
+ int cutoff = oto . Cutoff < 0 ?
42
+ ConvertMsToFrqLength ( frq , oto . Offset - oto . Cutoff )
43
+ : frq . f0 . Length - ConvertMsToFrqLength ( frq , oto . Cutoff ) ;
44
+ var completionF0 = Completion ( frq . f0 ) ;
45
+ var averageTone = MusicMath . FreqToTone ( frq . averageF0 ) ;
46
+ toneDiffFix = completionF0 . Skip ( offset ) . Take ( consonant - offset ) . Select ( f => MusicMath . FreqToTone ( f ) - averageTone ) . ToArray ( ) ;
47
+ toneDiffStretch = completionF0 . Skip ( consonant ) . Take ( cutoff - consonant ) . Select ( f => MusicMath . FreqToTone ( f ) - averageTone ) . ToArray ( ) ;
48
+
49
+ loaded = true ;
57
50
}
58
51
}
59
52
53
+ private bool Load ( string otoPath , out IFrqFiles ? frqFile ) {
54
+ var frq = new Frq ( ) ;
55
+ if ( frq . Load ( otoPath ) ) {
56
+ frqFile = frq ;
57
+ return true ;
58
+ }
59
+ // Please write a code to read other frequency files!
60
+
61
+ frqFile = null ;
62
+ return false ;
63
+ }
64
+
65
+ private int ConvertMsToFrqLength ( IFrqFiles frq , double lengthMs ) {
66
+ return ( int ) Math . Floor ( lengthMs / 1000 * frq . wavSampleRate / frq . hopSize ) ;
67
+ }
68
+
69
+ /// <summary>
70
+ /// When a pitch is out of tune, it is complemented by the preceding and following pitches.
71
+ /// </summary>
60
72
private double [ ] Completion ( double [ ] frqs ) {
61
73
var list = new List < double > ( ) ;
62
74
for ( int i = 0 ; i < frqs . Length ; i ++ ) {
@@ -94,18 +106,27 @@ private double[] Completion(double[] frqs) {
94
106
}
95
107
}
96
108
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 ;
109
+ public interface IFrqFiles {
110
+ public int hopSize { get ; }
111
+ public double averageF0 { get ; }
112
+ public double [ ] f0 { get ; }
113
+ public int wavSampleRate { get ; set ; }
105
114
106
115
/// <summary>
107
116
/// If the wav path is null (machine learning voicebank), return false.
108
- /// <summary>
117
+ /// </summary>
118
+ public bool Load ( string wavPath ) ;
119
+ }
120
+
121
+ public class Frq : IFrqFiles {
122
+ public const int kHopSize = 256 ;
123
+
124
+ public int hopSize { get ; private set ; }
125
+ public double averageF0 { get ; private set ; }
126
+ public double [ ] f0 { get ; private set ; } = new double [ 0 ] ;
127
+ public double [ ] amp { get ; private set ; } = new double [ 0 ] ;
128
+ public int wavSampleRate { get ; set ; }
129
+
109
130
public bool Load ( string wavPath ) {
110
131
if ( string . IsNullOrEmpty ( wavPath ) ) {
111
132
return false ;
0 commit comments