public byte[] ToPcm(byte[] audio, IAudioAttachData audioAttachData) { byte[] pcmdata = new byte[audio.Length * 2]; for (int i = 0, offset = 0; i < audio.Length; i++) { short value = AlawToLinear(audio[i]); pcmdata[offset++] = (byte)(value & 0xff); pcmdata[offset++] = (byte)((value >> 8) & 0xff); } return(pcmdata); }
//private byte[] Pcm16ToUlaw(byte[] pcmSamples) //{ // short[] dst = new short[pcmSamples.Length / 2]; // byte[] ulawSamples = new byte[pcmSamples.Length / 2]; // for (int i = 0, k = 0; i < pcmSamples.Length;) // { // dst[k++] = (short)((pcmSamples[i++] & 0xff) | ((pcmSamples[i++] & 0xff) << 8)); // } // for (int i = 0, k = 0; i < dst.Length; i++) // { // ulawSamples[k++] = Linear2ulaw(dst[i]); // } // return ulawSamples; //} //public byte[] ToG711(byte[] data) => Pcm16ToUlaw(data); public byte[] ToPcm(byte[] audio, IAudioAttachData audioAttachData) { return(UlawToPcm16(audio)); }
//public static byte[] ToAdpcm(short[] indata, AdpcmState state) //{ // int val; /* Current input sample value */ // int sign; /* Current adpcm sign bit */ // int delta; /* Current adpcm output value */ // int diff; /* Difference between val and valprev */ // int step; /* Stepsize */ // int valpred; /* Predicted output value */ // int vpdiff; /* Current change to valpred */ // int index; /* Current step change index */ // int outputbuffer = 0; /* place to keep previous 4-bit value */ // int bufferstep; /* toggle between outputbuffer/output */ // List<byte> outp = new List<byte>(); // short[] inp = indata; // var len = indata.Length; // valpred = state.Valprev; // index = state.Index; // step = stepsizeTable[index]; // bufferstep = 1; // int k = 0; // for (int i = 0; len > 0; len--, i++) // { // val = inp[i]; // /* Step 1 - compute difference with previous value */ // diff = val - valpred; // sign = (diff < 0) ? 8 : 0; // if (sign != 0) diff = (-diff); // /* Step 2 - Divide and clamp */ // /* Note: // ** This code *approximately* computes: // ** delta = diff*4/step; // ** vpdiff = (delta+0.5)*step/4; // ** but in shift step bits are dropped. The net result of this is // ** that even if you have fast mul/div hardware you cannot put it to // ** good use since the fixup would be too expensive. // */ // delta = 0; // vpdiff = (step >> 3); // if (diff >= step) // { // delta = 4; // diff -= step; // vpdiff += step; // } // step >>= 1; // if (diff >= step) // { // delta |= 2; // diff -= step; // vpdiff += step; // } // step >>= 1; // if (diff >= step) // { // delta |= 1; // vpdiff += step; // } // /* Step 3 - Update previous value */ // if (sign != 0) // valpred -= vpdiff; // else // valpred += vpdiff; // /* Step 4 - Clamp previous value to 16 bits */ // if (valpred > 32767) // valpred = 32767; // else if (valpred < -32768) // valpred = -32768; // /* Step 5 - Assemble value, update index and step values */ // delta |= sign; // index += indexTable[delta]; // if (index < 0) index = 0; // if (index > 88) index = 88; // step = stepsizeTable[index]; // /* Step 6 - Output value */ // if (bufferstep != 0) // { // outputbuffer = (delta << 4) & 0xf0; // } // else // { // outp.Add((byte)((delta & 0x0f) | outputbuffer)); // } // bufferstep = bufferstep == 0 ? 1 : 0; // } // /* Output last step, if needed */ // if (bufferstep == 0) // outp.Add((byte)outputbuffer); // state.Valprev = (short)valpred; // state.Index = (byte)index; // return outp.ToArray(); //} /// <summary> /// 将adpcm转为pcm /// </summary> /// <see cref="https://github.com/ctuning/ctuning-programs/blob/master/program/cbench-telecom-adpcm-d/adpcm.c"/> /// <param name="audio"></param> /// <param name="audioAttachData"></param> /// <returns></returns> public byte[] ToPcm(byte[] audio, IAudioAttachData audioAttachData) { AdpcmState state = (AdpcmState)audioAttachData; // signed char *inp; /* Input buffer pointer */ // short *outp; /* output buffer pointer */ int sign; /* Current adpcm sign bit */ int delta; /* Current adpcm output value */ int step; /* Stepsize */ int valpred = state.Valprev; /* Predicted value */ int vpdiff; /* Current change to valpred */ byte index = state.Index; /* Current step change index */ int inputbuffer = 0; /* place to keep next 4-bit value */ bool bufferstep = false; /* toggle between inputbuffer/input */ step = stepsizeTable[index]; var outdata = new List <byte>(); var len = audio.Length * 2; for (int i = 0; len > 0; len--) { /* Step 1 - get the delta value */ if (bufferstep) { delta = inputbuffer & 0xf; } else { inputbuffer = audio[i++]; delta = (inputbuffer >> 4) & 0xf; } bufferstep = !bufferstep; /* Step 2 - Find new index value (for later) */ index += (byte)indexTable[delta]; if (index < 0) { index = 0; } if (index > 88) { index = 88; } /* Step 3 - Separate sign and magnitude */ sign = delta & 8; delta &= 7; /* Step 4 - Compute difference and new predicted value */ /* ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment ** in adpcm_coder. */ vpdiff = step >> 3; if ((delta & 4) > 0) { vpdiff += step; } if ((delta & 2) > 0) { vpdiff += step >> 1; } if ((delta & 1) > 0) { vpdiff += step >> 2; } if (sign != 0) { valpred -= vpdiff; } else { valpred += vpdiff; } /* Step 5 - clamp output value */ if (valpred > 32767) { valpred = 32767; } else if (valpred < -32768) { valpred = -32768; } /* Step 6 - Update step value */ step = stepsizeTable[index]; /* Step 7 - Output value */ outdata.AddRange(BitConverter.GetBytes((short)valpred)); } state.Valprev = (short)valpred; state.Index = index; return(outdata.ToArray()); }