/// ======================================================================================================= public static string WavPlay(string wav_path, string form_alias = "") { CAT.InteractiveAddNamedOverlay("WAVPLAY", "Preparing for play of " + wav_path); string returnvalue = ""; string path = API.DISK.AutoAddBaseDirectory(API.DISK.AutoAddExt(wav_path, ".wav")); DateTime starttime = DateTime.Now; if (!File.Exists(path)) { string err = "Error: Could not find file '" + path + "'"; CAT.InteractiveUpdateNamedOverlay("WAVPLAY", err, CAT.Status.FAIL); return(err); } string name = "p" + CircularBufer; CircularBufer++; mciSendString("open " + path + " type waveaudio alias " + name, null, 0, 0); mciSendString("play " + name, null, 0, 0); returnvalue += "Load time is " + (DateTime.Now - starttime).TotalMilliseconds + "ms. "; mciSendString("play " + name + " notify", null, 0, 0); StringBuilder sb = new StringBuilder(128); mciSendString("status " + name + " length", sb, 128, 0); string newsb = sb.ToString(); ulong songlength = Convert.ToUInt64(sb.ToString()); CAT.FormAccess(CAT.FormDelegates.SetLength, new object[] { songlength }, form_alias); returnvalue += "Length is " + songlength + "ms. "; ulong position = 0; while (!CAT.AbortAll && !CAT.AbortCurrent && position < songlength) { Thread.Sleep(1); // 1 ms resolution - frees up CPU mciSendString("status " + name + " position", sb, 128, 0); newsb = sb.ToString(); position = Convert.ToUInt64(sb.ToString()); CAT.InteractiveUpdateNamedOverlay("WAVPLAY", "Playing " + path + " " + position + @"/" + songlength + "ms", CAT.Status.BUSY); if (SetPos) { SetPos = false; double pos = (double)CAT.FormAccess(CAT.FormDelegates.GetPosTrackBar, null, form_alias) * songlength; mciSendString("seek " + name + " to " + (int)(pos), null, 0, 0); mciSendString("play " + name + " notify", null, 0, 0); } else { CAT.FormAccess(CAT.FormDelegates.SetPosTrackBar, new object[] { ((double)position / songlength) }, form_alias); } if (Restarter) { Restarter = false; mciSendString("seek " + name + " to start", sb, 128, 0); mciSendString("play " + name + " notify", null, 0, 0); } } mciSendString("close " + name, null, 0, 0); return(returnvalue); }
/// ======================================================================================================= public static Return BUILD(string source_path, string timebase_ms, string resolution, string output_folder) { CAT.InteractiveAddNamedOverlay("WAVBUILD", "Preparing for build of " + source_path); string sourcepath = DISK.AutoAddExt(source_path, ".txt"); string[] sourcelines = File.ReadAllLines(DISK.AutoAddBaseDirectory(sourcepath)); DateTime starttime = DateTime.Now; WAVFormat masterfmt = new WAVFormat(2, 96000, 3); // Ideal format double timebase = string.IsNullOrWhiteSpace(timebase_ms) ? 250 : Convert.ToDouble(timebase_ms); int res = string.IsNullOrWhiteSpace(resolution) ? 32 : Convert.ToInt16(resolution); int totaltimems = res == 1 ? Convert.ToInt32(timebase * res) : Convert.ToInt32(timebase * res) + 5000; // 5 seconds decay uint masterdatasize = ConvertMsToNumberOfBytes(Convert.ToUInt32(totaltimems), masterfmt); byte[] masteralldata = CreateBlankWave(Convert.ToUInt32(totaltimems), masterfmt); int masterstartofdata = GetStartOfDataIndex(masteralldata); uint masterlocation = 0; int rowcount = 0; int rowmax = sourcelines.Length / 2; CAT.InteractiveUpdateNamedOverlay("WAVBUILD", "Starting build of " + source_path); for (int linenumber = 0; linenumber < sourcelines.Length - 1; linenumber += 2) { rowcount++; string files; byte[] newalldata; double volumeleft = 1.0; double volumeright = 1.0; if (sourcelines[linenumber].Contains("\t")) { files = sourcelines[linenumber].Split('\t')[0]; try { string volstring = sourcelines[linenumber].Split('\t')[1]; if (volstring.Contains(";")) { volumeleft = Convert.ToDouble(volstring.Split(';')[0]); volumeright = Convert.ToDouble(volstring.Split(';')[1]); } else if (volstring.Contains(":")) { volumeleft = Convert.ToDouble(volstring.Split(':')[0]); volumeright = Convert.ToDouble(volstring.Split(':')[1]); } else { volumeleft = Convert.ToDouble(volstring); volumeright = Convert.ToDouble(volstring); } } catch { /* use default */ } } else { files = sourcelines[linenumber]; } int filecount = 0; foreach (string filename in files.Split(';')) { filecount++; string updatedfilename = filename; if (!filename.Contains(".wav")) { updatedfilename = filename + ".wav"; } // Auto add extension if (!File.Exists(updatedfilename)) { updatedfilename = output_folder + @"\" + updatedfilename; } // auto add output folder if (File.Exists(updatedfilename)) { newalldata = File.ReadAllBytes(updatedfilename); WAVFormat newfmt = ReadFormat(newalldata); int newstartofdata = GetStartOfDataIndex(newalldata); int newdatasize = newalldata.Length - newstartofdata; byte[] newdata = new byte[newdatasize]; Array.Copy(newalldata, newstartofdata, newdata, 0, newdatasize); // copy data - only data is used from new file (header is discarded) string argument = sourcelines[linenumber + 1]; if (!string.IsNullOrWhiteSpace(argument)) { string[] arguments = argument.Split(','); int locationcount = 0; foreach (string location in arguments) { locationcount++; uint locationtouse = Convert.ToUInt32(Convert.ToDouble(location)); if (location.Contains("+")) { masterlocation += locationtouse; } else { masterlocation = locationtouse; } string currentbuilditem = " (row:" + rowcount + @"/" + rowmax + " file:" + filecount + @"/" + files.Split(';').Length + " location:" + locationcount + @"/" + arguments.Length + ")"; CAT.InteractiveUpdateNamedOverlay("WAVBUILD", source_path + ": Adding " + updatedfilename + " at " + masterlocation + currentbuilditem, API.CAT.Status.PASS); uint masteroffset = ConvertMsToNumberOfBytes(masterlocation, masterfmt); bool isleft = true; // Scroll through each of the new data indeces for (int newindex = 0; newindex < newdatasize - (int)newfmt.ByteDepth; newindex += (int)(newfmt.NumberOfChannels * newfmt.ByteDepth)) { double masterkhz = ((ulong)masterfmt.ByteDepth * (ulong)masterfmt.NumberOfChannels * (ulong)masterfmt.SampleRate) / 1000.0; double newkhz = ((ulong)newfmt.ByteDepth * (ulong)newfmt.NumberOfChannels * (ulong)newfmt.SampleRate) / 1000.0; double ratio = masterkhz / newkhz; int masterindex = (int)(newindex * ratio); if (masterindex + masteroffset < masterdatasize) { // Scroll to (left channel) sample start byte while ((masterindex + masteroffset) % (masterfmt.NumberOfChannels * masterfmt.ByteDepth) != 0) { masterindex--; } for (int i = 0; i < newfmt.NumberOfChannels; i++) { for (int j = 0; j < (int)Math.Ceiling((double)(masterfmt.SampleRate / newfmt.SampleRate)); j++) // Fill in gaps { int mastersamplelocation = masterstartofdata + (int)masteroffset + masterindex + i * (int)masterfmt.ByteDepth + j * ((int)masterfmt.NumberOfChannels * (int)masterfmt.ByteDepth); int mastersample = Deserialise(masteralldata, mastersamplelocation, (int)masterfmt.ByteDepth); int newsample = Deserialise(newdata, newindex + i * (int)newfmt.ByteDepth, (int)newfmt.ByteDepth); double masternorm = Normalise(mastersample, (int)masterfmt.ByteDepth); double volume = isleft ? volumeleft : volumeright; isleft = !isleft; double combined = (masternorm + volume * Normalise(newsample, (int)newfmt.ByteDepth)); // Limiting proved highly effective if (combined > 0.499999) { combined = 0.499999; // returndata += "Clip (positive) detected at " + ConvertNumberOfBytesToMs((uint)j, newfmt); } if (combined < -0.499999) { combined = -0.499999; // returndata += "Clip (negative) detected at " + ConvertNumberOfBytesToMs((uint)j, newfmt); } Serialise(ref masteralldata, mastersamplelocation, Denormalise(combined, (int)masterfmt.ByteDepth), (int)masterfmt.ByteDepth); // Copy to both channels if (newfmt.NumberOfChannels == 1) { Serialise(ref masteralldata, masterstartofdata + (int)masteroffset + masterindex + (int)masterfmt.ByteDepth, Denormalise(combined, (int)masterfmt.ByteDepth), (int)masterfmt.ByteDepth); } } } } } } } else { CAT.InteractiveAddOverlay(updatedfilename + " ignored - no times specified", API.CAT.Status.WARN); } } else { CAT.InteractiveAddOverlay(updatedfilename + " does not exist... continued", API.CAT.Status.FAIL); } } } if (!Directory.Exists(output_folder)) { Directory.CreateDirectory(output_folder); CAT.InteractiveAddOverlay("Created " + output_folder + " directory", API.CAT.Status.WARN); } try { string outputfilename = output_folder + "\\" + Path.GetFileNameWithoutExtension(sourcepath) + ".wav"; File.WriteAllBytes(outputfilename, masteralldata); CAT.InteractiveAddOverlay("Built " + outputfilename, API.CAT.Status.PASS); CAT.InteractiveAddOverlay("Build time " + (DateTime.Now - starttime).TotalMilliseconds + "ms", API.CAT.Status.INFO); } catch (Exception e) { CAT.InteractiveAddOverlay("Failed build:\r\n" + API.CAT.ErrorMsg(e), API.CAT.Status.FAIL); } return(new Return("Done")); }