How to produce same mfcc result as librosa using aubio? - librosa

I am trying to calculate Mfcc feature in C++. And I found Aubio (https://github.com/aubio/aubio) but I cannot produce same result as Librosa of Python (this is important).
Librosa code:
X, sample_rate = sf.read(file_name, dtype='float32')
mfccs = librosa.feature.mfcc(y=X, sr=sample_rate, n_mfcc=40)
Aubio code:
#include "utils.h"
#include "parse_args.h"
#include <stdlib.h>
aubio_pvoc_t *pv; // a phase vocoder
cvec_t *fftgrain; // outputs a spectrum
aubio_mfcc_t * mfcc; // which the mfcc will process
fvec_t * mfcc_out; // to get the output coefficients
uint_t n_filters = 128;
uint_t n_coefs = 40;
void process_block (fvec_t *ibuf, fvec_t *obuf)
{
fvec_zeros(obuf);
//compute mag spectrum
aubio_pvoc_do (pv, ibuf, fftgrain);
//compute mfccs
aubio_mfcc_do(mfcc, fftgrain, mfcc_out);
}
void process_print (void)
{
/* output times in selected format */
print_time (blocks * hop_size);
outmsg ("\t");
/* output extracted mfcc */
fvec_print (mfcc_out);
}
int main(int argc, char **argv) {
int ret = 0;
// change some default params
buffer_size = 2048;
hop_size = 512;
examples_common_init(argc,argv);
verbmsg ("using source: %s at %dHz\n", source_uri, samplerate);
verbmsg ("buffer_size: %d, ", buffer_size);
verbmsg ("hop_size: %d\n", hop_size);
pv = new_aubio_pvoc (buffer_size, hop_size);
fftgrain = new_cvec (buffer_size);
mfcc = new_aubio_mfcc(buffer_size, n_filters, n_coefs, samplerate);
mfcc_out = new_fvec(n_coefs);
if (pv == NULL || fftgrain == NULL || mfcc == NULL || mfcc_out == NULL) {
ret = 1;
goto beach;
}
examples_common_process(process_block, process_print);
printf("\nlen=%u\n", mfcc_out->length);
del_aubio_pvoc (pv);
del_cvec (fftgrain);
del_aubio_mfcc(mfcc);
del_fvec(mfcc_out);
beach:
examples_common_del();
return ret;
}
Please help to obtain same result of Librosa or suggest any C++ library do this well.
Thanks

This might be what you are looking for: C Speech Features
The library is a complete port of python_speech_features to C and according to the documentation, you should be able to use it in a C++ projects. The results will not be the same of Librosa, here is why but you should be able to work with them.

Related

Ceres Solver for logistic growth Curve Fit

I attempt to test how well ceres solver autodiff in fitting a simple logistic growth curve against actual observed data , to my surprise the solver seemed unable to provide solution . Using other c++ solvers , result can be easily obtained with ease , k=9643.61,c=84.61 and b=3.8121. I am not sure is the code having issue or just the ceres solver autodiff are not that well built? Any advice pls?
below is the sample
#include "ceres/ceres.h"
#include "glog/logging.h"
#include <cmath>
#include <iostream>
#include <stdio.h>
using ceres::AutoDiffCostFunction;
using ceres::CauchyLoss;
using ceres::CostFunction;
using ceres::Problem;
using ceres::Solve;
using ceres::Solver;
struct ExponentialResidual
{
ExponentialResidual(double x, double y)
: x_(x), y_(y) {}
template <typename T>
bool operator()(const T *const k,
const T *const c,
const T *const b,
//const T* const g,
T *residual) const
{
residual[0] = y_ - (k[0] / (1.0 + (pow((x_ / c[0]), b[0]))));
return true;
}
private:
const double x_;
const double y_;
};
const int kNumObservations = 247;
double data[] = {
0,3,
1,4,
2,4,
3,4,
4,7,
5,8,
6,8,
7,8,
8,8,
9,8,
10,10,
11,12,
12,12,
13,12,
14,16,
15,16,
16,18,
17,18,
18,18,
19,19,
20,19,
21,22,
22,22,
23,22,
24,22,
25,22,
26,22,
27,22,
28,22,
29,22,
30,22,
31,22,
32,22,
33,23,
34,23,
35,25,
36,29,
37,32,
38,36,
39,50,
40,55,
41,83,
42,93,
43,99,
44,117,
45,129,
46,149,
47,158,
48,197,
49,238,
50,428,
51,553,
52,673,
53,790,
54,900,
55,1030,
56,1183,
57,1306,
58,1518,
59,1624,
60,1796,
61,2031,
62,2161,
63,2320,
64,2470,
65,2626,
66,2766,
67,2908,
68,3116,
69,3333,
70,3483,
71,3662,
72,3793,
73,3963,
74,4119,
75,4228,
76,4346,
77,4530,
78,4683,
79,4817,
80,4987,
81,5072,
82,5182,
83,5251,
84,5305,
85,5389,
86,5425,
87,5482,
88,5532,
89,5603,
90,5691,
91,5742,
92,5780,
93,5820,
94,5851,
95,5945,
96,6002,
97,6071,
98,6176,
99,6298,
100,6353,
101,6383,
102,6428,
103,6467,
104,6535,
105,6589,
106,6656,
107,6726,
108,6742,
109,6779,
110,6819,
111,6855,
112,6872,
113,6894,
114,6941,
115,6978,
116,7009,
117,7059,
118,7137,
119,7185,
120,7245,
121,7417,
122,7604,
123,7619,
124,7629,
125,7732,
126,7762,
127,7819,
128,7857,
129,7877,
130,7970,
131,8247,
132,8266,
133,8303,
134,8322,
135,8329,
136,8336,
137,8338,
138,8369,
139,8402,
140,8445,
141,8453,
142,8494,
143,8505,
144,8515,
145,8529,
146,8535,
147,8556,
148,8572,
149,8587,
150,8590,
151,8596,
152,8600,
153,8606,
154,8616,
155,8634,
156,8637,
157,8639,
158,8640,
159,8643,
160,8648,
161,8658,
162,8663,
163,8668,
164,8674,
165,8677,
166,8683,
167,8696,
168,8704,
169,8718,
170,8725,
171,8729,
172,8734,
173,8737,
174,8755,
175,8764,
176,8779,
177,8800,
178,8815,
179,8831,
180,8840,
181,8861,
182,8884,
183,8897,
184,8904,
185,8943,
186,8956,
187,8964,
188,8976,
189,8985,
190,8999,
191,9001,
192,9002,
193,9023,
194,9038,
195,9063,
196,9070,
197,9083,
198,9094,
199,9103,
200,9114,
201,9129,
202,9149,
203,9175,
204,9200,
205,9212,
206,9219,
207,9235,
208,9240,
209,9249,
210,9257,
211,9267,
212,9274,
213,9285,
214,9291,
215,9296,
216,9306,
217,9317,
218,9334,
219,9340,
220,9354,
221,9360,
222,9374,
223,9385,
224,9391,
225,9397,
226,9459,
227,9559,
228,9583,
229,9628,
230,9810,
231,9868,
232,9915,
233,9946,
234,9969,
235,10031,
236,10052,
237,10147,
238,10167,
239,10219,
240,10276,
241,10358,
242,10505,
243,10576,
244,10687,
245,10769,
246,10919,
};
int main(int argc, char const *argv[])
{
google::InitGoogleLogging(argv[0]);
double k = 20000.0;
//double c=0.5;
double c = kNumObservations / 2.0;
double b = 0.5;
double g = 1.0;
Problem problem;
for (int i = 0; i < kNumObservations; i++)
{
problem.AddResidualBlock(
new AutoDiffCostFunction<ExponentialResidual, 1, 1, 1, 1>(
new ExponentialResidual(data[2 * i]*1.00, data[2 * i + 1]*1.00)),
new CauchyLoss(0.5), &k, &c, &b);
}
Solver::Options options;
options.max_num_iterations = 1000;
options.linear_solver_type = ceres::DENSE_QR;
//options.trust_region_strategy_type=ceres::DOGLEG;
//options.gradient_tolerance=1e-8;
//options.parameter_tolerance=1e-10;
//options.function_tolerance=1e-8;
options.minimizer_progress_to_stdout = true;
Solver::Summary summary;
Solve(options, &problem, &summary);
//std::cout<<summary.BriefReport()<<std::endl;
std::cout << summary.FullReport() << std::endl;
std::cout << "Final k: " << k << " c: " << c << " b: " << b << " g: " << g << "\n";
/* code */
return 0;
}
look like if I ignore the first observed data 0,3 , ceres solver is able to obtain result !

Manipulate files older than X

I've searched a lot how to delete files older than a number X given but I've only found questions too old to trust.
I have directory filled with files .zip those files are created to make space but one day i won't have anymore space so i've thought that i can choose a number of days (X) to choose when i want to delete some files and which files i want to delete. At the moment i'm searching for a way to select the files from a folder given that are older than Today - X and tha tdelete them.
void fCamImgCanc(long pThreadId)
{
ULARGE_INTEGER rFreeBytesAvailable, rTotalNumberOfBytes, rTotalNumberOfFreeBytes;
if(sys.Logs.CamImgSave && sys.Logs.ImageSMod == 1)
{
if (::GetDiskFreeSpaceEx ("C:\\S\\LOGBOOK\\Cam\\Logfold", &rFreeBytesAvailable, &rTotalNumberOfBytes, &rTotalNumberOfFreeBytes))
{
if (rTotalNumberOfBytes.QuadPart < ((rTotalNumberOfBytes.QuadPart * sys.LogB.FreeSpaceOnDisk) / 100)) //if disk size < __% delete the older day
{
do
{
//Date of the oldest group of files > Today - sys.LogB.OlderThanD setted for example to 13
if("C:\\S\\LOGBOOK\\Cam\\Logfold\\FilenameData" > Today - sys.LogB.OlderThanD)
{
DeleteFile("C:\\S\\LOGBOOK\\Cam\\Logfold");
}
}while(rTotalNumberOfBytes.QuadPart < ((rTotalNumberOfBytes.QuadPart * sys.LogB.FreeSpaceOnDisk) / 100)); //free space till we have the space that we need
}
fAddOnZip("C:\\S\\LOGBOOK\\Cam");
}
}
else //ImageSMod = 0 -> Relative "save of the images of the lot and at the next lot delete of them"
{
DO OTHER THINGS
}
}
I've got the delete function and the zip function yet
Enumerate files in a directory with FindFirstFile and FindNextFile.
Get the current time with GetSystemTime (and convert to "file time" with SystemTimeToFileTime).
Do the approriate math to get the timestamp from N days ago. It's all based on 100ns units. (10 million of those equals "one second").
Then DeleteFile to actually delete the file.
And some helper functions from the Windows SDK to concatenate paths. Link with PatchCch.lib.
Here's some code to get you started. If you invoke:
delete_all_old_files_in_directory(L"C:\\Users\\YourName\\Downloads", 7);
It will delete everything from the Downloads folder older than a week.
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#include <windows.h>
#include <strsafe.h>
#include <PathCch.h>
#include <stdint.h>
#pragma comment(lib, "pathcch")
void delete_all_old_files_in_directory(const wchar_t* dir, DWORD dwDays)
{
SYSTEMTIME st = { 0 };
wchar_t szPath[MAX_PATH * 2 + 2];
BOOL succeeded = TRUE;
uint64_t filetimeNow = 0;
uint64_t filetimeCompare = 0;
uint64_t delta;
HANDLE h = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW data = { 0 };
// dont't try to delete directories or special files
const DWORD dwMask = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
GetSystemTime(&st);
::SystemTimeToFileTime(&st, (FILETIME*)&filetimeNow);
delta = 10000000ULL * dwDays * 60 * 60 * 24;
filetimeCompare = filetimeNow - delta;
StringCchCopy(szPath, ARRAYSIZE(szPath), dir);
PathCchAppend(szPath, ARRAYSIZE(szPath), L"*.*");
h = FindFirstFile(szPath, &data);
succeeded = (h != INVALID_HANDLE_VALUE);
while (succeeded)
{
uint64_t fileTimeThisFile = *(uint64_t*)(&data.ftCreationTime);
wchar_t szDeletePath[MAX_PATH] = { 0 };
StringCchCopy(szDeletePath, ARRAYSIZE(szDeletePath), dir);
PathCchAppend(szDeletePath, ARRAYSIZE(szDeletePath), data.cFileName);
if ((fileTimeThisFile < filetimeCompare) && !(data.dwFileAttributes & dwMask))
{
wprintf(L"Deleting: %ls\n", szDeletePath);
DeleteFile(szDeletePath);
}
else
{
wprintf(L"Keeping: %ls\n", szDeletePath);
}
succeeded = FindNextFile(h, &data);
}
if (h != INVALID_HANDLE_VALUE)
{
FindClose(h);
h = NULL;
}
}
int main()
{
delete_all_old_files_in_directory(L"C:\\Users\\YourName\\Downloads", 7);
return 0;
}

Why is physical process in Castalia outputting wrong data?

I am trying to simulate a sensor array in Castalia capable of using more than one sensor per node but when I run the simulation it takes the names of the sensors as one item and ends up displaying the sensor index and value of the sensor mentioned first. Please help!! how can I get it to detect more than one sensor per node
omnetpp.ini (valueReporting)
[General]
# ==========================================================
# Always include the main Castalia.ini file
# ==========================================================
include ../Parameters/Castalia.ini
sim-time-limit = 600s
SN.field_x = 100 # meters
SN.field_y = 100 # meters
SN.numNodes = 36
SN.deployment = "6x6"
SN.node[*].Communication.Radio.RadioParametersFile = "../Parameters/Radio/CC2420.txt"
SN.node[*].Communication.MACProtocolName = "TMAC"
SN.node[*].Communication.RoutingProtocolName = "MultipathRingsRouting"
#SN.node[*].Communication.Routing.collectTraceInfo = true
SN.node[*].ApplicationName = "ValueReporting"
SN.node[3].Application.isSink = true
# test 2 physical processes
SN.numPhysicalProcesses = 2
SN.physicalProcess[0].printDebugInfo = true
SN.physicalProcess[1].printDebugInfo = true
SN.physicalProcess[0].description = "Degrees Celsius"
SN.physicalProcess[1].description = "Blood Glucose"
SN.physicalProcess[0].inputType = 1
SN.physicalProcess[1].inputType = 1
#SN.physicalProcess[0].directNodeValueAssignment = "(0) 0:25 1:23 2:21 3:24 4:26"
#SN.physicalProcess[1].directNodeValueAssignment = "(0) 0:360 1:380 2:375 3:390 4:390"
SN.node[*].SensorManager.​numSensingDevices = 2
SN.node[*].SensorManager.​sensorTypes = "Temperature Bloodglucose"
SN.node[*].SensorManager.​corrPhyProcess = "0 1"
In the SensorManager.ned file, I changed these lines as for the rest of the file everything is left as is
string sensorTypes = default ("Temperature,Bloodglucose");
// string array of comma-separated Names for the sensing devices
string corrPhyProcess = default ("0,1");
Now the temperature physical process files
TemperaturePhysicalProcess.ned
package physicalProcess.temperaturePhysicalProcess;
simple TemperaturePhysicalProcess like physicalProcess.iPhysicalProcess {
parameters:
bool collectTraceInfo = default (true);
double temperature = default (37); //normal body temperature is 37 degrees celcius
string description = default ("Degrees Celsius");
gates:
output toNode[];
input fromNode[];
}
TemperaturePhysicalProcess.h
#ifndef _TEMPERATUREPHYSICALPROCESS_H_
#define _TEMPERATUREPHYSICALPROCESS_H_
#define SIMTIME_STEP 0.01
#include "CastaliaModule.h"
#include "PhysicalProcessMessage_m.h"
using namespace std;
typedef struct {
simtime_t time;
double x;
double y;
} sourceSnapshot;
class TemperaturePhysicalProcess: public CastaliaModule {
private:
bool printDebugInfo;
int temperature;
const char *description;
protected:
virtual void initialize();
virtual void handleMessage(cMessage * msg);
virtual void finishSpecific();
};
#endif
TemperaturePhysicalProcess.cc
#include "TemperaturePhysicalProcess.h"
Define_Module(TemperaturePhysicalProcess);
void TemperaturePhysicalProcess::initialize()
{
temperature=37;
//Search for snapshots in castalia manual
}
void TemperaturePhysicalProcess::handleMessage(cMessage * msg)
{
if (msg->getKind() != PHYSICAL_PROCESS_SAMPLING)
{
opp_error("Physical Process received message other than PHYSICAL_PROCESS_SAMPLING");
}
PhysicalProcessMessage *receivedMsg = check_and_cast < PhysicalProcessMessage * >(msg);
int nodeIndex = receivedMsg->getSrcID();
// Send reply back to the node who made the request
receivedMsg->setValue(temperature);
send(receivedMsg, "toNode", nodeIndex);
}
void TemperaturePhysicalProcess::finishSpecific() {}
Now we'll go to the Blood Glucose physical process
BloodGlucoseLevelPhysicalProcess.ned
package physicalProcess.bloodGlucoseLevelPhysicalProcess;
simple BloodGlucoseLevelPhysicalProcess like physicalProcess.iPhysicalProcess {
parameters:
bool collectTraceInfo = default (false);
int averagebloodglucose = default (100); // the amount is in mg per dL
int age = default (20);
string description = default ("Blood Glucose");
gates:
output toNode[];
input fromNode[];
}
BloodGlucoseLevelPhysicalProcess.h
#ifndef _BLOOODGLUCOSELEVELPHYSICALPROCESS_H_
#define _BLOOODGLUCOSELEVELPHYSICALPROCESS_H_
#define SIMTIME_STEP 0.01
#include "CastaliaModule.h"
#include "PhysicalProcessMessage_m.h"
using namespace std;
typedef struct {
simtime_t time;
double x;
double y;
} sourceSnapshot;
class BloodGlucoseLevelPhysicalProcess: public CastaliaModule {
private:
bool printDebugInfo;
int averagebloodglucose;
double A1c;
const char *description;
protected:
virtual void initialize();
virtual void handleMessage(cMessage * msg);
virtual void finishSpecific();
};
#endif
BloodGlucoseLevelLevelPhysicalProcess.cc
#include "BloodGlucoseLevelPhysicalProcess.h"
Define_Module(BloodGlucoseLevelPhysicalProcess);
void BloodGlucoseLevelPhysicalProcess::initialize()
{
averagebloodglucose = par("averagebloodglucose");
description = par("description").stringValue();
A1c = (46.7 + averagebloodglucose) / 28.7;
//Search for snapshots in castalia manual
}
void BloodGlucoseLevelPhysicalProcess::handleMessage(cMessage * msg)
{
if (msg->getKind() != PHYSICAL_PROCESS_SAMPLING)
opp_error("Physical Process received message other than PHYSICAL_PROCESS_SAMPLING");
PhysicalProcessMessage *receivedMsg = check_and_cast < PhysicalProcessMessage * >(msg);
int nodeIndex = receivedMsg->getSrcID();
//int sensorIndex = receivedMsg->getSensorIndex();
double returnValue;
// Send reply back to the node who made the request
//receivedMsg->setValue(returnValue);
receivedMsg->setValue(A1c);
send(receivedMsg, "toNode", nodeIndex);
}
void BloodGlucoseLevelPhysicalProcess::finishSpecific() {
}
Since I'm running the simulation using the ValueReporting application
ValueReporting.h
#define _VALUEREPORTING_H_
#include "VirtualApplication.h"
#include "ValueReportingPacket_m.h"
using namespace std;
enum ValueReportingTimers {
REQUEST_SAMPLE = 1,
SEND_DATA = 2,
};
class ValueReporting: public VirtualApplication {
private:
double maxSampleInterval;
double minSampleInterval;
int routingLevel;
double lastSensedValue;
int currSentSampleSN;
double randomBackoffIntervalFraction;
bool sentOnce;
int recipientId;
string recipientAddress;
protected:
void startup();
void fromNetworkLayer(ApplicationPacket *, const char *, double, double);
void handleSensorReading(SensorReadingMessage *);
void timerFiredCallback(int);
void requestSensorReading(const char *);
};
#endif // _VALUEREPORTING_APPLICATIONMODULE_H_
ValueReporting.cc
#include "ValueReporting.h"
#include <iostream> // std::cout
#include <iomanip>
#include <string> // std::string, std::to_string
#include <stdlib.h> /* atof */
#include <math.h>
#include<sstream>
#include <cstring>
#include <vector>
#include <array>
#include <string>
#include <algorithm>
Define_Module(ValueReporting);
void ValueReporting::startup()
{
maxSampleInterval = ((double)par("maxSampleInterval")) / 1000.0;
minSampleInterval = ((double)par("minSampleInterval")) / 1000.0;
currSentSampleSN = 0;
randomBackoffIntervalFraction = genk_dblrand(0);
sentOnce = false;
setTimer(REQUEST_SAMPLE, maxSampleInterval * randomBackoffIntervalFraction);
}
void ValueReporting::timerFiredCallback(int index)
{
switch (index) {
case REQUEST_SAMPLE:{
requestSensorReading("Temperature");
//requestSensorReading("Urine");
setTimer(REQUEST_SAMPLE, maxSampleInterval);
break;
}
}
}
void ValueReporting::fromNetworkLayer(ApplicationPacket * genericPacket,
const char *source, double rssi, double lqi)
{
ValueReportingDataPacket *rcvPacket = check_and_cast<ValueReportingDataPacket*>(genericPacket);
ValueReportData theData = rcvPacket->getExtraData();
trace() << "Sink received from: " << theData.nodeID << " \tvalue=" << rcvPacket->getData();
}
void ValueReporting::handleSensorReading(SensorReadingMessage * rcvReading)
{
int sensIndex = rcvReading->getSensorIndex();
string sensType(rcvReading->getSensorType());
double sensValue = rcvReading->getSensedValue();
double x_coor = mobilityModule->getLocation().x;
double y_coor = mobilityModule->getLocation().y;
string sensorindex = to_string(sensIndex);
string sensvalue = to_string(sensValue);
string xcoor = to_string(x_coor);
string ycoor = to_string(y_coor);
string sensorinfo= sensorindex + " " + sensvalue + " " + xcoor + " " + ycoor + " " + sensType;
trace() << sensorinfo;
ValueReportData tmpData;
tmpData.nodeID = (unsigned short)self;
tmpData.locX = mobilityModule->getLocation().x;
tmpData.locY = mobilityModule->getLocation().y;
ValueReportingDataPacket *packet2Net =
new ValueReportingDataPacket("Value reporting pck", APPLICATION_PACKET);
packet2Net->setExtraData(tmpData);
packet2Net->setData(sensValue);
packet2Net->setSequenceNumber(currSentSampleSN);
currSentSampleSN++;
toNetworkLayer(packet2Net, SINK_NETWORK_ADDRESS);
//toNetworkLayer(packet2Net, "6");
sentOnce = true;
}
void ValueReporting::requestSensorReading(const char * type){
SensorReadingMessage *reqMsg =
new SensorReadingMessage("App to Sensor Mgr: sample request", SENSOR_READING_MESSAGE);
if(type == "Temperature"){
reqMsg->setSensorType(type);
reqMsg->setSensorIndex(0);
}
if(type =="BloodGlucose"){
reqMsg->setSensorType(type);
reqMsg->setSensorIndex(1);
}
send(reqMsg, "toSensorDeviceManager");
}
Some things I noticed:
There is no printDebugInfo parameter in the PhysicalProcess module. Probably what you are after is collectTraceInfo.
If you just want to update the values some parameters take, it's not a good idea to edit ned files. This is what ini files are for. So instead of changing the default values in ned files, simply assign these values in your ini file. For example, you already assign these parameters in your ini file:
SN.node[*].SensorManager.​sensorTypes = "Temperature Bloodglucose"
SN.node[*].SensorManager.​corrPhyProcess = "0 1"
You do not need to set them in the ned file as well. Also notice that in the ned file you set the second string as "0,1" not "0 1". The ini file will override the value of the ned file, so what you'll get it "0 1". Fortunately, space separated values is the correct syntax.
You then start defining new .ned .cc and .h files. Why? These do not have any effect. You have not set the variable SN.physicalProcessName in your ini file. This means it takes the default value which is CustomizablePhysicalProcess. You seem to be treating your physical process modules as CustomizablePhysicalProcess because I see you define their parameters inputType and directNodeValueAssignment, which only exist for the CustomizablePhysicalProcess module. So I do not understand what you expect to get by trying to define new physical process modules altogether.
Since you have 2 physical processes, it means that the SensorManager in every node needs to connect to these 2 physical process (the 2 modules that define your physical processes). To do this just set all the parameters of your SensorManager that can be defined as an array (formatted as a space-separated string) as arrays of 2 items.
You can find all relevant parameters in the SensorManager.ned (but do NOT edit the ned file, just set them in your ini file). Here are the parameters just for reference (note that you have already set sensorTypes and corrPhyProcess in your ini file, you just need to also set the rest) :
string pwrConsumptionPerDevice = default ("0.02");
string sensorTypes = default ("Temperature"); // Humidity OR Temperature OR Light
string corrPhyProcess = default ("0"); //holds the indexes of the corresponding phy processes for
//each sensor (usually it should be : "0 1 2 3")
string maxSampleRates = default ("1"); //number of samples per second for each sensor
string devicesBias = default ("0.1"); //If the output signal is not zero when the measured property is zero
string devicesDrift = default (""); //If the output signal slowly changes independent of the
//measured property
string devicesNoise = default ("0.1"); //random deviation of the signal that varies in time
string devicesHysterisis = default (""); //the sensor not instantly follows the change of the property
//being measured and therefore involves the history of the
//measured property
string devicesSensitivity = default ("0"); //holds the minimum value which can be sensed by each sensing device.
string devicesResolution = default ("0.001"); //holds the sensing resolution for each device
I am not sure whether there are other problems with multiple phyProcesses and multiple sensing modalities, because this feature has not been tested in versions after 2.0, so it might not work at all (but hopefully it's a small adjustment to make it work).

FFT of samples from portAudio stream

Beginner here, (OSX 10.9.5, Xcode 6)
I have a portAudio stream that gives out noise. Now I'd like to get those random values generated in the callback and run them through an fftw plan. As far as I know, fftw needs to be executed in the main. So how can I show the numbers from the callback to the main? I have a feeling it has something to do with pointers but that's a very uneducated guess...
I'm having some difficulty with joining two different libraries. Little help would be greatly appreciated, thank you!
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "portaudio.h"
#include "fftw3.h"
#define NUM_SECONDS (1)
#define SAMPLE_RATE (44100)
typedef struct
{
float left_phase;
float right_phase;
}
paTestData;
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
/* Cast data passed through stream to our structure. */
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned int i;
(void) inputBuffer; /* Prevent unused variable warning. */
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = data->left_phase; /* left */
*out++ = data->right_phase; /* right */
/* Generate random value that ranges between -1.0 and 1.0. */
data->left_phase = (((float)rand()/(float)(RAND_MAX)) * 2) - 1 ;
data->right_phase = (((float)rand()/(float)(RAND_MAX)) * 2) - 1 ;
printf("%f, %f\n", data->left_phase, data->right_phase);
}
return 0;
}
/*******************************************************************/
static paTestData data;
int main(void);
int main(void)
{
PaStream *stream;
PaError err;
printf("PortAudio Test: output noise.\n");
/* Initialize our data for use by callback. */
data.left_phase = data.right_phase = 0.0;
/* Initialize library before making any other calls. */
err = Pa_Initialize();
if( err != paNoError ) goto error;
/* Open an audio I/O stream. */
err = Pa_OpenDefaultStream( &stream,
0, /* no input channels */
2, /* stereo output */
paFloat32, /* 32 bit floating point output */
SAMPLE_RATE,
512, /* frames per buffer */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
/* Sleep for several seconds. */
Pa_Sleep(NUM_SECONDS*1000);
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
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 ) );
return err;
}
You could try running the stream in "blocking write" mode instead of using the callback. To use this mode, you pass NULL for the streamCallback parameter of Pa_OpenDefaultStream and then you continually call Pa_WriteStream in a loop. The call will block as necessary. Something like this pseudo code:
Pa_OpenStream(&stream, 0, 2, paFloat32, SAMPLE_RATE, 512, NULL, NULL);
Pa_StartStream(stream);
float interleavedSamples[2*512];
for (int i = 0 ; i < SAMPLE_RATE/512 ; i++) // approx 1 second
{
GenerateNoise(&interleavedSamples, 2, 512, &data);
RunFft(interleavedSamples, ...);
PaWriteStream(stream, interleavedSamples, 512);
}

