const float bufferSize = 0.05f; // 1/20 second buffer /// <summary> /// Find the start of music or silence /// </summary> /// <param name="start">seconds</param> /// <param name="silence">true to find silence, false to find music</param> /// <param name="maxLength">Max seconds to process (0 or less means rest of file)</param> /// <returns>True if music or silence found</returns> public bool FindGap(float start, bool silence, float maxLength) { if (start < 0) start = 0; // End of file Position = m_Reader.WaveFormat.BytesToSeconds(m_Reader.Length); AverageVolume = 0; if (start > Position) return false; // Beyond end of file m_Reader.Position = Math.Max(0, m_Reader.WaveFormat.SecondsToBytes(start)); // Try to work out where the music starts and/or ends m_Provider = new FilteredSampleProvider(m_Reader, Properties.Settings.Default.SilenceFilterCentre, Properties.Settings.Default.SilenceFilterQ); int length = m_Provider.StandardBufferSize; // Number of samples from beginning of file long count = m_Reader.WaveFormat.SecondsToSamples(start); float silenceThreshold = silence ? Properties.Settings.Default.StartSilenceThreshold : Properties.Settings.Default.EndSilenceThreshold; int foundCount = 0; // Number of contiguous matching buffers found so far int minBuffers = 10; // Number of contiguous buffers required int maxBuffers = maxLength <= 0 ? int.MaxValue : (int)(maxLength / bufferSize); // Max buffers to read float[] volumes = new float[minBuffers + 1]; // Volumes of each of the last few buffers float totalVolume = 0; // Lags minBuffers behind current read bool result = false; int i = 0; try { for ( ; i < maxBuffers; i++) { float avg = m_Provider.AvgBlockVolume(); totalVolume += volumes[0]; // Accumulate total from minBuffers ago Array.Copy(volumes, 1, volumes, 0, minBuffers); // Shift array down 1 volumes[minBuffers] = avg; // And add latest value if (silence == (avg <= silenceThreshold)) { // Found a buffer of what we are looking for if (++foundCount == minBuffers) { // Have found minBuffers contiguous of what we are looking for count -= foundCount * length; // Go back to first buffer that was what we are looking for if (!silence) count--; // leave a buffer of silent gap before the start of the music Position = m_Reader.WaveFormat.SamplesToSeconds(count); // Position in seconds result = true; break; } } else { foundCount = 0; // Not enough contiguous buffers - restart count } count += length; } } catch (System.IO.EndOfStreamException) { } AverageVolume = totalVolume / (i - foundCount); return result; }
private void WaveControl_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { stopPlayer(); if (e.Button == MouseButtons.Left) { cursorEvent = null; m_DragStart = e; if (m_Cursors != null) { // Work out which cursor we are close to float pixelsPerSecond = Width / m_LengthSeconds; int l = -1, r = -1; for (int i = 0; i < m_Cursors.Length; i++) { PositionCursor c = m_Cursors[i]; if (!c.Active) continue; float x = (c.Position - m_StartSeconds) * pixelsPerSecond; // Position of cursor in pixels if (Math.Abs(x - e.X) < 10) { // We are close to this cursor if (x < e.X) { // Cursor to left of mouse if (l == -1 || c.Position >= m_Cursors[l].Position) l = i; // It's the closest one to the mouse, or same position but larger cursor no } else { // Cursor to right of mouse if (r == -1 || c.Position < m_Cursors[r].Position) r = i; // It's the closest one to the mouse or same position but smaller cursor no } } } int csr = -1; // Cursor we want to drag if(l == -1) { // No cursor to left if(r == -1) // Or right either return; csr = r; // Choose one to right } else if (r == -1) { // No cursor to right csr = l; // Choose one to left } else { // Cursors on both sides - choose closest float lx = (m_Cursors[l].Position - m_StartSeconds) * pixelsPerSecond; float rx = (m_Cursors[r].Position - m_StartSeconds) * pixelsPerSecond; if (rx - e.X < e.X - lx) csr = r; else csr = l; } // Set up cursor event for cursor cursorEvent = new CursorMovedEventArgs(m_Cursors[csr]); m_Dragging = false; // Not dragging yet } } else if (e.Button == System.Windows.Forms.MouseButtons.Right) { // Right click displays filtered average volume in a tooltip try { float pixelsPerSecond = Width / m_LengthSeconds; float p = m_StartSeconds + e.X / pixelsPerSecond; // Position of click in seconds m_Wavefile.Position = WaveFormat.SecondsToBytes(p); FilteredSampleProvider f = new FilteredSampleProvider(m_Wavefile, Properties.Settings.Default.SilenceFilterCentre, Properties.Settings.Default.SilenceFilterQ); // Display average volume of block at this position float avg = f.AvgBlockVolume(); string tip = string.Format("pos={0} level={1:#0.0####}", p.ToTimeSpanString(), avg); Program.Trace(tip); toolTip.Show(tip, this); } catch { } } }