// Событие записи для объекта Wave - анализ сигнала с управлением автоподстройкой и световыми эффектами private void WaveIn_DataAvailable(object sender, WaveInEventArgs e) { int samplesRecorded = e.BytesRecorded / (waveIn.WaveFormat.BitsPerSample / 8); // размер полученного буфера int numChannels = waveIn.WaveFormat.Channels; float sampleRate = waveIn.WaveFormat.SampleRate; UnionStruct u = new UnionStruct(); u.bytes = e.Buffer; Complex[] data = new Complex[size]; // буфер для БПФ float currentAmplitude = 0; // готовим сигнал к БПФ int j = 0; for (int i = 0; i < samplesRecorded && j < size; i += numChannels) { float left = u.floats[i]; float right = u.floats[i + (numChannels - 1)]; float avg = (left + right) / 2; if (Math.Abs(avg) > currentAmplitude) { currentAmplitude = Math.Abs(avg); } //float value = avg * (float)FastFourierTransform.BlackmannHarrisWindow(j, size); float value = avg * blackmanWindow(j, size); data[j].X = value; data[j].Y = 0; j++; } if (currentAmplitude > inNoiseLevel) { stopWatch.Reset(); if (agcCheckBox.Checked) { float regulatorRatio = currentAmplitude * gain < targetAmplitude ? upRegulatorRatio : downRegulatorRatio; gain += regulatorRatio * (targetAmplitude / currentAmplitude - gain); for (int i = 0; i < j; i++) { data[i].X *= gain; } } // остаток наполняем нулями while (j < size) { data[j].X = 0; data[j].Y = 0; j++; } FastFourierTransform.FFT(true, log2N, data); // выполняем быстрое преобразование Фурье int maxI = -1; // индекс макисмальной амплитуды float max = -1; // значение максимальной амплитуды int band = 0; for (int i = 0; i < numBands; i++) { values[i] = 0; } for (int i = 0; i < size / 2; i++) { float currentFreq = sampleRate * i / size; if (band < numBands - 1 && currentFreq > bandDefs[band]) { band++; } float amp = data[i].X * data[i].X + data[i].Y * data[i].Y; if (amp > outNoiseLevel) { values[band] += amp; } if (amp > max) { max = amp; maxI = i; } } for (int i = 0; i < numBands; i++) { values[i] = (float)Math.Sqrt(values[i]) * valuesScale[i]; } } else { stopWatch.Stop(); double seconds = stopWatch.Elapsed.TotalSeconds; stopWatch.Start(); if (seconds > downtimeInSeconds && fadeCheckBox.Checked) { light_effects(values, RGB_FADE_EFFECT); } else { for (int i = 0; i < numBands; i++) { values[i] = 0; } } } try { connectedPort.Write("set rgb " + limit(values[0]) + " " + limit(values[1]) + " " + limit(values[2]) + "\n"); } catch (TimeoutException) { MessageBox.Show("Последовательный порт " + connectedPort.PortName + " стал недоступен. Попробуйте подключиться ещё раз", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); connected = false; if (connectedPort.IsOpen) { connectedPort.Close(); } waveIn.StopRecording(); } }