From f382697c6303616dcd5ec1f037bb45b933d4b9da Mon Sep 17 00:00:00 2001 From: Smanar Date: Sun, 7 Aug 2016 11:47:02 +0200 Subject: [PATCH] Rhonda can now record wav, convert to flac and send it to google without using intermediate file. Rhonda can now record wav, convert to flac and send it to google without using intermediate file. --- audio.cpp | 939 +++++++++++++++++++++++++++++++++++++ rhonda/applications.cpp | 31 ++ rhonda/applications.h | 2 + rhonda/audio.cpp | 24 +- rhonda/audio.h | 2 +- rhonda/config.xml | 3 +- rhonda/flac.c | 260 +++++++--- rhonda/flac.h | 5 +- rhonda/prog.cpp | 25 +- rhonda/traitement.cpp | 28 +- rhonda/traitement.h | 1 + rhonda/translategoogle.cpp | 46 +- rhonda/translategoogle.h | 2 +- 13 files changed, 1250 insertions(+), 118 deletions(-) create mode 100644 audio.cpp diff --git a/audio.cpp b/audio.cpp new file mode 100644 index 0000000..49ce927 --- /dev/null +++ b/audio.cpp @@ -0,0 +1,939 @@ +#include +#include +#include + + +//#include "record.h" +#include "flac.h" +#include "stdio.h" +#include "hardware.h" +//#include +#include "audio.h" + +#include "prog.h" + +#ifndef _WIN32 +#include +#endif + +#pragma comment(lib,"libs/libsnowboy-detect.a") +//#pragma comment(lib,"libs/portaudio/install/lib/libportaudio.so") + + +#define NUM_CHANNELS (1) +#define SAMPLE_RATE (44100) +#define FRAMES_PER_BUFFER (512) +#define MAXSILENCE 900 +#define MINSILENCE 500 +#define MINFRAME 45000 + +#define MAGICNUMBER 8000 + +#define BUFFER + +int fd = 0; + +bool PortAudioInitialised = false; + +int Config_Gain=2; +int Min_Amplitude = 2000; + + +WaveHeader *genericWAVHeader(WaveHeader*hdr, uint32_t sample_rate, uint16_t bit_depth, uint16_t channels) +{ + if (!hdr) return NULL; + + memcpy(&hdr->RIFF_marker, "RIFF", sizeof(hdr->RIFF_marker)); + memcpy(&hdr->filetype_header, "WAVE", sizeof(hdr->filetype_header)); + memcpy(&hdr->format_marker, "fmt ", sizeof(hdr->format_marker)); + 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(FILE* fd, WaveHeader *hdr) +{ + uint32_t file_size; + file_size = hdr->data_size + 36; + + if (!hdr) return -1; + + fwrite(hdr->RIFF_marker, sizeof(hdr->RIFF_marker), 1, fd); + fwrite(&file_size, sizeof(hdr->data_size), 1, fd); + fwrite(hdr->filetype_header, sizeof(hdr->filetype_header), 1, fd); + fwrite(hdr->format_marker, sizeof(hdr->format_marker), 1, fd); + fwrite(&hdr->data_header_length, sizeof(hdr->data_header_length), 1, fd); + fwrite(&hdr->format_type, sizeof(hdr->format_type), 1, fd); + fwrite(&hdr->number_of_channels, sizeof(hdr->number_of_channels), 1, fd); + fwrite(&hdr->sample_rate, sizeof(hdr->sample_rate), 1, fd); + fwrite(&hdr->bytes_per_second, sizeof(hdr->bytes_per_second), 1, fd); + fwrite(&hdr->bytes_per_frame, sizeof(hdr->bytes_per_frame), 1, fd); + fwrite(&hdr->bits_per_sample, sizeof(hdr->bits_per_sample), 1, fd); + fwrite("data", 4, 1, fd); + fwrite(&hdr->data_size, sizeof(hdr->data_size), 1, fd); + + return 0; +} + + +int writeWAVHeaderBuffer(char* buff2, WaveHeader *hdr) +{ + uint32_t file_size; + + char *buff = buff2; + char t[5] = "data"; + + file_size = hdr->data_size + 36; + + if (!hdr) return -1; + + memcpy(buff, hdr->RIFF_marker, sizeof(hdr->RIFF_marker)); + buff += sizeof(hdr->RIFF_marker); + memcpy(buff, &file_size, sizeof(hdr->data_size)); + buff += sizeof(hdr->data_size); + memcpy(buff, hdr->filetype_header, sizeof(hdr->filetype_header)); + buff += sizeof(hdr->filetype_header); + memcpy(buff, hdr->format_marker, sizeof(hdr->format_marker)); + buff += sizeof(hdr->format_marker); + memcpy(buff, &hdr->data_header_length, sizeof(hdr->data_header_length)); + buff += sizeof(hdr->data_header_length); + memcpy(buff, &hdr->format_type, sizeof(hdr->format_type)); + buff += sizeof(hdr->format_type); + memcpy(buff, &hdr->number_of_channels, sizeof(hdr->number_of_channels)); + buff += sizeof(hdr->number_of_channels); + memcpy(buff, &hdr->sample_rate, sizeof(hdr->sample_rate)); + buff += sizeof(hdr->sample_rate); + memcpy(buff, &hdr->bytes_per_second, sizeof(hdr->bytes_per_second)); + buff += sizeof(hdr->bytes_per_second); + memcpy(buff, &hdr->bytes_per_frame, sizeof(hdr->bytes_per_frame)); + buff += sizeof(hdr->bytes_per_frame); + memcpy(buff, &hdr->bits_per_sample, sizeof(hdr->bits_per_sample)); + buff += sizeof(hdr->bits_per_sample); + memcpy(buff, t, 4); + buff += 4; + memcpy(buff, &hdr->data_size, sizeof(hdr->data_size)); + buff += sizeof(hdr->data_size); + + return 0; +} + +/**************************************************************************/ +/****** Common fonction ******/ +/**************************************************************************/ + +int InitPortAudio(void) +{ + + if (PortAudioInitialised) return true; + + +#ifndef _WIN32 + //disable output error + fd = dup(fileno(stdout)); + freopen("/dev/null", "w", stderr); +#endif + + + // Initializes PortAudio. + PaError pa_init_ans = Pa_Initialize(); + + if (pa_init_ans != paNoError) { + wprintf(L"Fail to initialize PortAudio, error message is %s\n", Pa_GetErrorText(pa_init_ans)); + return false; + } + + + { + int i; + + PaDeviceIndex numDevices = Pa_GetDeviceCount(); + if (numDevices < 0) + { + wprintf(L"ERROR: Pa_GetDeviceCount returned 0x%x\n", numDevices); + } + + wprintf(L"Number of devices = %d\n", numDevices); + for (i = 0; iname); + + if (i == Pa_GetDefaultInputDevice()) + { + wprintf(L"[ Default Input ]"); + } + if (i == Pa_GetDefaultOutputDevice()) + { + wprintf(L"[ Default Output ]"); + } + wprintf(L"\n"); + } + } + + PortAudioInitialised = true; + +#ifndef _WIN32 + //clear and restore it + fflush(stderr); + dup2(fd, fileno(stderr)); +#endif + + return true; +} + + +/**************************************************************************/ +/****** Snowboy fonction ******/ +/**************************************************************************/ + + + +int PortAudioCallback(const void* input, void* output, unsigned long frame_count, const PaStreamCallbackTimeInfo* time_info, PaStreamCallbackFlags status_flags, void* user_data); + + + +PortAudioWrapper::PortAudioWrapper(int sample_rate, int num_channels, int bits_per_sample) { + num_lost_samples_ = 0; + pa_stream_ = NULL; + ready = false; + min_read_samples_ = (int)(sample_rate * 0.1); + ringbuffer_ = NULL; + + ringbuffer_size = 16384; + + wprintf(L"\033[0;31mInitialise Snowboy\033[0;37m\n"); + + InitPortAudio(); + + if (Init(sample_rate, num_channels, bits_per_sample)) ready = true; +} + + + +void PortAudioWrapper::Read(std::vector* data) { + assert(data != NULL); + + if (!ready) return; + + // Checks ring buffer overflow. + if (num_lost_samples_ > 0) { + wprintf(L"Lost %d samples due to ring buffer overflow.\n", num_lost_samples_); + num_lost_samples_ = 0; + } + + ring_buffer_size_t num_available_samples = 0; + + while (true) { + num_available_samples = PaUtil_GetRingBufferReadAvailable(&pa_ringbuffer_); + if (num_available_samples >= min_read_samples_) { + break; + } + Pa_Sleep(5); + } + + // Reads data. + num_available_samples = PaUtil_GetRingBufferReadAvailable(&pa_ringbuffer_); + data->resize(num_available_samples); + + ring_buffer_size_t num_read_samples = PaUtil_ReadRingBuffer(&pa_ringbuffer_, data->data(), num_available_samples); + + if (num_read_samples != num_available_samples) + { + wprintf(L"%d samples were available, but only %d samples were read.\n", num_available_samples, num_read_samples); + } +} + +int PortAudioWrapper::Callback(const void* input, void* output, unsigned long frame_count, const PaStreamCallbackTimeInfo* time_info, PaStreamCallbackFlags status_flags) +{ + // Input audio. + ring_buffer_size_t num_written_samples = PaUtil_WriteRingBuffer(&pa_ringbuffer_, input, frame_count); + num_lost_samples_ += frame_count - num_written_samples; + return paContinue; +} + +PortAudioWrapper::~PortAudioWrapper() { + if (pa_stream_) + { + //Pa_StopStream(pa_stream_); + //Pa_CloseStream(pa_stream_); + Stop(); + } + Pa_Terminate(); + PaUtil_FreeMemory(ringbuffer_); +} + + +bool PortAudioWrapper::Init(int sample_rate, int num_channels, int bits_per_sample) +{ + // Allocates ring buffer memory. + if (ringbuffer_) PaUtil_FreeMemory(ringbuffer_); + ringbuffer_ = static_cast( PaUtil_AllocateMemory(bits_per_sample / 8 * ringbuffer_size)); + + if (ringbuffer_ == NULL) { + wprintf(L"Fail to allocate memory for ring buffer.\n"); + return false; + } + + sample_rate_ = sample_rate; + num_channels_ = num_channels; + bits_per_sample_ = bits_per_sample; + + return Start(); +} + + +void PortAudioWrapper::Stop() +{ + if (pa_stream_) + { + Pa_StopStream(pa_stream_); + //Pa_AbortStream(pa_stream_); + Pa_CloseStream(pa_stream_); + pa_stream_ = NULL; + } +} + +bool PortAudioWrapper::Start() +{ + + PaError pa_open_ans; + + if (pa_stream_) return false; + + if (bits_per_sample_ == 8) + { + pa_open_ans = Pa_OpenDefaultStream(&pa_stream_, num_channels_, 0, paUInt8, sample_rate_, paFramesPerBufferUnspecified, PortAudioCallback, this); + } + else if (bits_per_sample_ == 16) + { + pa_open_ans = Pa_OpenDefaultStream(&pa_stream_, num_channels_, 0, paInt16, sample_rate_, paFramesPerBufferUnspecified, PortAudioCallback, this); + } + else if (bits_per_sample_ == 32) + { + pa_open_ans = Pa_OpenDefaultStream(&pa_stream_, num_channels_, 0, paInt32, sample_rate_, paFramesPerBufferUnspecified, PortAudioCallback, this); + } + else { + wprintf(L"Unsupported BitsPerSample: %d\n", bits_per_sample_); + return false; + } + if (pa_open_ans != paNoError) { + wprintf(L"Fail to open PortAudio stream, error message is %s\n", Pa_GetErrorText(pa_open_ans)); + return false; + } + + PaError pa_stream_start_ans = Pa_StartStream(pa_stream_); + if (pa_stream_start_ans != paNoError) { + wprintf(L"Fail to start PortAudio stream, error message is %s\n", Pa_GetErrorText(pa_stream_start_ans)); + return false; + } + + // Initializes PortAudio ring buffer. + ring_buffer_size_t rb_init_ans = PaUtil_InitializeRingBuffer(&pa_ringbuffer_, bits_per_sample_ / 8, ringbuffer_size, ringbuffer_); + + if (rb_init_ans == -1) { + wprintf(L"Ring buffer size is not power of 2"); + return false; + } + + return true; +} + +int PortAudioCallback(const void* input,void* output,unsigned long frame_count, const PaStreamCallbackTimeInfo* time_info, PaStreamCallbackFlags status_flags, void* user_data) +{ + PortAudioWrapper* pa_wrapper = reinterpret_cast(user_data); + pa_wrapper->Callback(input, output, frame_count, time_info, status_flags); + return paContinue; +} + + + + +/**************************************************************************/ +/****** Recorder fonction ******/ +/**************************************************************************/ + + +#define ENR_ATTENTE 0 +#define ENR_ENCOURS 1 +#define ENR_FINI 2 +#define ENR_RATE 3 + +long amplitude; +int Enr_etat; +int silence; +long temposilence; +long tempobruit; + +void Initchecker(void) +{ + Enr_etat = ENR_ATTENTE; + amplitude = 0; + temposilence = 0; + tempobruit = 0; +} + +int Checkamplitude(long value) +{ + //wprintf(L"Debug %d.\n", value); + + if (Enr_etat == ENR_RATE) return Enr_etat; + + if (value > Min_Amplitude) + { + if (Enr_etat == ENR_ATTENTE) + { + wprintf(L"Son detecte, Demmarage enregistrement. Valeur : %ld\n",value); + _DisplaySpectro(-1); + + Enr_etat = ENR_ENCOURS; + + } + temposilence = 0; + } + else + { + temposilence += 1; + + if (((temposilence > MAXSILENCE) && (Enr_etat == ENR_ATTENTE)) || ((temposilence > MINSILENCE) && (Enr_etat == ENR_ENCOURS))) + { + if (Enr_etat != ENR_FINI) + { + wprintf(L"Too much silence.\n"); + if (Enr_etat == ENR_ENCOURS) Enr_etat = ENR_FINI; + else Enr_etat = ENR_RATE; + } + } + } + + return Enr_etat; +} + +long compteur; +void SetSpectro(long val) +{ + unsigned short int spect; + + compteur++; + + if (Enr_etat == ENR_ATTENTE) return; + + if (compteur % 30 == 0) + { + spect = (unsigned short int)(val * MAGICNUMBER / 65537); + spect = (int)(spect * 100 / 65537); + //wprintf(L"Spectro %ld %d\n", val, spect); + _DisplaySpectro(spect); + } +} + +/* This routine will be called by the PortAudio engine when audio is needed. +** It may be called at interrupt level on some machines so don't do anything +** that could mess up the system like calling malloc() or free(). +*/ +static int recordCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData) +{ + PAData *data = (PAData*)userData; + const SAMPLE *rptr = (const SAMPLE*)inputBuffer; + SAMPLE *wptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS]; + long framesToCalc; + long i; + int finished; + + long totalamplitude = 0; + long v; + int detection; + + unsigned long framesLeft = data->maxFrameIndex - data->frameIndex; + + (void)outputBuffer; /* Prevent unused variable warnings. */ + (void)timeInfo; + (void)statusFlags; + (void)userData; + + + if (framesLeft < framesPerBuffer) + { + wprintf(L"Depassement duree max\n"); + framesToCalc = framesLeft; + finished = paComplete; + } + else + { + framesToCalc = framesPerBuffer; + finished = paContinue; + } + + //check amplitude + if (inputBuffer == NULL) + { + totalamplitude = 0; + } + else + { + for (i = 0; i < framesToCalc * NUM_CHANNELS; i += NUM_CHANNELS) + { + v = (long)rptr[i]; + if (v < 0) v = -v; + totalamplitude += v; + } + } + + totalamplitude = totalamplitude / NUM_CHANNELS; + + detection = Checkamplitude(totalamplitude / framesToCalc); + //stop if too much silence + if ((detection == ENR_FINI) || (detection == ENR_RATE)) finished = paComplete; + + + //Display spectrographe + SetSpectro(totalamplitude); + + //buffer copy + //all the time or only if there is sound ??? TODO : need to test + if (1 == 1) //(Enr_etat == ENR_ENCOURS) + { + if (inputBuffer == NULL) + { + for (i = 0; i < framesToCalc; i++) + { + *wptr++ = SAMPLE_SILENCE; /* left */ + if (NUM_CHANNELS == 2) *wptr++ = SAMPLE_SILENCE; /* right */ + + } + } + else + { + for (i = 0; i < framesToCalc; i++) + { + *wptr++ = (*rptr++) * Config_Gain; /* left */ + if (NUM_CHANNELS == 2) *wptr++ = *rptr++; /* right */ + } + + } + + data->frameIndex += framesToCalc; + } + + return finished; +} + +/**************************************/ + +void AudioRecordConfig(int g,int ma) +{ + if ((g > 0) && (g < 10)) + { + Config_Gain = g; + } + if ((ma > 0) && (ma < 20000)) + { + Min_Amplitude = ma; + } + +} + + +cRecord::cRecord() +{ + stream = NULL; + data.recordedSamples = NULL; + hdr = NULL; + + hdr = (WaveHeader *)malloc(sizeof(*hdr)); + + wprintf(L"\033[0;31mInitialise sound recorder\033[0;37m\n"); + + InitPortAudio(); + + //making header + hdr = genericWAVHeader(hdr, SAMPLE_RATE, 8 * sizeof(SAMPLE), NUM_CHANNELS); + if (!hdr) + { + wprintf(L"Error allocating WAV header.\n"); + } + + //initialising var + +} + +cRecord::~cRecord() +{ + Pa_Terminate(); + if (data.recordedSamples) /* Sure it is NULL or valid. */ + free(data.recordedSamples); + + if (hdr) free(hdr); +} + +bool cRecord::Start() +{ + PaStreamParameters inputParameters; + PaError err = paNoError; + + inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */ + if (inputParameters.device == paNoDevice) { + wprintf(L"Error: No default input device.\n"); + return 1; + } + inputParameters.channelCount = NUM_CHANNELS; + inputParameters.sampleFormat = PA_SAMPLE_TYPE; + inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency; + inputParameters.hostApiSpecificStreamInfo = NULL; + + /* Record some audio. -------------------------------------------- */ + err = Pa_OpenStream(&stream, &inputParameters, NULL, hdr->sample_rate, paFramesPerBufferUnspecified, paClipOff, recordCallback, &data); + if (err) + { + wprintf(L"Can't open record stream\n"); + return false; + } + + err = Pa_StartStream(stream); + if (err) + { + wprintf(L"Can't start record stream\n"); + return false; + } + + + return true; + +} + +void cRecord::Stop() +{ + if (stream) + { + Pa_CloseStream(stream); + } +} + + + +char * cRecord::RecordFLAC(uint32_t duration,size_t *sizeflac) +{ + + PaError err = paNoError; + + int MaxFrames; + int numSamples; + int numBytes; + int i; + + Initchecker(); + + + + //ok start to recording + data.maxFrameIndex = MaxFrames = duration * hdr->sample_rate; /* Record for a few seconds. */ + data.frameIndex = 0; + numSamples = MaxFrames * NUM_CHANNELS; + numBytes = numSamples * sizeof(SAMPLE); + data.recordedSamples = (SAMPLE *) malloc( numBytes ); /* From now on, recordedSamples is initialised. */ + if(!data.recordedSamples) + { + wprintf(L"Could not allocate record array.\n"); + return NULL; + } + + for(i = 0; i < numSamples; i++) data.recordedSamples[i] = 0; + + if (!(Start())) return NULL; + + + wprintf(L"Now recording!! Please speak into the microphone.\n"); + + _DisplayIcone(MICRO); + + while((err = Pa_IsStreamActive(stream)) == 1) + { + Pa_Sleep(1000); + //wprintf(L"index = %d\n", data.frameIndex); + } + if (err < 0) return NULL; + + Stop(); + + wprintf(L"Nbre de frames = %d\n",data.frameIndex); + if (data.frameIndex < MINFRAME) + { + wprintf(L"Fichier trop petit, nbre frame = %d < %d\n",data.frameIndex,MINFRAME); + return NULL; + } + + if (Enr_etat == ENR_RATE) + { + wprintf(L"Recording cancelled\n"); + return NULL; + } + + +#if 0 + /* Measure maximum peak amplitude. */ + max = 0; + average = 0.0; + for(i = 0; i < numSamples; i++) + { + val = data.recordedSamples[i]; + if( val < 0 ) val = -val; /* ABS */ + if( val > max ) + { + max = val; + } + average += val; + } + + average /= (double)numSamples; +#endif + +#ifdef RAW + { + FILE *fid; + fid = fopen("recorded.raw", "wb"); + if( fid == NULL ) + { + printf("Could not open file."); + err = 1; + } + else + { + fwrite( data.recordedSamples, NUM_CHANNELS * sizeof(SAMPLE), data.frameIndex, fid ); + fclose( fid ); + printf("Wrote data to 'recorded.raw'\n"); + } + } +#elif FILE + { + FILE* fid = fopen(fileName, "wb"); + if(!fid) + { + printf("Could not open file."); + err = 1; + } + else + { + hdr->data_size = data.frameIndex * (NUM_CHANNELS * sizeof(SAMPLE)); + writeWAVHeader(fid, hdr); + fwrite(data.recordedSamples, NUM_CHANNELS * sizeof(SAMPLE), data.frameIndex, fid); + fclose(fid); + } + } +#else + { + char *WavBuffer; + int size; + char * buff_flac; + + hdr->data_size = data.frameIndex * (NUM_CHANNELS * sizeof(SAMPLE)); + size = hdr->data_size + 44; + + //Save wav in buffer + WavBuffer = (char*) malloc (size * sizeof(char)); + writeWAVHeaderBuffer(WavBuffer,hdr); + memcpy(WavBuffer+44,data.recordedSamples,NUM_CHANNELS * sizeof(SAMPLE) * data.frameIndex); + + //convert wav buffer to flac buffer + printf("Sound recorded, convertion to flac\n"); + buff_flac = ConvertWavBufferToFlacBuffer(WavBuffer, NUM_CHANNELS * sizeof(SAMPLE) * data.frameIndex + 44, sizeflac); + + if (WavBuffer) free(WavBuffer); + WavBuffer = NULL; + + return buff_flac; + } +#endif + + return NULL; +} + +/**************************************************************************/ +/****** Wav player fonction ******/ +/**************************************************************************/ + +int bytesPerSample, bitsPerSample; +FILE* wavfile; +int numChannels; + +#define CHECK(x) { if(!(x)) { wprintf(L"%s:%i: failure at: %s\n", __FILE__, __LINE__, #x); return 0; } } + + +std::string freadStr(FILE* f, size_t len) { + std::string s(len, '\0'); + CHECK(fread(&s[0], 1, len, f) == len); + return s; +} + +template +T freadNum(FILE* f) { + T value; + CHECK(fread(&value, sizeof(value), 1, f) == 1); + return value; // no endian-swap for now... WAV is LE anyway... +} + +cPlay::cPlay() +{ + stream = NULL; + ready = false; + + wprintf(L"\033[0;31mInitialise sound output\033[0;37m\n"); + + InitPortAudio(); + + ready = true; + +} + +cPlay::~cPlay() +{ + if (stream) Pa_CloseStream(stream); + Pa_Terminate(); +} + +int cPlay::PlayWav(char * file) +{ + + if (!ready) return false; + + wavfile = fopen(file, "r"); + CHECK(wavfile != NULL); + + CHECK(freadStr(wavfile, 4) == "RIFF"); + uint32_t wavechunksize = freadNum(wavfile); + CHECK(freadStr(wavfile, 4) == "WAVE"); + while (true) { + std::string chunkName = freadStr(wavfile, 4); + uint32_t chunkLen = freadNum(wavfile); + if (chunkName == "fmt ") + readFmtChunk(chunkLen); + else if (chunkName == "data") { + CHECK(sampleRate != 0); + CHECK(numChannels > 0); + CHECK(bytesPerSample > 0); + //wprintf(L"len: %.0f secs\n", double(chunkLen) / sampleRate / numChannels / bytesPerSample); + break; // start playing now + } + else { + // skip chunk + CHECK(fseek(wavfile, chunkLen, SEEK_CUR) == 0); + } + } + + if (!portAudioOpen()) + { + wprintf(L"Can't initialise sound output\n"); + } + + wprintf(L"Playing wav : %s\n",file); + + // wait until stream has finished playing + while (Pa_IsStreamActive(stream) > 0) + { + //usleep(1000); + Pa_Sleep(100); + } + + if (stream) + { + Pa_StopStream(stream); + Pa_CloseStream(stream); + } + + fclose(wavfile); + + return true; +} + +int cPlay_paStreamCallback(const void *input, void *output,unsigned long frameCount,const PaStreamCallbackTimeInfo* timeInfo,PaStreamCallbackFlags statusFlags,void *userData) +{ + size_t numRead = fread(output, bytesPerSample * numChannels, frameCount, wavfile); + output = (uint8_t*)output + numRead * numChannels * bytesPerSample; + frameCount -= numRead; + + if (frameCount > 0) { + memset(output, 0, frameCount * numChannels * bytesPerSample); + return paComplete; + } + + return paContinue; +} + +bool cPlay::portAudioOpen() { + //CHECK(Pa_Initialize() == paNoError); + + PaStreamParameters outputParameters; + + outputParameters.device = Pa_GetDefaultOutputDevice(); + CHECK(outputParameters.device != paNoDevice); + + outputParameters.channelCount = numChannels; + outputParameters.sampleFormat = sampleFormat; + outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;//->defaultHighOutputLatency; + outputParameters.hostApiSpecificStreamInfo = NULL; + + PaError ret = Pa_OpenStream( + &stream, + NULL, // no input + &outputParameters, + sampleRate, + paFramesPerBufferUnspecified, // framesPerBuffer + 0, // flags + &cPlay_paStreamCallback, + NULL //void *userData + ); + + if (ret != paNoError) { + wprintf(L"(SO) Pa_OpenStream failed: (err %i) %s\n", ret, Pa_GetErrorText(ret)); + if (stream) + Pa_CloseStream(stream); + return false; + } + + CHECK(Pa_StartStream(stream) == paNoError); + return true; +} + +int cPlay::readFmtChunk(uint32_t chunkLen) { + CHECK(chunkLen >= 16); + uint16_t fmttag = freadNum(wavfile); // 1: PCM (int). 3: IEEE float + CHECK(fmttag == 1 || fmttag == 3); + numChannels = freadNum(wavfile); + CHECK(numChannels > 0); + //wprintf(L"%i channels\n", numChannels); + sampleRate = freadNum(wavfile); + //wprintf(L"%i Hz\n", sampleRate); + uint32_t byteRate = freadNum(wavfile); + uint16_t blockAlign = freadNum(wavfile); + bitsPerSample = freadNum(wavfile); + bytesPerSample = bitsPerSample / 8; + CHECK(byteRate == sampleRate * numChannels * bytesPerSample); + CHECK(blockAlign == numChannels * bytesPerSample); + if (fmttag == 1 /*PCM*/) { + switch (bitsPerSample) { + case 8: sampleFormat = paInt8; break; + case 16: sampleFormat = paInt16; break; + case 32: sampleFormat = paInt32; break; + default: CHECK(false); + } + //wprintf(L"PCM %ibit int\n", bitsPerSample); + } + else { + CHECK(fmttag == 3 /* IEEE float */); + CHECK(bitsPerSample == 32); + sampleFormat = paFloat32; + //wprintf(L"32bit float\n"); + } + if (chunkLen > 16) { + uint16_t extendedSize = freadNum(wavfile); + CHECK(chunkLen == 18 + extendedSize); + fseek(wavfile, extendedSize, SEEK_CUR); + } + + return true; +} diff --git a/rhonda/applications.cpp b/rhonda/applications.cpp index f543f0e..0e4b69c 100644 --- a/rhonda/applications.cpp +++ b/rhonda/applications.cpp @@ -301,6 +301,37 @@ int GetMeteo(wchar_t *s) } +/*******************************************************************************/ +#ifdef _WIN32 +char * FindFile(char * path, char *f, char *ret) +{ + return NULL; +} +#else +#include + +char * FindFile(char * path, char *f, char *ret) +{ + DIR *d; + struct dirent *dir; + + d = opendir("path"); + if (d) + { + while ((dir = readdir(d)) != NULL) + { + if (strstr(dir->d_name, f)) + { + wprintf(L"%s\n", dir->d_name); + } + } + + closedir(d); + } +} + +#endif + /*******************************************************************************/ int GetDefinition(char *mot, wchar_t * def) diff --git a/rhonda/applications.h b/rhonda/applications.h index 896913d..8239581 100644 --- a/rhonda/applications.h +++ b/rhonda/applications.h @@ -33,5 +33,7 @@ int RSSMonitor(); int GetFilmCinema(wchar_t *s,int l); +char * FindFile(char * path, char *f, char *ret); + void Savedata(void); diff --git a/rhonda/audio.cpp b/rhonda/audio.cpp index 0894499..49ce927 100644 --- a/rhonda/audio.cpp +++ b/rhonda/audio.cpp @@ -617,7 +617,7 @@ void cRecord::Stop() -int cRecord::RecordFLAC(const char *fileName, uint32_t duration) +char * cRecord::RecordFLAC(uint32_t duration,size_t *sizeflac) { PaError err = paNoError; @@ -640,12 +640,12 @@ int cRecord::RecordFLAC(const char *fileName, uint32_t duration) if(!data.recordedSamples) { wprintf(L"Could not allocate record array.\n"); - return 0; + return NULL; } for(i = 0; i < numSamples; i++) data.recordedSamples[i] = 0; - if (!(Start())) return 0; + if (!(Start())) return NULL; wprintf(L"Now recording!! Please speak into the microphone.\n"); @@ -657,7 +657,7 @@ int cRecord::RecordFLAC(const char *fileName, uint32_t duration) Pa_Sleep(1000); //wprintf(L"index = %d\n", data.frameIndex); } - if (err < 0) return 0; + if (err < 0) return NULL; Stop(); @@ -665,13 +665,13 @@ int cRecord::RecordFLAC(const char *fileName, uint32_t duration) if (data.frameIndex < MINFRAME) { wprintf(L"Fichier trop petit, nbre frame = %d < %d\n",data.frameIndex,MINFRAME); - return 0; + return NULL; } if (Enr_etat == ENR_RATE) { wprintf(L"Recording cancelled\n"); - return 0; + return NULL; } @@ -729,22 +729,28 @@ int cRecord::RecordFLAC(const char *fileName, uint32_t duration) { char *WavBuffer; int size; + char * buff_flac; hdr->data_size = data.frameIndex * (NUM_CHANNELS * sizeof(SAMPLE)); size = hdr->data_size + 44; - //convert buffer data wav to flac + //Save wav in buffer WavBuffer = (char*) malloc (size * sizeof(char)); writeWAVHeaderBuffer(WavBuffer,hdr); memcpy(WavBuffer+44,data.recordedSamples,NUM_CHANNELS * sizeof(SAMPLE) * data.frameIndex); + //convert wav buffer to flac buffer printf("Sound recorded, convertion to flac\n"); - ConvertFlacBuffer(WavBuffer,size, fileName); + buff_flac = ConvertWavBufferToFlacBuffer(WavBuffer, NUM_CHANNELS * sizeof(SAMPLE) * data.frameIndex + 44, sizeflac); + if (WavBuffer) free(WavBuffer); + WavBuffer = NULL; + + return buff_flac; } #endif - return 1; + return NULL; } /**************************************************************************/ diff --git a/rhonda/audio.h b/rhonda/audio.h index 4aef987..8555c14 100644 --- a/rhonda/audio.h +++ b/rhonda/audio.h @@ -130,7 +130,7 @@ class cRecord cRecord(); // M�thodes - int RecordFLAC(const char *fileName, uint32_t duration); + char * RecordFLAC(uint32_t duration, size_t *size); void Stop(void); bool Start(void); diff --git a/rhonda/config.xml b/rhonda/config.xml index 2e94d6a..587ced1 100644 --- a/rhonda/config.xml +++ b/rhonda/config.xml @@ -47,7 +47,7 @@ - + @@ -83,6 +83,7 @@ + diff --git a/rhonda/flac.c b/rhonda/flac.c index 2ed3855..2a07fe9 100644 --- a/rhonda/flac.c +++ b/rhonda/flac.c @@ -46,23 +46,159 @@ static unsigned total_samples = 0; /* can use a 32-bit number due to WAVE size l static FLAC__byte buffer[READSIZE/*samples*/ * 2/*bytes_per_sample*/ * 1/*channels*/]; /* we read the WAVE data into here */ static FLAC__int32 pcm[READSIZE/*samples*/ * 1/*channels*/]; + +/******************************************************************/ + +typedef struct sprec_encoder_state +{ + char *buf; + size_t length; +} sprec_encoder_state; + +static FLAC__StreamEncoderWriteStatus flac_write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data ) +{ + sprec_encoder_state *flac_data = client_data; + + flac_data->buf = realloc(flac_data->buf, flac_data->length + bytes); + memcpy(flac_data->buf + flac_data->length, buffer, bytes); + flac_data->length += bytes; + + return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; +} + + + +char * ConvertWavBufferToFlacBuffer(char *buff_wave, size_t size_wave,size_t *size) +{ + + FLAC__bool ok = true; + FLAC__StreamEncoder *encoder = 0; + FLAC__StreamEncoderInitStatus init_status; + + unsigned sample_rate = 0; + unsigned channels = 0; + unsigned bps = 0; + + sprec_encoder_state flac_data; + flac_data.buf = NULL; + flac_data.length = 0; + + + if (size_wave < 44) + { + wprintf(L"ERROR: Buffer problem\n"); + } + memcpy(buffer, buff_wave, 44); + size_wave -= 44; + buff_wave += 44; + + sample_rate = ((((((unsigned)buffer[27] << 8) | buffer[26]) << 8) | buffer[25]) << 8) | buffer[24]; + channels = 1; + bps = 16; + + total_samples = (((((((unsigned)buffer[43] << 8) | buffer[42]) << 8) | buffer[41]) << 8) | buffer[40]) / 2;// par 2 au lieu de 4 + /* allocate the encoder */ + if ((encoder = FLAC__stream_encoder_new()) == NULL) { + wprintf(L"ERROR: allocating encoder\n"); + return 0; + } + + + + //fprintf(stderr, "Total samples %d \n",total_samples); + ok &= FLAC__stream_encoder_set_verify(encoder, true); + ok &= FLAC__stream_encoder_set_compression_level(encoder, 5); + ok &= FLAC__stream_encoder_set_channels(encoder, channels); + ok &= FLAC__stream_encoder_set_bits_per_sample(encoder, bps); + ok &= FLAC__stream_encoder_set_sample_rate(encoder, sample_rate); + ok &= FLAC__stream_encoder_set_total_samples_estimate(encoder, total_samples); + + + ok = FLAC__stream_encoder_init_stream( + encoder, + flac_write_callback, + NULL, // seek() stream + NULL, // tell() stream + NULL, // metadata writer + &flac_data + ); + + if (ok != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { + fprintf(stderr, "ERROR: initializing encoder: %s\n", FLAC__StreamEncoderInitStatusString[init_status]); + ok = false; + + free(flac_data.buf); + FLAC__stream_encoder_delete(encoder); + return NULL; + } + ok = true; + + /* read blocks of samples from WAVE file and feed to encoder */ + if (ok) { + size_t left = (size_t)total_samples; + while (ok && left) { + size_t need = (left>READSIZE ? (size_t)READSIZE : (size_t)left); + if (size_wave < (unsigned long)(channels*(bps / 8) * need)) { + fprintf(stderr, "ERROR: reading from WAVE file\n"); + ok = false; + } + else { + /* convert the packed little-endian 16-bit PCM samples from WAVE into an interleaved FLAC__int32 buffer for libFLAC */ + size_t i; + + memcpy(buffer, buff_wave, channels*(bps / 8) * need); + size_wave -= channels*(bps / 8) * need; + buff_wave += channels*(bps / 8) * need; + + + for (i = 0; i < need*channels; i++) { + /* inefficient but simple and works on big- or little-endian machines */ + pcm[i] = (FLAC__int32)(((FLAC__int16)(FLAC__int8)buffer[2 * i + 1] << 8) | (FLAC__int16)buffer[2 * i]); + } + /* feed samples to encoder */ + ok = FLAC__stream_encoder_process_interleaved(encoder, pcm, need); + } + left -= need; + } + } + + ok &= FLAC__stream_encoder_finish(encoder); + + if (!ok) + { + wprintf(L"encoding: %s\n", ok ? L"succeeded" : L"FAILED"); + wprintf(L"state: %s\n", FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder)]); + } + FLAC__stream_encoder_delete(encoder); + + #if 0 + //To make file + { + FILE *fout; + fout = fopen("test2.flac", "wb"); + fwrite(flac_data.buf, 1, flac_data.length, fout); + fclose(fout); + } +#endif + + + *size = flac_data.length; + + return flac_data.buf; + +} -int ConvertFlac(char * sour, char * dest) +int ConvertWaveToFlacBuffer(char * sour, long size, const char * dest) { FLAC__bool ok = true; FLAC__StreamEncoder *encoder = 0; FLAC__StreamEncoderInitStatus init_status; - FILE *fin; + unsigned sample_rate = 0; unsigned channels = 0; unsigned bps = 0; - if((fin = fopen(sour, "rb")) == NULL) { - fprintf(stderr, "ERROR: opening %s for input\n", sour); - return 0; - } - /* read wav header and validate it */ /* if( @@ -76,12 +212,13 @@ int ConvertFlac(char * sour, char * dest) return 1; } */ - - if (fread(buffer, 1, 44, fin) != 44) + if (size < 44) { - fprintf(stderr, "ERROR: opening %s for read\n", sour); - return 0; + wprintf(L"ERROR: Buffer problem\n"); } + memcpy(buffer,sour,44); + size -= 44; + sour += 44; sample_rate = ((((((unsigned)buffer[27] << 8) | buffer[26]) << 8) | buffer[25]) << 8) | buffer[24]; channels = 1; @@ -90,8 +227,7 @@ int ConvertFlac(char * sour, char * dest) total_samples = (((((((unsigned)buffer[43] << 8) | buffer[42]) << 8) | buffer[41]) << 8) | buffer[40]) / 2;// par 2 au lieu de 4 /* allocate the encoder */ if((encoder = FLAC__stream_encoder_new()) == NULL) { - fprintf(stderr, "ERROR: allocating encoder\n"); - fclose(fin); + wprintf(L"ERROR: allocating encoder\n"); return 0; } @@ -109,23 +245,29 @@ int ConvertFlac(char * sour, char * dest) if(ok) { init_status = FLAC__stream_encoder_init_file(encoder, dest, progress_callback, /*client_data=*/NULL); if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { - fprintf(stderr, "ERROR: initializing encoder: %s\n", FLAC__StreamEncoderInitStatusString[init_status]); + wprintf(L"ERROR: initializing encoder: %s\n", FLAC__StreamEncoderInitStatusString[init_status]); ok = false; } } - /* read blocks of samples from WAVE file and feed to encoder */ + /* read blocks of samples from WAVE file and feed to encoder */memcpy(buffer,sour,44); if(ok) { size_t left = (size_t)total_samples; while(ok && left) { size_t need = (left>READSIZE? (size_t)READSIZE : (size_t)left); - if(fread(buffer, channels*(bps/8), need, fin) != need) { - fprintf(stderr, "ERROR: reading from WAVE file\n"); + //if(fread(buffer, channels*(bps/8), need, fin) != need) { + if (size < (long)(channels*(bps/8) * need )) { + wprintf(L"ERROR: reading from buffer\n"); ok = false; } else { - /* convert the packed little-endian 16-bit PCM samples from WAVE into an interleaved FLAC__int32 buffer for libFLAC */ size_t i; + + memcpy(buffer,sour, channels*(bps/8) * need); + size -= channels*(bps/8) * need; + sour += channels*(bps/8) * need; + + /* convert the packed little-endian 16-bit PCM samples from WAVE into an interleaved FLAC__int32 buffer for libFLAC */ for(i = 0; i < need*channels; i++) { /* inefficient but simple and works on big- or little-endian machines */ pcm[i] = (FLAC__int32)(((FLAC__int16)(FLAC__int8)buffer[2*i+1] << 8) | (FLAC__int16)buffer[2*i]); @@ -139,26 +281,31 @@ int ConvertFlac(char * sour, char * dest) ok &= FLAC__stream_encoder_finish(encoder); - fprintf(stderr, "encoding: %s\n", ok? "succeeded" : "FAILED"); - fprintf(stderr, "state: %s\n", FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder)]); + if (!ok) + { + wprintf(L"encoding: %s\n", ok ? L"succeeded" : L"FAILED"); + wprintf(L"state: %s\n", FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder)]); + } FLAC__stream_encoder_delete(encoder); - fclose(fin); return 1; } -#endif -int ConvertFlacBuffer(char * sour, long size, const char * dest) +#if 0 +int ConvertWaveFileToFlacFile(char * sour, char * dest) { FLAC__bool ok = true; FLAC__StreamEncoder *encoder = 0; FLAC__StreamEncoderInitStatus init_status; - + FILE *fin; unsigned sample_rate = 0; unsigned channels = 0; unsigned bps = 0; - + if ((fin = fopen(sour, "rb")) == NULL) { + fprintf(stderr, "ERROR: opening %s for input\n", sour); + return 0; + } /* read wav header and validate it */ /* if( @@ -172,65 +319,51 @@ int ConvertFlacBuffer(char * sour, long size, const char * dest) return 1; } */ - if (size < 44) + if (fread(buffer, 1, 44, fin) != 44) { - wprintf(L"ERROR: Buffer problem\n"); + fprintf(stderr, "ERROR: opening %s for read\n", sour); + return 0; } - memcpy(buffer,sour,44); - size -= 44; - sour += 44; - sample_rate = ((((((unsigned)buffer[27] << 8) | buffer[26]) << 8) | buffer[25]) << 8) | buffer[24]; channels = 1; bps = 16; - total_samples = (((((((unsigned)buffer[43] << 8) | buffer[42]) << 8) | buffer[41]) << 8) | buffer[40]) / 2;// par 2 au lieu de 4 /* allocate the encoder */ - if((encoder = FLAC__stream_encoder_new()) == NULL) { - wprintf(L"ERROR: allocating encoder\n"); + if ((encoder = FLAC__stream_encoder_new()) == NULL) { + fprintf(stderr, "ERROR: allocating encoder\n"); + fclose(fin); return 0; } - //fprintf(stderr, "Total samples %d \n",total_samples); - ok &= FLAC__stream_encoder_set_verify(encoder, true); ok &= FLAC__stream_encoder_set_compression_level(encoder, 5); ok &= FLAC__stream_encoder_set_channels(encoder, channels); ok &= FLAC__stream_encoder_set_bits_per_sample(encoder, bps); ok &= FLAC__stream_encoder_set_sample_rate(encoder, sample_rate); ok &= FLAC__stream_encoder_set_total_samples_estimate(encoder, total_samples); - - /* initialize encoder */ - if(ok) { + if (ok) { init_status = FLAC__stream_encoder_init_file(encoder, dest, progress_callback, /*client_data=*/NULL); - if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { - wprintf(L"ERROR: initializing encoder: %s\n", FLAC__StreamEncoderInitStatusString[init_status]); + if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { + fprintf(stderr, "ERROR: initializing encoder: %s\n", FLAC__StreamEncoderInitStatusString[init_status]); ok = false; } } - - /* read blocks of samples from WAVE file and feed to encoder */memcpy(buffer,sour,44); - if(ok) { + /* read blocks of samples from WAVE file and feed to encoder */ + if (ok) { size_t left = (size_t)total_samples; - while(ok && left) { - size_t need = (left>READSIZE? (size_t)READSIZE : (size_t)left); - //if(fread(buffer, channels*(bps/8), need, fin) != need) { - if (size < (long)(channels*(bps/8) * need )) { - wprintf(L"ERROR: reading from buffer\n"); + while (ok && left) { + size_t need = (left>READSIZE ? (size_t)READSIZE : (size_t)left); + if (fread(buffer, channels*(bps / 8), need, fin) != need) { + fprintf(stderr, "ERROR: reading from WAVE file\n"); ok = false; } else { - size_t i; - - memcpy(buffer,sour, channels*(bps/8) * need); - size -= channels*(bps/8) * need; - sour += channels*(bps/8) * need; - /* convert the packed little-endian 16-bit PCM samples from WAVE into an interleaved FLAC__int32 buffer for libFLAC */ - for(i = 0; i < need*channels; i++) { + size_t i; + for (i = 0; i < need*channels; i++) { /* inefficient but simple and works on big- or little-endian machines */ - pcm[i] = (FLAC__int32)(((FLAC__int16)(FLAC__int8)buffer[2*i+1] << 8) | (FLAC__int16)buffer[2*i]); + pcm[i] = (FLAC__int32)(((FLAC__int16)(FLAC__int8)buffer[2 * i + 1] << 8) | (FLAC__int16)buffer[2 * i]); } /* feed samples to encoder */ ok = FLAC__stream_encoder_process_interleaved(encoder, pcm, need); @@ -238,19 +371,14 @@ int ConvertFlacBuffer(char * sour, long size, const char * dest) left -= need; } } - ok &= FLAC__stream_encoder_finish(encoder); - - if (!ok) - { - wprintf(L"encoding: %s\n", ok ? L"succeeded" : L"FAILED"); - wprintf(L"state: %s\n", FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder)]); - } - + fprintf(stderr, "encoding: %s\n", ok ? "succeeded" : "FAILED"); + fprintf(stderr, "state: %s\n", FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder)]); FLAC__stream_encoder_delete(encoder); - + fclose(fin); return 1; } +#endif void progress_callback(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data) diff --git a/rhonda/flac.h b/rhonda/flac.h index 7f4d75c..8ae1296 100644 --- a/rhonda/flac.h +++ b/rhonda/flac.h @@ -6,8 +6,9 @@ extern "C" { #endif -int ConvertFlac(char * sour, char * dest); -int ConvertFlacBuffer(char * sour, long size,const char * dest); +//int ConvertWaveFileToFlacFile(char * sour, char * dest); +int ConvertWaveToFlacBuffer(char * sour, long size, const char * dest); +char *ConvertWavBufferToFlacBuffer(char *buff_wave, size_t size_wave, size_t *size); #ifdef __cplusplus } diff --git a/rhonda/prog.cpp b/rhonda/prog.cpp index 565841f..d72b04e 100644 --- a/rhonda/prog.cpp +++ b/rhonda/prog.cpp @@ -10,7 +10,7 @@ No comment yet #endif /* Special options*/ -#define DEBUG +//#define DEBUG #define SNOWBOY @@ -73,9 +73,9 @@ class cRecord cRecord; #ifdef _WIN32 #include -char RamTmpFile[] = "testfile.flac"; + #else -char RamTmpFile[] = "/dev/shm/testfile.flac"; + #endif @@ -95,6 +95,9 @@ int main(int argc, char* argv[]) { bool HotWord = false; + size_t size_flac; + char *buff_flac = NULL; + Resultat[0] = '\0'; /************************************************/ @@ -173,7 +176,8 @@ int main(int argc, char* argv[]) { //TranslateGoggle("vvv", Resultat); //TestTransmitter(0,12325261,1,"on"); //parle(L"test m\u00e9t\u00e9o"); - cTraitement.traite("quelle est la reponse au question sur la vie l univers"); + + cTraitement.traite("recherche le fichier test"); //CheckGitHubNotification(); @@ -289,16 +293,21 @@ int main(int argc, char* argv[]) { wprintf(L"Recording\n"); - /* /dev/shm is ram folder */ - err = cRecord.RecordFLAC(RamTmpFile, 5); + /* Recording sound and convert it to flac file */ + buff_flac = cRecord.RecordFLAC(5,&size_flac); //err = 0; - if (err != 0) + if (buff_flac != NULL) { + SP(); wprintf(L"Send to google\n"); cMatrixLed.DisplayIcone(SABLIER); - err = TranslateGoggle(RamTmpFile, Resultat); + + err = TranslateGoggle(buff_flac, size_flac, Resultat); + + free(buff_flac); + buff_flac = NULL; SP(); wprintf(L"Resultat with a score of (%d) : ", err); diff --git a/rhonda/traitement.cpp b/rhonda/traitement.cpp index 2b4ecab..51a765b 100644 --- a/rhonda/traitement.cpp +++ b/rhonda/traitement.cpp @@ -4,13 +4,13 @@ #include #include + #include "traitement.h" #include "hardware.h" #include "fonction.h" #include "applications.h" #include "prog.h" - //#define DEBUG_OUPUT /***************************************************************************/ @@ -445,6 +445,32 @@ void cTraitement::ManageAction(char *c) { Exit(); } + else if (strcmp("FINDFILE", Key) == 0) + { + char file[50]; + + file[49] = '\0'; + /* fichier a recuperer */ + if (GetWord(" ([a-zA-Z]+$)", commande, file, 49)) + { + char file2[50]; + file2[0] = '\0'; + FindFile("/home/pi", file, file2); + if ((file2) && (strlen(file2) > 1)) + { + LastResult = file2; + parle(L"J'ai trouv\u00e9 le fichier, j'en fais quoi ?"); + } + else + { + parle(L"Je n'ai pas trouv\u00e9 le fichier"); + } + } + else + { + parle(L"Je n'ai pas compris le fichier a chercher"); + } + } else { parle(GetCommonString(1)); // = "je n'ai pas compris" ? diff --git a/rhonda/traitement.h b/rhonda/traitement.h index 8355c41..54647ad 100644 --- a/rhonda/traitement.h +++ b/rhonda/traitement.h @@ -31,6 +31,7 @@ class cTraitement // Attributs char commande[255]; int comptcommande; + std::string LastResult; int NbreCommand; char **CommandeL; diff --git a/rhonda/translategoogle.cpp b/rhonda/translategoogle.cpp index b042490..4515131 100644 --- a/rhonda/translategoogle.cpp +++ b/rhonda/translategoogle.cpp @@ -96,7 +96,7 @@ static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp) return 0; /* no more data left to deliver */ } -int TranslateGoggle(char *filename,char *resultat) +int TranslateGoggle(char *Buff_flac, size_t s, char *resultat) { CURL *curl; // curl handle CURLcode res; @@ -112,11 +112,8 @@ int TranslateGoggle(char *filename,char *resultat) curl = curl_easy_init(); if (curl) { - FILE *file; - int fileSize = 0; struct curl_slist *chunk = NULL; - char *audioData; struct WriteThis pooh; char sizeHeader[255]; @@ -129,27 +126,18 @@ int TranslateGoggle(char *filename,char *resultat) apiurl = apiurl + "&key=" + GoogleApiKey; - file = fopen(filename, "r"); - fseek(file, 0, SEEK_END); - fileSize = ftell(file); - fseek(file, 0, SEEK_SET); + if (s == 0) return 0; - if (fileSize == 0) return 0; - - wprintf(L"File size %d\n",fileSize); - audioData = (char*)malloc(fileSize); + wprintf(L"File size %d Kb\n",s/1000); //chunk = curl_slist_append(chunk, "Content-Type: audio/l16; rate=44100"); chunk = curl_slist_append(chunk, "Content-Type: audio/x-flac; rate=44100"); - fread(audioData, fileSize, 1, file); - fclose(file); - - pooh.readptr = audioData; - pooh.sizeleft = fileSize; - pooh.totalsize = fileSize; + pooh.readptr = Buff_flac; + pooh.sizeleft = s; + pooh.totalsize = s; - sprintf(sizeHeader,"Content-Length: %d",fileSize); + sprintf(sizeHeader,"Content-Length: %d",s); chunk = curl_slist_append(chunk, sizeHeader); //disalbe Expect: 100-continue @@ -174,7 +162,7 @@ int TranslateGoggle(char *filename,char *resultat) res = curl_easy_perform(curl); - wprintf(L"Resultat From Google\n %s \n",data.memory); + Mywprintf(L"Resultat From Google\n %s \n",data.memory); { @@ -186,20 +174,20 @@ int TranslateGoggle(char *filename,char *resultat) if (slre_match("{\"transcript\":\"([^\"]+)\",\"confidence\":([0-9\.]+)}", data.memory, data.size, caps, 2, 0) > 0) { char *tmp2; + int l; strncpy(resultat, caps[0].ptr, caps[0].len); - strncpy(resultat + caps[0].len, "\0", 1); + resultat[caps[0].len] = '\0'; - tmp2 = (char *)malloc((caps[1].len + 1) * sizeof(char)); - strncpy(tmp2, caps[1].ptr, caps[1].len); - strncpy(tmp2 + caps[1].len, "\0", 1); - if (caps[1].len > 4) - { - tmp2 += 2; - tmp2[2] = '\0'; - } + l = caps[1].len; + if (l > 4) l = 4; + tmp2 = (char *)malloc((l + 1) * sizeof(char)); + strncpy(tmp2, caps[1].ptr + 2, l - 2); + tmp2[l - 2] = '\0'; bestscore = 1 + (atoi(tmp2)); + + free(tmp2); } else diff --git a/rhonda/translategoogle.h b/rhonda/translategoogle.h index a406968..a7ca8c5 100644 --- a/rhonda/translategoogle.h +++ b/rhonda/translategoogle.h @@ -2,6 +2,6 @@ #include -int TranslateGoggle(char *filename,char *resultat); +int TranslateGoggle(char *buff, size_t s, char *resultat); void SetGoogleApiKey(char *s);