From f17a2bb6dce820973a821ec7a20e8dce737d5416 Mon Sep 17 00:00:00 2001 From: Edouard Dupin Date: Thu, 28 Jun 2012 18:28:53 +0200 Subject: [PATCH] Add wav decoder file (simple and not compleate)==> but it work for basic test --- Sources/libewol/ewol/Audio/audio.cpp | 44 ++-- Sources/libewol/ewol/Audio/decWav.cpp | 311 ++++++++++++++++++++++++++ Sources/libewol/ewol/Audio/decWav.h | 40 ++++ Sources/libewol/ewol/base/gui.cpp | 30 ++- Sources/libewol/file.mk | 3 +- 5 files changed, 410 insertions(+), 18 deletions(-) create mode 100644 Sources/libewol/ewol/Audio/decWav.cpp create mode 100644 Sources/libewol/ewol/Audio/decWav.h diff --git a/Sources/libewol/ewol/Audio/audio.cpp b/Sources/libewol/ewol/Audio/audio.cpp index 412c5996..04abb33b 100644 --- a/Sources/libewol/ewol/Audio/audio.cpp +++ b/Sources/libewol/ewol/Audio/audio.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -89,6 +90,10 @@ void ewol::audio::GetData(int16_t * bufferInterlace, int32_t nbSample, int32_t n ewol::audio::music::GetData(bufferInterlace, nbSample, nbChannels); // add effects : ewol::audio::effects::GetData(bufferInterlace, nbSample, nbChannels); + static FILE * plop = fopen("/home/edupin/testFile48khzstereo.raw", "w"); + if (plop!=NULL) { + fwrite(bufferInterlace, sizeof(int16_t), nbSample*nbChannels, plop); + } } @@ -199,7 +204,20 @@ void ewol::audio::music::MuteSet(bool newMute) void ewol::audio::music::GetData(int16_t * bufferInterlace, int32_t nbSample, int32_t nbChannels) { - + /*static int32_t maxValue = 0; + static float angle = 0; + maxValue +=10; + if (maxValue > 16000) { + maxValue = 0; + } + for (int iii = 0; iii=360) { + angle -= 360.0; + } + }*/ } @@ -214,20 +232,9 @@ class EffectsLoaded { { m_file = file; m_requestedTime = 1; - m_nbSamples = 6000; // 0.25s - m_data = (int16_t*)malloc(sizeof(int16_t)*m_nbSamples); - if (NULL == m_data) { - EWOL_CRITICAL("MEM allocation error ..."); - return; - } - float tmp_angle = 0.0; - //int32_t test1 = M_PI / (50.0*m_file.Size()); - for (int iii = 0; iii=360) { - tmp_angle -= 360.0; - } + m_data = ewol::audio::wav::LoadData(file, 1, 48000, m_nbSamples); + if (m_data == NULL) { + // write an error ... } } etk::UString m_file; @@ -250,6 +257,10 @@ class RequestPlay { if (true==m_freeSlot) { return; } + if (m_effect->m_data == NULL) { + m_freeSlot = true; + return; + } int32_t processTimeMax = etk_min(nbSample, m_effect->m_nbSamples - m_playTime); processTimeMax = etk_max(0, processTimeMax); int16_t * pointer = bufferInterlace; @@ -259,7 +270,7 @@ class RequestPlay { // TODO : Set volume and spacialisation ... for (int32_t jjj=0; jjj has been removed"); return; } + EWOL_ERROR("effect play : " << effectId ); // try to find an empty slot : for (int32_t iii=0; iiiIsFree()) { diff --git a/Sources/libewol/ewol/Audio/decWav.cpp b/Sources/libewol/ewol/Audio/decWav.cpp new file mode 100644 index 00000000..eaa97880 --- /dev/null +++ b/Sources/libewol/ewol/Audio/decWav.cpp @@ -0,0 +1,311 @@ +/** + ******************************************************************************* + * @file ewol/Audio/decWav.cpp + * @brief basic ewol Wav decoder (sources) + * @author Edouard DUPIN + * @date 28/06/2012 + * @par Project + * ewol + * + * @par Copyright + * Copyright 2011 Edouard DUPIN, all right reserved + * + * This software is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY. + * + * Licence summary : + * You can modify and redistribute the sources code and binaries. + * You can send me the bug-fix + * + * Term of the licence in in the file licence.txt. + * + ******************************************************************************* + */ + +#include +#include +#include +#include +#include + + +typedef struct { + char riffTag[4]; //!< 00-03 + uint32_t size; //!< 04-07 + char waveTag[4]; //!< 08-0b + char fmtTag[4]; //!< 0c-0f + uint32_t waveFormatSize; //!< 10-13 + struct { + uint16_t type; //!< 00-01 + uint16_t channelCount; //!< 02-03 + uint32_t samplesPerSec; //!< 04-07 + uint32_t bytesPerSec; //!< 08-0b + uint16_t bytesPerFrame; //!< 0c-0d + uint16_t bitsPerSample; //!< 0e-0f + }waveFormat; //!< 14-23 + char dataTag[4]; //!< 24-27 + uint32_t dataSize; //!< 28-2b +}waveHeader; + + +#define CONVERT_UINT32(littleEndien,data) (littleEndien)?(((uint32_t)((uint8_t*)data)[0] | (uint32_t)((uint8_t*)data)[1] << 8 | (uint32_t)((uint8_t*)data)[2] << 16 | (uint32_t)((uint8_t*)data)[3] << 24)): \ + (((uint32_t)((uint8_t*)data)[3] | (uint32_t)((uint8_t*)data)[2] << 8 | (uint32_t)((uint8_t*)data)[1] << 16 | (uint32_t)((uint8_t*)data)[0] << 24)) + +#define CONVERT_INT32(littleEndien,data) (littleEndien)?(((int32_t)((uint8_t*)data)[0] | (int32_t)((uint8_t*)data)[1] << 8 | (int32_t)((uint8_t*)data)[2] << 16 | (int32_t)((int8_t*)data)[3] << 24)): \ + (((int32_t)((uint8_t*)data)[3] | (int32_t)((uint8_t*)data)[2] << 8 | (int32_t)((uint8_t*)data)[1] << 16 | (int32_t)((int8_t*)data)[0] << 24)) + +#define CONVERT_UINT24(littleEndien,data) (littleEndien)?(((uint32_t)((uint8_t*)data)[0]<<8 | (uint32_t)((uint8_t*)data)[1] << 16 | (uint32_t)((uint8_t*)data)[2] << 24)): \ + (((uint32_t)((uint8_t*)data)[2]<<8 | (uint32_t)((uint8_t*)data)[1] << 16 | (uint32_t)((uint8_t*)data)[0] << 24)) + +#define CONVERT_INT24(littleEndien,data) (littleEndien)?(((int32_t)((uint8_t*)data)[0]<<8 | (int32_t)((uint8_t*)data)[1] << 16 | (int32_t)((int8_t*)data)[2] << 24)): \ + (((int32_t)((uint8_t*)data)[2]<<8 | (int32_t)((uint8_t*)data)[1] << 16 | (int32_t)((int8_t*)data)[0] << 24)) + +#define CONVERT_UINT16(littleEndien,data) (littleEndien)?(((uint16_t)((uint8_t*)data)[0] | (uint16_t)((uint8_t*)data)[1] << 8)): \ + (((uint16_t)((uint8_t*)data)[1] | (uint16_t)((uint8_t*)data)[0] << 8)) + +#define CONVERT_INT16(littleEndien,data) (littleEndien)?(((int16_t)((uint8_t*)data)[0] | (int16_t)((int8_t*)data)[1] << 8)): \ + (((int16_t)((uint8_t*)data)[1] | (int16_t)((int8_t*)data)[0] << 8)) + +#define COMPR_PCM (1) +#define COMPR_MADPCM (2) +#define COMPR_ALAW (6) +#define COMPR_MULAW (7) +#define COMPR_ADPCM (17) +#define COMPR_YADPCM (20) +#define COMPR_GSM (49) +#define COMPR_G721 (64) +#define COMPR_MPEG (80) + +int16_t * ewol::audio::wav::LoadData(etk::UString filename, int8_t nbChan, int32_t frequency, int32_t & nbSampleOut) +{ + nbSampleOut = 0; + waveHeader myHeader; + memset(&myHeader, 0, sizeof(waveHeader)); + etk::File fileAccess(filename, etk::FILE_TYPE_DATA); + // Start loading the XML : + EWOL_DEBUG("open file (WAV) \"" << fileAccess << "\""); + + if (false == fileAccess.Exist()) { + EWOL_ERROR("File Does not exist : \"" << fileAccess << "\""); + return NULL; + } + int32_t fileSize = fileAccess.Size(); + if (0==fileSize) { + EWOL_ERROR("This file is empty : \"" << fileAccess << "\""); + return NULL; + } + if (false == fileAccess.fOpenRead()) { + EWOL_ERROR("Can not open the file : \"" << fileAccess << "\""); + return NULL; + } + // try to find endienness : + if (fileSize < sizeof(waveHeader)) { + EWOL_ERROR("File : \"" << fileAccess << "\" ==> has not enouth data inside might be minumum of " << sizeof(waveHeader)); + return NULL; + } + // ---------------------------------------------- + // read the header : + // ---------------------------------------------- + if (fileAccess.fRead(&myHeader.riffTag, 1, 4)!=4) { + EWOL_ERROR("Can not 4 element in the file : \"" << fileAccess << "\""); + return NULL; + } + bool littleEndien = false; + if( myHeader.riffTag[0] == 'R' + && myHeader.riffTag[1] == 'I' + && myHeader.riffTag[2] == 'F' + && (myHeader.riffTag[3] == 'F' || myHeader.riffTag[3] == 'X') ) { + if (myHeader.riffTag[3] == 'F' ) { + littleEndien = true; + } + } else { + EWOL_ERROR("file: \"" << fileAccess << "\" Does not start with \"RIF\" " ); + return NULL; + } + // get the data size : + unsigned char tmpData[32]; + if (fileAccess.fRead(tmpData, 1, 4)!=4) { + EWOL_ERROR("Can not 4 element in the file : \"" << fileAccess << "\""); + return NULL; + } + myHeader.size = CONVERT_UINT32(littleEndien, tmpData); + + // get the data size : + if (fileAccess.fRead(&myHeader.waveTag, 1, 4)!=4) { + EWOL_ERROR("Can not 4 element in the file : \"" << fileAccess << "\""); + return NULL; + } + if( myHeader.waveTag[0] != 'W' + || myHeader.waveTag[1] != 'A' + || myHeader.waveTag[2] != 'V' + || myHeader.waveTag[3] != 'E' ) { + EWOL_ERROR("file: \"" << fileAccess << "\" This is not a wave file " << myHeader.waveTag[0] << myHeader.waveTag[1] << myHeader.waveTag[2] << myHeader.waveTag[3] ); + return NULL; + } + + // get the data size : + if (fileAccess.fRead(&myHeader.fmtTag, 1, 4)!=4) { + EWOL_ERROR("Can not 4 element in the file : \"" << fileAccess << "\""); + return NULL; + } + if( myHeader.fmtTag[0] != 'f' + || myHeader.fmtTag[1] != 'm' + || myHeader.fmtTag[2] != 't' + || myHeader.fmtTag[3] != ' ' ) { + EWOL_ERROR("file: \"" << fileAccess << "\" header error ..." << myHeader.fmtTag[0] << myHeader.fmtTag[1] << myHeader.fmtTag[2] << myHeader.fmtTag[3]); + return NULL; + } + // get the data size : + if (fileAccess.fRead(tmpData, 1, 4)!=4) { + EWOL_ERROR("Can not 4 element in the file : \"" << fileAccess << "\""); + return NULL; + } + myHeader.waveFormatSize = CONVERT_UINT32(littleEndien, tmpData); + + if (myHeader.waveFormatSize != 16) { + EWOL_ERROR("file : \"" << fileAccess << "\" ==> header error ..."); + return NULL; + } + if (fileAccess.fRead(tmpData, 1, 16)!=16) { + EWOL_ERROR("Can not 16 element in the file : \"" << fileAccess << "\""); + return NULL; + } + unsigned char * tmppp = tmpData; + myHeader.waveFormat.type = CONVERT_UINT16(littleEndien, tmppp); + tmppp += 2; + myHeader.waveFormat.channelCount = CONVERT_UINT16(littleEndien, tmppp); + tmppp += 2; + myHeader.waveFormat.samplesPerSec = CONVERT_UINT32(littleEndien, tmppp); + tmppp += 4; + myHeader.waveFormat.bytesPerSec = CONVERT_UINT32(littleEndien, tmppp); + tmppp += 4; + myHeader.waveFormat.bytesPerFrame = CONVERT_UINT16(littleEndien, tmppp); + tmppp += 2; + myHeader.waveFormat.bitsPerSample = CONVERT_UINT16(littleEndien, tmppp); + EWOL_DEBUG("audio properties : "); + EWOL_DEBUG(" type : " << myHeader.waveFormat.type); + EWOL_DEBUG(" channelCount : " << myHeader.waveFormat.channelCount); + EWOL_DEBUG(" samplesPerSec : " << myHeader.waveFormat.samplesPerSec); + EWOL_DEBUG(" bytesPerSec : " << myHeader.waveFormat.bytesPerSec); + EWOL_DEBUG(" bytesPerFrame : " << myHeader.waveFormat.bytesPerFrame); + EWOL_DEBUG(" bitsPerSample : " << myHeader.waveFormat.bitsPerSample); + // get the data size : + if (fileAccess.fRead(&myHeader.dataTag, 1, 4)!=4) { + EWOL_ERROR("Can not 4 element in the file : \"" << fileAccess << "\""); + return NULL; + } + if( myHeader.dataTag[0] != 'd' + || myHeader.dataTag[1] != 'a' + || myHeader.dataTag[2] != 't' + || myHeader.dataTag[3] != 'a' ) { + EWOL_ERROR("file: \"" << fileAccess << "\" header error ..." << myHeader.dataTag[0] << myHeader.dataTag[1] << myHeader.dataTag[2] << myHeader.dataTag[3]); + return NULL; + } + // get the data size : + if (fileAccess.fRead(tmpData, 1, 4)!=4) { + EWOL_ERROR("Can not 4 element in the file : \"" << fileAccess << "\""); + return NULL; + } + myHeader.dataSize = CONVERT_UINT32(littleEndien, tmpData); + + // ---------------------------------------------- + // end of the header reading done ... + // ---------------------------------------------- + + //Parse the data and transform it if needed ... + if (COMPR_PCM != myHeader.waveFormat.type) { + EWOL_ERROR("File : \"" << fileAccess << "\" ==> support only PCM compression ..."); + return NULL; + } + if (myHeader.waveFormat.channelCount==0 || myHeader.waveFormat.channelCount>2) { + EWOL_ERROR("File : \"" << fileAccess << "\" ==> support only mono or stereo ..." << myHeader.waveFormat.channelCount); + return NULL; + } + if ( ! ( myHeader.waveFormat.bitsPerSample==16 + || myHeader.waveFormat.bitsPerSample==24 + || myHeader.waveFormat.bitsPerSample==32 ) ) { + EWOL_ERROR("File : \"" << fileAccess << "\" ==> not supported bit/sample ..." << myHeader.waveFormat.bitsPerSample); + return NULL; + } + if( ! ( 44100 == myHeader.waveFormat.samplesPerSec + || 48000 == myHeader.waveFormat.samplesPerSec) ) { + EWOL_ERROR("File : \"" << fileAccess << "\" ==> not supported frequency " << myHeader.waveFormat.samplesPerSec << " != 48000"); + return NULL; + } + EWOL_DEBUG(" dataSize : " << myHeader.dataSize); + int32_t globalDataSize = myHeader.dataSize; + int32_t nbSample = (myHeader.dataSize/((myHeader.waveFormat.bitsPerSample/8)*myHeader.waveFormat.channelCount)); + int32_t outputSize = nbChan*nbSample; + int16_t * outputData = (int16_t*)malloc(outputSize*sizeof(int16_t)); + if (NULL == outputData) { + EWOL_ERROR("Allocation ERROR try to allocate " << (outputSize*sizeof(int16_t) ) << "bytes"); + return NULL; + } + int16_t * tmpOut = outputData; + for( int32_t iii=0; iii>1 + right>>1)>>16); + } else { + *tmpOut++ = (int16_t)(left>>16); + *tmpOut++ = (int16_t)(left>>16); + } + } + // close the file: + fileAccess.fClose(); + nbSampleOut = nbSample; + return outputData; +} + + diff --git a/Sources/libewol/ewol/Audio/decWav.h b/Sources/libewol/ewol/Audio/decWav.h new file mode 100644 index 00000000..b9d5f74f --- /dev/null +++ b/Sources/libewol/ewol/Audio/decWav.h @@ -0,0 +1,40 @@ +/** + ******************************************************************************* + * @file ewol/Audio/decWav.h + * @brief basic ewol Wav decoder (header) + * @author Edouard DUPIN + * @date 28/06/2012 + * @par Project + * ewol + * + * @par Copyright + * Copyright 2011 Edouard DUPIN, all right reserved + * + * This software is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY. + * + * Licence summary : + * You can modify and redistribute the sources code and binaries. + * You can send me the bug-fix + * + * Term of the licence in in the file licence.txt. + * + ******************************************************************************* + */ + +#ifndef __EWOL_AUDIO_DEC_WAV_H__ +#define __EWOL_AUDIO_DEC_WAV_H__ + +#include +#include + +namespace ewol { + namespace audio { + namespace wav { + int16_t * LoadData(etk::UString filename, int8_t nbChan, int32_t frequency, int32_t & nbSampleOut); + }; + }; +}; + +#endif + diff --git a/Sources/libewol/ewol/base/gui.cpp b/Sources/libewol/ewol/base/gui.cpp index efe57959..c364b9f4 100644 --- a/Sources/libewol/ewol/base/gui.cpp +++ b/Sources/libewol/ewol/base/gui.cpp @@ -158,6 +158,12 @@ void guiAbstraction::KeyboardHide(void) static int64_t startTime = -1; static int64_t nbCallTime = 0; static int64_t nbDisplayTime = 0; +static int64_t min = 99999999999999; +static int64_t avg = 0; +static int64_t max = 0; +static int64_t min2 = 99999999999999; +static int64_t avg2 = 0; +static int64_t max2 = 0; // display every second ... #define DISPLAY_PERIODE_US (1000000) @@ -179,6 +185,7 @@ void EWOL_GenericDraw(bool everyTime) everyTime = true; } ewol::widgetManager::DoubleBufferLock(); + int64_t currentTime3 = GetCurrentTime(); if( true == ewol::widgetManager::GetDoubleBufferNeedDraw() || true == everyTime) { @@ -189,9 +196,30 @@ void EWOL_GenericDraw(bool everyTime) ewol::widgetManager::DoubleBufferUnLock(); // send Message that we just finished a display ... EWOL_ThreadEventHasJustDisplay(); - + int64_t currentTime2 = GetCurrentTime(); + int64_t processTimeLocal = (currentTime2 - currentTime); + min = etk_min(min, processTimeLocal); + max = etk_max(max, processTimeLocal); + avg += processTimeLocal; + processTimeLocal = (currentTime2 - currentTime3); + min2 = etk_min(min2, processTimeLocal); + max2 = etk_max(max2, processTimeLocal); + avg2 += processTimeLocal; if (true == display) { EWOL_DEBUG("display property : " << nbDisplayTime << "/" << nbCallTime << "fps"); + EWOL_DEBUG("timeToProcess1 : " << (float)((float)min / 1000.0) << "ms " + << (float)((float)avg/(float)nbDisplayTime / 1000.0) << "ms " + << (float)((float)max / 1000.0) << "ms "); + EWOL_DEBUG("timeToProcess2 : " << (float)((float)min2 / 1000.0) << "ms " + << (float)((float)avg2/(float)nbDisplayTime / 1000.0) << "ms " + << (float)((float)max2 / 1000.0) << "ms "); + max2 = 0; + max = 0; + min = 99999999999999; + min2 = 99999999999999; + avg=0; + avg2=0; + nbCallTime = 0; nbDisplayTime = 0; startTime = -1; diff --git a/Sources/libewol/file.mk b/Sources/libewol/file.mk index ce3cd317..cb911782 100644 --- a/Sources/libewol/file.mk +++ b/Sources/libewol/file.mk @@ -53,6 +53,7 @@ FILE_LIST = ewol/ewol.cpp \ ewol/widgetMeta/FileChooser.cpp \ ewol/widgetMeta/ColorChooser.cpp \ ewol/theme/Theme.cpp \ - ewol/Audio/audio.cpp + ewol/Audio/audio.cpp \ + ewol/Audio/decWav.cpp