IMFTransform interface of Color Converter DSP giving E_INVALIDARG on SetInputType/SetOutputType

I'm trying to use Color Converter DMO (http://msdn.microsoft.com/en-us/library/windows/desktop/ff819079(v=vs.85).aspx) to convert RBG24 to YV12/NV12 via Media Foundation. I've created an instance of Color Converter DSP via CLSID_CColorConvertDMO and then tried to set the needed input/output types, but the calls always return E_INVALIDARG even when using media types that are returned by GetOutputAvailableType and GetInputAvailableType. If I set the media type to NULL then i get the error that the media type is invalid, that makes sense. I've seen examples from MSDN, where people do the same - enumerate available types and then set them as input types - and they claim it works, but i'm kinda stuck on the E_INVALIDARG. I understand that this is hard to answer without a code example, if no one has had similar experience, I'll try to post a snipplet, but maybe someone has experienced the same issue?
This DMO/DSP is dual interfaced and is both a DMO with IMediaObject and an MFT with IMFTransform. The two interfaces share a lot common, and here is a code snippet to test initialization of RGB24 into YV12 conversion:
#include "stdafx.h"
#include <dshow.h>
#include <dmo.h>
#include <wmcodecdsp.h>
#pragma comment(lib, "strmiids.lib")
#pragma comment(lib, "wmcodecdspuuid.lib")
int _tmain(int argc, _TCHAR* argv[])
{
ATLVERIFY(SUCCEEDED(CoInitialize(NULL)));
CComPtr<IMediaObject> pMediaObject;
ATLVERIFY(SUCCEEDED(pMediaObject.CoCreateInstance(CLSID_CColorConvertDMO)));
VIDEOINFOHEADER InputVideoInfoHeader;
ZeroMemory(&InputVideoInfoHeader, sizeof InputVideoInfoHeader);
InputVideoInfoHeader.bmiHeader.biSize = sizeof InputVideoInfoHeader.bmiHeader;
InputVideoInfoHeader.bmiHeader.biWidth = 1920;
InputVideoInfoHeader.bmiHeader.biHeight = 1080;
InputVideoInfoHeader.bmiHeader.biPlanes = 1;
InputVideoInfoHeader.bmiHeader.biBitCount = 24;
InputVideoInfoHeader.bmiHeader.biCompression = BI_RGB;
InputVideoInfoHeader.bmiHeader.biSizeImage = 1080 * (1920 * 3);
DMO_MEDIA_TYPE InputMediaType;
ZeroMemory(&InputMediaType, sizeof InputMediaType);
InputMediaType.majortype = MEDIATYPE_Video;
InputMediaType.subtype = MEDIASUBTYPE_RGB24;
InputMediaType.bFixedSizeSamples = TRUE;
InputMediaType.bTemporalCompression = FALSE;
InputMediaType.lSampleSize = InputVideoInfoHeader.bmiHeader.biSizeImage;
InputMediaType.formattype = FORMAT_VideoInfo;
InputMediaType.cbFormat = sizeof InputVideoInfoHeader;
InputMediaType.pbFormat = (BYTE*) &InputVideoInfoHeader;
const HRESULT nSetInputTypeResult = pMediaObject->SetInputType(0, &InputMediaType, 0);
_tprintf(_T("nSetInputTypeResult 0x%08x\n"), nSetInputTypeResult);
VIDEOINFOHEADER OutputVideoInfoHeader = InputVideoInfoHeader;
OutputVideoInfoHeader.bmiHeader.biBitCount = 12;
OutputVideoInfoHeader.bmiHeader.biCompression = MAKEFOURCC('Y', 'V', '1', '2');
OutputVideoInfoHeader.bmiHeader.biSizeImage = 1080 * 1920 * 12 / 8;
DMO_MEDIA_TYPE OutputMediaType = InputMediaType;
OutputMediaType.subtype = MEDIASUBTYPE_YV12;
OutputMediaType.lSampleSize = OutputVideoInfoHeader.bmiHeader.biSizeImage;
OutputMediaType.cbFormat = sizeof OutputVideoInfoHeader;
OutputMediaType.pbFormat = (BYTE*) &OutputVideoInfoHeader;
const HRESULT nSetOutputTypeResult = pMediaObject->SetOutputType(0, &OutputMediaType, 0);
_tprintf(_T("nSetOutputTypeResult 0x%08x\n"), nSetOutputTypeResult);
// TODO: ProcessInput, ProcessOutput
pMediaObject.Release();
CoUninitialize();
return 0;
}
This should work fine and print two S_OKs out...

Resources