Encoding WAV file cuts off early - c++
In my previous question here, I managed to get a working .wav file as the output. However, when I throw this .wav file into my encoder (tested with other .wav files and works perfectly), my encoder throws back an error back at me right before it finishes.
Here is my output:
$ ./capture 2
Capture device is plughw:1,0
Finished writing to /tmp/filevXDDX6.wav
Starting encode to /tmp/filevXDDX6.flac
Wrote 3641 bytes, 4096/88200 samples, 2/22 frames
Wrote 6132 bytes, 8192/88200 samples, 2/22 frames
Wrote 8748 bytes, 12288/88200 samples, 3/22 frames
Wrote 11253 bytes, 16384/88200 samples, 4/22 frames
Wrote 13697 bytes, 20480/88200 samples, 5/22 frames
Wrote 16222 bytes, 24576/88200 samples, 6/22 frames
Wrote 18811 bytes, 28672/88200 samples, 7/22 frames
Wrote 21900 bytes, 32768/88200 samples, 8/22 frames
Wrote 24681 bytes, 36864/88200 samples, 9/22 frames
Wrote 27408 bytes, 40960/88200 samples, 10/22 frames
Wrote 30494 bytes, 45056/88200 samples, 11/22 frames
Wrote 34107 bytes, 49152/88200 samples, 12/22 frames
Wrote 37447 bytes, 53248/88200 samples, 13/22 frames
Wrote 40719 bytes, 57344/88200 samples, 14/22 frames
Wrote 45257 bytes, 61440/88200 samples, 15/22 frames
Wrote 48735 bytes, 65536/88200 samples, 16/22 frames
Wrote 52842 bytes, 69632/88200 samples, 17/22 frames
Wrote 56529 bytes, 73728/88200 samples, 18/22 frames
Wrote 60185 bytes, 77824/88200 samples, 19/22 frames
Wrote 63906 bytes, 81920/88200 samples, 20/22 frames
ERROR: reading from WAVE file
Wrote 67687 bytes, 86016/88200 samples, 21/22 frames
Encoding: FAILED
State: FLAC__STREAM_ENCODER_UNINITIALIZED
I'm not sure why it's cutting off early, though I'm pretty sure it has to do with how I'm trying to record my own .wav file (since my encoder worked fine with other files).
Here is my code (sorry it's a bit long, I cut down as much as possible):
// Compile with "g++ test.ccp -o test -lasound"
// Use the newer ALSA API
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
struct WaveHeader
{
char RIFF_marker[4];
uint32_t file_size;
char filetype_header[4];
char format_marker[4];
uint32_t data_header_length;
uint16_t format_type;
uint16_t number_of_channels;
uint32_t sample_rate;
uint32_t bytes_per_second;
uint16_t bytes_per_frame;
uint16_t bits_per_sample;
};
struct WaveHeader *genericWAVHeader(uint32_t sample_rate, uint16_t bit_depth, uint16_t channels)
{
struct WaveHeader *hdr;
hdr = (WaveHeader*) malloc(sizeof(*hdr));
if (!hdr)
return NULL;
memcpy(&hdr->RIFF_marker, "RIFF", 4);
memcpy(&hdr->filetype_header, "WAVE", 4);
memcpy(&hdr->format_marker, "fmt ", 4);
hdr->data_header_length = 16;
hdr->format_type = 1;
hdr->number_of_channels = channels;
hdr->sample_rate = sample_rate;
hdr->bytes_per_second = sample_rate * channels * bit_depth / 8;
hdr->bytes_per_frame = channels * bit_depth / 8;
hdr->bits_per_sample = bit_depth;
return hdr;
}
int writeWAVHeader(int fd, struct WaveHeader *hdr)
{
if (!hdr)
return -1;
write(fd, &hdr->RIFF_marker, 4);
write(fd, &hdr->file_size, 4);
write(fd, &hdr->filetype_header, 4);
write(fd, &hdr->format_marker, 4);
write(fd, &hdr->data_header_length, 4);
write(fd, &hdr->format_type, 2);
write(fd, &hdr->number_of_channels, 2);
write(fd, &hdr->sample_rate, 4);
write(fd, &hdr->bytes_per_second, 4);
write(fd, &hdr->bytes_per_frame, 2);
write(fd, &hdr->bits_per_sample, 2);
write(fd, "data", 4);
uint32_t data_size = hdr->file_size + 8 - 44;
write(fd, &data_size, 4);
return 0;
}
int recordWAV(const char *fileName, struct WaveHeader *hdr, uint32_t duration)
{
int err;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int sampleRate = hdr->sample_rate;
int dir;
snd_pcm_uframes_t frames = 32;
char *device = (char*) "plughw:1,0";
char *buffer;
int filedesc;
printf("Capture device is %s\n", device);
/* Open PCM device for recording (capture). */
err = snd_pcm_open(&handle, device, SND_PCM_STREAM_CAPTURE, 0);
if (err)
{
fprintf(stderr, "Unable to open PCM device: %s\n", snd_strerror(err));
return err;
}
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(¶ms);
/* Fill it in with default values. */
snd_pcm_hw_params_any(handle, params);
/* ### Set the desired hardware parameters. ### */
/* Interleaved mode */
err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
if (err)
{
fprintf(stderr, "Error setting interleaved mode: %s\n", snd_strerror(err));
snd_pcm_close(handle);
return err;
}
/* Signed 16-bit little-endian format */
if (hdr->bits_per_sample == 16) err = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
else err = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_U8);
if (err)
{
fprintf(stderr, "Error setting format: %s\n", snd_strerror(err));
snd_pcm_close(handle);
return err;
}
/* Two channels (stereo) */
err = snd_pcm_hw_params_set_channels(handle, params, hdr->number_of_channels);
if (err)
{
fprintf(stderr, "Error setting channels: %s\n", snd_strerror(err));
snd_pcm_close(handle);
return err;
}
/* 44100 bits/second sampling rate (CD quality) */
sampleRate = hdr->sample_rate;
err = snd_pcm_hw_params_set_rate_near(handle, params, &sampleRate, &dir);
if (err)
{
fprintf(stderr, "Error setting sampling rate (%d): %s\n", sampleRate, snd_strerror(err));
snd_pcm_close(handle);
return err;
}
hdr->sample_rate = sampleRate;
/* Set period size*/
err = snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
if (err)
{
fprintf(stderr, "Error setting period size: %s\n", snd_strerror(err));
snd_pcm_close(handle);
return err;
}
/* Write the parameters to the driver */
err = snd_pcm_hw_params(handle, params);
if (err < 0)
{
fprintf(stderr, "Unable to set HW parameters: %s\n", snd_strerror(err));
snd_pcm_close(handle);
return err;
}
/* Use a buffer large enough to hold one period */
err = snd_pcm_hw_params_get_period_size(params, &frames, &dir);
if (err)
{
fprintf(stderr, "Error retrieving period size: %s\n", snd_strerror(err));
snd_pcm_close(handle);
return err;
}
size = frames * hdr->bits_per_sample / 8 * hdr->number_of_channels; /* 2 bytes/sample, 2 channels */
buffer = (char *) malloc(size);
if (!buffer)
{
fprintf(stdout, "Buffer error.\n");
snd_pcm_close(handle);
return -1;
}
err = snd_pcm_hw_params_get_period_time(params, &sampleRate, &dir);
if (err)
{
fprintf(stderr, "Error retrieving period time: %s\n", snd_strerror(err));
snd_pcm_close(handle);
free(buffer);
return err;
}
uint32_t pcm_data_size = hdr->sample_rate * hdr->bytes_per_frame * duration / 1000;
hdr->file_size = pcm_data_size + 44 - 8;
filedesc = open(fileName, O_WRONLY | O_CREAT, 0644);
err = writeWAVHeader(filedesc, hdr);
if (err)
{
fprintf(stderr, "Error writing .wav header.");
snd_pcm_close(handle);
free(buffer);
close(filedesc);
return err;
}
fprintf(stdout, "Channels: %d\n", hdr->number_of_channels);
for(int i = duration * 1000 / sampleRate; i > 0; i--)
{
err = snd_pcm_readi(handle, buffer, frames);
if (err == -EPIPE) fprintf(stderr, "Overrun occurred: %d\n", err);
if (err < 0) err = snd_pcm_recover(handle, err, 0);
// Still an error, need to exit.
if (err < 0)
{
fprintf(stderr, "Error occured while recording: %s\n", snd_strerror(err));
snd_pcm_close(handle);
free(buffer);
close(filedesc);
return err;
}
write(filedesc, buffer, size);
}
close(filedesc);
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
printf("Finished writing to %s\n", fileName);
return 0;
}
int main(int argc, char *argv[])
{
if(argc != 2)
{
fprintf(stderr, "Usage: %s (record duration)\n", argv[0]);
return -1;
}
int err;
struct WaveHeader *hdr;
// Creates a temporary file in /tmp
char wavFile[L_tmpnam + 5];
char *tempFilenameStub = tmpnam(NULL);
sprintf(wavFile, "%s.wav", tempFilenameStub);
hdr = genericWAVHeader(44000, 16, 2);
if (!hdr)
{
fprintf(stderr, "Error allocating WAV header.\n");
return -1;
}
err = recordWAV(wavFile, hdr, 1000 * strtod(argv[1], NULL));
if (err)
{
fprintf(stderr, "Error recording WAV file: %d\n", err);
return err;
}
free(hdr);
return 0;
}
Any suggestions?
Edit - I was told to compare the headers of my .wav file to that of one generated by arecord. Here are the results:
$ stat -c %s arecord.wav
352844
$ stat -c %s /tmp/filevXDDX6.wav
345004
$ xxd -g1 arecord.wav | head
0000000: 52 49 46 46 44 62 05 00 57 41 56 45 66 6d 74 20 RIFFDb..WAVEfmt
0000010: 10 00 00 00 01 00 02 00 44 ac 00 00 10 b1 02 00 ........D.......
0000020: 04 00 10 00 64 61 74 61 20 62 05 00 08 00 08 00 ....data b......
0000030: 08 00 08 00 07 00 07 00 fe ff fe ff f7 ff f7 ff ................
0000040: f6 ff f6 ff ee ff ee ff ee ff ee ff f6 ff f6 ff ................
0000050: f0 ff f0 ff e7 ff e7 ff ee ff ee ff f4 ff f4 ff ................
0000060: f4 ff f4 ff f7 ff f7 ff fe ff fe ff fc ff fc ff ................
0000070: fa ff fa ff f5 ff f5 ff ed ff ed ff ee ff ee ff ................
0000080: f8 ff f8 ff f4 ff f4 ff ed ff ed ff ee ff ee ff ................
0000090: f8 ff f8 ff f6 ff f6 ff f0 ff f0 ff ee ff ee ff ................
$ xxd -g1 /tmp/filevXDDX6.wav | head
0000000: 52 49 46 46 44 62 05 00 57 41 56 45 66 6d 74 20 RIFFDb..WAVEfmt
0000010: 10 00 00 00 01 00 02 00 44 ac 00 00 10 b1 02 00 ........D.......
0000020: 04 00 10 00 64 61 74 61 20 62 05 00 71 00 71 00 ....data b..q.q.
0000030: 6f 00 6f 00 79 00 79 00 75 00 75 00 63 00 63 00 o.o.y.y.u.u.c.c.
0000040: 3e 00 3e 00 1b 00 1b 00 07 00 07 00 fb ff fb ff >.>.............
0000050: 00 00 00 00 0c 00 0c 00 0f 00 0f 00 1c 00 1c 00 ................
0000060: 30 00 30 00 31 00 31 00 24 00 24 00 1e 00 1e 00 0.0.1.1.$.$.....
0000070: 24 00 24 00 31 00 31 00 2c 00 2c 00 28 00 28 00 $.$.1.1.,.,.(.(.
0000080: 31 00 31 00 3c 00 3c 00 36 00 36 00 31 00 31 00 1.1.<.<.6.6.1.1.
0000090: 39 00 39 00 40 00 40 00 3d 00 3d 00 30 00 30 00 9.9.#.#.=.=.0.0.
$ file arecord.wav
test.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz
$ file /tmp/filevXDDX6.wav
/tmp/filevXDDX6.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz
Your program does not write the correct number of samples to the .wav file.
snd_pcm_readi returns the number of frames that was actually read.
You can only write that many frames to the output.
The integer division in duration * 1000 / sampleRate might be rounded.
It is likely that duration * 1000 / sampleRate * frames is not exactly the same as the number of frames you actually want to read.
You should restructure your loop to count the total number of frames.
Related
C++ structure/array initialization
I have a C++ array or structure initialization issue that I have not been able to resolve. I have a 4-level nested structure. Each level is actually the same 48 bytes wrapped in the structure next level up. The issue is when the structure is initialized and declared as a scalar value, it is correctly initialized with the provided values. However, when it is declared as a single element array, all 48 bytes become zeros, as shown below. Unfortunately the structures are too complicated to be pasted here. If I define 4 simple structures, one containing another, with the innermost one containing the same 12 unsigned integers, then it is initialized correctly, even if it is declared in an array. Has anyone experienced similar issues? What am I missing? What compiler flags, options, etc could lead to such a problem? Appreciate any comments and help. #include <stdint.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include "bls12_381/fq.hpp" static constexpr embedded_pairing::bls12_381::Fq scalar = { {{{.std_words = {0x1c7238e5, 0xcf1c38e3, 0x786f0c70, 0x1616ec6e, 0x3a6691ae, 0x21537e29, 0x4d9e82ef, 0xa628f1cb, 0x2e5a7ddf, 0xa68a205b, 0x47085aba, 0xcd91de45}}}} }; static constexpr embedded_pairing::bls12_381::Fq array[1] = { {{{{.std_words = {0x1c7238e5, 0xcf1c38e3, 0x786f0c70, 0x1616ec6e, 0x3a6691ae, 0x21537e29, 0x4d9e82ef, 0xa628f1cb, 0x2e5a7ddf, 0xa68a205b, 0x47085aba, 0xcd91de45}}}}} }; void print_struct(const char *title, const uint8_t *cbuf, int len) { printf("\n"); printf("[%s] %d\n", title, len); for (int i = 0; i < len; i++) { if (i % 30 == 0 && i != 0) printf("\n"); else if ((i % 10 == 0 || i % 20 == 0) && i != 0) printf(" "); printf("%02X ", cbuf[i]); } printf("\n"); } void run_tests() { print_struct("scalar", (const uint8_t *) &scalar, sizeof(scalar)); print_struct("array", (const uint8_t *) &array[0], sizeof(array[0])); } [scalar] 48 E5 38 72 1C E3 38 1C CF 70 0C 6F 78 6E EC 16 16 AE 91 66 3A 29 7E 53 21 EF 82 9E 4D CB F1 28 A6 DF 7D 5A 2E 5B 20 8A A6 BA 5A 08 47 45 DE 91 CD [array] 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 I've just narrowed down the example. The following is a complete and standalone example. I also forgot to mention that the initialization on Linux using g++ 9.3.0, -std=c++17, gets the expected results of all FF's. However, on an embedded device, the inherited structure gets all 0's. #include <stdint.h> #include <stdio.h> #include <string.h> #include <stdlib.h> struct Data { uint32_t words; }; struct Overlay { Data val; }; struct Inherit : Data { }; static Overlay overlay[1] = { {{.words = 0xffffffff}} }; static Inherit inherit[1] = { {{.words = 0xffffffff}} }; void print_struct(const char *title, const uint8_t *cbuf, int len) { printf("[%s] %d\n", title, len); for (int i = 0; i < len; i++) { printf("%02X ", cbuf[i]); } printf("\n"); } int main() { print_struct("overlay", (const uint8_t *) &overlay[0], sizeof(overlay[0])); // FF FF FF FF print_struct("inherit", (const uint8_t *) &inherit[0], sizeof(inherit[0])); // 00 00 00 00 <-- incorrect? return 0; }
c++ openssl 1.1.1 running RSA algorithm in thread causing memory leaks
This is very strange! I look around and find nothing. My test code is below: #include "pch.h" #include "Windows.h" #include "openssl/ssl.h" #pragma comment(lib,"../Include/lib/libssl.lib") #pragma comment(lib,"../Include/lib/libcrypto.lib") #pragma comment(lib,"Crypt32.lib") #pragma comment(lib,"ws2_32.lib") #include <stdlib.h> #include <crtdbg.h> #define _CRTDBG_MAP_ALLOC const char* priKey = "607BC8BA457EC0A1B5ABAD88061502BEA5844E17C7DD247345CD57E501B3300B4B8889D3DFCF5017847606508DF8B283C701F35007D5F4DBA96023DD3B0CCE062D8F63BCC16021B944A1E88861B70D456BAA1E0E69C90DFCA13B4D4EA5403DA25FEBF94B0515644A7D2DF88299189688DA5D8951512ADC3B1A35BAEEC147F69AB101048B9029E65A77A438A05AE30337E82B0571B80A955C72EA0DB3B457ECC8B81F346624E3D22755FEB3D84F810431974803E13E26BF95AF7AB590E17C0113BFE9B36BE12BE16D89273348E0CC094526CAF54ABF8044565EC9500EBF657265474BC362EBDFD78F513282AAF0EEF9BA0BB00F7FF9C7E61F00465BBD379D6201"; const char* pubKey = "AE7DF3EB95DF1F864F86DA9952BB44E760152986731253C96C135E5391AEFF68F5C1640552F1CCC2BA2C12C0C68C051E343B786F13215CEFC8221D9FA97D50E895EAF50D1AF32DC5EB40C9F1F8CA5145B43CEF83F2A89C9661AFA73A70D32951271C6BEFE1B5F24B512520DA7FD4EEC982F2D8057FE1938FA2FB54D8D282A25D8397298B75E154739EF16B8E2F18368F5BEEAD3D18528B9B1A63C731A71735CDB6102E187EF3377B72B58A124FA280891A79A2BD789D5DBA3618BBD74367F5C50A220204D90A59828C3C81FDBD9D2A91CBF6C8563C6FE987BE21B19BBC340DE4D42290D63909AD5D856D13B8CDC91D5701570045CE3609D4F8884F69120AD9A3"; void rsa_test(const char* n,const char* d) { RSA* rsa = RSA_new(); BIGNUM* bn = BN_new(); BIGNUM* bd = BN_new(); BIGNUM* be = BN_new(); BN_set_word(be, 0x10001); if (n) BN_hex2bn(&bn, n); if (d) BN_hex2bn(&bd, d); RSA_set0_key(rsa, bn, be, bd); //calc hash const char* msg = "hello,rsa!!"; BYTE shaResult[SHA256_DIGEST_LENGTH] = { 0 }; SHA256((unsigned char*)msg, strlen(msg), shaResult); //sign unsigned int olen; unsigned char sign[256] = { 0 }; RSA_sign(NID_sha256, shaResult, SHA256_DIGEST_LENGTH, sign, &olen,rsa); RSA_free(rsa); } DWORD thread_test(LPVOID lpParam) { rsa_test(pubKey, priKey); return 0; } int main() { //_CrtSetBreakAlloc(159); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); //CreateThread(nullptr, 0, thread_test, nullptr, 0, nullptr); //rsa_test(pubKey,priKey); system("pause"); } Calling rsa_test(pubKey,priKey) directly in the main thread DO NOT cause memory leaks! Calling CreateThread(nullptr, 0, thread_test, nullptr, 0, nullptr) comes out memory leaks!!! Console output as follows: Detected memory leaks! Dumping objects -> {173} normal block at 0x000002BDE6D44000, 264 bytes long. Data: < _W- :_ s ! 6> D8 89 FD 5F 57 2D C5 3A 5F 82 73 F1 00 21 FA 36 {162} normal block at 0x000002BDE6D43AC0, 264 bytes long. Data: < > 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F {161} normal block at 0x000002BDE6D2E2A0, 160 bytes long. Data: <` > 60 F1 0F 91 F6 7F 00 00 00 00 00 00 00 00 00 00 {160} normal block at 0x000002BDE6D2DBA0, 160 bytes long. Data: <` > 60 F1 0F 91 F6 7F 00 00 00 00 00 00 00 00 00 00 {159} normal block at 0x000002BDE6D48230, 352 bytes long. Data: < P > 00 00 00 00 00 00 00 00 50 AB D3 E6 BD 02 00 00 {158} normal block at 0x000002BDE6D286B0, 12 bytes long. Data: < > 00 00 00 00 00 00 00 00 01 00 00 00 Object dump complete. Then I use _CrtSetBreakAlloc(159) (or other memory id) to location,and here is my call stack screenshot: my vs2017 showing the break point at CRYPTO_zalloc(crypto/mem.c) So my question is how to free those leak memory in thread! Thanks a lot!! Download my test code(build with visual studio 2017 x64)
https://www.openssl.org/docs/man1.1.0/man3/OPENSSL_thread_stop.html OPENSSL_thread_stop(); will do it for you. You can call it like below DWORD thread_test(LPVOID lpParam) { rsa_test(pubKey, priKey); OPENSSL_thread_stop(); return 0; }
How to send an array of bytes between nucleo f446re with mbed through USB with UARTSerial class?
I have to send an array of data between a nucleo f446re and a pc with ubuntu using the UARTSerial class. The code that I'm using on the mbed is the following: int main() { UARTSerial pc(USBTX, USBRX, 921600); uint8_t buff[256] = { 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4 }; pc.sync(); while(true) { pc.write(buff, 23); pc.sync(); wait(1); } return 0; } The code that I'm running on the pc is: int main() { struct termios tattr{0}; // open the device in read/write sync int com = open("/dev/ttyACM0", O_RDWR | O_NOCTTY | O_SYNC ); if (com == -1) throw std::runtime_error("ERROR: can't open the serial"); tcgetattr(com, &tattr); tattr.c_iflag &= ~(INLCR|IGNCR|ICRNL|IXON); tattr.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET); tattr.c_cflag = CS8 | CREAD | CLOCAL; tattr.c_lflag &= ~(ICANON|ECHO); tattr.c_cc[VMIN] = 1; tattr.c_cc[VTIME] = 0; tattr.c_ispeed = 921600; tattr.c_ospeed = 921600; tcsetattr (com, TCSAFLUSH, &tattr); while (true) { usleep(1000); tcflush(com, TCIOFLUSH); uint8_t buff[24]; ::read(com, buff, 23); printf("reading frame... "); for (auto b : buff) { printf("%02X ", b); } puts("\n"); } } The output that I receive on the pc is: [...] reading frame... 00 00 8D 9C 1E 7F 00 00 00 00 00 00 00 00 00 00 70 5B C7 01 AD 55 00 00 reading frame... 00 00 8D 9C 1E 7F 00 00 00 00 00 00 00 00 00 00 70 5B C7 01 AD 55 00 00 [...] As you can see the result is not the same that I'm expecting. I've already tried to send one byte at a time with a loop, but the result is the same. I cannot understand why I can't read the USB I've tried to flush the usb both on the pc and on the nucleo board.
you have to use a decoder to decode the bytes from the serial port see the link below: https://codereview.stackexchange.com/questions/200846/a-simple-and-efficient-packet-frame-encoder-decoder
I found the problem. It was the setting of the baudrate, I have to use this lines: // receive speed cfsetispeed (&tattr, B921600); // transmit speed cfsetospeed (&tattr, B921600); instead of this: // receive speed tattr.c_ispeed = 921600; tattr.c_ospeed = 921600;
Using minizip to decompress a char array
I have a vector (which is just a wrapper over a char array) that is the input. The pkzip was created using c# sharpZipLib. I stored the data into a file which I ran through a hex editor zip template that checked out. The input is good, it's not malformed. This all but the compressed data: 50 4B 03 04 14 00 00 00 08 00 51 B2 8B 4A B3 B6 6C B0 F6 18 00 00 40 07 01 00 07 00 00 00 2D 33 31 2F 31 32 38 <compressed data (6390 bytes)> 50 4B 01 02 14 00 14 00 00 00 08 00 51 B2 8B 4A B3 B6 6C B0 F6 18 00 00 40 07 01 00 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2D 33 31 2F 31 32 38 50 4B 05 06 00 00 00 00 01 00 01 00 35 00 00 00 1B 19 00 00 00 00 I have another vector which is to be the output. The inflated data will have about 67-68k, so I know it fits into the buffer. For the life of me, I cannot get the minizip to inflate the former and store it into latter. This is what I have so far: #include "minizip\zlib.h" #define ZLIB_WINAPI std::vector<unsigned char> data; /*...*/ std::vector<unsigned char> outBuffer(1024 * 1024); z_stream stream; stream.zalloc = Z_NULL; stream.zfree = Z_NULL; stream.opaque = Z_NULL; stream.data_type = Z_BINARY; stream.avail_in = data.size(); stream.avail_out = outBuffer.size(); stream.next_in = &data[0]; stream.next_out = &outBuffer[0]; int ret = inflateInit(&stream); ret = inflate(&stream, 1); ret = inflateEnd(&stream); I used the debugger to step through the method and monitor the ret. inflate returned value -3 with message "incorrect header check". This is a pkzip, which is a wrapper around zlib, but minizip should be a wrapper library around zlib that should support pkzip, shouldn't it be? How do I have to modify this to work?
Since it starts with 50 4B 03 04 it is a PKZIP file, according to https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html If these are zip files, then inflate is the wrong function. The zlib, gzip and zip formats are all different. You can read zip with zlib, if you use the right functions to do so. If you don't have the contrib, maybe download and rebuild zlib. Here's some old code I have which works for zip files, using the zlib library. I might have moved some headers around, because the official zlib has them under zlib/contrib/minizip. The arguments are filenames, so you'll have to modify it, or write your array to a file. // #include <zlib/unzip.h> #include <zlib/contrib/minizip/unzip.h> /// return list of filenames in zip archive std::list<std::string> GetZipFilenames(const char *szZipArchive){ std::list<std::string> results; unzFile zip = unzOpen(szZipArchive); if (zip){ unz_global_info info; int rv = unzGetGlobalInfo(zip, &info); if (UNZ_OK == unzGoToFirstFile(zip)){ do { char szFilename[BUFSIZ]; if (UNZ_OK == unzGetCurrentFileInfo(zip, NULL, szFilename, sizeof(szFilename), NULL, 0, NULL, 0)) results.push_back(std::string(szFilename)); } while (UNZ_OK == unzGoToNextFile(zip)); } } return results; } /// extract the contents of szFilename inside szZipArchive bool ExtractZipFileContents(const char *szZipArchive, const char *szFilename, std::string &contents){ bool result = false; unzFile zip = unzOpen(szZipArchive); if (zip){ if (UNZ_OK == unzLocateFile(zip, szFilename, 0)){ if (UNZ_OK == unzOpenCurrentFile(zip)){ char buffer[BUFSIZ]; size_t bytes; while (0 < (bytes = unzReadCurrentFile(zip, buffer, sizeof(buffer)))){ contents += std::string(buffer, bytes); } unzCloseCurrentFile(zip); result = (bytes == 0); } } unzClose(zip); } return result; }
If I understand the question correctly, you are trying to decompress the 6390 bytes of compressed data. That compressed data is a raw deflate stream, which has no zlib header or trailer. For that you would need to use inflateInit2(&stream, -MAX_WBITS) instead of inflateInit(&stream). The -MAX_WBITS requests decompression of raw deflate.
Zip-Utils std::vector<unsigned char> inputBuffer; std::vector<unsigned char> outBuffer(1024 * 1024); HZIP hz = OpenZip(&inputBuffer[0], inputBuffer.capacity(), 0); ZIPENTRY ze; GetZipItem(hz, 0, &ze); UnzipItem(hz, 0, &outBuffer[0], 1024 * 1024); outBuffer.resize(ze.unc_size); If inputBuffer contains a pkzip file, this snippet will unzip it and store contents in outBuffer. That is all.
C++ display array of bytes in hex
I've made a dll hook that will send address for Byte array that I need every time the event occurs on the main apps. Display code : void receivedPacket(char *packet){ short header = packet[2]; TCHAR str[255]; _stprintf(str, _T("Header : %lX\n"), header); // This works fine. It return 0x38 as it should. WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), str, strlen(str), 0, 0); WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), packet, 34, 0, 0); } this is the example of the byte array from that address, and this is how I want it to be displayed : 05 01 38 00 60 00 9D 01 00 00 00 00 00 70 C9 7D 0E 00 00 00 00 00 00 00 FF 20 79 40 00 00 00 00 But, with my current code, it will only display weird symbols. So how can we convert all those weird symbol to hex? I'm actually new to the C++.
Format each byte in the string: static TCHAR const alphabet[] = _T("0123456789ABCDEF"); for (TCHAR * p = str; *p; ++p) { TCHAR const s[2] = { alphabet[p / 16], alphabet[p % 16] }; WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), s, 2, 0, 0); }