00001 /**************************************************************** 00002 * 00003 * Copyright (c) 2010 00004 * 00005 * Fraunhofer Institute for Manufacturing Engineering 00006 * and Automation (IPA) 00007 * 00008 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00009 * 00010 * Project name: care-o-bot 00011 * ROS stack name: cob_driver 00012 * ROS package name: cob_light 00013 * Description: Switch robots led color by sending data to 00014 * the led-µC over serial connection. 00015 * 00016 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00017 * 00018 * Author: Benjamin Maidel, email:benjamin.maidel@ipa.fraunhofer.de 00019 * Supervised by: Benjamin Maidel, email:benjamin.maidel@ipa.fraunhofer.de 00020 * 00021 * Date of creation: August 2012 00022 * ToDo: 00023 * 00024 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00025 * 00026 * Redistribution and use in source and binary forms, with or without 00027 * modification, are permitted provided that the following conditions are met: 00028 * 00029 * * Redistributions of source code must retain the above copyright 00030 * notice, this list of conditions and the following disclaimer. 00031 * * Redistributions in binary form must reproduce the above copyright 00032 * notice, this list of conditions and the following disclaimer in the 00033 * documentation and/or other materials provided with the distribution. 00034 * * Neither the name of the Fraunhofer Institute for Manufacturing 00035 * Engineering and Automation (IPA) nor the names of its 00036 * contributors may be used to endorse or promote products derived from 00037 * this software without specific prior written permission. 00038 * 00039 * This program is free software: you can redistribute it and/or modify 00040 * it under the terms of the GNU Lesser General Public License LGPL as 00041 * published by the Free Software Foundation, either version 3 of the 00042 * License, or (at your option) any later version. 00043 * 00044 * This program is distributed in the hope that it will be useful, 00045 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00046 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00047 * GNU Lesser General Public License LGPL for more details. 00048 * 00049 * You should have received a copy of the GNU Lesser General Public 00050 * License LGPL along with this program. 00051 * If not, see <http://www.gnu.org/licenses/>. 00052 * 00053 ****************************************************************/ 00054 00055 #include "fft.h" 00056 00057 namespace mybeat 00058 { 00059 00060 00061 FFT::FFT(uint16_t size=0) 00062 { 00063 this->m_size=size; 00064 m_magnitude = new double[size/2]; 00065 m_maxMagnitude=0; 00066 /*We should use fftw_malloc instead of new since fftw_malloc aligns the memory for optimal speed*/ 00067 m_outputSignal = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * size); 00068 m_inputSignal = new double[size]; 00069 m_SoundBuffer = NULL; 00070 00071 //This has to happen prior to any initialisation of the input array 00072 plan_forward = fftw_plan_dft_r2c_1d(m_size, m_inputSignal, m_outputSignal , 0); 00073 00074 } 00075 FFT::~FFT() 00076 { 00077 fftw_destroy_plan(plan_forward); 00078 delete [] m_inputSignal; 00079 delete [] m_magnitude; 00080 fftw_free(m_outputSignal); 00081 } 00082 void FFT::process_data() 00083 { 00084 if(m_SoundBuffer == NULL) 00085 { 00086 printf("libbeat: No Soundbuffer has been set!"); 00087 return; 00088 } 00089 00090 //fill our array with data and apply windows if needed 00091 #ifdef USE_BLACKMAN 00092 double a0 = (1-0.16)/2; 00093 double a1 = 0.5; 00094 double a2 = 0.16/2; 00095 for(uint16_t i=0; i<m_size; i++) 00096 { 00097 double mult = a0+a1*cos((2*M_PI*i)/(m_size-1))+a2*cos((4*M_PI*i)/(m_size-1)); 00098 m_inputSignal[i] = (double)m_SoundBuffer->read(i) * mult; 00099 } 00100 #endif 00101 #ifdef USE_HANNING 00102 for(uint16_t i=0; i<m_size; i++) 00103 { 00104 double mult = 0.5 * (1.00 - cos(2*M_PI*i/m_size-1)); 00105 m_inputSignal[i] = (double)m_SoundBuffer->read(i) * mult; 00106 } 00107 #endif 00108 #ifdef USE_NO_WINDOW 00109 for(uint16_t i=0; i<m_size;i++) 00110 { 00111 m_inputSignal[i]=(double)m_SoundBuffer->read(i); 00112 } 00113 #endif 00114 00115 fftw_execute(plan_forward); 00116 00117 //Calculate Magnitude 00118 #ifdef CLEAR_NOISE 00119 //We delete some values since these will ruin our output 00120 m_outputSignal[0][0]=0; 00121 m_outputSignal[0][1]=0; 00122 m_outputSignal[1][0]=0; 00123 m_outputSignal[1][1]=0; 00124 m_outputSignal[2][0]=0; 00125 m_outputSignal[2][1]=0; 00126 #endif 00127 00128 for(uint16_t i=0;i<m_size/2;i++) 00129 { 00130 m_magnitude[i] = sqrt(pow(m_outputSignal[i][0],2)+pow(m_outputSignal[i][1],2)); 00131 if(m_magnitude[i] > m_maxMagnitude) 00132 m_maxMagnitude=m_magnitude[i]; 00133 } 00134 } 00135 double FFT::get_element_i(uint16_t pos) 00136 { 00137 if(pos < m_size) 00138 return m_outputSignal[pos][1]; 00139 else 00140 return 0; 00141 } 00142 double FFT::get_element_r(uint16_t pos) 00143 { 00144 if(pos < m_size) 00145 return m_outputSignal[pos][0]; 00146 else 00147 return 0; 00148 } 00149 double FFT::get_magnitude(uint16_t pos) 00150 { 00151 if(pos < m_size/2) 00152 return m_magnitude[pos]; 00153 else 00154 return 0; 00155 } 00156 double FFT::get_magnitude_max() 00157 { 00158 return m_maxMagnitude; 00159 } 00160 } //namespace libbeat