public QAM(int amplitudes, int phases, int frequencies, int frameLength) { m_NumFrequencies = frequencies; m_NumAmplitudes = amplitudes; m_NumPhases = phases; m_FrameLength = frameLength; m_FFT = new FFT(frameLength); }
private void paintControl1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(Color.Black); int frameLength = 64; int numFreqs = (int)numericUpDown4.Value; int numAmps = (int)Math.Pow(2.0f, (float)numericUpDown1.Value); int numPhases = (int)Math.Pow(2.0f, (float)numericUpDown2.Value); Constellation constellation = comboBox1.SelectedIndex == 0 ? (Constellation)new CircularConstellation(numAmps, numPhases) : (Constellation)new RectangularConstellation(numAmps, numPhases); SymbolStream symbolStream = new SymbolStream(constellation.NumSymbols); QAM modulator = new QAM(constellation, numFreqs, frameLength); string inString = "Hello World!"; byte[] inBytes = Encoding.ASCII.GetBytes(inString); List<uint> inSymbols = symbolStream.EncodeSymbols(inBytes); List<float> stream = new List<float>(); int symbolIndex = 0; m_NumFrames = 0; while (symbolIndex < inSymbols.Count) { int symbolCount = Math.Min(inSymbols.Count - symbolIndex, numFreqs); List<uint> subSymbols = inSymbols.GetRange(symbolIndex, symbolCount); subSymbols.Add(0); float[] fragment = modulator.Modulate(subSymbols); stream.AddRange(fragment); symbolIndex += symbolCount; m_NumFrames++; } float noiseScale = (float)numericUpDown3.Value / 20.0f; float[] noise = Noise.GenerateNoise(stream.Count, (float)numericUpDown3.Value / 20.0f); List<float> noisyStream = new List<float>(); int shifter = (int)(Math.Round((m_Random.NextDouble() * 2.0f - 1.0f) * (float)numericUpDown5.Value)); for (int i = 0; i < stream.Count; i++) { noisyStream.Add(noise[i] + stream[Math.Max(0, Math.Min(stream.Count - 1, i + shifter))]); } List<uint> outSymbols = new List<uint>(); for (int i = 0; i < noisyStream.Count; i += frameLength) { float[] fragment = noisyStream.GetRange(i, frameLength).ToArray(); List<uint> subSymbols = modulator.Demodulate(fragment); outSymbols.AddRange(subSymbols); } byte[] outBytes = symbolStream.DecodeSymbols(outSymbols); string outString = Encoding.ASCII.GetString(outBytes); float curY = 100.0f; float streamScale = 840.0f / stream.Count; float streamSize = frameLength * streamScale; float symbolsPerByte = m_NumFrames / (float)inBytes.Length; for (int i = 0; i < inString.Length; i++) { float symbol = (float)i * symbolsPerByte; g.DrawString(inString[i].ToString(), m_Font, Brushes.White, new PointF(20.0f + symbol * streamSize, curY)); } curY += 16.0f; for (int f = 0; f < m_NumFrames; f++) { int symbolStart = f * numFreqs; int symbolEnd = Math.Min(inSymbols.Count - 1, symbolStart + numFreqs); float frameStart = streamSize * f; float Y = 0.0f; float X = 0.0f; for (int i = symbolStart; i < symbolEnd; i++) { string str = inSymbols[i].ToString(); SizeF strSize = g.MeasureString(str, m_Font); if (X >= streamSize - 10.0f) { X = 0.0f; Y += strSize.Height + 2; } g.DrawString(str, m_Font, Brushes.White, new PointF(20.0f + frameStart + X, curY + Y)); X += strSize.Width; } } int graphMax = 0; curY += 26.0f; m_SourceY = curY; m_SourceX = 20.0f; m_SourceWidth = streamScale * (float)stream.Count; int useFrame = Math.Min(m_NumFrames - 1, m_ActiveFrame); DrawGraph(g, 20, curY, stream.ToArray(), streamScale, 32.0f, Pens.Aqua, Pens.SteelBlue, frameLength, useFrame, out graphMax); m_SourceHeight = graphMax + 10.0f; curY += graphMax + 10.0f; DrawGraph(g, 20, curY, noise, streamScale, 32.0f, Pens.Red, Pens.Red, 1, -1, out graphMax); curY += 32.0f * noiseScale * 1.5f + 10.0f; DrawGraph(g, 20, curY, noisyStream.ToArray(), streamScale, 32.0f, Pens.Yellow, Pens.LightYellow, frameLength, -1, out graphMax); curY += graphMax + 10.0f; for (int f = 0; f < m_NumFrames; f++) { int symbolStart = f * numFreqs; int symbolEnd = Math.Min(inSymbols.Count - 1, symbolStart + numFreqs); float frameStart = streamSize * f; float Y = 0.0f; float X = 0.0f; for (int i = symbolStart; i < symbolEnd; i++) { string str = outSymbols[i].ToString(); SizeF strSize = g.MeasureString(str, m_Font); if (X >= streamSize - 10.0f) { X = 0.0f; Y += strSize.Height + 2; } Brush useBrush = outSymbols[i] != inSymbols[i] ? Brushes.Red : new SolidBrush(Color.FromArgb(0, 255, 0)); g.DrawString(str, m_Font, useBrush, new PointF(20.0f + frameStart + X, curY + Y)); X += strSize.Width; } } curY += 16.0f; for (int i = 0; i < inString.Length; i++) { float symbol = (float)i * symbolsPerByte; Brush useBrush = outString[i] != inString[i] ? Brushes.Red : new SolidBrush(Color.FromArgb(0, 255, 0)); g.DrawString(outString[i].ToString(), m_Font, useBrush, new PointF(20.0f + symbol * streamSize, curY)); } curY += 16.0f; g.DrawString("amps", m_Font, Brushes.Yellow, new PointF(5, 25)); g.DrawString("phases", m_Font, Brushes.Yellow, new PointF(65, 25)); g.DrawString("freqs", m_Font, Brushes.Yellow, new PointF(125, 25)); g.DrawString("noise", m_Font, Brushes.Yellow, new PointF(205, 25)); g.DrawString(String.Format("QAM-{0} x{1}, {2} bits per frame, {3} message len", modulator.NumSymbols, modulator.NumFrequencies, Math.Log(Math.Pow(modulator.NumSymbols, modulator.NumFrequencies), 2), m_NumFrames), m_Font, Brushes.Yellow, new PointF(310, 25)); float markerSize = constellation.NumSymbols > 64 ? 6 : 12; DrawConstellation(g, constellation, 200, 550, 150.0f, markerSize); { int symbolStart = useFrame * numFreqs; int symbolEnd = Math.Min(inSymbols.Count - 1, symbolStart + numFreqs); FFT fft = new FFT(frameLength); float[] data = noisyStream.GetRange(useFrame * frameLength, frameLength).ToArray(); float nrm = (float)numFreqs; List<FFT.Complex> coeffs = fft.DFT(data, nrm).ToList(); coeffs = coeffs.OrderBy(x => -x.Magnitude).ToList(); coeffs = coeffs.GetRange(0, numFreqs); coeffs = coeffs.OrderBy(x => x.freq).ToList(); float magNrm = 2.0f / (float)frameLength; List<uint> correctSymbols = inSymbols.GetRange(symbolStart, symbolEnd - symbolStart); for (int f = 0; f < correctSymbols.Count; f++) { uint subSymbol = (uint)constellation.FindSymbol(coeffs[f].Magnitude * magNrm, coeffs[f].Angle); float x = (float)Math.Cos(coeffs[f].Angle) * coeffs[f].Magnitude * magNrm * 150.0f; float y = (float)Math.Sin(coeffs[f].Angle) * coeffs[f].Magnitude * magNrm * 150.0f; x += 200.0f; y += 550.0f; Pen usePen = subSymbol != correctSymbols[f] ? Pens.Red : new Pen(Color.FromArgb(0, 255, 0)); g.DrawLine(usePen, x - markerSize * 0.5f, y, x + markerSize * 0.5f, y); g.DrawLine(usePen, x, y - markerSize * 0.5f, x, y + markerSize * 0.5f); } } }
public QAM(Constellation constellation, int frequencies, int frameLength) { m_Constellation = constellation; m_NumFrequencies = frequencies; m_FrameLength = frameLength; m_FFT = new FFT(frameLength); }