public Sound(Sound other) { mChannels = other.mChannels; mDescretionRate = other.mDescretionRate; mBitsPerSample = other.mBitsPerSample; mSound = new float[mChannels][]; for (int i = 0; i < mChannels; i++) { mSound[i]=new float[other.mSound[i].Length]; Array.Copy(other.mSound[i],mSound[i],other.mSound[i].Length); } }
/// <summary> /// Combination of sound copying and volume adjusting /// </summary> /// <param name="percent">Target volume level in percents</param> /// <param name="channel">Channel to use in setVolume</param> /// <returns></returns> public Sound CopyWithVolume( double percent, int channel) { Sound result = new Sound(this); result.SetVolume(percent,channel); return result; }
bool SameSized(Sound sound) { if (mSound == null || sound.mSound == null) return false; if (mSound.Length != sound.mSound.Length) return false; for (int i = 0; i < mSound.Length; i++) { if (mSound[i].Length != sound.mSound[i].Length) return false; } return true; }
public void Convolve(Sound kernel,int channelTo, int channelFrom) { FloatVector kernelVector = new FloatVector(kernel.mSound[channelFrom]); FloatVector dataVector = new FloatVector(mSound[channelTo]); Float1DConvolution convolution = new Float1DConvolution(kernelVector,dataVector.Length); FloatVector result = convolution.Convolve(dataVector); mSound[channelTo] = result.ToArray(); }
public void Copy(Sound sound) { mChannels = sound.mChannels; mDescretionRate = sound.mDescretionRate; mBitsPerSample = sound.mBitsPerSample; if (!SameSized(sound)) { mSound = new float[mChannels][]; for (int i = 0; i < mChannels; i++) { mSound[i] = new float[sound.mSound[i].Length]; Array.Copy(sound.mSound[i], mSound[i], sound.mSound[i].Length); } } else { for (int i = 0; i < mChannels; i++) { Array.Copy(sound.mSound[i], mSound[i], sound.mSound[i].Length); } } }
/// <summary> /// Create simple sine soundwave /// </summary> /// <param name="freq">Frequency of wave</param> /// <returns></returns> public static Sound SimpleWave(int freq) { Sound result = new Sound(1, 44100, 16); result.mSound = new float[1][]; result.mSound[0] = new float[result.mDescretionRate*10]; for (int i = 0; i < result.mSound[0].Length; i++) { double x = freq*i/(result.mDescretionRate*Math.PI); result.mSound[0][i] = (float) Math.Sin(x); } return result; }
/// <summary> /// Adding one sound to another /// </summary> /// <param name="sound">Sound to add</param> /// <param name="channelFrom">Channel of sound to use for sum</param> /// <param name="channelTo">Target channel of sound</param> /// <param name="offset">Time offset in milliseconds</param> /// <param name="volume">Optional parameter to add with certain volume level</param> public void Add(Sound sound,int channelFrom,int channelTo, int offset, double volume = 1) { if(channelTo>mChannels || channelTo<0) throw new ArgumentException("Channel number invalid"); if (channelFrom > sound.mChannels || channelFrom<0) throw new ArgumentException("Channel number invalid"); if(mDescretionRate != sound.mDescretionRate) throw new ArgumentException("different discretion rates"); if(mSound[channelTo] == null) mSound[channelTo] = new float[0]; float[] fromSound = sound.mSound[channelFrom]; float[] temp = new float[Math.Max(mSound[channelTo].Length, offset + fromSound.Length)]; for (int i = 0; i < mSound[channelTo].Length; i++) { temp[i] = mSound[channelTo][i]; } mSound[channelTo] = null; for (int i = offset; i < temp.Length; i++) { temp[i] += i - offset < fromSound.Length ? (float)volume*fromSound[i - offset] : 0; } mSound[channelTo] = temp; }
private void RecordButton_Click(object sender, RoutedEventArgs e) { if (!mRoom.IsValid()) { MessageBox.Show(this, "Room is invalid, check status bar for further instructions"); return; } try { mReflectionWorker = new BackgroundWorker(); mReflectionWorker.WorkerSupportsCancellation = true; RecordButton.IsEnabled = false; for (int i = 0; i < buttonNumber - 1; i++) { mToolButtons[i].IsChecked = false; mToolButtons[i].IsEnabled = false; } RoomOpenMenuItem.IsEnabled = false; SoundOpenMenuItem.IsEnabled = false; UndoMenuItem.IsEnabled = false; RedoMenuItem.IsEnabled = false; ClearMenuItem.IsEnabled = false; PropsAccItem.IsEnabled = false; PresetsAccItem.IsEnabled = false; CeilingHeightBox.IsEnabled = false; FloorMaterialBox.IsEnabled = false; RefVolumeSlider.IsEnabled = false; RefDepthSlider.IsEnabled = false; CeilingMaterialBox.IsEnabled = false; PlayButton.IsEnabled = false; CancelButton.IsEnabled = true; RoomCanvas.MouseUp -= RoomCanvas_MouseUp; ((TextBlock)PropsPanel.Children[0]).Text = "Properties"; PropsPanel.Children.RemoveRange(1, PropsPanel.Children.Count - 1); mSelectedRoomObject = null; DrawRoom(); SoundProgressBar.Visibility = Visibility.Visible; SoundProgressBar.Value = 0; SoundProgressBar.Maximum = mRoom.Sources.Count*mRoom.Listeners.Count*(mRoom.Walls.Count*2+1)+2; mReflectionWorker.WorkerReportsProgress = true; int num = 0; EventHandler reporter= delegate { mReflectionWorker.ReportProgress(num++); }; mRoom.CalculationProgress += reporter; mReflectionWorker.DoWork += delegate { try { mRoom.CalculateSound(mReflectedVolume); } catch (Exception ex) { Dispatcher.Invoke((Action) delegate { if (CancelButton.IsEnabled) { MessageBox.Show(this, "Error occurred during recording process: " + ex.Message); throw ex; } }); } }; mReflectionWorker.RunWorkerCompleted += delegate { if (!CancelButton.IsEnabled) return; CancelButton.IsEnabled = false; mResultSound = mRoom.GetSoundFromListeners(); mResultSound.AdjustVolume(0.75); if (!mReflectionWorker.CancellationPending) { SoundSaveMenuItem.IsEnabled = true; PlayButton.IsEnabled = true; } RecordButton.IsEnabled = true; mRoom.CalculationProgress -= reporter; SoundProgressBar.Visibility = Visibility.Hidden; for (int i = 0; i<buttonNumber-1;i++) { mToolButtons[i].IsEnabled = true; } RoomOpenMenuItem.IsEnabled = true; SoundOpenMenuItem.IsEnabled = true; UndoMenuItem.IsEnabled = true; RedoMenuItem.IsEnabled = true; ClearMenuItem.IsEnabled = true; PropsAccItem.IsEnabled = true; PresetsAccItem.IsEnabled = true; CeilingHeightBox.IsEnabled = true; FloorMaterialBox.IsEnabled = true; RefVolumeSlider.IsEnabled = true; RefDepthSlider.IsEnabled = true; CeilingMaterialBox.IsEnabled = true; RoomCanvas.MouseUp+=RoomCanvas_MouseUp; StatusBlock.Foreground=Brushes.DarkGreen; StatusBlock.Text = mReflectionWorker.CancellationPending?"Recording cancelled":"Recording successfully finished"; }; mReflectionWorker.ProgressChanged += (obj,args)=> { SoundProgressBar.Value++; }; mReflectionWorker.RunWorkerAsync(); } catch (Exception exception) { MessageBox.Show(this, "Error occurred during recording process: " + exception.Message); } }
/// <summary> /// Get wave sound data from file /// </summary> /// <param name="filename">Path to file</param> /// <returns></returns> public static Sound GetSoundFromWav(string filename) { FileInfo file = new FileInfo(filename); if(!file.Exists || file.Extension.Substring(1)!="wav") throw new ArgumentException("The given file is not an existent wav file"); Sound sound = new Sound(); try { byte[] bytes = File.ReadAllBytes(filename); if(bytes[20]!=1 || bytes[21]!=0) throw new ArgumentException("The given file is not in standart WAV format"); sound.mChannels = bytes[23]*256 + bytes[22]; sound.mDescretionRate = bytes[27]*16777216 + bytes[26]*65536 + bytes[25]*256 + bytes[24]; sound.mBitsPerSample = BytesToInt(bytes[34], bytes[35]); if (sound.mBitsPerSample == 0) sound.mBitsPerSample = 16; int pos = 12; while (!(bytes[pos] == 100 && bytes[pos + 1] == 97 && bytes[pos + 2] == 116 && bytes[pos + 3] == 97)) { pos += 4; int chunkSize = bytes[pos] + bytes[pos + 1]*256 + bytes[pos + 2]*65536 + bytes[pos + 3]*16777216; pos += 4 + chunkSize; } pos += 8; int samples = (bytes.Length - pos)/(sound.mBitsPerSample/8); if (sound.mChannels == 2) samples = (samples%2 == 0) ? samples/2 : samples/2 + 1; sound.mSound = new float[sound.mChannels][]; for (int i = 0; i < sound.mChannels; i++) { sound.mSound[i] = new float[samples]; } int j = 0; sound.mMaxValue = (int) (Math.Pow(256, sound.mBitsPerSample/8)/2); while (pos + 1 < bytes.Length) { for (int k = 0; k < sound.mChannels; k++) { if (pos + 1 >= bytes.Length) break; if (sound.mBitsPerSample == 16) { sound.mSound[k][j] = (float) BytesToInt(bytes[pos], bytes[pos + 1])/sound.mMaxValue; } else { int curSound = 0; int bytesNum = sound.mBitsPerSample/8; for (int i = 0; i < bytesNum; i++) { byte nextByte = bytes[pos + i]; nextByte <<= 8*i; curSound |= nextByte; } if (curSound > sound.mMaxValue + 1) { curSound -= 2*sound.mMaxValue + 1; } sound.mSound[k][j] = (float) curSound/sound.mMaxValue; } pos += (sound.mBitsPerSample/8); } j++; } return sound; } catch (Exception e) { ArgumentException ex = new ArgumentException("The chosen file seems not to be a valid .wav file"); throw ex; } }
private void OpenKernelSoundButton_Click(object sender, RoutedEventArgs e) { OpenFileDialog dialog = new OpenFileDialog { CheckPathExists = true, CheckFileExists = true, Filter = "Wave Sound Files (*.wav)|*.wav" }; bool? result = dialog.ShowDialog(); if (result == true) { try { mKernelSound = Sound.GetSoundFromWav(dialog.FileName); } catch (Exception exception) { MessageBox.Show("Error occured during opening: " + exception.Message); ConvolveButton.IsEnabled = false; return; } KernelSeries.DataContext = mKernelSound.ToKeyValuePairs(0); MessageBox.Show("Successfully opened " + dialog.FileName, "Sound Open", MessageBoxButton.OK); if (mConvolveBaseSound != null) { if (CheckSound(mKernelSound, mConvolveBaseSound)) { ConvolveButton.IsEnabled = true; ConvolutionStatusBlock.Foreground=Brushes.Green; ConvolutionStatusBlock.Text = "Everything is OK. You can start convolution."; } else { ConvolveButton.IsEnabled = false; ConvolutionStatusBlock.Foreground = Brushes.Red; ConvolutionStatusBlock.Text = "Chosen sound and impulse response should have same sound parameters"; } } KernelSoundBlock.Text = dialog.SafeFileName; } }
private void PlayButton_OnChecked(object sender, RoutedEventArgs e) { if (mResultSound != null) { const string filename = "~temp_sound.wav"; Sound resultTwoCh = new Sound(2,mResultSound.DiscretionRate,mResultSound.BitsPerSample); resultTwoCh.Add(mResultSound,0,0,0); resultTwoCh.Add(mResultSound, mResultSound.Channels > 1 ? 1 : 0, 1, 0); resultTwoCh.CreateWav(filename); File.SetAttributes(filename,File.GetAttributes(filename)|FileAttributes.Hidden); mPlayer = new SoundPlayer(filename); mPlayer.Load(); mPlayer.PlayLooping(); } }
private void ConvolveButton_Click(object sender, RoutedEventArgs e) { BackgroundWorker worker =new BackgroundWorker(); ConvolutionStatusBlock.Text = "In progress..."; ConvolveButton.IsEnabled = false; OpenBaseSoundButton.IsEnabled = false; OpenKernelSoundButton.IsEnabled = false; SaveConvolvedButton.IsEnabled = false; worker.DoWork += delegate { if (mKernelSound.Channels < mConvolveBaseSound.Channels) { for (int i = 0; i < mConvolveBaseSound.Channels; i++) { mConvolveBaseSound.Convolve(mKernelSound, i, 0); } } else { if (mKernelSound.Channels > mConvolveBaseSound.Channels) { Sound TempSound = new Sound(mKernelSound.Channels,mConvolveBaseSound.DiscretionRate,mConvolveBaseSound.BitsPerSample); for (int i = 0; i < mKernelSound.Channels; i++) { TempSound.Add(mConvolveBaseSound,0,i,0); } mConvolveBaseSound = TempSound; } for (int i = 0; i < mConvolveBaseSound.Channels; i++) { mConvolveBaseSound.Convolve(mKernelSound, i, i); } } mConvolveResultSound = mConvolveBaseSound; mConvolveResultSound.AdjustVolume(0.8); mConvolveBaseSound = null; mKernelSound = null; }; worker.RunWorkerCompleted += delegate { BaseSoundBlock.Text = KernelSoundBlock.Text = "No file loaded"; ConvolutionStatusBlock.Text = "Convolution finished. Feel free to save result"; mConvolveBaseSound = null; mKernelSound = null; if (mConvolveResultSound == null) { ConvolutionStatusBlock.Foreground=Brushes.Red; ConvolutionStatusBlock.Text = "NMath library needs to be installed for convolution"; } OpenBaseSoundButton.IsEnabled = true; OpenKernelSoundButton.IsEnabled = true; SaveConvolvedButton.IsEnabled = true; }; worker.RunWorkerAsync(); }
private bool CheckSound(Sound first, Sound second) { return (first.BitsPerSample == second.BitsPerSample); }
private void SoundOpenMenuItem_Click(object sender, RoutedEventArgs e) { OpenFileDialog dialog = new OpenFileDialog {CheckPathExists = true, CheckFileExists = true, Filter = "Wave Sound Files (*.wav)|*.wav"}; bool? result = dialog.ShowDialog(); if (result == true) { try { mBaseSound = Sound.GetSoundFromWav(dialog.FileName); } catch (Exception exception) { MessageBox.Show("Error occured during opening: " + exception.Message); return; } RecordButton.IsEnabled = true; MessageBox.Show("Successfully opened " + dialog.FileName,"Sound Open",MessageBoxButton.OK); foreach (SoundPoint source in mRoom.Sources) { source.Sound = mBaseSound; } FileNameBlock.Text = "Source: "+dialog.SafeFileName; SoundSeries.DataContext = mBaseSound.ToKeyValuePairs(0); // Timeline.Visibility = Visibility.Visible; DrawRoom(); } }
public void PrimaryReflectionsComplexTest() { AS.Wall.Material mat = AS.Wall.Material.OakWoodCarpeted; AS.Room room = new AS.Room(); room.FloorMaterial = AS.Wall.Material.Brick; room.CeilingMaterial = AS.Wall.Material.OakWood; room.CeilingHeight = 2; room.AddWall(new AS.Wall(0, 0, 4, 0, mat)); room.AddWall(new AS.Wall(0, 0, 0, 10, mat)); room.AddWall(new AS.Wall(4, 0, 4, 10, mat)); room.AddWall(new AS.Wall(0, 10, 4, 10, mat)); AS.SoundPoint source = new AS.SoundPoint(2, 1); source.Sound = AS.Sound.GetSoundFromWav(@"D:\Whistling.wav"); room.AddSource(source); room.AddListener(new AS.ListenerPoint(1, 8,new AS.Line(0,0,-1,0),AS.ListenerPoint.Cardioid)); room.AddListener(new AS.ListenerPoint(3, 8, new AS.Line(0,0,1,0),AS.ListenerPoint.Cardioid )); room.CalculateSound(); AS.Sound sound = new AS.Sound(2,source.Sound.DiscretionRate,source.Sound.BitsPerSample); sound.Add(room.Listeners[1].Sound,0,0,0); sound.Add(room.Listeners[0].Sound,0,1,0); sound.AdjustVolume(0.75); //sound.SetVolume(0.6,0); //sound.SetVolume(0.6,1); sound.CreateWav(@"D:\Result.wav"); }
public void PrimaryReflectionsHugeTest() { AS.Wall.Material mat = AS.Wall.Material.Brick; AS.Room room = new AS.Room(); room.FloorMaterial = AS.Wall.Material.Brick; room.CeilingMaterial = AS.Wall.Material.OakWood; room.CeilingHeight = 2; room.AddWall(new AS.Wall(0,5,10,0,mat)); room.AddWall(new AS.Wall(10,0,20,5,mat)); room.AddWall(new AS.Wall(20,5,20,45,mat)); room.AddWall(new AS.Wall(20,45,0,45,mat)); room.AddWall(new AS.Wall(0,45,0,5, mat)); AS.SoundPoint source = new AS.SoundPoint(10,40); source.Sound = AS.Sound.GetSoundFromWav(@"D:\dirac.wav"); room.AddSource(source); room.AddListener(new AS.ListenerPoint(9,4)); room.AddListener(new AS.ListenerPoint(11,4)); room.CalculateSound(); AS.Sound sound = new AS.Sound(2, source.Sound.DiscretionRate, source.Sound.BitsPerSample); sound.Add(room.Listeners[1].Sound, 0, 0, 0); sound.Add(room.Listeners[0].Sound, 0, 1, 0); sound.AdjustVolume(0.75); //sound.SetVolume(0.6, 0); //sound.SetVolume(0.6, 1); sound.CreateWav(@"D:\diracR.wav"); Console.WriteLine(GC.GetTotalMemory(false)/(1024*1024)+""); }