private void WMDataFill() { //int bufferwriteoffset = 0; using (WmaStream str = new WmaStream(file)) { byte[] buffer = new byte[131072]; int firstread = str.Read(buffer, 0, buffer.Length); sound.Write(0, buffer, LockFlag.None); //firstread = str.Read(buffer, 0, buffer.Length); //sound.Write(131072, buffer, LockFlag.None); try { int count = 0; int read; while ((read = str.Read(buffer, 0, buffer.Length)) > 0) { BufferNotificationEvent.WaitOne(); if (sound.PlayPosition < 131071) { sound.Write(131072, buffer, LockFlag.None); } else { sound.Write(0, buffer, LockFlag.None); } count++; } } finally { str.Close(); str.Dispose(); } BufferNotificationEvent.WaitOne(); End(); } }
public static void FileEncode(SortableBindingList <FileEntryClass> workinglist, string m4boutputfile, int TargetRate, int Quant, int usetns, ProgressUpdate procprogress, AudioBookConverterMain _owner) { Owner = _owner; long inputsamples = 0; long maxbytes = 0; ulong filesamples = 0; ulong totalms = 0; ulong filems; int read; int fileindex = 0; int lastupdate = 0; bool havechapters = false; int bufferfactor = 256; //scan the files, see if we need chapter processing foreach (FileEntryClass listitem in workinglist) { if (listitem.Chapter) { havechapters = true; if (listitem.ChapterTitle == null) { if (listitem.Title != null) { listitem.ChapterTitle = listitem.Title; } else { listitem.ChapterTitle = Path.GetFileNameWithoutExtension(listitem.FilePath); } } } } WmaStream wavfile = new WmaStream(workinglist[fileindex].FilePath); uint samplerate = (uint)wavfile.Format.nSamplesPerSec; uint numchannels = (uint)wavfile.Format.nChannels; string tempfile = Path.GetTempFileName(); //FileStream outputfile = new FileStream(tempfile, FileMode.Create); Bento4Writer mp4writer = new Bento4Writer(m4boutputfile, tempfile); // Faac Settings faac encoder = new faac(samplerate, numchannels); inputsamples = encoder.InputSamples; maxbytes = encoder.MaxBytes; encoder.QuantQual = Quant; encoder.InputFormat = 1; //encoder.BandWidth = 8000;// (int)samplerate / 6; encoder.UseTNS = usetns; encoder.UseLFE = 0; encoder.BitRate = TargetRate * 1000; byte[] decoderspecific = encoder.DecoderSpecInfo; string[] chaptitles = new string[255]; ulong[] chapstart = new ulong[255]; uint totalchapters = 0; if (havechapters) { chapstart[0] = 0; totalchapters = 0; if (!workinglist[fileindex].Chapter) { chaptitles[0] = "Begin"; } else { chaptitles[0] = workinglist[fileindex].ChapterTitleResolver; } } procprogress.TotalFiles = workinglist.Count; procprogress.TotalKbytes = (int)wavfile.Length / 1024; procprogress.CurrentFile = fileindex + 1; procprogress.CurrentFilename = workinglist[fileindex].FilePath; read = 0; //setup buffer for data coming from faac byte[] aac_buffer = new byte[maxbytes * bufferfactor]; int aac_buffer_offset = 0; int aac_buffer_frames = 0; //DateTime start = DateTime.Now; while (fileindex < workinglist.Count && read != -1) { if (Owner.bgAACEncoder.CancellationPending) { wavfile.Close(); //outputfile.Close(); //System.IO.File.Delete(tempfile); return; } short[] isamples = new short[inputsamples]; byte[] wavbytes = new byte[inputsamples * 2]; int bytes = 0; //read from source file bytes = wavfile.Read(wavbytes, 0, (int)inputsamples * 2); //update filesamples with number of samples filesamples += (ulong)bytes / (numchannels * 2); if (wavfile.Position >= wavfile.Length || bytes < inputsamples * 2) { filems = filesamples * 1000 / samplerate; workinglist[fileindex].Duration = TimeSpan.FromMilliseconds(filems); //if that file we just ran was flagged as a chapter start, finalize the last and create a new if (workinglist[fileindex].Chapter && fileindex != 0) { chapstart[totalchapters] = totalms; totalchapters++; chaptitles[totalchapters] = workinglist[fileindex].ChapterTitleResolver; } //accumulate the total millisecond counter totalms += filems; fileindex++; //out of data, move to next file wavfile.Close(); if (fileindex < workinglist.Count) { wavfile = new WmaStream(workinglist[fileindex].FilePath); //need to read more to get required number of input samples if (bytes < inputsamples * 2) { int requiredbytes = (int)(inputsamples * 2) - bytes; byte[] extrawavbytes = new byte[requiredbytes]; int extrabytes; extrabytes = wavfile.Read(extrawavbytes, 0, requiredbytes); Array.Copy(extrawavbytes, 0, wavbytes, bytes, extrabytes); bytes += extrabytes; filesamples = (ulong)extrabytes / (numchannels * 2); } else { filesamples = 0; } procprogress.CurrentFile = fileindex + 1; procprogress.CurrentKbyte = 1; procprogress.TotalKbytes = (int)wavfile.Length / 1024; procprogress.CurrentFilename = workinglist[fileindex].FilePath; Owner.bgAACEncoder.ReportProgress(0, procprogress); lastupdate = 0; } } //Notification to user front-end if (lastupdate > 200) { if (bytes == inputsamples * 2) { procprogress.CurrentKbyte = (int)wavfile.Position / 1024; } else { procprogress.CurrentKbyte = procprogress.TotalKbytes; } lastupdate = 0; Owner.bgAACEncoder.ReportProgress(0, procprogress); } lastupdate++; //convert the byte[] into a short[] int z = 0; for (int x = 0; x < bytes; x += 2) { isamples[z] = (short)((wavbytes[x + 1] << 8) | wavbytes[x] << 0); z++; } byte[] output = new byte[maxbytes]; uint buffersize = 0; int inputsam = isamples.Length; //feed the samples to the aac encoder read = encoder.Encode(isamples, inputsam, out output, out buffersize); //if the encoder encoded, write it out to the aac buffer if (read > 0) { Array.Copy(output, 0, aac_buffer, aac_buffer_offset, read); aac_buffer_offset += read; aac_buffer_frames++; //if the buffer is full, write it out to bento if (aac_buffer_frames == bufferfactor) { mp4writer.Write(aac_buffer, aac_buffer_frames); aac_buffer_frames = 0; aac_buffer_offset = 0; } } } //end sample processing loop //flush the sample_buffer if (aac_buffer_frames > 0) { mp4writer.Write(aac_buffer, aac_buffer_frames); } encoder.Close(); encoder.Dispose(); wavfile.Close(); wavfile.Dispose(); if (havechapters) { chapstart[totalchapters] = totalms; totalchapters++; mp4writer.WriteChapters(chaptitles, chapstart, totalchapters); } ////fake chapter data //for (int fx = 0; fx < 35; fx++) { // chaptitles[fx] = "Chapter " + fx; // chapstart[fx] = (ulong)((2500 * fx) + fx); //} //totalchapters = 35; if (Owner.bgAACEncoder.CancellationPending) { return; } procprogress.CurrentFilename = "Packaging Mpeg4 Audiobook File"; procprogress.TotalFiles = 1; procprogress.CurrentFile = 1; procprogress.BentoWorking = true; Owner.bgAACEncoder.ReportProgress(0, procprogress); //tempfile = "c:\\mp4utils\\file.aac"; //chapdata = "c:\\mp4utils\\chapdata.txt"; //BentoSharp.Bento4 BentoClass = new Bento4(); //int bentoerror = BentoClass.aac2mp4(tempfile, m4boutputfile, decoderspecific, chapdata, chapstart, totalchapters); //bentoerror = BentoClass.mp4chapter("c:\\mp4utils\\bentoout.m4b","c:\\mp4utils\\chapout.m4b",chapdata,chaptimes,totalchapters); //BentoClass = null; mp4writer.Save(); //System.IO.File.Delete(tempfile); //System.IO.File.Delete(chapdata); mp4writer.Dispose(); }