public void Add(NodeHuf nodeHuf) { Count++; Node aux; if (Head == null || Head.element.Frequency > nodeHuf.Frequency) { Head = new Node(nodeHuf, Head); } else { aux = Head; while (aux.nodeNext != null && aux.nodeNext.element.Frequency <= nodeHuf.Frequency) { aux = aux.nodeNext; } aux.nodeNext = new Node(nodeHuf, aux.nodeNext); //aux = new Node(nodeHuf, aux.nodeNext); } if (Count == 1) { Tail = Head; } else { aux = Head; while (aux.nodeNext != null) { aux = aux.nodeNext; } Tail = aux; } }
//algoritmo de huffman public void Build() { while (Count > 1) { NodeHuf newNH = new NodeHuf(); newNH.Symbol = -666; newNH.Left = Head.element; Head = Head.nodeNext; newNH.Right = Head.element; Head = Head.nodeNext; newNH.Frequency = newNH.Left.Frequency + newNH.Right.Frequency; Count -= 2; Add(newNH); } //Indicamos la raíz del árbol de huffman. Root = Head.element; //La cabeza y cola de la lista enlazada ya no serán utilizadas. Head = Tail = null; }
public short[] Decode(BitArray bits) { NodeHuf current = this.Root; short[] decoded = new short[bits.Length]; int i = 0; foreach (bool bit in bits) { if (bit) { if (current.Right != null) { current = current.Right; } } else { if (current.Left != null) { current = current.Left; } } //Con este método sabremos cuando se ha llegado a un símbolo u hoja. if (IsLeaf(current)) { //decoded += current.Symbol; decoded[i] = current.Symbol; i++; current = this.Root; } } return(decoded); }
public Node(NodeHuf element, Node next = null) { this.element = element; nodeNext = next; }
public bool IsLeaf(NodeHuf node) { return(node.Left == null && node.Right == null); }
void backWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) { System.ComponentModel.BackgroundWorker b = sender as System.ComponentModel.BackgroundWorker; int samples = 32; short[] buffer = new short[samples]; bw = new BinaryWriter(File.Open(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/Code.huf", FileMode.Create)); stream = Bass.BASS_StreamCreateFile(path, 0L, 0L, BASSFlag.BASS_STREAM_DECODE); ww = new WaveWriter(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/HufSound.wav", stream, true); int mult = 0; long len = Bass.BASS_ChannelGetLength(stream, BASSMode.BASS_POS_BYTES); while (Bass.BASS_ChannelIsActive(stream) == BASSActive.BASS_ACTIVE_PLAYING) { int length = Bass.BASS_ChannelGetData(stream, buffer, samples * 2); mult++; b.ReportProgress((int)(((samples * mult) * 100) / len * 2)); List <short> listBuffer = new List <short>(); HuffmanTree tree = new HuffmanTree(); if (length > 0) { listBuffer.AddRange(buffer); short[] auxbuf = new short[buffer.Length]; auxbuf = buffer; canvasWavComp.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.SystemIdle, new Action(delegate { //Whole Wave //double xScale = canvasWavComp.Width / samples; //Formula by Manuel García. Dude you're amazing. //NOTE: multiply by 2 'cos I supoused some relation with Nyquist Theorem double xScale = (canvasWavComp.Width * samples) / len * 2; double yScale = (canvasWavComp.Height / (double)(amplitude * 2)) * ((double)amplitude / MAX_AMP); Polyline graphLine = new Polyline(); //This Line is used to move on the x axis Canvas.SetLeft(graphLine, xAxis); graphLine.Stroke = new SolidColorBrush(Color.FromRgb(244, 67, 54)); graphLine.StrokeThickness = 2; for (int i = 0; i < buffer.Length; i++) { graphLine.Points.Add(new Point(xScale * i, (canvasWavComp.Height / 2) - (buffer[i] * yScale))); } xAxis += xScale; //canvasWavComp.Children.Clear(); canvasWavComp.Children.Add(graphLine); })); double entaux = 0; foreach (var sym in listBuffer.GroupBy(i => i)) { NodeHuf nodeHuf = new NodeHuf(); nodeHuf.Symbol = sym.Key; nodeHuf.Frequency = sym.Count(); nodeHuf.Right = nodeHuf.Left = null; tree.Add(nodeHuf); double prob = (double)nodeHuf.Frequency / samples; //entropy -= prob * (Math.Log(prob) / Math.Log(2)); entaux += prob * Math.Log(1 / (prob), 2); entauxlbl = entaux; } entropy += entaux; entcount++; tree.Build(); //Encode System.Collections.BitArray encoded = tree.Encode(auxbuf); byte[] arrayBytes = new byte[encoded.Length / 8 + (encoded.Length % 8 == 0 ? 0 : 1)]; encoded.CopyTo(arrayBytes, 0); File.WriteAllBytes("Compress.bin", arrayBytes); //Decode byte[] data; Stream fs = File.OpenRead("Compress.bin"); data = new byte[fs.Length]; fs.Read(data, 0, data.Length); System.Collections.BitArray bitDec = new System.Collections.BitArray(data); short[] decoded = tree.Decode(bitDec); if (decoded.Length > 0) { ww.Write(decoded, length); } bw.Write(data); fs.Close(); } } //Delete temporaly file File.Delete("Compress.bin"); //Close de Stream WAV ww ww.Close(); //If you not add this line, the backgroundworker will be restat but when file is create again //there will be an incongruence because the bw never was closed. bw.Close(); entropy /= entcount;// (len / samples); entcount = 0; }