Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have a binary string with ASCII like this
^#^#^#^A^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^A^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^A^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^A^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^A^#^#^O ^#^#^#^#^#^BÜ-^#^#^#^A^#^#^O ^#^#^#^#^#^BÜ-^#^#^#^A^#^#^#^#^#^#^#^#^EÜ?^#^#^#^A^#^#^#^#^#^#^#^#^EÜ?^#^#^#^A^#^#.à^#^#^#^#^#^Häð^#^#^#^A^#^#.à^#^#^#^#^#^Häð^#^#^#^A^#^#><80>^#^#^#^#^#^KÖ<80>^#^#^#^A^#^#><80>^
Perl code:
#!/usr/bin/env perl
use warnings;
use strict;
use Data::Dumper;
open(INDEX, $ARGV[0]);
binmode(INDEX);
my $buff;
my $ret = read(INDEX, $buff, 4);
my $fragment = unpack 'N', $buff;
$ret = read(INDEX, $buff, 4);
my $timestamp = unpack 'N', $buff;
$ret = read(INDEX, $buff, 8);
my $offset = unpack 'N', $buff;
print "timestamp = $timestamp fragment # $fragment offset = $offset\n";
Output:
timestamp = 0 fragment # 1 offset = 0
timestamp = 0 fragment # 1 offset = 0
timestamp = 0 fragment # 1 offset = 0
timestamp = 0 fragment # 1 offset = 0
timestamp = 4000 fragment # 1 offset = 187437
timestamp = 4000 fragment # 1 offset = 187437
timestamp = 8000 fragment # 1 offset = 384063
timestamp = 8000 fragment # 1 offset = 384063
timestamp = 12000 fragment # 1 offset = 582896
timestamp = 12000 fragment # 1 offset = 582896
I want to replicate the above work done by unpack in C++
How to do it?
What I was trying:
#include <iostream>
#include <stdlib.h>
using namespace std;
int main ()
{
int k;
char buf1[5];
char buf2[5];
char buf3[9];
int i;
char *str;
//Assume str contains the entire binary data
for(int i=0;str[i];)
{
while(k<32)
{
buf1[k]=str[i];
++k;++i;
}
k=0;
while(k<32)
{
buf2[k]=str[i];
++k;
}
k=0;
while(k<64)
{
buf3[k]=str[i];
++k;++i;
}
k=0;
uint32_t a1,b1,a2,b2;
uint64_t a3,b3;
a1=atoi(buf1);
b1=ntohl(a1);
a2=atoi(buf2);
b2=ntohl(a2);
a3=atoi(buf1);
b3=ntohl(a3);
print "timestamp ="<< b2 << "fragment #"<<b1<<" offset ="<<b3<<"\n";
}
return 0;
}
Here you go:
#include <stdint.h>
#include <iostream>
#include <fstream>
using namespace std;
int main( int argc, char *argv[] )
{
if (argc < 2)
{
cerr << "Input filename required" << endl;
return 1;
}
ifstream f( argv[1], ios::binary );
if (!f.good())
{
cerr << "Cannot open input file '" << argv[1] << "'" << endl;
return 1;
}
while (!f.eof())
{
uint8_t buf[8];
f.read( reinterpret_cast< char * >( buf ), 4 );
uint32_t fragment = ( ( buf[0] * 256U + buf[1] ) * 256U + buf[2] ) * 256U + buf[3];
f.read( reinterpret_cast< char * >( buf ), 4 );
uint32_t timestamp = ( ( buf[0] * 256U + buf[1] ) * 256U + buf[2] ) * 256U + buf[3];
f.read( reinterpret_cast< char * >( buf ), 8 );
uint64_t offset = ( ( ( ( ( ( buf[0] * 256LL + buf[1] ) * 256LL + buf[2] ) * 256LL + buf[3] )
* 256LL + buf[4] ) * 256LL + buf[5] ) * 256LL + buf[6] ) * 256LL + buf[7];
if (f.good())
{
cout << "timestamp = " << timestamp;
cout << " fragment = " << fragment;
cout << " offset = " << offset << endl;
}
}
return 0;
}
Read 4 bytes, then use
uint32_t n;
n = buf[0] << 24
| buf[1] << 16
| buf[2] << 8
| buf[3] << 0;
For example,
uint32_t n;
unsigned char buf[4];
size_t bytes_read = fread (buf, 1, 4, stream);
if (bytes_read < 4) {
if (ferror(stream)) {
// Error
// ...
}
else if (feof(stream)) {
// Premature EOF
// ...
}
}
else {
n = buf[0] << 24
| buf[1] << 16
| buf[2] << 8
| buf[3] << 0;
}
Related
I am trying to write to wav by taking data from the microphone input, and other headers, and putting that into the wav file. I do that, but it still says corrupted file. One note about the code is that in the struct with the headers, it's not in the correct order. In the WriteToWav function I entered it in the correct order based on the chunk and sub chunks. Here's the code:
struct WavHeaders {
//Fmt
char SubChunk1ID[4];
int SubChunk1Size = 16;
int AudioFormat = 1;
int NumChannels = 2;
int SampleRate = 44100;
int BitsPerSample = 16;
int ByteRate = SampleRate * NumChannels * BitsPerSample / 8;
int BlockAlign = NumChannels * BitsPerSample / 8;
//Data
char SubChunk2ID[4];
int SubChunk2Size = 1 * NumChannels * BitsPerSample / 8;
//RIFF
char ChunkID[4];
int ChunkSize = 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size);
char Format[4];
};
void _AudioReader::AudioReader::AudioToWav() {
WAVEFORMATEX wfx = {};
wfx.wFormatTag = WAVE_FORMAT_PCM; // PCM is standard
wfx.nChannels = 2; // 2 channels = stereo sound
wfx.nSamplesPerSec = 44100; // Samplerate. 44100 Hz
wfx.wBitsPerSample = 16; // 16 bit samples
wfx.nBlockAlign = wfx.wBitsPerSample * wfx.nChannels / 8;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
HWAVEIN wi;
waveInOpen(
&wi,
WAVE_MAPPER,
&wfx,
NULL, NULL,
CALLBACK_NULL | WAVE_FORMAT_DIRECT
);
char buffers[2][44100 * 2 * 2 / 2];
WAVEHDR headers[2] = { {},{} };
for (int i = 0; i < 2; ++i){
headers[i].lpData = buffers[i];
headers[i].dwBufferLength = 44100 * 2 * 2 / 2;
waveInPrepareHeader(wi, &headers[i], sizeof(headers[i]));
waveInAddBuffer(wi, &headers[i], sizeof(headers[i]));
}
//Set Header IDS as char array
WavHeaders Wav_Headers;
Wav_Headers.SubChunk1ID[0] = 'f';
Wav_Headers.SubChunk1ID[1] = 'm';
Wav_Headers.SubChunk1ID[2] = 't';
Wav_Headers.SubChunk1ID[3] = ' ';
Wav_Headers.SubChunk2ID[0] = 'd';
Wav_Headers.SubChunk2ID[1] = 'a';
Wav_Headers.SubChunk2ID[2] = 't';
Wav_Headers.SubChunk2ID[3] = 'a';
Wav_Headers.ChunkID[0] = 'R';
Wav_Headers.ChunkID[1] = 'I';
Wav_Headers.ChunkID[2] = 'F';
Wav_Headers.ChunkID[3] = 'F';
Wav_Headers.Format[0] = 'W';
Wav_Headers.Format[1] = 'A';
Wav_Headers.Format[2] = 'V';
Wav_Headers.Format[3] = 'E';
std::ofstream AudioFile("Audio.wav", std::ios_base::out | std::ios_base::binary);
//Write Headers to audio file
for(int i = 0; i < 4; i++) //RIFF Chunk
AudioFile << Wav_Headers.ChunkID[i];
AudioFile << Wav_Headers.ChunkSize << Wav_Headers.Format;
for (int i = 0; i < 4; i++) //fmt(format) sub-chunk
AudioFile << Wav_Headers.SubChunk1ID[i];
AudioFile <<
Wav_Headers.SubChunk1Size <<
Wav_Headers.AudioFormat <<
Wav_Headers.NumChannels <<
Wav_Headers.SampleRate <<
Wav_Headers.ByteRate <<
Wav_Headers.BlockAlign <<
Wav_Headers.BitsPerSample;
for (int i = 0; i < 4; i++) //Data sub-chunk
AudioFile << Wav_Headers.SubChunk2ID[i];
AudioFile << Wav_Headers.SubChunk2Size;
std::cout << "Started recording! Press escape when you're ready to stop!\n";
waveInStart(wi);
while (!(GetAsyncKeyState(VK_ESCAPE) & 0x8000)) {
for (auto& h : headers) {
if (h.dwFlags & WHDR_DONE) {
AudioFile.write(h.lpData, h.dwBufferLength); //dump audio binary to wav file
h.dwFlags = 0;
h.dwBytesRecorded = 0;
waveInPrepareHeader(wi, &h, sizeof(h));
waveInAddBuffer(wi, &h, sizeof(h));
}
}
}
waveInStop(wi);
for (auto& h : headers){
waveInUnprepareHeader(wi, &h, sizeof(h));
}
waveInClose(wi);
}```
So the issue was that I had to keep in mind formatting and Endianess. Instead of using << or .write, you have to have a precise format for it. A way to write to the file in the correct format is to use the following function I used below, and enter the same WAV headers.
template <typename T>
std::ostream& LittleEndianToFile(std::ostream& file, T value, unsigned size = sizeof(T)) {
for (; size; --size, value >>= 8)
file.put(static_cast <char> (value & 0xFF));
return file;
}
usage: LittleEndianToFile(AudioFile,SampleRate, 4);
I'm doing practice of bit manipulation in arduino with a 74HC595 shift register.
I would like to create an algorithm that allows the binary digit to perform this way:
1 0 0 0 0 0 0 1
0 1 0 0 0 0 1 0
0 0 1 0 0 1 0 0
.
.
.
1 0 0 0 0 0 0 1
In this type of function the decimal values are: (129,66,36,24,24,36,66,129) and so on in a loop.
How can I perform this type of shifting? I don't have any fluency thinking this type of operation, I have only performed a circular shift with "an algorithm" like:
//my circular shift
myByte = myByte*128 + myByte/2
But I don't know how to perform the output that I showed.
How can I do this? Thanks
For example you can use the following approach
#include <iostream>
#include <iomanip>
#include <limits>
int main()
{
unsigned char b = 0b10000001;
int width = std::numeric_limits<unsigned char>::digits / 2;
for ( int i = 0; i < width; i++ )
{
std::cout << std::hex << static_cast<int>( b ) << " - "
<< std::dec << static_cast<int>( b ) << '\n';
b = ( b & ( 0b1111 << width ) ) >> 1 | ( b & 0b1111 ) << 1;
}
for ( int i = 0; i < width; i++ )
{
std::cout << std::hex << static_cast<int>( b ) << " - "
<< std::dec << static_cast<int>( b ) << '\n';
b = ( b & ( 0b1111 << width ) ) << 1 | ( b & 0b1111 ) >> 1;
}
return 0;
}
The program output is
81 - 129
42 - 66
24 - 36
18 - 24
18 - 24
24 - 36
42 - 66
81 - 129
You're looking for a single operation that can be applied to an 8 bit number and result in the given pattern.
You want
x_(n+1) = f(x_(n))
for all given inputs and outputs. The problem is that there are a few potential inputs that have one of two possible outputs. You want both
36 = f(66)
and
129 = f(66)
This can't be done using only one variable. You can either implement a lookup table for the sequence you want (which is what I suggest). Or you can take two variables, implement circular shifts (in opposite directions) on each, and take the bitwise OR of the results.
uint8_t n1 = 128, n2 = 1;
for(;;)
{
std::cout << n1 | n2 << "\n";
n1 = circular_right_shift(n1);
n2 = circular_left_shift(n2);
}
Noticing that:
129,66,36,24,24,36,66,129 = 128+1; 64+2 ; 32+4; 16+8; 16+8; 32+4; 64+2; 128+1;
I ended up with this code:
int latchPin = 11;
int clockPin = 9;
int dataPin = 12;
int dt = 2000;
uint8_t n1 = 128, n2 = 1;
byte myByte = 0b10000001; //in BIN
void setup() {
Serial.begin(9600);
pinMode(latchPin,OUTPUT);
pinMode(dataPin,OUTPUT);
pinMode(clockPin,OUTPUT);
}
//circular shift to the left
void loop() {
digitalWrite(latchPin,LOW);
shiftOut(dataPin,clockPin,LSBFIRST,myByte);
digitalWrite(latchPin,HIGH);
int i;
myByte = 0b10000001; //restarting the value of 129
Serial.print("BIN: ");
Serial.print(myByte,BIN);
Serial.print(" --> ");
Serial.print("HEX: ");
Serial.print(myByte,HEX);
Serial.print(" --> ");
Serial.print("DEC: ");
Serial.println(myByte,DEC);
delay(200);
for (int i = 0; i < 7; i++) {
Serial.print("i: ");
Serial.println(i);
//int i1 = i+1;
//int myGap = myByte - (pow(2,i)); //no need to round when it's raised to 0;
//int firstpart = (myGap/2);
//int secondpart = 0.5 + pow(2,i1); //because it rounds the number. (i.e --> 1.9999 = 1)
//myByte = firstpart+ secondpart;
myByte = (myByte - (pow(2,i)))/2 + (0.5 + pow(2,i+1));
//Serial.print("firstpart: ");
//Serial.println(firstpart);
//Serial.print("secondpart: ");
//Serial.println(secondpart);
//delay(3000);
Serial.print("BIN: ");
Serial.print(myByte,BIN);
Serial.print(" --> ");
Serial.print("HEX: ");
Serial.print(myByte,HEX);
Serial.print(" --> ");
Serial.print("DEC: ");
Serial.println(myByte,DEC);
digitalWrite(latchPin,LOW);
shiftOut(dataPin,clockPin,LSBFIRST,myByte);
digitalWrite(latchPin,HIGH);
delay(100);
}
//myByte = myByte*2; //shift by right //using MSBFIRTS
//delay(dt);
}
And it works.
I have BYTE bMins = 36; and I want bMin1 = 3; and bMin2 = 6;
Is it possible without long switches, etc.?
I've already tried it with case, but that's very slow.
Integer division and modulo help:
BYTE bMins = 36;
BYTE bMin1 = bMins / 10;
BYTE bMin2 = bMins % 10;
Here is a demonstrative program
#include <iostream>
#include <cstdlib>
int main()
{
typedef unsigned char BYTE;
BYTE bMins = 36;
BYTE bMin1, bMin2;
auto d = std::div( bMins, 10 );
bMin1 = d.quot;
bMin2 = d.rem;
std::cout << "bMin1 = " << ( int )bMin1 << ", bMin2 = " << ( int )bMin2 << std::endl;
}
The program output is
bMin1 = 3, bMin2 = 6
An alternative way is to convert to a string and use the digit characters:
BYTE bMins = 36;
std::string s = std::to_string(bMins);
BYTE bMin1 = s[0] - '0';
BYTE bMin2 = s[1] - '0';
How would it be possible to feed the TEA cipher without exceeding a systems ram with large files?
I have tried doing this however it has all ended with massive failure and hours of tinkering that leads to nothing. So could someone give me an example of how this can be done or any meaningful information on how to do it?
void decodeXtea(unsigned int* v, unsigned int* w, unsigned int* k) {
register unsigned int v0=v[0], v1=v[1], i, sum=0xC6EF3720;
register unsigned int delta=0x9E3779B9;
for(i=0; i<32; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
}
w[0]=v0; w[1]=v1;
}
void TeaDecode ( const std::string& str, const std::string& key, std::string* out )
{
unsigned int v[2];
unsigned int w[2];
unsigned int k[4];
unsigned int keybuffer [ 4 ];
// Clear buffers
memset ( v, 0, sizeof(v) );
memset ( w, 0, sizeof(w) );
memset ( k, 0, sizeof(k) );
memset ( keybuffer, 0, sizeof(keybuffer) );
out->clear ();
// Count the number of passes that we need
int numBlocks = str.length() / 4;
int numPasses = numBlocks - 1;
if ( numPasses <= 0 )
return;
// Process the key
int len = key.length ();
if ( len > 16 )
len = 16;
memcpy ( keybuffer, key.c_str(), len );
for ( int i = 0; i < 4; ++i )
k[i] = keybuffer[i];
// Create a temporary buffer to store the result
unsigned char* buffer = new unsigned char [ numPasses * 4 + 4 ];
memset ( buffer, 0, numPasses * 4 + 4 );
// Decode it!
const char* p = str.c_str();
v[1] = *(unsigned int*)&p[numPasses * 4];
for ( int i = 0; i < numPasses; ++i )
{
v[0] = *(unsigned int*)&p[(numPasses-i-1)*4];
decodeXtea ( &v[0], &w[0], &k[0] );
*(unsigned int*)&buffer[(numPasses-i-1)*4] = w[0];
v[1] = w[1];
}
out->assign ( (char *)buffer, numPasses*4 );
delete [] buffer;
}
void encodeXtea(unsigned int* v, unsigned int* w, unsigned int* k) {
register unsigned int v0=v[0], v1=v[1], i, sum=0;
register unsigned int delta=0x9E3779B9;
for(i=0; i<32; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
}
w[0]=v0; w[1]=v1;
}
void TeaEncode ( const std::string& str, const std::string& key, std::string* out )
{
unsigned int v[2];
unsigned int w[2];
unsigned int k[4];
unsigned int keybuffer [ 4 ];
// Clear buffers
memset ( v, 0, sizeof(v) );
memset ( w, 0, sizeof(w) );
memset ( k, 0, sizeof(k) );
memset ( keybuffer, 0, sizeof(keybuffer) );
out->clear ();
// Process the key
int len = key.length ();
if ( len > 16 )
len = 16;
memcpy ( keybuffer, key.c_str(), len );
for ( int i = 0; i < 4; ++i )
k[i] = keybuffer[i];
// Copy the input string to a buffer of size multiple of 4
int strbuflen = str.length ();
if ( strbuflen == 0 )
return;
if ( (strbuflen % 4) > 0 )
strbuflen += 4 - (strbuflen % 4);
unsigned char* strbuf = new unsigned char [ strbuflen ];
memset ( strbuf, 0, strbuflen );
memcpy ( strbuf, str.c_str(), str.length() );
// Encode it!
v[1] = 0;
for ( int i = 0; i < strbuflen; i += 4 )
{
v[0] = *(unsigned int*)&strbuf[i];
encodeXtea ( &v[0], &w[0], &k[0] );
out->append ( (char*)&w[0], 4 );
v[1] = w[1];
}
out->append ( (char*)&v[1], 4 );
delete [] strbuf;
}
This fixed it.
void readSystem(string fname,string outFileName,string key,string mode)
{
//size_t buffer_size = 1<<20;
size_t buffer_size;
if(mode == "E")
{
buffer_size = 32;
}
else
{
buffer_size = 36;
}
//char *buffer = new char[buffer_size];
string buffer(buffer_size,'\0');
string data,output;
//data.resize(buffer_size);
// The input
std::ifstream fin(fname,ios::binary);
// The output
ofstream outFile(outFileName,ios::binary);// | ios::app);
// Anti overwrite
if(getSize(outFileName) > 0)
{
cout << "Overwrite error" << endl;
exit(0);
}
while (fin)
{
// Try to read next chunk of data
// fin.read(buffer, buffer_size);
fin.read(&buffer.front(), buffer_size);
// Get the number of bytes actually read
size_t count = fin.gcount();
data = buffer;
//data = encode(data,key);
if(mode == "E")
{
data = encode(data,key);
}
if(mode == "D")
{
data = decode(data,key);
}
//blockXor(data,key);
//outFile.write(data.c_str(),count);
outFile.write(data.c_str(),data.length());
// If nothing has been read, break
if (!count)
break;
// Do whatever you need with first count bytes in the buffer
}
outFile.close();
fin.close();
// delete[] buffer;
}
I am looking to convert existing code in C to perform the following: I am attempting to write a hex dump program that prints out address: values printable characters.
Currently, the code for values is printing in the following format:
0003540: 05 04 06 75 6e 73 69 67 6e 65 64 20 63 68 61 72 ...unsigned char
Desired hex output:
0003540: 0504 0675 6e73 6967 6e65 6420 6368 6172 ...unsigned char
Current code printing in pairs:
addr = 0;
while ( ( cnt = ( long )
fread ( buf, sizeof ( unsigned char ), 16, filein ) ) > 0 ) {
b = buf;
/* Print the address in hexadecimal. */
fprintf ( fileout, "%07lx ", addr );
addr = addr + 16;
/* Print 16 data items, in pairs, in hexadecimal. */
cnt2 = 0;
for ( m = 0; m < 16; m++ ) {
cnt2 = cnt2 + 1;
if ( cnt2 <= cnt ) {
fprintf ( fileout, "%02x", *b++ );
}
else {
fprintf ( fileout, " " );
}
fprintf ( fileout, " " );
}
/* Print the printable characters, or a period if unprintable. */
fprintf ( fileout, " " );
cnt2 = 0;
for ( n = 0; n < 16; n++ ) {
cnt2 = cnt2 + 1;
if ( cnt2 <= cnt ) {
if ( ( buf[n] < 32 ) || ( buf[n] > 126 ) ) {
fprintf ( fileout, "%c", '.' );
}
else {
fprintf ( fileout, "%c", buf[n] );
}
}
}
fprintf( fileout, "\n" );
}
How can I alter this code to achieve the AB12 CD34 format?
Thanks!
Use the modulo (remainder) operator % to test if m is divisible by 2. Only write the space when it is:
for ( m = 0; m < 16; m++ ) {
if ( m > 0 && m % 2 == 0 ) {
fprintf ( fileout, " " );
}
fprintf ( fileout, "%02x", *b++ );
}
Edit 3:
for ( m = 0; m < 16; m++ ) {
if ( m > 0 && m % 2 == 0 ) {
fprintf ( fileout, " " ); // space between every second byte
}
if ( m < cnt ) {
fprintf ( fileout, "%02x", *b++ );
} else {
fprintf ( fileout, " " ); // blank if run out of bytes on this line
}
}
I think this can be simplified quite a bit. For example, I'd consider starting with something like this:
#include <stdio.h>
#include <ctype.h>
int main(){
char buffer[17];
size_t bytes;
int i;
while (0 < (bytes = fread(buffer, 1, 16, stdin))) {
for (i = 0; i < bytes / 2; i++) // print out bytes, 2 at a time
printf("%02x%02x ", buffer[i * 2], buffer[i * 2 + 1]);
if (i * 2 < bytes) // take care of (possible) odd byte
printf("%02x ", buffer[i * 2]);
for (; i < 8; i++) // right pad hex bytes
printf(" ");
for (i = 0; i < bytes; i++) // change unprintable to '.'
if (!isprint(buffer[i]))
buffer[i] = '.';
buffer[i] = '\0'; // terminate string
printf("\t%s\n", buffer); // print out characters
}
return 0;
}