1- import { updateProgress } from "./updateProgress.js" ;
2-
31const SAMPLE_RATE = 24000 ;
42
53export class AudioDiskSaver {
@@ -10,6 +8,7 @@ export class AudioDiskSaver {
108 this . processedAudioChunks = 0 ;
119 this . headerWritten = false ;
1210 this . bytesWritten = 0 ;
11+ // For WAV header updates
1312 this . fileSize = 0 ;
1413 this . dataSize = 0 ;
1514 }
@@ -28,11 +27,8 @@ export class AudioDiskSaver {
2827
2928 this . fileStream = await fileHandle . createWritable ( ) ;
3029
31- // --- THIS IS MODIFIED ---
32- // We no longer need to get the speed, just write the default header
33- await this . writeWavHeader ( ) ;
34- // --- END OF MODIFIED BLOCK ---
35-
30+ // Write placeholder WAV header
31+ await this . writeWavHeader ( ) ; // Writes a standard header
3632 this . headerWritten = true ;
3733 } catch ( error ) {
3834 console . error ( "Error initializing file save:" , error ) ;
@@ -65,6 +61,7 @@ export class AudioDiskSaver {
6561 throw new Error ( "No file stream available" ) ;
6662 }
6763 try {
64+ // Update the WAV header with final sizes
6865 await this . updateWavHeader ( ) ;
6966 await this . fileStream . close ( ) ;
7067 this . reset ( ) ;
@@ -84,7 +81,10 @@ export class AudioDiskSaver {
8481 return ;
8582 }
8683 try {
84+ // Give the worker a moment to process the stop message
8785 await new Promise ( resolve => setTimeout ( resolve , 100 ) ) ;
86+
87+ // Update the WAV header before closing to ensure a valid WAV file
8888 await this . updateWavHeader ( ) ;
8989 await this . fileStream . close ( ) ;
9090 console . log ( "Disk save operation stopped" ) ;
@@ -117,13 +117,12 @@ export class AudioDiskSaver {
117117 return Math . min ( ( this . processedAudioChunks / this . totalAudioChunks ) * 100 , 99 ) ;
118118 }
119119
120- // --- THIS FUNCTION IS MODIFIED ---
121- // It now ONLY writes the standard 24000 Hz header
120+ // Write WAV header at the start
122121 async writeWavHeader ( ) {
123122 const headerBuffer = new ArrayBuffer ( 44 ) ;
124123 const view = new DataView ( headerBuffer ) ;
125124
126- const bitsPerSample = 32 ;
125+ const bitsPerSample = 32 ; // This file saves as 32-bit float
127126 const numChannels = 1 ;
128127 const blockAlign = ( numChannels * bitsPerSample ) / 8 ;
129128 const byteRate = SAMPLE_RATE * blockAlign ;
@@ -134,33 +133,48 @@ export class AudioDiskSaver {
134133 }
135134 }
136135
136+ // "RIFF" chunk descriptor
137137 writeString ( view , 0 , 'RIFF' ) ;
138- view . setUint32 ( 4 , 0 , true ) ; // Placeholder for file size
138+
139+ // Placeholder for file size (updated later)
140+ view . setUint32 ( 4 , 0 , true ) ;
141+
142+ // "WAVE" format
139143 writeString ( view , 8 , 'WAVE' ) ;
144+
145+ // "fmt " subchunk
140146 writeString ( view , 12 , 'fmt ' ) ;
141- view . setUint32 ( 16 , 16 , true ) ;
142- view . setUint16 ( 20 , 3 , true ) ;
143- view . setUint16 ( 22 , numChannels , true ) ;
144- view . setUint32 ( 24 , SAMPLE_RATE , true ) ; // Use standard rate
145- view . setUint32 ( 28 , byteRate , true ) ; // Use standard rate
146- view . setUint16 ( 32 , blockAlign , true ) ;
147- view . setUint16 ( 34 , bitsPerSample , true ) ;
147+
148+ view . setUint32 ( 16 , 16 , true ) ; // Subchunk1Size (16 for PCM)
149+ view . setUint16 ( 20 , 3 , true ) ; // AudioFormat (3 for float)
150+ view . setUint16 ( 22 , numChannels , true ) ; // NumChannels (1 for mono)
151+ view . setUint32 ( 24 , SAMPLE_RATE , true ) ; // SampleRate (STANDARD RATE)
152+ view . setUint32 ( 28 , byteRate , true ) ; // ByteRate (STANDARD RATE)
153+ view . setUint16 ( 32 , blockAlign , true ) ; // BlockAlign
154+ view . setUint16 ( 34 , bitsPerSample , true ) ; // BitsPerSample (32 for float)
155+
156+ // "data" subchunk
148157 writeString ( view , 36 , 'data' ) ;
149- view . setUint32 ( 40 , 0 , true ) ; // Placeholder for data size
158+
159+ // Placeholder for data size (updated later)
160+ view . setUint32 ( 40 , 0 , true ) ;
150161
151162 await this . fileStream . write ( headerBuffer ) ;
152- this . bytesWritten = 44 ;
163+ this . bytesWritten = 44 ; // Header size
153164 }
154165
155166 // Update the WAV header with final sizes
156167 async updateWavHeader ( ) {
168+ // File size = header (44) + data size - 8 bytes for RIFF/size
157169 this . fileSize = this . dataSize + 36 ;
158170
171+ // Seek to file size position (offset 4) and update
159172 await this . fileStream . seek ( 4 ) ;
160173 const fileSizeBuffer = new ArrayBuffer ( 4 ) ;
161174 new DataView ( fileSizeBuffer ) . setUint32 ( 0 , this . fileSize , true ) ;
162175 await this . fileStream . write ( fileSizeBuffer ) ;
163176
177+ // Seek to data size position (offset 40) and update
164178 await this . fileStream . seek ( 40 ) ;
165179 const dataSizeBuffer = new ArrayBuffer ( 4 ) ;
166180 new DataView ( dataSizeBuffer ) . setUint32 ( 0 , this . dataSize , true ) ;
0 commit comments