URL
https://opencores.org/ocsvn/ima_adpcm_enc_dec/ima_adpcm_enc_dec/trunk
Subversion Repositories ima_adpcm_enc_dec
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/ima_adpcm_enc_dec/trunk/doc/IMA ADPCM EncDec Core Specifications.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
ima_adpcm_enc_dec/trunk/doc/IMA ADPCM EncDec Core Specifications.pdf
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ima_adpcm_enc_dec/trunk/doc
===================================================================
--- ima_adpcm_enc_dec/trunk/doc (nonexistent)
+++ ima_adpcm_enc_dec/trunk/doc (revision 2)
ima_adpcm_enc_dec/trunk/doc
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: ima_adpcm_enc_dec/trunk/verilog/bench/tb_ima_adpcm.v
===================================================================
--- ima_adpcm_enc_dec/trunk/verilog/bench/tb_ima_adpcm.v (nonexistent)
+++ ima_adpcm_enc_dec/trunk/verilog/bench/tb_ima_adpcm.v (revision 2)
@@ -0,0 +1,283 @@
+//---------------------------------------------------------------------------------------
+// Project: ADPCM Encoder / Decoder
+//
+// Filename: tb_ima_adpcm.v (April 26, 2010 )
+//
+// Author(s): Moti Litochevski
+//
+// Description:
+// This file implements the ADPCM encoder & decoder test bench. The input samples
+// to be encoded are read from a binary input file. The encoder stream output and
+// decoded samples are also compared with binary files generated by the Scilab
+// simulation.
+//
+//---------------------------------------------------------------------------------------
+//
+// To Do:
+// -
+//
+//---------------------------------------------------------------------------------------
+//
+// Copyright (C) 2010 Moti Litochevski
+//
+// This source file may be used and distributed without restriction provided that this
+// copyright statement is not removed from the file and that any derivative work
+// contains the original copyright notice and the associated disclaimer.
+//
+// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND
+// FITNESS FOR A PARTICULAR PURPOSE.
+//
+//---------------------------------------------------------------------------------------
+
+`timescale 1ns / 1ns
+
+module test;
+//---------------------------------------------------------------------------------------
+// internal signal
+reg clock; // global clock
+reg reset; // global reset
+reg [15:0] inSamp; // encoder input sample
+reg inValid; // encoder input valid flag
+wire inReady; // encoder input ready indication
+wire [3:0] encPcm; // encoder encoded output value
+wire encValid; // encoder output valid flag
+wire [15:0] decSamp; // decoder output sample value
+wire decValid; // decoder output valid flag
+integer sampCount, encCount, decCount;
+integer infid, encfid, decfid;
+integer intmp, enctmp, dectmp;
+reg [3:0] encExpVal;
+reg [15:0] decExpVal;
+reg [31:0] dispCount;
+
+// global definitions
+`define EOF -1
+
+// file names
+`define IN_FILE "../../../scilab/test_in.bin"
+`define ENC_FILE "../../../scilab/test_enc.bin"
+`define DEC_FILE "../../../scilab/test_dec.bin"
+
+//---------------------------------------------------------------------------------------
+// test bench implementation
+// global signals generation
+initial
+begin
+ clock = 0;
+ reset = 1;
+ #40 reset = 0;
+end
+
+// clock generator - 50MHz clock
+always
+begin
+ #10 clock = 0;
+ #10 clock = 1;
+end
+
+// test bench dump variables
+initial
+begin
+ $display("");
+ $display("IMA ADPCM encoder & decoder simulation");
+ $display("--------------------------------------");
+ $dumpfile("test.vcd");
+ $dumpvars(0, test);
+end
+
+//------------------------------------------------------------------
+// encoder input samples read process
+initial
+begin
+ // clear encoder input signal
+ inSamp = 16'b0;
+ inValid = 1'b0;
+ // clear samples counter
+ sampCount = 0;
+
+ // binary input file
+ infid = $fopen(`IN_FILE, "rb");
+
+ // wait for reset release
+ while (reset) @(posedge clock);
+ repeat (50) @(posedge clock);
+
+ // read input samples file
+ intmp = $fgetc(infid);
+ while (intmp != `EOF)
+ begin
+ // read the next character to form the new input sample
+ // Note that first byte is used as the low byte of the sample
+ inSamp[7:0] <= intmp;
+ inSamp[15:8] <= $fgetc(infid);
+ // sign input sample is valid
+ inValid <= 1'b1;
+ @(posedge clock);
+
+ // update the sample counter
+ sampCount = sampCount + 1;
+
+ // wait for encoder input ready assertion to confirm the new sample was read
+ // by the encoder.
+ while (!inReady)
+ @(posedge clock);
+
+ // read next character from the input file
+ intmp = $fgetc(infid);
+ end
+ // sign input is not valid
+ inValid <= 1'b0;
+ @(posedge clock);
+
+ // close input file
+ $fclose(infid);
+end
+
+// encoder output checker - the encoder output is compared to the value read from
+// the ADPCM coded samples file.
+initial
+begin
+ // clear encoded sample value
+ encCount = 0;
+ // open input file
+ encfid = $fopen(`ENC_FILE, "rb");
+
+ // wait for reset release
+ while (reset) @(posedge clock);
+
+ // encoder output compare loop
+ enctmp = $fgetc(encfid);
+ while (enctmp != `EOF)
+ begin
+ // assign the expected value to a register with the same width
+ encExpVal = enctmp;
+
+ // wait for encoder output valid
+ while (!encValid)
+ @(posedge clock);
+
+ // compare the encoded value with the value read from the input file
+ if (encPcm != encExpVal)
+ begin
+ // announce error detection and exit simulation
+ $display(" Error!");
+ $display("Error found in encoder output index %0d.", encCount+1);
+ $display(" (expected value 'h%x, got value 'h%x)", encExpVal, encPcm);
+ // wait for a few clock cycles before ending simulation
+ repeat (20) @(posedge clock);
+ $finish;
+ end
+
+ // update the encoded sample counter
+ encCount = encCount + 1;
+ // delay for a clock cycle after comparison
+ @(posedge clock);
+
+ // read next char from input file
+ enctmp = $fgetc(encfid);
+ end
+
+ // close input file
+ $fclose(encfid);
+end
+
+// decoder output checker - the decoder output is compared to the value read from
+// the ADPCM decoded samples file.
+initial
+begin
+ // clear decoded sample value
+ decCount = 0;
+ dispCount = 0;
+ // open input file
+ decfid = $fopen(`DEC_FILE, "rb");
+
+ // wait for reset release
+ while (reset) @(posedge clock);
+
+ // display simulation progress bar title
+ $write("Simulation progress: ");
+
+ // decoder output compare loop
+ dectmp = $fgetc(decfid);
+ while (dectmp != `EOF)
+ begin
+ // read the next char to form the expected 16 bit sample value
+ decExpVal[7:0] = dectmp;
+ decExpVal[15:8] = $fgetc(decfid);
+
+ // wait for decoder output valid
+ while (!decValid)
+ @(posedge clock);
+
+ // compare the decoded value with the value read from the input file
+ if (decSamp != decExpVal)
+ begin
+ // announce error detection and exit simulation
+ $display(" Error!");
+ $display("Error found in decoder output index %0d.", decCount+1);
+ $display(" (expected value 'h%x, got value 'h%x)", decExpVal, decSamp);
+ // wait for a few clock cycles before ending simulation
+ repeat (20) @(posedge clock);
+ $finish;
+ end
+ // delay for a clock cycle after comparison
+ @(posedge clock);
+
+ // update the decoded sample counter
+ decCount = decCount + 1;
+
+ // check if simulation progress should be displayed
+ if (dispCount[31:13] != (decCount >> 13))
+ $write(".");
+ // update the display counter
+ dispCount = decCount;
+
+ // read next char from input file
+ dectmp = $fgetc(decfid);
+ end
+
+ // close input file
+ $fclose(decfid);
+
+ // when decoder output is done announce simulation was successful
+ $display(" Done");
+ $display("Simulation ended successfully after %0d samples", decCount);
+ $finish;
+end
+
+//------------------------------------------------------------------
+// device under test
+// Encoder instance
+ima_adpcm_enc enc
+(
+ .clock(clock),
+ .reset(reset),
+ .inSamp(inSamp),
+ .inValid(inValid),
+ .inReady(inReady),
+ .outPCM(encPcm),
+ .outValid(encValid),
+ .outPredictSamp(/* not used */),
+ .outStepIndex(/* not used */)
+);
+
+// Decoder instance
+ima_adpcm_dec dec
+(
+ .clock(clock),
+ .reset(reset),
+ .inPCM(encPcm),
+ .inValid(encValid),
+ .inReady(decReady),
+ .inPredictSamp(16'b0),
+ .inStepIndex(7'b0),
+ .inStateLoad(1'b0),
+ .outSamp(decSamp),
+ .outValid(decValid)
+);
+
+endmodule
+//---------------------------------------------------------------------------------------
+// Th.. Th.. Th.. Thats all folks !!!
+//---------------------------------------------------------------------------------------
Index: ima_adpcm_enc_dec/trunk/verilog/bench
===================================================================
--- ima_adpcm_enc_dec/trunk/verilog/bench (nonexistent)
+++ ima_adpcm_enc_dec/trunk/verilog/bench (revision 2)
ima_adpcm_enc_dec/trunk/verilog/bench
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: ima_adpcm_enc_dec/trunk/verilog/rtl/ima_adpcm_enc.v
===================================================================
--- ima_adpcm_enc_dec/trunk/verilog/rtl/ima_adpcm_enc.v (nonexistent)
+++ ima_adpcm_enc_dec/trunk/verilog/rtl/ima_adpcm_enc.v (revision 2)
@@ -0,0 +1,387 @@
+//---------------------------------------------------------------------------------------
+// Project: ADPCM Encoder
+//
+// Filename: ima_adpcm_enc.v (February 18, 2010)
+//
+// Author(s): Moti Litochevski
+//
+// Description:
+// This module implements the IMA ADPCM audio encoding algorithm. The input samples
+// interface is 16 bits wide. ADPCM encoded data output is 4 bits wide and is sent
+// for every new input sample.
+//
+//---------------------------------------------------------------------------------------
+//
+// To Do:
+// -
+//
+//---------------------------------------------------------------------------------------
+//
+// Copyright (C) 2010 Moti Litochevski
+//
+// This source file may be used and distributed without restriction provided that this
+// copyright statement is not removed from the file and that any derivative work
+// contains the original copyright notice and the associated disclaimer.
+//
+// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND
+// FITNESS FOR A PARTICULAR PURPOSE.
+//
+//---------------------------------------------------------------------------------------
+
+module ima_adpcm_enc
+(
+ clock, reset,
+ inSamp, inValid,
+ inReady,
+ outPCM, outValid,
+ outPredictSamp, outStepIndex
+);
+//---------------------------------------------------------------------------------------
+// global inputs
+input reset;
+input clock;
+
+// input interface
+input [15:0] inSamp; // input sample
+input inValid; // input valid flag
+output inReady; // input ready indication
+
+// output interface
+output [3:0] outPCM; // ADPCM encoded value
+output outValid; // output valid flag
+output [15:0] outPredictSamp; // predictor sample value output
+output [6:0] outStepIndex; // step index value output
+
+//---------------------------------------------------------------------------------------
+// registers output
+reg [3:0] outPCM;
+reg outValid, inReady;
+
+// internals
+reg [2:0] pcmSq;
+reg [19:0] sampDiff, prePredSamp;
+reg [18:0] predictorSamp, dequantSamp;
+reg [3:0] prePCM;
+reg [14:0] stepSize; // unsigned
+reg [6:0] stepIndex; // unsigned
+reg [4:0] stepDelta;
+wire [7:0] preStepIndex;
+
+// constant declarations
+// main state machine
+`define PCM_IDLE 3'd0
+`define PCM_SIGN 3'd1
+`define PCM_BIT2 3'd2
+`define PCM_BIT1 3'd3
+`define PCM_BIT0 3'd4
+`define PCM_DONE 3'd5
+
+//---------------------------------------------------------------------------------------
+// module implementation
+// encoder main control process
+always @ (posedge clock or posedge reset)
+begin
+ if (reset)
+ begin
+ pcmSq <= 3'b0;
+ sampDiff <= 20'b0;
+ predictorSamp <= 19'b0;
+ dequantSamp <= 19'b0;
+ prePCM <= 4'b0;
+ inReady <= 1'b0;
+ end
+ else
+ begin
+ case (pcmSq)
+ // waiting for a new input sample
+ `PCM_IDLE:
+ // on a new input sample calculate the difference between the input
+ // sample and predictor output
+ if (inValid)
+ begin
+ // compute the difference between the current predictor output and the input
+ // sample with extended width to prevent any wrapping.
+ sampDiff <= {inSamp[15], inSamp, 3'b0} - {predictorSamp[18], predictorSamp};
+
+ // sign that input is not ready
+ inReady <= 1'b0;
+
+ // switch to next state
+ pcmSq <= `PCM_SIGN;
+ end
+ else
+ // sign that input is ready
+ inReady <= 1'b1;
+
+ // check the difference sign and set PCM sign bit accordingly
+ `PCM_SIGN:
+ begin
+ // check the difference sign
+ if (sampDiff[19])
+ begin
+ // set PCM sign bit and negate the calculated sample difference
+ prePCM[3] <= 1'b1;
+ sampDiff <= (~sampDiff) + 1;
+ end
+ else
+ // clear the PCM sign bit
+ prePCM[3] <= 1'b0;
+
+ // prepare the de-quantizer sample
+ dequantSamp <= {4'b0, stepSize};
+
+ // switch to next state
+ pcmSq <= `PCM_BIT2;
+ end
+
+ // determine quantizer bit 2 value
+ `PCM_BIT2:
+ begin
+ // check if the difference is larger than step size
+ if (sampDiff[19:3] >= {2'b0, stepSize})
+ begin
+ // bit 2 of PCM nibble is set
+ prePCM[2] <= 1'b1;
+ // update the difference value and the de-quantizer value
+ sampDiff[19:3] <= sampDiff[19:3] - {2'b0, stepSize};
+ dequantSamp <= dequantSamp + {1'b0, stepSize, 3'b0};
+ end
+ else
+ // bit 2 of PCM nibble is zero
+ prePCM[2] <= 1'b0;
+
+ // switch to next state
+ pcmSq <= `PCM_BIT1;
+ end
+
+ // determine quantizer bit 1 value
+ `PCM_BIT1:
+ begin
+ // check if the difference is larger than step size
+ if (sampDiff[19:2] >= {3'b0, stepSize})
+ begin
+ // bit 1 of PCM nibble is set
+ prePCM[1] <= 1'b1;
+ // update the difference value and the de-quantizer value
+ sampDiff[19:2] <= sampDiff[19:2] - {3'b0, stepSize};
+ dequantSamp <= dequantSamp + {2'b0, stepSize, 2'b0};
+ end
+ else
+ // bit 1 of PCM nibble is zero
+ prePCM[1] <= 1'b0;
+
+ // switch to next state
+ pcmSq <= `PCM_BIT0;
+ end
+
+ // determine quantizer bit 0 value
+ `PCM_BIT0:
+ begin
+ // check if the difference is larger than step size
+ if (sampDiff[19:1] >= {4'b0, stepSize})
+ begin
+ // bit 0 of PCM nibble is set
+ prePCM[0] <= 1'b1;
+ // update the de-quantizer value
+ dequantSamp <= dequantSamp + {3'b0, stepSize, 1'b0};
+ end
+ else
+ // bit 0 of PCM nibble is zero
+ prePCM[0] <= 1'b0;
+
+ // switch to next state
+ pcmSq <= `PCM_DONE;
+ end
+
+ // check saturation condition on new predictor sample and update it
+ `PCM_DONE:
+ begin
+ // check the new predictor output saturation conditions
+ if (prePredSamp[19] && !prePredSamp[18])
+ // negative saturation
+ predictorSamp <= {1'b1, 18'b0};
+ else if (!prePredSamp[19] && prePredSamp[18])
+ // positive saturation
+ predictorSamp <= {1'b0, {18{1'b1}}};
+ else
+ // no saturation
+ predictorSamp <= prePredSamp[18:0];
+
+ // sign that input is ready
+ inReady <= 1'b1;
+
+ // return to idle state
+ pcmSq <= `PCM_IDLE;
+ end
+
+ // unused states
+ default: pcmSq <= `PCM_IDLE;
+ endcase
+ end
+end
+// internal state output assignment
+assign outPredictSamp = predictorSamp[18:3] + predictorSamp[2];
+assign outStepIndex = stepIndex;
+
+// calculate the update predictor sample before it is updated by the state machine
+always @ (prePCM or predictorSamp or dequantSamp)
+begin
+ if (prePCM[3])
+ prePredSamp <= {predictorSamp[18], predictorSamp} - {1'b0, dequantSamp};
+ else
+ prePredSamp <= {predictorSamp[18], predictorSamp} + {1'b0, dequantSamp};
+end
+
+// output interface
+always @ (posedge clock or posedge reset)
+begin
+ if (reset)
+ begin
+ outPCM <= 4'b0;
+ outValid <= 1'b0;
+ end
+ else if (pcmSq == `PCM_DONE)
+ begin
+ outPCM <= prePCM;
+ outValid <= 1'b1;
+ end
+ else
+ outValid <= 1'b0;
+end
+
+// quantizer index adaptation lookup table
+always @ (prePCM)
+begin
+ case (prePCM[2:0])
+ 3'd0: stepDelta <= 5'd31; // = -1
+ 3'd1: stepDelta <= 5'd31; // = -1
+ 3'd2: stepDelta <= 5'd31; // = -1
+ 3'd3: stepDelta <= 5'd31; // = -1
+ 3'd4: stepDelta <= 5'd2;
+ 3'd5: stepDelta <= 5'd4;
+ 3'd6: stepDelta <= 5'd6;
+ 3'd7: stepDelta <= 5'd8;
+ endcase
+end
+// calculate the new index value before saturation
+assign preStepIndex = {1'b0, stepIndex} + {{3{stepDelta[4]}}, stepDelta};
+
+// update the step index with saturation checking
+always @ (posedge clock or posedge reset)
+begin
+ if (reset)
+ stepIndex <= 7'b0;
+ else if (pcmSq == `PCM_DONE)
+ begin
+ // check is the updated step value should be saturated
+ if (preStepIndex[7])
+ stepIndex <= 7'd0;
+ else if (preStepIndex[6:0] > 7'd88)
+ stepIndex <= 7'd88;
+ else
+ stepIndex <= preStepIndex[6:0];
+ end
+end
+
+// quantizer step size lookup table
+always @ (posedge clock)
+begin
+ case (stepIndex)
+ 7'd0: stepSize <= 15'd7;
+ 7'd1: stepSize <= 15'd8;
+ 7'd2: stepSize <= 15'd9;
+ 7'd3: stepSize <= 15'd10;
+ 7'd4: stepSize <= 15'd11;
+ 7'd5: stepSize <= 15'd12;
+ 7'd6: stepSize <= 15'd13;
+ 7'd7: stepSize <= 15'd14;
+ 7'd8: stepSize <= 15'd16;
+ 7'd9: stepSize <= 15'd17;
+ 7'd10: stepSize <= 15'd19;
+ 7'd11: stepSize <= 15'd21;
+ 7'd12: stepSize <= 15'd23;
+ 7'd13: stepSize <= 15'd25;
+ 7'd14: stepSize <= 15'd28;
+ 7'd15: stepSize <= 15'd31;
+ 7'd16: stepSize <= 15'd34;
+ 7'd17: stepSize <= 15'd37;
+ 7'd18: stepSize <= 15'd41;
+ 7'd19: stepSize <= 15'd45;
+ 7'd20: stepSize <= 15'd50;
+ 7'd21: stepSize <= 15'd55;
+ 7'd22: stepSize <= 15'd60;
+ 7'd23: stepSize <= 15'd66;
+ 7'd24: stepSize <= 15'd73;
+ 7'd25: stepSize <= 15'd80;
+ 7'd26: stepSize <= 15'd88;
+ 7'd27: stepSize <= 15'd97;
+ 7'd28: stepSize <= 15'd107;
+ 7'd29: stepSize <= 15'd118;
+ 7'd30: stepSize <= 15'd130;
+ 7'd31: stepSize <= 15'd143;
+ 7'd32: stepSize <= 15'd157;
+ 7'd33: stepSize <= 15'd173;
+ 7'd34: stepSize <= 15'd190;
+ 7'd35: stepSize <= 15'd209;
+ 7'd36: stepSize <= 15'd230;
+ 7'd37: stepSize <= 15'd253;
+ 7'd38: stepSize <= 15'd279;
+ 7'd39: stepSize <= 15'd307;
+ 7'd40: stepSize <= 15'd337;
+ 7'd41: stepSize <= 15'd371;
+ 7'd42: stepSize <= 15'd408;
+ 7'd43: stepSize <= 15'd449;
+ 7'd44: stepSize <= 15'd494;
+ 7'd45: stepSize <= 15'd544;
+ 7'd46: stepSize <= 15'd598;
+ 7'd47: stepSize <= 15'd658;
+ 7'd48: stepSize <= 15'd724;
+ 7'd49: stepSize <= 15'd796;
+ 7'd50: stepSize <= 15'd876;
+ 7'd51: stepSize <= 15'd963;
+ 7'd52: stepSize <= 15'd1060;
+ 7'd53: stepSize <= 15'd1166;
+ 7'd54: stepSize <= 15'd1282;
+ 7'd55: stepSize <= 15'd1411;
+ 7'd56: stepSize <= 15'd1552;
+ 7'd57: stepSize <= 15'd1707;
+ 7'd58: stepSize <= 15'd1878;
+ 7'd59: stepSize <= 15'd2066;
+ 7'd60: stepSize <= 15'd2272;
+ 7'd61: stepSize <= 15'd2499;
+ 7'd62: stepSize <= 15'd2749;
+ 7'd63: stepSize <= 15'd3024;
+ 7'd64: stepSize <= 15'd3327;
+ 7'd65: stepSize <= 15'd3660;
+ 7'd66: stepSize <= 15'd4026;
+ 7'd67: stepSize <= 15'd4428;
+ 7'd68: stepSize <= 15'd4871;
+ 7'd69: stepSize <= 15'd5358;
+ 7'd70: stepSize <= 15'd5894;
+ 7'd71: stepSize <= 15'd6484;
+ 7'd72: stepSize <= 15'd7132;
+ 7'd73: stepSize <= 15'd7845;
+ 7'd74: stepSize <= 15'd8630;
+ 7'd75: stepSize <= 15'd9493;
+ 7'd76: stepSize <= 15'd10442;
+ 7'd77: stepSize <= 15'd11487;
+ 7'd78: stepSize <= 15'd12635;
+ 7'd79: stepSize <= 15'd13899;
+ 7'd80: stepSize <= 15'd15289;
+ 7'd81: stepSize <= 15'd16818;
+ 7'd82: stepSize <= 15'd18500;
+ 7'd83: stepSize <= 15'd20350;
+ 7'd84: stepSize <= 15'd22385;
+ 7'd85: stepSize <= 15'd24623;
+ 7'd86: stepSize <= 15'd27086;
+ 7'd87: stepSize <= 15'd29794;
+ 7'd88: stepSize <= 15'd32767;
+ default: stepSize <= 15'd32767;
+ endcase
+end
+
+endmodule
+//---------------------------------------------------------------------------------------
+// Th.. Th.. Th.. That's all folks !!!
+//---------------------------------------------------------------------------------------
Index: ima_adpcm_enc_dec/trunk/verilog/rtl/ima_adpcm_dec.v
===================================================================
--- ima_adpcm_enc_dec/trunk/verilog/rtl/ima_adpcm_dec.v (nonexistent)
+++ ima_adpcm_enc_dec/trunk/verilog/rtl/ima_adpcm_dec.v (revision 2)
@@ -0,0 +1,292 @@
+//---------------------------------------------------------------------------------------
+// Project: ADPCM Decoder
+//
+// Filename: ima_adpcm_enc.v (February 19, 2010)
+//
+// Author(s): Moti Litochevski
+//
+// Description:
+// This module implements the IMA ADPCM audio decoding algorithm. The input ADPCM
+// encoded data is 4 bits wide and is converted to linearly quantized 16 bits
+// samples for every new input.
+// The decoder module implemented here is not compatible to any particular protocol
+// or file format. The module include optional interface to load the decoder
+// internal state which includes the internal predictor sample and step index
+// provided by the encoder.
+//
+//---------------------------------------------------------------------------------------
+//
+// To Do:
+// -
+//
+//---------------------------------------------------------------------------------------
+//
+// Copyright (C) 2010 Moti Litochevski
+//
+// This source file may be used and distributed without restriction provided that this
+// copyright statement is not removed from the file and that any derivative work
+// contains the original copyright notice and the associated disclaimer.
+//
+// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND
+// FITNESS FOR A PARTICULAR PURPOSE.
+//
+//---------------------------------------------------------------------------------------
+
+module ima_adpcm_dec
+(
+ clock, reset,
+ inPCM, inValid,
+ inReady, inPredictSamp,
+ inStepIndex, inStateLoad,
+ outSamp, outValid
+);
+//---------------------------------------------------------------------------------------
+// global inputs
+input reset;
+input clock;
+
+// input interface
+input [3:0] inPCM; // input PCM nibble
+input inValid; // input valid flag
+output inReady; // input ready indication
+// optional decoder state load
+input [15:0] inPredictSamp; // predictor sample load input
+input [6:0] inStepIndex; // step index load input
+input inStateLoad; // internal state load input control
+
+// output interface
+output [15:0] outSamp; // output sample value
+output outValid; // output valid flag
+
+//---------------------------------------------------------------------------------------
+// registers output
+reg [15:0] outSamp;
+reg outValid;
+
+// internals
+reg [18:0] predictorSamp;
+wire [18:0] dequantSamp;
+reg predValid;
+wire [19:0] prePredSamp;
+reg [14:0] stepSize; // unsigned
+reg [6:0] stepIndex; // unsigned
+reg [4:0] stepDelta;
+wire [7:0] preStepIndex;
+wire [16:0] preOutSamp;
+
+//---------------------------------------------------------------------------------------
+// module implementation
+// main decoder process
+always @ (posedge clock or posedge reset)
+begin
+ if (reset)
+ begin
+ predictorSamp <= 19'b0;
+ predValid <= 1'b0;
+ end
+ else if (inStateLoad)
+ begin
+ // load predictor sample value
+ predictorSamp <= {inPredictSamp, 3'b0};
+ // clear the internal delayed flag
+ predValid <= 1'b0;
+ end
+ else if (inValid)
+ begin
+ // check updated predictor sample saturation conditions
+ if (prePredSamp[19] && !prePredSamp[18])
+ // negative saturation
+ predictorSamp <= {1'b1, 18'b0};
+ else if (!prePredSamp[19] && prePredSamp[18])
+ // positive saturation
+ predictorSamp <= {1'b0, {18{1'b1}}};
+ else
+ // no saturation
+ predictorSamp <= prePredSamp[18:0];
+
+ // sign that predictor value is valid
+ predValid <= 1'b1;
+ end
+ else
+ predValid <= 1'b0;
+end
+// calculate the de-quantized difference value
+assign dequantSamp = (inPCM[2] ? {1'b0, stepSize, 3'b0} : 19'b0) +
+ (inPCM[1] ? {2'b0, stepSize, 2'b0} : 19'b0) +
+ (inPCM[0] ? {3'b0, stepSize, 1'b0} : 19'b0) +
+ {4'b0, stepSize};
+// updated predictor output sample
+assign prePredSamp = inPCM[3] ? ({predictorSamp[18], predictorSamp} - {1'b0, dequantSamp}) :
+ ({predictorSamp[18], predictorSamp} + {1'b0, dequantSamp});
+
+// input interface is busy while updating the step size
+assign inReady = ~predValid;
+
+// calculate the output sample before saturation
+assign preOutSamp = {predictorSamp[18], predictorSamp[18:3]} + predictorSamp[2];
+
+// output interface
+always @ (posedge clock or posedge reset)
+begin
+ if (reset)
+ begin
+ outSamp <= 16'b0;
+ outValid <= 1'b0;
+ end
+ else if (predValid)
+ begin
+ // output is taken from the predictor output with saturation check
+ if (!preOutSamp[16] && preOutSamp[15])
+ // positive saturation condition
+ outSamp <= {1'b0, {15{1'b1}}};
+ else if (preOutSamp[16] && !preOutSamp[15])
+ // negative saturation condition
+ outSamp <= {1'b1, 15'b0};
+ else
+ outSamp <= preOutSamp[15:0];
+
+ // sign output is valid
+ outValid <= 1'b1;
+ end
+ else
+ outValid <= 1'b0;
+end
+
+// quantizer index adaptation lookup table
+always @ (inPCM)
+begin
+ case (inPCM[2:0])
+ 3'd0: stepDelta <= 5'd31; // = -1
+ 3'd1: stepDelta <= 5'd31; // = -1
+ 3'd2: stepDelta <= 5'd31; // = -1
+ 3'd3: stepDelta <= 5'd31; // = -1
+ 3'd4: stepDelta <= 5'd2; // = +2
+ 3'd5: stepDelta <= 5'd4; // = +4
+ 3'd6: stepDelta <= 5'd6; // = +6
+ 3'd7: stepDelta <= 5'd8; // = +8
+ endcase
+end
+// calculate the new index value before saturation
+assign preStepIndex = {1'b0, stepIndex} + {{3{stepDelta[4]}}, stepDelta};
+
+// update the step index with saturation checking
+always @ (posedge clock or posedge reset)
+begin
+ if (reset)
+ stepIndex <= 7'b0;
+ else if (inStateLoad)
+ stepIndex <= inStepIndex;
+ else if (inValid)
+ begin
+ // check is the updated step value should be saturated
+ if (preStepIndex[7])
+ stepIndex <= 7'd0;
+ else if (preStepIndex[6:0] > 7'd88)
+ stepIndex <= 7'd88;
+ else
+ stepIndex <= preStepIndex[6:0];
+ end
+end
+
+// quantizer step size lookup table
+always @ (posedge clock)
+begin
+ case (stepIndex)
+ 7'd0: stepSize <= 15'd7;
+ 7'd1: stepSize <= 15'd8;
+ 7'd2: stepSize <= 15'd9;
+ 7'd3: stepSize <= 15'd10;
+ 7'd4: stepSize <= 15'd11;
+ 7'd5: stepSize <= 15'd12;
+ 7'd6: stepSize <= 15'd13;
+ 7'd7: stepSize <= 15'd14;
+ 7'd8: stepSize <= 15'd16;
+ 7'd9: stepSize <= 15'd17;
+ 7'd10: stepSize <= 15'd19;
+ 7'd11: stepSize <= 15'd21;
+ 7'd12: stepSize <= 15'd23;
+ 7'd13: stepSize <= 15'd25;
+ 7'd14: stepSize <= 15'd28;
+ 7'd15: stepSize <= 15'd31;
+ 7'd16: stepSize <= 15'd34;
+ 7'd17: stepSize <= 15'd37;
+ 7'd18: stepSize <= 15'd41;
+ 7'd19: stepSize <= 15'd45;
+ 7'd20: stepSize <= 15'd50;
+ 7'd21: stepSize <= 15'd55;
+ 7'd22: stepSize <= 15'd60;
+ 7'd23: stepSize <= 15'd66;
+ 7'd24: stepSize <= 15'd73;
+ 7'd25: stepSize <= 15'd80;
+ 7'd26: stepSize <= 15'd88;
+ 7'd27: stepSize <= 15'd97;
+ 7'd28: stepSize <= 15'd107;
+ 7'd29: stepSize <= 15'd118;
+ 7'd30: stepSize <= 15'd130;
+ 7'd31: stepSize <= 15'd143;
+ 7'd32: stepSize <= 15'd157;
+ 7'd33: stepSize <= 15'd173;
+ 7'd34: stepSize <= 15'd190;
+ 7'd35: stepSize <= 15'd209;
+ 7'd36: stepSize <= 15'd230;
+ 7'd37: stepSize <= 15'd253;
+ 7'd38: stepSize <= 15'd279;
+ 7'd39: stepSize <= 15'd307;
+ 7'd40: stepSize <= 15'd337;
+ 7'd41: stepSize <= 15'd371;
+ 7'd42: stepSize <= 15'd408;
+ 7'd43: stepSize <= 15'd449;
+ 7'd44: stepSize <= 15'd494;
+ 7'd45: stepSize <= 15'd544;
+ 7'd46: stepSize <= 15'd598;
+ 7'd47: stepSize <= 15'd658;
+ 7'd48: stepSize <= 15'd724;
+ 7'd49: stepSize <= 15'd796;
+ 7'd50: stepSize <= 15'd876;
+ 7'd51: stepSize <= 15'd963;
+ 7'd52: stepSize <= 15'd1060;
+ 7'd53: stepSize <= 15'd1166;
+ 7'd54: stepSize <= 15'd1282;
+ 7'd55: stepSize <= 15'd1411;
+ 7'd56: stepSize <= 15'd1552;
+ 7'd57: stepSize <= 15'd1707;
+ 7'd58: stepSize <= 15'd1878;
+ 7'd59: stepSize <= 15'd2066;
+ 7'd60: stepSize <= 15'd2272;
+ 7'd61: stepSize <= 15'd2499;
+ 7'd62: stepSize <= 15'd2749;
+ 7'd63: stepSize <= 15'd3024;
+ 7'd64: stepSize <= 15'd3327;
+ 7'd65: stepSize <= 15'd3660;
+ 7'd66: stepSize <= 15'd4026;
+ 7'd67: stepSize <= 15'd4428;
+ 7'd68: stepSize <= 15'd4871;
+ 7'd69: stepSize <= 15'd5358;
+ 7'd70: stepSize <= 15'd5894;
+ 7'd71: stepSize <= 15'd6484;
+ 7'd72: stepSize <= 15'd7132;
+ 7'd73: stepSize <= 15'd7845;
+ 7'd74: stepSize <= 15'd8630;
+ 7'd75: stepSize <= 15'd9493;
+ 7'd76: stepSize <= 15'd10442;
+ 7'd77: stepSize <= 15'd11487;
+ 7'd78: stepSize <= 15'd12635;
+ 7'd79: stepSize <= 15'd13899;
+ 7'd80: stepSize <= 15'd15289;
+ 7'd81: stepSize <= 15'd16818;
+ 7'd82: stepSize <= 15'd18500;
+ 7'd83: stepSize <= 15'd20350;
+ 7'd84: stepSize <= 15'd22385;
+ 7'd85: stepSize <= 15'd24623;
+ 7'd86: stepSize <= 15'd27086;
+ 7'd87: stepSize <= 15'd29794;
+ 7'd88: stepSize <= 15'd32767;
+ default: stepSize <= 15'd32767;
+ endcase
+end
+
+endmodule
+//---------------------------------------------------------------------------------------
+// Th.. Th.. Th.. That's all folks !!!
+//---------------------------------------------------------------------------------------
Index: ima_adpcm_enc_dec/trunk/verilog/rtl
===================================================================
--- ima_adpcm_enc_dec/trunk/verilog/rtl (nonexistent)
+++ ima_adpcm_enc_dec/trunk/verilog/rtl (revision 2)
ima_adpcm_enc_dec/trunk/verilog/rtl
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: ima_adpcm_enc_dec/trunk/verilog/sim/icarus/test.log
===================================================================
--- ima_adpcm_enc_dec/trunk/verilog/sim/icarus/test.log (nonexistent)
+++ ima_adpcm_enc_dec/trunk/verilog/sim/icarus/test.log (revision 2)
@@ -0,0 +1,6 @@
+
+IMA ADPCM encoder & decoder simulation
+--------------------------------------
+VCD info: dumpfile test.vcd opened for output.
+Simulation progress: ..................... Done
+Simulation ended successfully after 174080 samples
Index: ima_adpcm_enc_dec/trunk/verilog/sim/icarus/test.sav
===================================================================
--- ima_adpcm_enc_dec/trunk/verilog/sim/icarus/test.sav (nonexistent)
+++ ima_adpcm_enc_dec/trunk/verilog/sim/icarus/test.sav (revision 2)
@@ -0,0 +1,82 @@
+[timestart] 245407
+[size] 1440 848
+[pos] 7 21
+*-6.233498 245600 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] test.
+@28
+test.clock
+test.reset
+@24
+test.sampCount[31:0]
+@420
+test.inSamp[15:0]
+@28
+test.inValid
+test.inReady
+@24
+test.encCount[31:0]
+test.encExpVal[3:0]
+test.encPcm[3:0]
+@28
+test.encValid
+@24
+test.decCount[31:0]
+@420
+test.decExpVal[15:0]
+@28
+test.decReady
+@420
+test.decSamp[15:0]
+@28
+test.decValid
+@200
+-adpcm_enc
+@420
+test.enc.inSamp[15:0]
+@28
+test.enc.inValid
+@421
+test.enc.sampDiff[19:0]
+@24
+test.enc.stepIndex[6:0]
+test.enc.stepSize[14:0]
+@420
+test.enc.prePredSamp[19:0]
+test.enc.predictorSamp[18:0]
+@24
+test.enc.preStepIndex[7:0]
+@420
+test.enc.stepDelta[4:0]
+@24
+test.enc.stepIndex[6:0]
+test.enc.stepSize[14:0]
+@200
+-adpcm_dec
+@28
+test.dec.clock
+@420
+test.dec.dequantSamp[18:0]
+@22
+test.dec.inPCM[3:0]
+@28
+test.dec.inReady
+test.dec.inValid
+@420
+test.dec.outSamp[15:0]
+@28
+test.dec.outValid
+@420
+test.dec.prePredSamp[19:0]
+@24
+test.dec.preStepIndex[7:0]
+@28
+test.dec.predValid
+@420
+test.dec.predictorSamp[18:0]
+@28
+test.dec.reset
+@420
+test.dec.stepDelta[4:0]
+@24
+test.dec.stepIndex[6:0]
+test.dec.stepSize[14:0]
Index: ima_adpcm_enc_dec/trunk/verilog/sim/icarus/block.cfg
===================================================================
--- ima_adpcm_enc_dec/trunk/verilog/sim/icarus/block.cfg (nonexistent)
+++ ima_adpcm_enc_dec/trunk/verilog/sim/icarus/block.cfg (revision 2)
@@ -0,0 +1,4 @@
++incdir+../../bench
+../../bench/tb_ima_adpcm.v
+../../rtl/ima_adpcm_enc.v
+../../rtl/ima_adpcm_dec.v
Index: ima_adpcm_enc_dec/trunk/verilog/sim/icarus/run.bat
===================================================================
--- ima_adpcm_enc_dec/trunk/verilog/sim/icarus/run.bat (nonexistent)
+++ ima_adpcm_enc_dec/trunk/verilog/sim/icarus/run.bat (revision 2)
@@ -0,0 +1 @@
+vvp -l test.log test.vvp
Index: ima_adpcm_enc_dec/trunk/verilog/sim/icarus/gtk.bat
===================================================================
--- ima_adpcm_enc_dec/trunk/verilog/sim/icarus/gtk.bat (nonexistent)
+++ ima_adpcm_enc_dec/trunk/verilog/sim/icarus/gtk.bat (revision 2)
@@ -0,0 +1 @@
+gtkwave test.vcd -a test.sav
Index: ima_adpcm_enc_dec/trunk/verilog/sim/icarus/compile.bat
===================================================================
--- ima_adpcm_enc_dec/trunk/verilog/sim/icarus/compile.bat (nonexistent)
+++ ima_adpcm_enc_dec/trunk/verilog/sim/icarus/compile.bat (revision 2)
@@ -0,0 +1 @@
+iverilog -o test.vvp -cblock.cfg
Index: ima_adpcm_enc_dec/trunk/verilog/sim/icarus
===================================================================
--- ima_adpcm_enc_dec/trunk/verilog/sim/icarus (nonexistent)
+++ ima_adpcm_enc_dec/trunk/verilog/sim/icarus (revision 2)
ima_adpcm_enc_dec/trunk/verilog/sim/icarus
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: ima_adpcm_enc_dec/trunk/verilog/sim
===================================================================
--- ima_adpcm_enc_dec/trunk/verilog/sim (nonexistent)
+++ ima_adpcm_enc_dec/trunk/verilog/sim (revision 2)
ima_adpcm_enc_dec/trunk/verilog/sim
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: ima_adpcm_enc_dec/trunk/verilog
===================================================================
--- ima_adpcm_enc_dec/trunk/verilog (nonexistent)
+++ ima_adpcm_enc_dec/trunk/verilog (revision 2)
ima_adpcm_enc_dec/trunk/verilog
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: ima_adpcm_enc_dec/trunk/scilab/test_dec.bin
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: ima_adpcm_enc_dec/trunk/scilab/test_dec.bin
===================================================================
--- ima_adpcm_enc_dec/trunk/scilab/test_dec.bin (nonexistent)
+++ ima_adpcm_enc_dec/trunk/scilab/test_dec.bin (revision 2)
ima_adpcm_enc_dec/trunk/scilab/test_dec.bin
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ima_adpcm_enc_dec/trunk/scilab/test_ima_adpcm.sce
===================================================================
--- ima_adpcm_enc_dec/trunk/scilab/test_ima_adpcm.sce (nonexistent)
+++ ima_adpcm_enc_dec/trunk/scilab/test_ima_adpcm.sce (revision 2)
@@ -0,0 +1,77 @@
+// this script tests the ADC encoder & decoder
+mode(-1)
+
+// set script parameters
+// set to non zero to enable user selected WAV file
+select_file_gui = 1;
+// set default file name when GUI is disabled or canceled
+default_filename = "1234.wav";
+// maximum length of audio samples to limit the runtime & verilog vector files
+// set to 0 to disable any size limiting
+maximum_samp_len = 0;
+// set to non zero value to enable verilog simulation input & output vectors creation
+verilog_vec_enable = 0;
+
+// get the functions
+getd();
+
+// set name of input WAV file
+if (select_file_gui),
+ // get file from the user
+ fname=uigetfile("*.wav", "", "Select WAV File");
+ // check if default file should be used
+ if ~length(fname),
+ fname = default_filename;
+ end
+else
+ // use default filename
+ fname = default_filename;
+end
+
+// load the WAV linear samples file
+[samp, wav_Fs, wav_bits] = wavread(fname);
+// only use a single channel
+samp = samp(1, :);
+// number of bits must be 16
+if (wav_bits ~= 16),
+ error("ERROR: WAV file must be 16 bits.");
+end
+
+// limit the length of the input samples vector
+if (maximum_samp_len),
+ samp = samp(1:min(maximum_samp_len, length(samp)));
+end
+
+// call the encoder
+enc_samp = ima_adpcm_enc(samp);
+
+// call the decoder
+dec_samp = ima_adpcm_dec(enc_samp);
+
+// sound the result
+sound(dec_samp/max(abs(dec_samp)), wav_Fs);
+
+// enable the following code to write Verilog simulation binary files
+if (verilog_vec_enable),
+ // save the input samples to a binary file used by the verilog simulation
+ samp = round(samp * (2^15-1));
+ fid = mopen("test_in.bin", "wb");
+ mput(samp, "s");
+ mclose(fid);
+
+ // save the ADPCM encoded values
+ fid = mopen("test_enc.bin", "wb");
+ mput(enc_samp, "uc");
+ mclose(fid);
+
+ // before saving the decoder samples they should be rounded using the hardware
+ // rounding implementation which only creates differences for negative .5
+ // values.
+// round_dec_samp = round(dec_samp);
+// cor_idx = find((round_dec_samp - dec_samp) == -0.5);
+// round_dec_samp(cor_idx) = round_dec_samp(cor_idx) + 1;
+ // save the decoded samples
+ fid = mopen("test_dec.bin", "wb");
+ mput(dec_samp, "s");
+ mclose(fid);
+end
Index: ima_adpcm_enc_dec/trunk/scilab/ima_adpcm_dec.sci
===================================================================
--- ima_adpcm_enc_dec/trunk/scilab/ima_adpcm_dec.sci (nonexistent)
+++ ima_adpcm_enc_dec/trunk/scilab/ima_adpcm_dec.sci (revision 2)
@@ -0,0 +1,74 @@
+function out_samp = ima_adpcm_dec(in_pcm)
+// This function decodes an IMA ADPCM compressed audio. The output is reconstructed
+// to 16 bits per sample.
+//
+// Author: Moti Litochevski
+// Date: February 17, 2010
+//
+
+// step quantizer adaptation lookup table
+STEP_LUT = [ ...
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, ...
+ 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, ...
+ 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, ...
+ 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, ...
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, ...
+ 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, ...
+ 20350, 22385, 24623, 27086, 29794, 32767];
+// index quantizer adaptation lookup table
+INDEX_LUT = [-1, -1, -1, -1, 2, 4, 6, 8];
+
+// prepare loop variables
+predictor_samp = zeros(1, length(in_pcm)+1);
+qstep_index = ones(1, length(in_pcm)+1);
+// convert the input coded signal to binary form & calculate the PCM value (without sign)
+pcm_bin = de2bi(in_pcm, 4);
+pcm_val = pcm_bin(:,[2:4]) * [4, 2, 1]';
+
+// decoding loop
+for idx = [1:length(in_pcm)],
+ // extract the current quantizer step size
+ qstep_size = STEP_LUT(qstep_index(idx));
+
+ // de-quantizer implementation starts from the middle of the current
+ // quantization step (qstep_size/8)
+ dequant_samp = qstep_size;
+ // de-quantize bit by bit
+ dequant_samp = dequant_samp + pcm_bin(idx, 2) * qstep_size * 8;
+ dequant_samp = dequant_samp + pcm_bin(idx, 3) * qstep_size * 4;
+ dequant_samp = dequant_samp + pcm_bin(idx, 4) * qstep_size * 2;
+
+ // update the predictor output sample according to the sign bit
+ if (pcm_bin(idx, 1)),
+ predictor_samp(idx+1) = predictor_samp(idx) - dequant_samp;
+ else
+ predictor_samp(idx+1) = predictor_samp(idx) + dequant_samp;
+ end
+ // check for predictor sample saturation condition
+ if (predictor_samp(idx+1) > (2^18-1)),
+ predictor_samp(idx+1) = 2^18-1;
+ elseif (predictor_samp(idx+1) < -2^18),
+ predictor_samp(idx+1) = -2^18;
+ end
+
+ // update the step size index
+ qstep_index(idx+1) = qstep_index(idx) + INDEX_LUT(pcm_val(idx)+1);
+ // check index saturation conditions
+ if (qstep_index(idx+1) < 1)
+ qstep_index(idx+1) = 1;
+ elseif (qstep_index(idx+1) > 89)
+ qstep_index(idx+1) = 89;
+ end
+end
+
+// output sample is just the saturated & scaled predictor output
+out_samp = predictor_samp(2:$)/8;
+// implement rounding
+out_samp = round(out_samp);
+cor_idx = find((out_samp - predictor_samp(2:$)/8) == -0.5);
+out_samp(cor_idx) = out_samp(cor_idx) + 1;
+// check for saturation
+out_samp(find(predictor_samp(2:$)/8 > 32767)) = 32767;
+out_samp(find(predictor_samp(2:$)/8 < -32768)) = -32768;
+
+endfunction
Index: ima_adpcm_enc_dec/trunk/scilab/1234.wav
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: ima_adpcm_enc_dec/trunk/scilab/1234.wav
===================================================================
--- ima_adpcm_enc_dec/trunk/scilab/1234.wav (nonexistent)
+++ ima_adpcm_enc_dec/trunk/scilab/1234.wav (revision 2)
ima_adpcm_enc_dec/trunk/scilab/1234.wav
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ima_adpcm_enc_dec/trunk/scilab/test_enc.bin
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: ima_adpcm_enc_dec/trunk/scilab/test_enc.bin
===================================================================
--- ima_adpcm_enc_dec/trunk/scilab/test_enc.bin (nonexistent)
+++ ima_adpcm_enc_dec/trunk/scilab/test_enc.bin (revision 2)
ima_adpcm_enc_dec/trunk/scilab/test_enc.bin
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ima_adpcm_enc_dec/trunk/scilab/test_in.bin
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: ima_adpcm_enc_dec/trunk/scilab/test_in.bin
===================================================================
--- ima_adpcm_enc_dec/trunk/scilab/test_in.bin (nonexistent)
+++ ima_adpcm_enc_dec/trunk/scilab/test_in.bin (revision 2)
ima_adpcm_enc_dec/trunk/scilab/test_in.bin
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ima_adpcm_enc_dec/trunk/scilab/ima_adpcm_enc.sci
===================================================================
--- ima_adpcm_enc_dec/trunk/scilab/ima_adpcm_enc.sci (nonexistent)
+++ ima_adpcm_enc_dec/trunk/scilab/ima_adpcm_enc.sci (revision 2)
@@ -0,0 +1,92 @@
+function out_pcm = ima_adpcm_enc(in_samp)
+// This function encodes the input samples audio vector using IMA ADPCM algorithm. The
+// input is assumed to be sampled using 16 bits per sample. The output vector is a
+// compressed version of the input audio signal which requires only 4 bits per input
+// sample.
+// The function will scale the input vector to 16 bits per sample automatically if all
+// values in the vector are in the range [-1:1].
+//
+// Author: Moti Litochevski
+// Date: February 17, 2010
+//
+
+// check the input vector samples range
+if (abs(in_samp) <= 1),
+ in_samp = round(in_samp * (2^15-1));
+end
+
+// step quantizer adaptation lookup table
+STEP_LUT = [ ...
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, ...
+ 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, ...
+ 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, ...
+ 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, ...
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, ...
+ 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, ...
+ 20350, 22385, 24623, 27086, 29794, 32767];
+// quantizer index adaptation lookup table
+INDEX_LUT = [-1, -1, -1, -1, 2, 4, 6, 8];
+
+// prepare output vector
+out_pcm = zeros(length(in_samp), 4); // in binary format
+
+// prepare loop variables
+predictor_samp = zeros(1, length(in_samp)+1);
+qstep_index = ones(1, length(in_samp)+1);
+
+// compression loop
+for idx = [1:length(in_samp)],
+ // subtract the previous sample form the current input sample
+ samp_diff = in_samp(idx)*8 - predictor_samp(idx);
+
+ // extract the current quantizer step size
+ qstep_size = STEP_LUT(qstep_index(idx));
+
+ // start difference quantization from the sign bit
+ out_pcm(idx, 1) = 1 * (samp_diff < 0);
+ samp_diff = abs(samp_diff);
+
+ // quantize the absolute value bit by bit
+ // the same process is used to calculate the de-quantizer output sample. note that the
+ // de-quantizer sample is started from the middle of the current step size (qstep_size/8).
+ dequant_samp = qstep_size;
+ // bit 2
+ out_pcm(idx, 2) = 1 * (samp_diff >= (qstep_size * 8));
+ samp_diff = samp_diff - out_pcm(idx, 2) * qstep_size * 8;
+ dequant_samp = dequant_samp + out_pcm(idx, 2) * qstep_size * 8;
+ // bit 1
+ out_pcm(idx, 3) = 1 * (samp_diff >= (qstep_size * 4));
+ samp_diff = samp_diff - out_pcm(idx, 3) * qstep_size * 4;
+ dequant_samp = dequant_samp + out_pcm(idx, 3) * qstep_size * 4;
+ // bit 0
+ out_pcm(idx, 4) = 1 * (samp_diff >= (qstep_size * 2));
+ dequant_samp = dequant_samp + out_pcm(idx, 4) * qstep_size * 2;
+
+ // update the predictor sample for the next iteration according to the sign bit
+ if (out_pcm(idx, 1)),
+ predictor_samp(idx+1) = predictor_samp(idx) - dequant_samp;
+ else
+ predictor_samp(idx+1) = predictor_samp(idx) + dequant_samp;
+ end
+ // check for predictor sample saturation condition
+ if (predictor_samp(idx+1) > (2^18-1)),
+ predictor_samp(idx+1) = 2^18 - 1;
+ elseif (predictor_samp(idx+1) < -2^18),
+ predictor_samp(idx + 1) = -2^18;
+ end
+
+ // update the step size index
+ pcm_val = out_pcm(idx, [2:4]) * [4, 2, 1]';
+ qstep_index(idx+1) = qstep_index(idx) + INDEX_LUT(pcm_val+1);
+ // check index saturation conditions
+ if (qstep_index(idx+1) < 1)
+ qstep_index(idx+1) = 1;
+ elseif (qstep_index(idx+1) > 89)
+ qstep_index(idx+1) = 89;
+ end
+end
+
+// convert the resulting compressed binary values to decimal
+out_pcm = bi2de(out_pcm);
+
+endfunction
Index: ima_adpcm_enc_dec/trunk/scilab
===================================================================
--- ima_adpcm_enc_dec/trunk/scilab (nonexistent)
+++ ima_adpcm_enc_dec/trunk/scilab (revision 2)
ima_adpcm_enc_dec/trunk/scilab
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property