Goto: [ Program Documentation ]
//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Tue May 14 20:21:29 PDT 1996
// Last Modified: Sat Apr 4 16:47:49 GMT-0800 1998
// Filename: ...sig/doc/examples/sig/sigfile/sndbit/sndbit.cpp
// Syntax: C++; sig
//
// Description: With this program you can mask bits in a 16-bit/sample
// soundfile, and you can also reorder the bits in the output sound file.
//
// To pass a bit to the output soundfile specify a '1' in the desired bit
// location of the -m option. To stop a bit from being passed to the output
// soundfile, specify a '0'. For example, to pass the 4 most significant
// bits of the sound samples, the following command would be used:
// sndbit -m1111000000000000 in.snd out.snd
//
// To verify that the ordering option is done properly, put the bits in
// a random order, and then reverse the process:
// sndbit -o0123456789abcdef in.snd out.snd # reverses bits
// sndbit -o0123456789abcdef out.snd in2.snd # reverses bits again
// Now in.snd and in2.snd should be the same.
//
// Bits can be repeated multiple times in the output ordering. For example,
// the following command will generate a sequence of 0's and -1's according
// to the value of the most-significant bit of the input sound samples:
// sndbit -m1000000000000000 -offffffffffffffff in.snd out.snd
//
#include "Options.h"
#include "sigAudio.h"
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#ifndef OLDCPP
#include <iostream>
using namespace std;
#else
#include <iostream.h>
#endif
// function declarations:
void checkOptions(Options& opts);
void example(void);
void exitUsage(const char* command);
void help(void);
ushort makeBitMask(const char*);
ushort mixbits(const int* mixingString, const char* maskingString,
ushort sample);
void printbinaryshort(ushort);
// global variables:
Options options; // for handling program input arguments
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[]) {
if (argc == 1) {
exitUsage(argv[0]);
}
options.define("m|mask=s:1111111111111111");
options.define("o|order=s");
options.define("h|help=b");
options.define("author=b");
options.define("version=b");
options.define("example=b");
options.define("usage=b");
options.process(argc, argv);
checkOptions(options);
SoundFileIn insound(options.getArgument(1));
if (insound.getBitsPerSample() != 16) {
cout << "Error: This program can only process 16-bit samples." << endl;
cout << " sample size in input soundfile is "
<< insound.getBitsPerSample() << "." << endl;
exit(1);
}
SoundFileOut outsound(options.getArgument(2), insound.getHeader());
const char* patternMaskStr = options.getString("mask");
const char* patternOrderStr = options.getString("order");
ushort twoByteMask; // for filtering bits from sound samples
twoByteMask = makeBitMask(patternMaskStr);
int orderingArray[16];
if (strlen(patternOrderStr) != 0) {
for (int i=0; i<16; i++) {
if (isalpha(patternOrderStr[i])) {
orderingArray[i] = tolower(patternOrderStr[i]) -'a' + 10;
if (orderingArray[i] >= 16) {
cout << "Error: invalid letter in ordering string.\n";
exitUsage(options.getCommand());
}
} else if (isdigit(patternOrderStr[i])) {
orderingArray[i] = patternOrderStr[i] -'0';
} else {
cout << "Error: invalid character in ordering string.\n";
exitUsage(options.getCommand());
}
}
}
int sampleCount; // total number of sound samples in input/output
sampleCount = insound.getSamples() * insound.getChannels();
ushort currentSample; // current sample to process
if (strlen(patternOrderStr) == 0) { // not moving bits around
for (int i=0; i<sampleCount; i++) {
currentSample = insound.extractSample16Bit();
currentSample &= twoByteMask;
outsound.insertSample16Bit(currentSample);
}
} else { // moving bits
for (int i=0; i<sampleCount; i++) {
currentSample = insound.extractSample16Bit();
currentSample &= twoByteMask;
outsound.insertSample16Bit(mixbits(orderingArray, patternMaskStr,
currentSample));
}
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// checkOptions -- make sure that all program options are ok.
//
void checkOptions(Options& opts) {
if (opts.getBoolean("help")) {
help();
exit(1);
}
if (opts.getBoolean("usage")) {
exitUsage(opts.getCommand());
}
if (opts.getBoolean("example")) {
example();
exit(1);
}
if (opts.getBoolean("author")) {
cout << "Written by Craig Stuart Sapp, "
<< "craig@ccrma.stanford.edu, May 1996" << endl;
exit(1);
}
if (opts.getBoolean("version")) {
cout << "sndbit version: Tue Apr 7 20:29:29 PDT 1998." << endl;
cout << SIG_VERSION << endl;
exit(1);
}
if (opts.getArgCount() != 2) {
cout << "Error: must specify input and output soundfiles." << endl;
exitUsage(opts.getCommand());
}
if (strlen(opts.getString("mask")) != 16) {
cout << "Error: must specify 16 bits in masking pattern.\n";
exitUsage(opts.getCommand());
}
const char *orderString = opts.getString("order");
if (!(strlen(orderString) == 16 || strlen(orderString) == 0)) {
cout << "Error: must specify 16 bits in ordering pattern.\n";
cout << " Length is " << strlen(orderString) << endl;
exitUsage(opts.getCommand());
}
}
//////////////////////////////
//
// example
//
void example(void) {
cout <<
"# sndbit example: \n"
"# Here is an example which will quantize a soundfile to \n"
"# 16 loudness levels: \n"
" osc \"0 0 1 440\" \"0 0 1 1 2 0\" -d 2 infile.snd \n"
" sndbit -m 1111000000000000 infile.snd outfile.snd \n"
"# \n"
"# Here are the least significant bits amplified: \n"
" sndbit -m 0000000000001111 -o3210ffffffffffff \\ \n"
" infile.snd outfile.snd \n"
<< endl;
}
//////////////////////////////
//
// exitUsage
//
void exitUsage(const char* command) {
cout << "\nUsage: " << command
<< " [-m maskingBitPattern][-o orderingBitPattern] inFile outFile\n";
cout << " Removes bits/reorders bits in a soundfile.\n"
<< " The default options will not change the input.\n";
cout << " Options are:\n";
cout << " -m maskingBitPattern = 0 removes a bit, 1 keeps a bit.\n";
cout << " Default is 1111111111111111\n";
cout << " -o orderingBitPattern = Default is fedcba9876543210\n";
cout << " -h for further help.\n";
cout << endl;
exit(1);
}
//////////////////////////////
//
// help
//
void help(void) {
cout <<
"Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>\n"
"Creation Date: Tue May 14 20:21:29 PDT 1996\n"
"Last Modified: Sat Apr 4 18:16:15 GMT-0800 1998 \n"
"\n"
"Description: With this program you can mask bits in a 16-bit/sample\n"
"soundfile, and you can also reorder the bits in the output sound file.\n"
"\n"
"To pass a bit to the output soundfile specify a '1' in the desired bit\n"
"location of the -m option. To stop a bit from being passed to the output \n"
"soundfile, specify a '0'. For example, to pass the 4 most significant \n"
"bits of the sound samples, the following command would be used:\n"
"sndbit -m1111000000000000 in.snd out.snd\n"
"\n"
"To verify that the ordering option is done properly, put the bits in \n"
"a random order, and then reverse the process:\n"
" sndbit -ofedcba9786543210 in.snd out.snd\n"
" sndbit -ofedcba9786543210 out.snd in2.snd\n"
"Now in.snd and in2.snd should be the same.\n"
"\n"
"Bits can be repeated multiple times in the output ordering. For example,\n"
"the following command will generate a sequence of 0's and -1's according\n"
"to the value of the most-significant bit of the input sound samples:\n"
" sndbit -m1000000000000000 -offffffffffffffff in.snd out.snd\n"
<< endl;
}
//////////////////////////////
//
// makeBitMask
//
ushort makeBitMask(const char* str) {
int i;
int length;
ushort value = 0;
length = strlen(str);
for (i=0; i<16; i++) {
if (str[i] == '1')
value = (value << 1) | 0x0001;
else if (str[i] == '0')
value = value << 1;
else {
fprintf(stderr, "Invalid masking pattern character: %c.", str[i]);
fprintf(stderr, " Must be a '1' or a '0'.\n");
}
}
return value;
}
//////////////////////////////
//
// mixbits
//
ushort mixbits(const int* mixingString, const char* maskingString,
ushort sample) {
int origPos, newPos, move;
ushort origBit, newBit;
ushort value = 0;
int i;
for (i=0; i<16; i++) {
origPos = mixingString[i];
if (maskingString[15 - origPos] == '0') continue;
origBit = (sample & (0x0001 << origPos));
newPos = 15 - i;
move = newPos - origPos;
newBit = (move >= 0) ? (origBit << move) : (origBit >> -move);
value = value | newBit;
}
return value;
}
///////////////////////////////
//
// printbinaryshort -- useful, but not used anymore.
//
void printbinaryshort(ushort input) {
int i;
for (i=15; i>=0; i--) {
if ((input & (0x0001 << i)) == 0)
printf("0");
else
printf("1");
}
printf("\n");
}
// md5sum: 718b226a74c0b0f6818bdb2eb6a62a13 sndbit.cpp [20050403]