I am Attempting to download a binary file(exe) from a php script. Been stuck for hours.
PHP Script:
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
header("Content-length: $fsize");
header("Cache-control: private"); //use this to open files directly
while(!feof($fd)) {
$buffer = fread($fd, 1048);
echo $buffer;
}
C:
char update[1024] = {0};
FILE *fileo;
fileo = fopen("test.exe", "wb");
instruction = recv(s, update, 1024, 0);
int result =returnBody();//Removes headers
fwrite(body, sizeof(body),1,fileo);
memset(update, 0, 1024);
while ((instruction = recv(s, update, 1024, 0)) > 0)
{
fwrite(update, sizeof(update),1,fileo);
memset(update, 0, 1024);
}
fclose(fileo);
returnbody function:
int returnBody(){
for(int x = 0; x < strlen(message); x++)
{
if(message[x] == '\r')
{
if(message[x + 1] == '\n')
{
if(message[x + 2] == '\r')
{
if(message[x + 3] == '\n')
{
int y = x + 4;
body = (char *)realloc(body, ((strlen(message) - y) * sizeof(char)));
memset(body, 0, sizeof(body));
for(int b = 0; y < strlen(message); y++, b++){
body[b] = message[y];
}
return 1;
}
}
}
}
}
return 0;
}
I succeed in writing the file but it doesn't run. Gets an error, unsupported
16 bit application.
My Question is do I need to parse it as binary before I write it to the file?
As pointed in comments:
you can't use strlen when using binary data
you can't use sizeof when using pointers on array.
Lets see:
/* you should have some static variables to store data */
static void * body = NULL;
size_t body_size = 0;
/* extract body from message */
int returnBody(void *message, size_t message_size){
if (! message || message_size < 5)
{
return 0;
}
/* if your system doesn't have memmem function, see https://stackoverflow.com/a/52989329/1212012 */
void *data = memmem(message, message_size, "\r\n\r\n", 4);
if (data) {
/* header found */
/* data are four bytes after the \r\n\r\n sequence */
data += 4;
size_t header_size = data - message;
body_size = message_size - header_size;
void *p = realloc(body, body_size);
if (!p) {
perror("realloc");
return 0;
}
body = p;
memcpy(body, data, body_size);
return 1;
}
return 0;
}
And your reading writting function should be like:
char update[1024] = {0};
FILE *fileo;
fileo = fopen("test.exe", "wb");
/* you should test `fileo` here */
/* first read */
instruction = recv(s, update, sizeof update, 0);
/* set message and its size for */
int result =returnBody(udpate, instruction);//Removes headers
/* you should test `result` here */
fwrite(body, body_size, 1, fileo);
/* clearing update is not necessary */
/*memset(update, 0, sizeof update); */
while ((instruction = recv(s, update, sizeof update, 0)) > 0)
{
fwrite(update, instruction, 1, fileo);
//memset(update, 0, sizeof update);
}
fclose(fileo);
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm a complete newbie in C and have an assignment that states I have to implement CRC-16 into a given UDP File Transfer solution. Given code is as follows:
#pragma comment(lib, "ws2_32.lib")
#include "stdafx.h"
#include <winsock2.h>
#include "ws2tcpip.h"
#include <stdio.h>
#define TARGET_IP "10.4.115.122"
//#define TARGET_IP "127.0.0.1"
#define BUFFERS_LEN 1024
#define SIZE_PACKET 10 // we can send up to 9 999 999 999 packets
#define HEADER_LEN (SIZE_PACKET + 5)
#define DATA_LEN (BUFFERS_LEN - HEADER_LEN)
//#define SENDER
#define END {getchar();return 0;}
#define RECEIVER
typedef struct Data
{
int size;
char *data;
}Data;
#ifdef SENDER
#define TARGET_PORT 5005
#define LOCAL_PORT 8888
#endif // SENDER
#ifdef RECEIVER
#define TARGET_PORT 8888
#define LOCAL_PORT 5005
#endif // RECEIVER
void InitWinsock()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
}
void print(char *data, int size)
{
for (int i = 0; i < size; i++)
{
if (data[i] == '\0')
{
printf("\\0");
}
else
{
printf("%c", data[i]);
}
}
printf("\n");
}
void clearBuffer(char *buffer, int size)
{
/* Put NULL character on the array */
for (int i = 0; i < size; i++)
{
buffer[i] = '\0';
}
}
void createHeaderBuffers(char *buffer, int info, int size)
{
// create the array containing the number of the packet and the data length
char temp[HEADER_LEN];
clearBuffer(temp, HEADER_LEN);
sprintf(temp, "%d", info);
int size_temp = strlen(temp);
int begin = size - size_temp;
for (int i = 0; i < size; i++)
{
if (i < begin) // fill the begining of the array with zero
{
buffer[i] = '0';
}
else // add the usefull info at the end e.g : 0000052
{
buffer[i] = temp[i - begin];
}
}
}
int createBuffer( char *buffer, char *data,int numPacket,int dataLength)
{
/* Create the buffer we will send*/
char numPacket_c[SIZE_PACKET+1];
char dataLength_c[5];
clearBuffer(buffer, BUFFERS_LEN);
clearBuffer(numPacket_c, 4);
clearBuffer(dataLength_c, 5);
createHeaderBuffers(numPacket_c, numPacket, SIZE_PACKET); // create the array containing the number of the packet
createHeaderBuffers(dataLength_c, dataLength, 4); // create the array containing the length of the data
for (int i = 0; i < BUFFERS_LEN; i++)
{
char ch;
if (i < SIZE_PACKET) // start by adding the number of the packet byte by byte
{
buffer[i] = numPacket_c[i];
}
else if (i < SIZE_PACKET+4) // then we add the length of the data
{
buffer[i] = dataLength_c[i- SIZE_PACKET];
}
else if (i < HEADER_LEN) // the the flag to say if it(s the end of the file
{
if(dataLength < DATA_LEN -1)
buffer[i] = '1';
else
buffer[i] = '0';
}
else if (i < HEADER_LEN + dataLength) // the the data
{
buffer[i] = data[i - HEADER_LEN];
}
else // fill the rest of the buffer with NULL character
{
buffer[i] = '\0';
}
}
return 0;
}
void copy(char *dest, char *source, int size)
{
/* Copy a buffer in another one byte by byte */
//printf("%s\n", source);
for (int i = 0; i < size; i++)
{
dest[i] = source[i];
//printf("%c\n", source[i]);
}
}
void readFile(char *buffer, int size, char *data, int *numPacket, int *dataLength, int *isEnd)
{
//print(buffer, size);
char isEnd_c[2];
char numPacket_c[SIZE_PACKET + 1];
char dataLength_c[5];
clearBuffer(isEnd_c, 2);
clearBuffer(numPacket_c, SIZE_PACKET + 1);
clearBuffer(dataLength_c, 5);
clearBuffer(data, DATA_LEN + 1);
for (int i = 0; i < size; i++)
{
if (i < SIZE_PACKET) // read the number of the packet
{
numPacket_c[i] = buffer[i];
printf("%c", buffer[i]);
}
else if (i < SIZE_PACKET + 4) // read the length of the data
{
dataLength_c[i - SIZE_PACKET] = buffer[i];
}
else if (i < HEADER_LEN) // read the isEnd FLAG
{
printf("\n%c\n", buffer[i]);
isEnd_c[0] = buffer[i];
}
else // read the data
{
data[i - HEADER_LEN] = buffer[i];
}
}
*numPacket = atoi(numPacket_c);
*isEnd = atoi(isEnd_c);
*dataLength = atoi(dataLength_c);
printf("%d ; %d ; %d\n", *numPacket, *dataLength, *isEnd);
}
unsigned short crc16(const unsigned char* numPacket, unsigned char length) {
unsigned char x;
unsigned short crc = 0xFFFF;
while (length--) {
x = crc >> 8 ^ *numPacket++;
x ^= x >> 4;
crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x << 5)) ^ ((unsigned short)x);
}
return crc;
}
//**********************************************************************
int main()
{
SOCKET socketS;
InitWinsock();
struct sockaddr_in local;
struct sockaddr_in from;
int fromlen = sizeof(from);
local.sin_family = AF_INET;
local.sin_port = htons(LOCAL_PORT);
local.sin_addr.s_addr = INADDR_ANY;
socketS = socket(AF_INET, SOCK_DGRAM, 0);
if (bind(socketS, (sockaddr*)&local, sizeof(local)) != 0) {
printf("Binding error!\n");
getchar(); //wait for press Enter
return 1;
}
//**********************************************************************
#ifdef SENDER
FILE *fp, *fp1;
char buffer_tx[BUFFERS_LEN];
int numPacket = 0;
char numberPacket[BUFFERS_LEN];
int isEnd = 0;
char test[100];
char header[HEADER_LEN];
char data[DATA_LEN];
char dataContent[DATA_LEN];
int len;
int num;
char *token;
sockaddr_in addrDest;
addrDest.sin_family = AF_INET;
addrDest.sin_port = htons(TARGET_PORT);
InetPton(AF_INET, _T(TARGET_IP), &addrDest.sin_addr.s_addr);
char *name = "test.jpg";
fp = fopen(name, "rb");
if (fp == NULL)
{
printf("error opening file\n");
}
fseek(fp, 0L, SEEK_END);
int sz = ftell(fp);
rewind(fp);
sz = (int)(sz / DATA_LEN) + 1;
strncpy(buffer_tx, name, BUFFERS_LEN); //put the nam of the file in the buffer
sendto(socketS, buffer_tx, BUFFERS_LEN, 0, (sockaddr*)&addrDest, sizeof(addrDest)); // send the name of the file
recvfrom(socketS, buffer_tx, BUFFERS_LEN, 0, (sockaddr*)&from, &fromlen); // wait aknowledgment
clearBuffer(buffer_tx, BUFFERS_LEN);
sprintf(buffer_tx, "%d", sz);
sendto(socketS, buffer_tx, BUFFERS_LEN, 0, (sockaddr*)&addrDest, sizeof(addrDest)); // send size of file
recvfrom(socketS, buffer_tx, BUFFERS_LEN, 0, (sockaddr*)&from, &fromlen); // wait aknowledgment
// This is to be sure that the receiver receive the name and the size correctly in the right order
clearBuffer(buffer_tx, BUFFERS_LEN);
clearBuffer(dataContent, DATA_LEN);
int n = 1;
int dataLength = 0;
while ((n = fread(dataContent, 1, DATA_LEN - 1,fp)) > 0) // read data of the file
{
clearBuffer(buffer_tx, BUFFERS_LEN); // clear the buffer for further utilisation
createBuffer(buffer_tx, dataContent, numPacket++, n); // add the header to the data |numPacket|dataLength|isEnd|data|
sendto(socketS, buffer_tx, BUFFERS_LEN, 0, (sockaddr*)&addrDest, sizeof(addrDest)); // send the packet
}
fclose(fp);
#endif // SENDER
#ifdef RECEIVER
FILE *fp;
char buffer_rx[BUFFERS_LEN];
Data *data;
int n = 0;
int k;
int how_many = 310;
//strncpy(buffer_rx, "12:1|salut", BUFFERS_LEN);
printf("Waiting for datagram ...\n");
int numPacket = 0;
int isEnd = 0;
int size = 0;
char size_file_c[BUFFERS_LEN];
int size_file = 0;
char header[HEADER_LEN];
char d[DATA_LEN + 1];
char name[BUFFERS_LEN];
char output[30];
char salut[DATA_LEN + 1];
sockaddr_in addrDest;
addrDest.sin_family = AF_INET;
addrDest.sin_port = htons(TARGET_PORT);
InetPton(AF_INET, _T(TARGET_IP), &addrDest.sin_addr.s_addr);
recvfrom(socketS, name, BUFFERS_LEN, 0, (sockaddr*)&from, &fromlen); // receiving name of file
sendto(socketS, name, BUFFERS_LEN, 0, (sockaddr*)&addrDest, sizeof(addrDest)); // send aknowledgment
recvfrom(socketS, size_file_c, BUFFERS_LEN, 0, (sockaddr*)&from, &fromlen); // receiving size of file
sendto(socketS, size_file_c, BUFFERS_LEN, 0, (sockaddr*)&addrDest, sizeof(addrDest)); // send aknowledgment
size_file = atoi(size_file_c);
// This is to be sure that the receiver receive the name and the size correctly in the right order
data = (Data *)calloc(size_file, sizeof(Data)); // allocate memory for the data
//closesocket(socketS);
//END;
//analyseBuffer(buffer_rx,d, &numPacket, &isEnd);
for (int i = 0; i < size_file; i++)
{
printf("waiting packet\n");
if ((k = recvfrom(socketS, buffer_rx, BUFFERS_LEN, 0, (sockaddr*)&from, &fromlen)) == SOCKET_ERROR) // receive a packet
{
printf("error during reception");
getchar();
return -1;
}
else
{
readFile(buffer_rx, BUFFERS_LEN, d, &numPacket, &size, &isEnd); // analyse the pacet to extract the data, the number of the packet, the data lenght and if it's the end
data[numPacket].data = (char*) calloc(size, 1); // allocate only the necessary memory
data[numPacket].size = size;
//print(d, DATA_LEN);
copy(data[numPacket].data, d, data[numPacket].size); // copy only the usefull info (without '\0')
printf("%d ; %d\n", i, size_file);
if (isEnd)
break;
clearBuffer(buffer_rx, BUFFERS_LEN); // clear the buffer for further utilisation
}
}
printf("file name : %s\n", name);
printf("enter the name of new file to be saved\n");
scanf("%s", output); // ask the user to set a file name
fp = fopen(output, "wb");
for (int i = 0; i <size_file; i++)
{
fwrite(data[i].data, data[i].size, 1, fp); // write the data to the file in the right order
}
fclose(fp); // close the file
closesocket(socketS);
#endif // RECEIVER
//**********************************************************************
getchar(); //wait for press Enter
return 0;
}
Notice the CRC-16 function , which is:
unsigned short crc16(const unsigned char* numPacket, unsigned char length) {
unsigned char x;
unsigned short crc = 0xFFFF;
while (length--) {
x = crc >> 8 ^ *numPacket++;
x ^= x >> 4;
crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x << 5)) ^ ((unsigned short)x);
}
return crc;
}
My question is : What is the best/easiest way to implement the CRC-16 function I have here? Do I pass a unsigned short crc parameter variable to the createBuffer() function, call the crc16() function inside the createBuffer() function and take the value it returns and assign it to the parameter value and then append it to the buffer?
Or is there a much simpler way to do it that I'm currently not thinking about?
Regarding What is the best/easiest way to implement the CRC-16 function I have here?
First, it appears your CRC-16 function is already implemented. How to use it is illustrated below.
CRC functions are typically used to take a file or buffer of any size as input, and produce a unique value for the purpose of verifying the contents of the file.
Here is a simple example of how I would use this function to read two types of input... (note, bufIn, and buf can be arrays of much larger sizes)
int main(void)
{
unsigned char bufIn[] = {1,45,76,23,245,9,54,55,210,90,23,54,78,14,27,86,34};
char buf[] = {"lkjahsloiwuyhfajsldnaouiyhrqkuhsldajnfdlakdsfa;jsidurfaliu;adjklflkja;sdlkjasdklfauiea;e"};
unsigned short crcOut1, crcOut2;
crcOut1 = crc16(bufIn, sizeof(bufIn)); //for bufIn returns 0x7782
crcOut2 = crc16(buf, sizeof(buf)); //for buf returns 0x98FB
return 0;
}
EDIT to address question in comment...
In your code, one possible way to use this is to call the crc16() function inside your fread while loop:
unsigned short packetCrc;
while ((n = fread(dataContent, 1, DATA_LEN - 1,fp)) > 0) // read data of the file
{
packetCrc = crc16(dataContent, n);
// verify packetCrc value against some expected value perhaps?
clearBuffer(buffer_tx, BUFFERS_LEN); // clear the buffer for further utilisation
createBuffer(buffer_tx, dataContent, numPacket++, n); // add the header to the data |numPacket|dataLength|isEnd|data|
sendto(socketS, buffer_tx, BUFFERS_LEN, 0, (sockaddr*)&addrDest, sizeof(addrDest)); // send the packet
}
I am trying to decode a audio file using ffmpeg, while I am doing this I am getting many unresolved external errors. I am new to ffmpeg libraries, any suggestion for the problem would be a great help.
Thank you.
void audioDecode(char* filename)
{
FILE *file;
AVFormatContext *audioInputFormatContext;
AVInputFormat *audioInputFormat = NULL;
AVCodec *audioCodec;
AVCodecContext *audioCodecContext;
av_register_all();
char *audioInputDeviceName = filename;
int ret;
int audioIndex = 0;
AVPacket pkt;
av_init_packet(&pkt);
avformat_network_init();
audioInputFormatContext = avformat_alloc_context();
ret = avformat_open_input(&audioInputFormatContext, audioInputDeviceName, audioInputFormat, NULL);
if (ret == 0)
{
ret = avformat_find_stream_info(audioInputFormatContext, 0);
if (ret >= 0)
{
for (int i = 0; i < audioInputFormatContext->nb_streams; i++) {
if (audioInputFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audioIndex = i;
break;
}
}
audioCodec = avcodec_find_decoder(audioInputFormatContext->streams[audioIndex]->codecpar->codec_id);
audioCodecContext = avcodec_alloc_context3(audioCodec);
avcodec_parameters_to_context(audioCodecContext, audioInputFormatContext->streams[audioIndex]->codecpar);
if (avcodec_open2(audioCodecContext, audioCodec, NULL) >= 0)
{
ret = av_read_frame(audioInputFormatContext, &pkt);
AVPacket encodePacket;
AVFrame* decodeFrame = av_frame_alloc();
int dec_got_frame = 0;
if (ret == 0)
{
ret = avcodec_send_packet(audioCodecContext, &pkt);
if (ret < 0)
printf("Error");
}
ret = avcodec_receive_frame(audioCodecContext, decodeFrame);
if (ret >= 0)
dec_got_frame = 1;
if (dec_got_frame)
{
fopen_s(&file, filename, "wb");
fwrite(pkt.data, 1, pkt.size, file);
fclose(file);
}
av_frame_free(&decodeFrame);
}
}
}
avformat_close_input(&audioInputFormatContext);
avcodec_free_context(&audioCodecContext);
av_packet_unref(&pkt);
}
I'm just going to assume that you've already connected to the stream source and have the codec context by what you've mentioned in the comments.
These are snippets from my own project decoding the audio frames.
Decode the audio packet:
void FFMPEG::process_audio_packet(AVPacket *pkt) {
int got;
avcodec_decode_audio4(aud_stream.context, aud_stream.frame, &got, pkt);
if (got) Audio.add_av_frame(aud_stream.frame);
}
Process the completed frame and extract a stereo 16 bit signed buffer:
void AudioManager::add_av_frame(AVFrame *frame) {
int nsamples = frame->nb_samples;
int sample_rate = frame->sample_rate;
int channels = frame->channels;
AVSampleFormat format = (AVSampleFormat) frame->format;
bool planar = av_sample_fmt_is_planar(format) == 1;
int64_t pts = av_frame_get_best_effort_timestamp(frame);
//double ftime;
/*if (ffmpeg.vid_stream.stream_id != -1)
ftime = av_q2d(ffmpeg.aud_stream.context->time_base) * pts;
else
ftime = av_q2d(ffmpeg.vid_stream.context->time_base) * pts;*/
AudioBuffer *buffer = NULL;
if (planar) { // handle planar audio frames
/*
* PLANAR frames conversion
* ------------------------
*/
if (channels == 1) { // MONO
//LOGD("Processing PLANAR MONO");
/*
* MONO
*/
if (format == AV_SAMPLE_FMT_S16P) { // 16 bit signed
if ((buffer = alloc_buffer(frame))) { // allocated okay?
short *channel = (short*)frame->data[0];
short *buff = buffer->data;
for (int c = 0; c < nsamples; c++) {
*buff++ = *channel;
*buff++ = *channel++;
}
queue_new_buffer(buffer);
}
return;
}
if (format == AV_SAMPLE_FMT_S32P) { // 32 bit signed
if ((buffer = alloc_buffer(frame))) { // allocated okay?
int32_t *channel = (int32_t*)frame->data[0];
short *buff = buffer->data;
for (int c = 0; c < nsamples; c++) {
int16_t s = (int16_t) (*channel++ >> 16);
*buff++ = s;
*buff++ = s;
}
queue_new_buffer(buffer);
}
return;
}
if (format == AV_SAMPLE_FMT_U8P) { // 8 bit unsigned
if ((buffer = alloc_buffer(frame))) { // allocated okay?
uint8_t *channel = (uint8_t*)frame->data[0];
short *buff = buffer->data;
for (int c = 0; c < nsamples; c++) {
int16_t s = ((int16_t)(*channel++ - 128) << 8);
*buff++ = s;
*buff++ = s;
}
queue_new_buffer(buffer);
}
}
return; // scrap if no audio buffer (highly unlikely)
} else if (channels == 2) { // STEREO
//LOGD("Processing PLANAR STEREO");
/*
* STEREO
*/
if (format == AV_SAMPLE_FMT_S16P) { // 16 bit signed
if ((buffer = alloc_buffer(frame))) { // allocated okay
short *channel1 = (short*)frame->data[0];
short *channel2 = (short*)frame->data[1];
short *buff = buffer->data;
for (int c = 0; c < nsamples; c++) {
*buff++ = *channel1++;
*buff++ = *channel2++;
}
queue_new_buffer(buffer);
}
return;
}
if (format == AV_SAMPLE_FMT_S32P) { // 32 bit signed
if ((buffer = alloc_buffer(frame))) { // allocated okay?
int32_t *channel1 = (int32_t*)frame->data[0];
int32_t *channel2 = (int32_t*)frame->data[1];
short *buff = buffer->data;
for (int c = 0; c < nsamples; c++) {
int16_t s1 = (int16_t) (*channel1++ >> 16);
int16_t s2 = (int16_t) (*channel2++ >> 16);
*buff++ = s1;
*buff++ = s2;
}
queue_new_buffer(buffer);
}
return;
}
if (format == AV_SAMPLE_FMT_U8P) { // 8 bit unsigned
if ((buffer = alloc_buffer(frame))) { // allocated okay?
uint8_t *channel1 = (uint8_t*)frame->data[0];
uint8_t *channel2 = (uint8_t*)frame->data[1];
short *buff = buffer->data;
for (int c = 0; c < nsamples; c++) {
int16_t s1 = ((int16_t)(*channel1++ - 128) << 8);
int16_t s2 = ((int16_t)(*channel2++ - 128) << 8);
*buff++ = s1;
*buff++ = s2;
}
queue_new_buffer(buffer);
}
}
return;
} // TODO: Handle more channels at a later date
} else { // handle non-planar audio frames
/*
* INTERLEAVED conversion
* ----------------------
*/
}
}
Process the audio buffer:
void AudioManager::queue_new_buffer(AudioBuffer *buffer) {
if (buffer) { // valid buffer
// apply volume gain (only working with stereo)
if (volume != 100) {
short *data = buffer->data;
int num_samples = buffer->nsamples << 1;
while (num_samples--) {
long sample = ((long)*data * volume) / 100;
if (sample < -32768) sample = -32768;
if (sample > 32767) sample = 32767;
*data++ = (short)sample;
}
}
// add buffer to queue
buffer->used = true;
double pts_start = get_pts_start_time();
decode_pos = (++decode_pos) % MAX_AUD_BUFFERS;
if (decode_pos == playback_pos)
playback_pos = (++playback_pos) % MAX_AUD_BUFFERS;
if (ffmpeg.vid_stream.stream_id == -1 && pts_start < 0.0) {
set_pts_start_time(buffer->frame_time);
set_sys_start_time(Display.get_current_render_time());
LOGD("START TIME FROM AUDIO STREAM...");
}
//LOGI("Audio buffer queued %d (%d)", decode_pos, playback_pos);
}
}
Running my program, I appear to not be writing the correct amount of frames according to the index.
$ ./test
Now recording!! Please speak into the microphone.
index = 0
Writing to: test.flac
audio.h:
#include <stdint.h>
#include <string.h>
typedef struct
{
uint32_t duration;
uint16_t format_type;
uint16_t number_of_channels;
uint32_t sample_rate;
uint32_t frameIndex; /* Index into sample array. */
uint32_t maxFrameIndex;
char* recordedSamples;
} AudioData;
int recordFLAC(AudioData* data, const char *fileName);
AudioData* initAudioData(uint32_t sample_rate, uint16_t channels, uint32_t duration);
capture.c:
#include <stdio.h>
#include <stdlib.h>
#include <portaudio.h>
#include <sndfile.h>
#include "audio.h"
AudioData* initAudioData(uint32_t sample_rate, uint16_t channels, uint32_t duration)
{
AudioData* data = malloc(sizeof(*data));
if (!data) return NULL;
data->duration = duration;
data->format_type = 1;
data->number_of_channels = channels;
data->sample_rate = sample_rate;
data->frameIndex = 0;
data->maxFrameIndex = sample_rate * duration;
data->recordedSamples = malloc(sizeof(data->maxFrameIndex));
if(!data->maxFrameIndex) return NULL;
return data;
}
static int recordCallback(const void *inputBuffer, void *outputBuffer, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
{
AudioData* data = (AudioData*)userData;
const char* buffer_ptr = (const char*)inputBuffer;
char* index_ptr = &data->recordedSamples[data->frameIndex];
(void) outputBuffer;
(void) timeInfo;
(void) statusFlags;
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
if(framesLeft < frameCount){
framesToCalc = framesLeft;
finished = paComplete;
}else{
framesToCalc = frameCount;
finished = paContinue;
}
if(!inputBuffer){
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0;
}
}else{
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = *buffer_ptr++;
}
}
data->frameIndex += framesToCalc;
return finished;
}
int recordFLAC(AudioData* data, const char *fileName)
{
PaStreamParameters inputParameters;
PaStream* stream;
int err = 0;
int totalFrames = data->maxFrameIndex;
int numSamples;
int numBytes;
char max, val;
double average;
numSamples = totalFrames * data->number_of_channels;
numBytes = numSamples;
data->recordedSamples = malloc(numBytes);
if(!data->recordedSamples)
{
printf("Could not allocate record array.\n");
goto done;
}
for(int i = 0; i < numSamples; i++) data->recordedSamples[i] = 0;
if((err = Pa_Initialize())) goto done;
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto done;
}
inputParameters.channelCount = data->number_of_channels; /* stereo input */
inputParameters.sampleFormat = data->format_type;
inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
/* Record some audio. -------------------------------------------- */
err = Pa_OpenStream(&stream, &inputParameters, NULL, data->sample_rate, paFramesPerBufferUnspecified, paClipOff, recordCallback, &data);
if(err) goto done;
if((err = Pa_StartStream(stream))) goto done;
puts("Now recording!! Please speak into the microphone.");
while((err = Pa_IsStreamActive(stream)) == 1)
{
Pa_Sleep(1000);
printf("index = %d\n", data->frameIndex);
}
if( err < 0 ) goto done;
err = Pa_CloseStream(stream);
if(err) goto done;
/* Measure maximum peak amplitude. */
max = 0;
average = 0.0;
for(int i = 0; i < numSamples; i++)
{
val = data->recordedSamples[i];
val = abs(val);
if( val > max )
{
max = val;
}
average += val;
}
average /= (double)numSamples;
done:
Pa_Terminate();
if(err)
{
fprintf(stderr, "An error occured while using the portaudio stream\n");
fprintf(stderr, "Error number: %d\n", err);
fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err));
err = 1; /* Always return 0 or 1, but no other return codes. */
}
else
{
SF_INFO sfinfo;
sfinfo.channels = 1;
sfinfo.samplerate = data->sample_rate;
sfinfo.format = SF_FORMAT_FLAC | SF_FORMAT_PCM_16;
// open to file
printf("Writing to: %s\n", fileName);
SNDFILE * outfile = sf_open(fileName, SFM_WRITE, &sfinfo);
if (!outfile) return -1;
// prepare a 3 second long buffer (sine wave)
const int size = data->sample_rate * 3;
// write the entire buffer to the file
sf_write_raw(outfile, data->recordedSamples, size);
// force write to disk
sf_write_sync(outfile);
// don't forget to close the file
sf_close(outfile);
}
return err;
}
I'm not quite sure where I am going wrong, I know I need to be writing more frames. Any suggestions?
There seems to be something wrong with your assumptions about the sample format. In the callback you are using char * (single bytes) for the sample format, but in your libsndfile call you're opening a 16 bit file with SF_FORMAT_PCM_16.
This is not so good:
data->format_type = 1;
I recommend using one of the symbolic constants in the PortAudio library for sample formatting. Maybe you want a 16 bit one? And if so, you want to be using short* not char* in the PA callback.
Finally, if your channel count is not 1, the copy loops are incorrect:
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0;
}
A "frame" contains data for all channels, so for example, if it's a stereo input your iteration needs to deal with both left and right channels like this:
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0; // left
*index_ptr++ = 0; // right
}
Same for the other loops.
Im new here and Ill love your help.
Im trying to serialize and deserialize a package (to use it in sockets) and the results are not the ones that I expect but I cant find the mistake. HereĀ“s the code.
typedef struct {
int32_t size;
char data[1024];
} t_socket_buffer;
typedef struct {
int16_t payloadLength;
int8_t type;
char *path;
} ReadRequestPackage;
The function that serializes
t_socket_buffer *Open_serializer(ReadRequestPackage *ReadPackage){
char data[1024];
t_socket_buffer *stream = malloc(sizeof(t_socket_buffer));
int8_t offset = 0, tmp_size = 0;
memcpy(data, &ReadPackage->payloadLength, tmp_size = sizeof(int16_t));
offset = tmp_size;
memcpy(data + offset,&ReadPackage->type, tmp_size = sizeof(int8_t));
offset+= tmp_size;
memcpy(data + offset, ReadPackage->path,tmp_size = strlen(ReadPackage->path)+1);
stream->size = offset + tmp_size;
memcpy(stream->data, data,strlen(data)+1);
return stream;
}
The function that DEserializes
ReadRequestPackage *Open_deserializer(t_socket_buffer *stream)
{
ReadRequestPackage *ReadPackage = malloc(sizeof(ReadRequestPackage));
int32_t offset = 0, tmp_size = 0;
memcpy(&ReadPackage->payloadLength,stream->data,tmp_size = sizeof(int16_t));
offset = tmp_size;
memcpy(&ReadPackage->type, stream->data + offset, tmp_size = sizeof(int8_t));
offset += tmp_size;
for(tmp_size = 1; (stream->data + offset)[tmp_size-1]!='\0';tmp_size++);
ReadPackage->path = malloc(tmp_size);
memcpy(ReadPackage->path, stream->data + offset, tmp_size);
return ReadPackage;
}
When I test it with this main()
int main (void){
ReadRequestPackage *pqt1 = malloc(sizeof(ReadRequestPackage));
ReadRequestPackage *pqt2;
t_socket_buffer *stream;
pqt1->path=malloc(sizeof("directory"));
strcpy(pqt1->path,"directory");
pqt1->payloadLength = strlen("directory")+1+sizeof(int8_t);
pqt1->type = 1;
stream = Open_serializer(pqt1);
pqt2 = Open_deserializer(stream);
printf("path 1: ");
puts(pqt1->path);
printf("path 2: ");
puts(pqt2->path);
printf("\ntype1:%d ",pck1->type);
printf("\ntype2:%d ",pck2->type);
printf("\nize:%d ",pck1->payloadLength);
printf("\nsize:%d ",pck2->payloadLength);
return 1;
}
The results are not the same and they should!
Thank you very much!
memcpy(stream->data, data,strlen(data)+1);
This line is not doing what you think it's doing. data is not a string.
BTW, have you thought about using a proper serialization library?