public double[] SynthetizeNoise(Bitmap image, int samplerate) { using (new DebugTimer("Spectrogram: SynthetizeNoise()")) { int samples = (int)image.Width * samplerate / pixpersec; Complex[] noise = SpectrogramUtils.GetPinkNoise(samplerate * 10); // 10 sec loop double filterscale = ((double)noise.Length * 2) / samplerate; Filterbank filterbank = Filterbank.GetFilterbank(frequency_axis, filterscale, basefreq, bandwidth, overlap); int top_index = (int)(maxfreq * filterscale); var @out = new double[samples]; for (int bandidx = 0; bandidx < image.Height; ++bandidx) { //if (cancelled()) // return List<int>(); OutputBandProgress(bandidx, image.Height - 1); // filter noise Pair <int, int> range = filterbank.GetBand(bandidx); //std::cout << bandidx << "/"<<image.height()<<"\n"; Console.Out.WriteLine("(noise) sample: {0}", range.Second - range.First); var filtered_noise = new Complex[noise.Length]; // TODO: copy noise into filtered_noise array //std.copy(noise.begin()+range.first, noise.begin()+Math.Min(range.second, top_index), filtered_noise.begin()+range.first); //apply_window(filtered_noise, range.first, filterscale); // ifft noise double[] noise_mod = SpectrogramUtils.padded_IFFT(ref filtered_noise); // resample spectrogram band double[] envelope = SpectrogramUtils.Resample(EnvelopeFromSpectrogram(image, bandidx), samples); // modulate with looped noise for (uint i = 0; i < samples; ++i) { @out[i] += envelope[i] * noise_mod[i % noise_mod.Length]; } } SpectrogramUtils.NormalizeSignal(ref @out); return(@out); } }
public double[] SynthetizeSine(Bitmap image, int samplerate) { using (new DebugTimer("Spectrogram: SynthetizeSine(Bitmap)")) { int samples = image.Width * samplerate / pixpersec; var spectrum = new Complex[samples / 2 + 1]; double filterscale = ((double)spectrum.Length * 2) / samplerate; Filterbank filterbank = Filterbank.GetFilterbank(frequency_axis, filterscale, basefreq, bandwidth, overlap); for (int bandidx = 0; bandidx < image.Height; ++bandidx) { // TODO: support cancelling this process OutputBandProgress(bandidx, image.Height); double[] envelope = EnvelopeFromSpectrogram(image, bandidx); // Find maximum number when all numbers are made positive. //double max = envelope.Max((b) => Math.Abs(b)); //Console.WriteLine(max); // random phase between +-pi double phase = SpectrogramUtils.RandomDoubleMinus1ToPlus1() * Math.PI; var bandsignal = new double[envelope.Length * 2]; for (int j = 0; j < 4; ++j) { double sine = Math.Cos(j * Math.PI / 2 + phase); for (int i = j; i < bandsignal.Length; i += 4) { bandsignal[i] = envelope[i / 2] * sine; } } var filterband = SpectrogramUtils.padded_FFT(ref bandsignal); for (int i = 0; i < filterband.Length; ++i) { double x = (double)i / filterband.Length; // normalized blackman window antiderivative filterband[i] *= x - ((0.5 / (2.0 * Math.PI)) * Math.Sin(2.0 * Math.PI * x) + (0.08 / (4.0 * Math.PI)) * Math.Sin(4.0 * Math.PI * x) / 0.42); } //Console.Out.WriteLine("Spectrum size: {0}", spectrum.Length); //std::cout << bandidx << ". filterband size: " << filterband.Length << "; start: " << filterbank->GetBand(bandidx).first <<"; end: " << filterbank->GetBand(bandidx).second << "\n"; double center = filterbank.GetCenter(bandidx); double offset = Math.Max((double)0, center - filterband.Length / 2); //Console.Out.WriteLine("Offset: {0} = {1} hz", offset, offset/filterscale); for (int i = 0; i < filterband.Length; ++i) { int spectrumIndex = (int)(offset + i); if (spectrumIndex > 0 && spectrumIndex < spectrum.Length) { spectrum[spectrumIndex] += filterband[i]; } } } double[] @out = SpectrogramUtils.padded_IFFT(ref spectrum); Console.Out.WriteLine("Samples: {0} -> {1}", @out.Length, samples); SpectrogramUtils.NormalizeSignal(ref @out); return(@out); } }