📄 converter.c
字号:
//*****************************************************************************
//
// converter.c - Program to convert 16-bit mono PCM files into C arrays for use
// by the Class-D audio driver.
//
// Copyright (c) 2007 Luminary Micro, Inc. All rights reserved.
//
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws. All rights are reserved. You may not combine
// this software with "viral" open-source software in order to form a larger
// program. Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 1952 of the Stellaris Peripheral Driver Library.
//
//*****************************************************************************
#include <stdio.h>
#include <unistd.h>
//*****************************************************************************
//
// The possible modes of the application.
//
//*****************************************************************************
#define MODE_NONE 0
#define MODE_PCM 1
#define MODE_ADPCM 2
//*****************************************************************************
//
// The adjustment to the step index based on the value of an encoded sample.
// The sign bit is ignored when using this table (that is, only the lower three
// bits are used).
//
//*****************************************************************************
static const char g_pcADPCMIndex[8] =
{
-1, -1, -1, -1, 2, 4, 6, 8
};
//*****************************************************************************
//
// The differential values for the ADPCM decoder. One of these is selected
// based on the step index.
//
//*****************************************************************************
static const unsigned short g_pusADPCMStep[89] =
{
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
};
//*****************************************************************************
//
// The current step index for the ADPCM decoder. This selects a differential
// value from g_pusADPCMStep.
//
//*****************************************************************************
static long g_lStepIndex;
//*****************************************************************************
//
// The previous output of the ADPCM decoder.
//
//*****************************************************************************
static short g_sPreviousOutput;
//*****************************************************************************
//
// Initializes the ADPCM decoder.
//
//*****************************************************************************
static void
ADPCMInit(void)
{
//
// Reset the step index and previous output values to zero.
//
g_lStepIndex = 0;
g_sPreviousOutput = 0;
}
//*****************************************************************************
//
// Decodes a sample of ADPCM data.
//
//*****************************************************************************
static short
ADPCMDecode(char cCode)
{
long lStep;
//
// Compute the sample delta based on the current nibble and step size.
//
lStep = (((2 * (cCode & 7)) + 1) * g_pusADPCMStep[g_lStepIndex]) / 8;
//
// Add or subtract the delta to the previous sample value, clipping if
// necessary.
//
if(cCode & 8)
{
lStep = (long)g_sPreviousOutput - lStep;
if(lStep < -32768)
{
lStep = -32768;
}
}
else
{
lStep = (long)g_sPreviousOutput + lStep;
if(lStep > 32767)
{
lStep = 32767;
}
}
//
// Store the generated sample.
//
g_sPreviousOutput = (short)lStep;
//
// Adjust the step size index based on the current nibble, clipping the
// value if required.
//
g_lStepIndex += g_pcADPCMIndex[cCode & 7];
if(g_lStepIndex < 0)
{
g_lStepIndex = 0;
}
if(g_lStepIndex > 88)
{
g_lStepIndex = 88;
}
//
// Return the generated sample.
//
return((short)lStep);
}
//*****************************************************************************
//
// Encodes a sample to ADPCM.
//
//*****************************************************************************
static char
ADPCMEncode(short sSample)
{
long lStep, lCode, lSign;
//
// Compute the difference between this sample and the previous output of
// the decoder.
//
lStep = sSample - g_sPreviousOutput;
//
// Determine the sign of the difference, and make the difference positive
// if it is negative.
//
if(lStep < 0)
{
lSign = 1;
lStep = 0 - lStep;
}
else
{
lSign = 0;
}
//
// Determine the encoded value based on the current step size in the
// decoder.
//
lCode = (4 * lStep) / g_pusADPCMStep[g_lStepIndex];
if(lCode > 7)
{
lCode = 7;
}
//
// Place the sign bit into the encoded value.
//
if(lSign)
{
lCode |= 8;
}
//
// Update the decoder based on this new sample.
//
ADPCMDecode(lCode);
//
// Return the encoded ADPCM value.
//
return(lCode);
}
//*****************************************************************************
//
// Prints out usage information for the application.
//
//*****************************************************************************
void
Usage(char *pcFilename)
{
fprintf(stderr, "Usage: %s [OPTION]... [INPUT FILE]\n",
basename(pcFilename));
fprintf(stderr, "Converts a raw 16-bit, mono PCM input file to a C array "
"with PCM or ADPCM.\n");
fprintf(stderr, "\n");
fprintf(stderr, "Options are:\n");
fprintf(stderr, " -a Encode to 4-bit IMA ADPCM\n");
fprintf(stderr, " -c COUNT Maximum number of output bytes\n");
fprintf(stderr, " -n NAME Specify the name of the C array\n");
fprintf(stderr, " -o FILENAME Specify the name of the output file\n");
fprintf(stderr, " -p Encode to 8-bit PCM\n");
fprintf(stderr, "\n");
fprintf(stderr, "If the input filename is not specified, standard input "
"will be used.\n");
fprintf(stderr, "If the output filename is not specified, standard output "
"will be used.\n");
fprintf(stderr, "\n");
fprintf(stderr, "Report bugs to <support@luminarymicro.com>.\n");
}
//*****************************************************************************
//
// An application to convert from 16-bit PCM data to either 8-bit PCM or 4-bit
// ADPCM data.
//
//*****************************************************************************
int
main(int argc, char *argv[])
{
long lCode, lMode, lCount, lSkip, lIdx;
char *pcInput, *pcOutput, *pcArray;
short psSample[4];
FILE *pIn, *pOut;
//
// Initialize the name of the input file, output file, and the name of the
// C array to produce.
//
pcInput = NULL;
pcOutput = NULL;
pcArray = "g_pucAudioData";
//
// Set the default number of samples to skip and bytes to produce.
//
lSkip = 0;
lCount = 0x7fffffff;
//
// Initialize the mode to none, requiring that one be specified on the
// command line.
//
lMode = MODE_NONE;
//
// Parse the command line arguments.
//
while((lCode = getopt(argc, argv, "?ac:dhn:o:ps:")) != -1)
{
//
// See which flag was found.
//
switch(lCode)
{
//
// Encoding to ADPCM has been requested.
//
case 'a':
{
lMode = MODE_ADPCM;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -