2
2
3
3
const fs = require ( "fs" ) ;
4
4
const optionator = require ( "optionator" ) ( require ( "./package" ) . cliOptions ) ;
5
+ const tickable = require ( "tickable-timer" ) ;
5
6
const wae = require ( "../src" ) ;
6
7
7
8
function requireSourceIfExists ( filepath ) {
@@ -15,7 +16,7 @@ function requireSourceIfExists(filepath) {
15
16
function createContextOptions ( opts ) {
16
17
return Object . assign ( {
17
18
sampleRate : + opts . rate ,
18
- numberOfChannels : opts . channels | 0 ,
19
+ numberOfChannels : Math . max ( 1 , opts . channels | 0 ) ,
19
20
} , {
20
21
u8 : { bitDepth : 8 } ,
21
22
s16 : { bitDepth : 16 } ,
@@ -25,12 +26,27 @@ function createContextOptions(opts) {
25
26
}
26
27
27
28
function createPrintFunc ( opts ) {
28
- if ( opts . noShowProgress ) {
29
- return ( ) => { } ;
29
+ if ( opts . verbose ) {
30
+ return ( msg ) => {
31
+ process . stderr . write ( msg + "\n" ) ;
32
+ } ;
30
33
}
31
- return ( msg ) => {
32
- process . stderr . write ( msg + "\n" ) ;
33
- } ;
34
+ return ( ) => { } ;
35
+ }
36
+
37
+ function fetchAudioBuffer ( context , filename ) {
38
+ if ( Array . isArray ( filename ) ) {
39
+ return Promise . all ( filename . map ( filename => fetchAudioBuffer ( context , filename ) ) ) ;
40
+ }
41
+
42
+ return new Promise ( ( resolve , reject ) => {
43
+ fs . readFile ( `${ __dirname } /assets/sound/${ filename } ` , ( err , data ) => {
44
+ if ( err ) {
45
+ return reject ( err ) ;
46
+ }
47
+ resolve ( context . decodeAudioData ( data ) ) ;
48
+ } ) ;
49
+ } ) ;
34
50
}
35
51
36
52
function showHelp ( ) {
@@ -58,20 +74,78 @@ function main(opts) {
58
74
return console . log ( `demo: ${ name } is not found` ) ;
59
75
}
60
76
61
- runWithStreamAudioContext ( func , opts ) ;
77
+ if ( opts . out ) {
78
+ runWithRenderingAudioContext ( func , opts ) ;
79
+ } else {
80
+ runWithStreamAudioContext ( func , opts ) ;
81
+ }
82
+ }
83
+
84
+ function runWithRenderingAudioContext ( func , opts ) {
85
+ const AudioContext = wae . RenderingAudioContext ;
86
+ const context = new AudioContext ( createContextOptions ( opts ) ) ;
87
+
88
+ let isEnded = false ;
89
+
90
+ const util = {
91
+ fetchAudioBuffer : fetchAudioBuffer . bind ( null , context ) ,
92
+ timerAPI : tickable ,
93
+ print : createPrintFunc ( opts ) ,
94
+ end : ( ) => { isEnded = true }
95
+ } ;
96
+
97
+ const promise = func ( context , util ) || Promise . resolve ( ) ;
98
+
99
+ promise . then ( ( ) => {
100
+ let currentTime = 0 ;
101
+ let counter = 0 ;
102
+
103
+ const beginTime = Date . now ( ) ;
104
+ const duration = Math . max ( 0 , opts . duration ) || 10 ;
105
+ const numberOfProcessing = Math . ceil ( ( duration * context . sampleRate ) / context . processingSizeInFrames ) ;
106
+ const processingTimeInFrames = context . processingSizeInFrames / context . sampleRate ;
107
+
108
+ for ( let i = 0 ; i < numberOfProcessing && ! isEnded ; i ++ ) {
109
+ tickable . tick ( processingTimeInFrames * 1000 ) ;
110
+ context . processTo ( processingTimeInFrames * i ) ;
111
+ }
112
+
113
+ const endTime = Date . now ( ) ;
114
+ const outputFilename = opts . out || "out.wav" ;
115
+ const audioData = context . exportAsAudioData ( ) ;
116
+
117
+ context . encodeAudioData ( audioData ) . then ( ( arrayBuffer ) => {
118
+ fs . writeFile ( outputFilename , new Buffer ( arrayBuffer ) , ( err ) => {
119
+ if ( err ) {
120
+ console . error ( err ) ;
121
+ } else {
122
+ const renderingTime = ( endTime - beginTime ) / 1000 ;
123
+ const duration = context . currentTime ;
124
+
125
+ console . log ( `rendering time: ${ renderingTime } sec; duration: ${ duration } sec` ) ;
126
+ }
127
+ } ) ;
128
+ } ) ;
129
+ } ) ;
62
130
}
63
131
64
132
function runWithStreamAudioContext ( func , opts ) {
65
133
const AudioContext = wae . StreamAudioContext ;
66
134
const context = new AudioContext ( createContextOptions ( opts ) ) ;
67
-
68
- func ( context , {
135
+ const util = {
136
+ fetchAudioBuffer : fetchAudioBuffer . bind ( null , context ) ,
69
137
timerAPI : global ,
70
- print : createPrintFunc ( opts )
71
- } ) ;
138
+ print : createPrintFunc ( opts ) ,
139
+ end : ( ) => { process . exit ( 0 ) }
140
+ } ;
72
141
73
142
context . pipe ( process . stdout ) ;
74
- context . resume ( ) ;
143
+
144
+ const promise = func ( context , util ) || Promise . resolve ( ) ;
145
+
146
+ promise . then ( ( ) => {
147
+ context . resume ( ) ;
148
+ } ) ;
75
149
}
76
150
77
151
const opts = optionator . parse ( process . argv ) ;
0 commit comments