annotate src/testApp.cpp @ 8:184a7c232049 tip

changed files since updating computer
author Venetian
date Thu, 14 Aug 2014 17:53:57 +0100
parents 7ec1ed0b2eb0
children
rev   line source
andrew@0 1 #include "testApp.h"
andrew@0 2
andrew@0 3
andrew@0 4 //--------------------------------------------------------------
andrew@0 5 void testApp::setup(){
andrew@0 6
andrew@0 7 ofSetVerticalSync(true);
andrew@0 8 ofSetCircleResolution(80);
andrew@0 9 ofBackground(54, 54, 54);
andrew@0 10
andrew@0 11 // 0 output channels,
andrew@0 12 // 2 input channels
andrew@0 13 // 44100 samples per second
andrew@0 14 // 256 samples per buffer
andrew@0 15 // 4 num buffers (latency)
andrew@0 16
andrew@0 17 soundStream.listDevices();
andrew@0 18 soundStream.setDeviceID(0);//this now uses the audio input rather than mic input for mac
andrew@0 19 //outputStream.setDeviceID(1);
andrew@0 20
andrew@0 21 //if you want to set a different device id
andrew@0 22 //soundStream.setDeviceID(0); //bear in mind the device id corresponds to all audio devices, including input-only and output-only devices.
andrew@0 23
andrew@0 24 bufferSize = 512;
andrew@0 25
andrew@0 26 left.assign(bufferSize, 0.0);
andrew@0 27 right.assign(bufferSize, 0.0);
andrew@0 28 volHistory.assign(400, 0.0);
andrew@0 29
andrew@0 30 bufferCounter = 0;
andrew@0 31 drawCounter = 0;
andrew@0 32 smoothedVol = 0.0;
andrew@0 33 scaledVol = 0.0;
andrew@0 34
andrew@0 35 soundStream.setup(this, 0, 2, 44100, bufferSize, 4);
andrew@0 36
andrew@0 37 //peak analysis
andrew@0 38 onsetSamples.assign(bufferSize, 0.0);
andrew@0 39 // recentBufferSamples.assign(bufferSize, 0.0);
andrew@0 40 holdOn = false;
andrew@0 41 exactOnsetIndex = 0;
andrew@0 42
andrew@0 43 precisionLocator.setup(bufferSize);
andrew@0 44
andrew@0 45 }
andrew@0 46
andrew@0 47 //--------------------------------------------------------------
andrew@0 48 void testApp::update(){
andrew@0 49 //lets scale the vol up to a 0-1 range
andrew@0 50 scaledVol = ofMap(smoothedVol, 0.0, 0.17, 0.0, 1.0, true);
andrew@0 51
andrew@0 52 //lets record the volume into an array
andrew@0 53 volHistory.push_back( scaledVol );
andrew@0 54
andrew@0 55 //if we are bigger the the size we want to record - lets drop the oldest value
andrew@0 56 if( volHistory.size() >= 400 ){
andrew@0 57 volHistory.erase(volHistory.begin(), volHistory.begin()+1);
andrew@0 58 }
andrew@0 59 }
andrew@0 60
andrew@0 61 //--------------------------------------------------------------
andrew@0 62 void testApp::draw(){
andrew@0 63
andrew@0 64 ofSetColor(225);
andrew@2 65 ofDrawBitmapString("AUDIO INPUT :: PRECISE ONSET DETECTION " + ofToString(exactOnsetIndex), 32, 32);
andrew@0 66 ofDrawBitmapString("press 's' to unpause the audio\n'e' to pause the audio", 31, 92);
andrew@0 67
andrew@0 68 ofNoFill();
andrew@0 69
andrew@0 70 // draw the left channel:
andrew@0 71 ofPushStyle();
andrew@0 72 ofPushMatrix();
andrew@0 73 ofTranslate(32, 120, 0);
andrew@0 74
andrew@0 75 ofSetColor(225);
andrew@0 76 ofDrawBitmapString("Left Channel", 4, 18);
andrew@0 77
andrew@0 78 ofSetLineWidth(1);
andrew@0 79 ofRect(0, 0, 512, 200);
andrew@0 80
andrew@0 81 ofSetColor(245, 58, 135);
andrew@0 82 ofSetLineWidth(3);
andrew@0 83
andrew@0 84 ofBeginShape();
andrew@0 85 for (int i = 0; i < left.size(); i++){
andrew@0 86 ofVertex(i, 100 -left[i]*180.0f);
andrew@0 87 }
andrew@0 88 ofEndShape(false);
andrew@0 89
andrew@0 90 ofPopMatrix();
andrew@0 91 ofPopStyle();
andrew@0 92
andrew@0 93 // draw the right channel:
andrew@0 94 ofPushStyle();
andrew@0 95 ofPushMatrix();
andrew@0 96 ofTranslate(32, 320, 0);
andrew@0 97
andrew@0 98 ofSetColor(225);
andrew@0 99 ofDrawBitmapString("Onset DF function", 4, 18);
andrew@0 100
andrew@0 101 ofSetLineWidth(1);
andrew@0 102 ofRect(0, 0, 512, 200);
andrew@2 103
andrew@2 104 //param
andrew@2 105 float heightFactor = 0.15;
andrew@2 106
andrew@0 107 ofSetColor(245, 58, 135);
andrew@0 108 ofSetLineWidth(3);
andrew@0 109
andrew@0 110 ofBeginShape();
andrew@0 111 for (int i = 0; i < peakProcess.recentDFsamples.size(); i++){
andrew@2 112 int height = 200 - peakProcess.recentDFsamples[i]*heightFactor;
andrew@0 113 ofVertex(i*6, height);
andrew@0 114 // if (recentDFonsetFound[i]){
andrew@0 115 // ofCircle(32+i*6, 376+height , 10);
andrew@0 116 // }
andrew@0 117 // ofVertex(i*2, 100 -right[i]*180.0f);
andrew@0 118 }
andrew@0 119 ofEndShape(false);
andrew@0 120
andrew@0 121 ofPopMatrix();
andrew@0 122 ofPopStyle();
andrew@0 123
andrew@0 124 //slope values
andrew@0 125 ofPushStyle();
andrew@0 126 ofPushMatrix();
andrew@0 127 ofTranslate(32, 320, 0);
andrew@0 128
andrew@0 129 ofSetLineWidth(1);
andrew@0 130
andrew@0 131 ofSetColor(25, 124, 235);
andrew@0 132 ofSetLineWidth(3);
andrew@0 133
andrew@0 134 ofBeginShape();
andrew@0 135 for (int i = 0; i < peakProcess.recentDFsamples.size(); i++){
andrew@2 136 int height = 200 - peakProcess.recentDFslopeValues[i]*heightFactor;
andrew@0 137 ofVertex(i*6, height);
andrew@0 138
andrew@0 139 }
andrew@0 140 ofEndShape(false);
andrew@0 141
andrew@0 142 ofPopMatrix();
andrew@0 143 ofPopStyle();
andrew@0 144
andrew@0 145
andrew@0 146 //ONSETS
andrew@0 147 ofPushStyle();
andrew@0 148 ofPushMatrix();
andrew@0 149 ofTranslate(32, 320, 0);
andrew@0 150
andrew@0 151 ofSetColor(25, 224, 135);
andrew@2 152
andrew@0 153 ofSetLineWidth(3);
andrew@0 154
andrew@0 155 ofBeginShape();
andrew@0 156 for (int i = 0; i < peakProcess.recentDFsamples.size(); i++){
andrew@0 157 if (peakProcess.recentDFonsetFound[i])
andrew@0 158 ofVertex(i*6, 0);
andrew@0 159 else {
andrew@2 160 ofVertex(i*6, 200);
andrew@0 161 }
andrew@0 162 }
andrew@0 163 ofEndShape(false);
andrew@0 164
andrew@0 165 ofPopMatrix();
andrew@0 166 ofPopStyle();
andrew@0 167
andrew@2 168
andrew@2 169
andrew@0 170 //ONSET Samples
andrew@0 171 ofPushStyle();
andrew@0 172 ofPushMatrix();
andrew@0 173 ofTranslate(32, 520, 0);
andrew@0 174
andrew@0 175 ofSetColor(245, 224, 235);
andrew@2 176 ofDrawBitmapString("exact onset index (in buffer) "+ofToString(exactOnsetIndex), 0, 20);
andrew@2 177
andrew@0 178 ofSetLineWidth(3);
andrew@0 179
andrew@0 180 ofBeginShape();
andrew@0 181 for (int i = 0; i < precisionLocator.onsetSamples.size(); i++){
andrew@0 182 int height = 100 + 100 * precisionLocator.onsetSamples[i];
andrew@0 183 ofVertex(i, height);
andrew@0 184 }
andrew@0 185 ofEndShape(false);
andrew@0 186
andrew@0 187 ofSetColor(240,0,0);
andrew@0 188 ofLine(exactOnsetIndex, 0, exactOnsetIndex, 200);//stripe where on
andrew@0 189
andrew@0 190 ofPopMatrix();
andrew@0 191 ofPopStyle();
andrew@0 192
andrew@0 193
andrew@0 194 // draw the average volume:
andrew@0 195 ofPushStyle();
andrew@0 196 ofPushMatrix();
andrew@0 197 ofTranslate(565, 120, 0);
andrew@0 198
andrew@0 199 ofSetColor(225);
andrew@0 200 ofDrawBitmapString("Scaled average vol (0-100): " + ofToString(scaledVol * 100.0, 0), 4, 18);
andrew@0 201 ofRect(0, 0, 400, 400);
andrew@0 202
andrew@0 203 ofSetColor(245, 58, 135);
andrew@0 204 ofFill();
andrew@0 205 ofCircle(200, 200, scaledVol * 190.0f);
andrew@0 206
andrew@0 207 //lets draw the volume history as a graph
andrew@0 208 ofBeginShape();
andrew@0 209 for (int i = 0; i < volHistory.size(); i++){
andrew@0 210 if( i == 0 ) ofVertex(i, 400);
andrew@0 211
andrew@0 212 ofVertex(i, 400 - volHistory[i] * 70);
andrew@0 213
andrew@0 214 if( i == volHistory.size() -1 ) ofVertex(i, 400);
andrew@0 215 }
andrew@0 216 ofEndShape(false);
andrew@0 217
andrew@0 218 ofPopMatrix();
andrew@0 219 ofPopStyle();
andrew@0 220
andrew@0 221 drawCounter++;
andrew@0 222
andrew@0 223 ofSetColor(225);
andrew@0 224 string reportString = "buffers received: "+ofToString(bufferCounter)+"\ndraw routines called: "+ofToString(drawCounter)+"\nticks: " + ofToString(soundStream.getTickCount());
andrew@0 225 ofDrawBitmapString(reportString, 32, 89);
andrew@0 226
andrew@0 227
andrew@0 228 if (peakProcess.newOnsetFound){
andrew@0 229 ofSetColor(255,0,0);
andrew@0 230 ofCircle(200,200,200);
andrew@0 231 }
andrew@0 232 }
andrew@0 233
andrew@0 234 //--------------------------------------------------------------
andrew@0 235 void testApp::audioIn(float * input, int bufferSize, int nChannels){
andrew@0 236
andrew@0 237 float curVol = 0.0;
andrew@0 238
andrew@0 239 // samples are "interleaved"
andrew@0 240 int numCounted = 0;
andrew@0 241
andrew@0 242 double frame[bufferSize];
andrew@0 243
andrew@0 244 for (int i = 0;i < bufferSize;i++){
andrew@0 245 frame[i] = (double) input[i*2];
andrew@0 246 }
andrew@0 247
andrew@0 248 double df_sample = (float) odf.getDFsample(frame);
andrew@0 249
andrew@0 250 bool peakFound = peakProcess.peakProcessing(df_sample);//our new fn to look for DF onset events
andrew@0 251
andrew@0 252 //when we find a peak, we get the precise location of it
andrew@0 253 if (peakFound && !holdOn){
andrew@1 254 exactOnsetIndex = precisionLocator.findExactOnset(&frame[0]);//divide by 512.0 or bufferSize to get [0,1] value
andrew@0 255 }
andrew@0 256
andrew@0 257 //need to store these continually to help in location process
andrew@0 258 precisionLocator.storeSamples(&frame[0]);
andrew@0 259
andrew@0 260
andrew@0 261 //lets go through each sample and calculate the root mean square which is a rough way to calculate volume
andrew@0 262 for (int i = 0; i < bufferSize; i++){
andrew@0 263
andrew@0 264 //recentBufferSamples[i] = frame[i];//store the last buffer in case needed for exact onset detection
andrew@0 265
andrew@0 266
andrew@0 267
andrew@0 268
andrew@0 269 left[i] = input[i*2]*0.5;
andrew@0 270 right[i] = input[i*2+1]*0.5;
andrew@0 271
andrew@0 272 curVol += left[i] * left[i];
andrew@0 273 curVol += right[i] * right[i];
andrew@0 274 numCounted+=2;
andrew@0 275
andrew@0 276 }
andrew@0 277
andrew@0 278 //this is how we get the mean of rms :)
andrew@0 279 curVol /= (float)numCounted;
andrew@0 280
andrew@0 281 // this is how we get the root of rms :)
andrew@0 282 curVol = sqrt( curVol );
andrew@0 283
andrew@0 284 smoothedVol *= 0.93;
andrew@0 285 smoothedVol += 0.07 * curVol;
andrew@0 286
andrew@0 287 bufferCounter++;
andrew@0 288
andrew@0 289 }
andrew@0 290 /*
andrew@0 291 int testApp::findExactOnset(){
andrew@0 292 double energySum = 0;
andrew@0 293 double lastEnergySum, hopsizeLastEnergySum;
andrew@0 294 double energyDifference;
andrew@0 295 int bestEnergyIndex = 0;
andrew@0 296 double bestEnergyDifference = 0;
andrew@0 297 int endIndex = bufferSize;
andrew@0 298 int hopSize;
andrew@0 299
andrew@0 300 for (int resolution = bufferSize/2;resolution > 1;resolution/=2){
andrew@0 301 printf("resolution %i\n", resolution);
andrew@0 302 /// for (int i = bufferSize - resolution;i < bufferSize;i++){
andrew@0 303 // lastEnergySum += recentBufferSamples[i] * recentBufferSamples[i];
andrew@0 304 // }
andrew@0 305
andrew@0 306 bestEnergyDifference = 0;
andrew@0 307 // printf("previous energy %f", lastEnergySum);
andrew@0 308 //initialise last energySum
andrew@0 309 hopSize = resolution/2;
andrew@0 310
andrew@0 311
andrew@0 312 lastEnergySum = getLastEnergySum(bestEnergyIndex, resolution);
andrew@0 313 hopsizeLastEnergySum = getLastEnergySum(bestEnergyIndex + hopSize, resolution);
andrew@0 314
andrew@0 315 for (int startIndex = bestEnergyIndex;startIndex + resolution <= endIndex;startIndex += hopSize){
andrew@0 316 printf("index %i last energy %f hop energy %f ", startIndex, lastEnergySum, hopsizeLastEnergySum);
andrew@0 317
andrew@0 318 //sum the energy for this new frame
andrew@0 319 energySum = 0;
andrew@0 320 for (int i = 0;i < resolution;i++){
andrew@0 321 energySum += onsetSamples[startIndex + i] * onsetSamples[startIndex + i];
andrew@0 322 }
andrew@0 323
andrew@0 324 printf("energysum %f\n", energySum);
andrew@0 325 //check if new max difference
andrew@0 326 energyDifference = energySum - lastEnergySum;
andrew@0 327 if (energyDifference > bestEnergyDifference){
andrew@0 328 bestEnergyDifference = energyDifference;
andrew@0 329 bestEnergyIndex = startIndex;
andrew@0 330 }
andrew@0 331
andrew@0 332 //store the values for checking in two loops time (because proceeding at resolution/2 each step)
andrew@0 333 //eg 0_to_128 compared to -128_to_0, 64_to_196 compared to -64_to_64, then 128_256 compared with 0_to_128,
andrew@0 334 lastEnergySum = hopsizeLastEnergySum;// energySum;
andrew@0 335 hopsizeLastEnergySum = energySum;
andrew@0 336
andrew@0 337 }
andrew@0 338 printf("winning index is %i\n", bestEnergyIndex);
andrew@0 339 endIndex = bestEnergyIndex + resolution;
andrew@0 340
andrew@0 341 }
andrew@0 342 printf("TOTAL WINNER %i\n", bestEnergyIndex);
andrew@0 343 return bestEnergyIndex;
andrew@0 344
andrew@0 345 }
andrew@0 346
andrew@0 347 double testApp::getLastEnergySum(const int& startIndex, const int& vectorSize){
andrew@0 348 double lastEnergySum = 0;
andrew@0 349
andrew@0 350 for (int i = startIndex - vectorSize;i < startIndex;i++){
andrew@0 351 if (i > 0)
andrew@0 352 lastEnergySum += onsetSamples[i] * onsetSamples[i];
andrew@0 353 else {
andrew@0 354 lastEnergySum += recentBufferSamples[bufferSize + i] * recentBufferSamples[bufferSize + i];
andrew@0 355 }
andrew@0 356 }
andrew@0 357 return lastEnergySum;
andrew@0 358
andrew@0 359 }
andrew@0 360 */
andrew@0 361 /*
andrew@0 362 bool testApp::peakProcessing(const double& newDFval){
andrew@0 363 recentDFsamples.erase (recentDFsamples.begin(), recentDFsamples.begin()+1);//erase first val
andrew@0 364 recentDFsamples.push_back(newDFval);
andrew@0 365
andrew@0 366 double slopeVal = getBestSlopeValue(newDFval);
andrew@0 367
andrew@0 368 newOnsetFound = checkForSlopeOnset(slopeVal);
andrew@0 369 printf("slope %f median %f det median %f\n", slopeVal, bestSlopeMedian, detectionTriggerThreshold);
andrew@0 370
andrew@0 371 if (newOnsetFound)
andrew@0 372 printf("BANG!\n");
andrew@0 373
andrew@0 374 recentDFslopeValues.erase (recentDFslopeValues.begin(), recentDFslopeValues.begin()+1);//erase first val
andrew@0 375 recentDFslopeValues.push_back(slopeVal);
andrew@0 376
andrew@0 377 recentDFonsetFound.erase (recentDFonsetFound.begin(), recentDFonsetFound.begin()+1);//erase first val
andrew@0 378 recentDFonsetFound.push_back(newOnsetFound);
andrew@0 379
andrew@0 380
andrew@0 381 //printf("\n");
andrew@0 382 // for (int i = 0;i < recentDFsamples.size();i++){
andrew@0 383 // printf("rdf[%i] %f\n", i, recentDFsamples[i]);
andrew@0 384 // }
andrew@0 385 //printf("SLOPE %f\n", slopeVal);
andrew@0 386 }
andrew@0 387
andrew@0 388
andrew@0 389 double testApp::getBestSlopeValue(const float& dfvalue){
andrew@0 390
andrew@0 391 //the idea is we want a high slope
andrew@0 392 double bestValue = 0;
andrew@0 393
andrew@0 394 for (int i = 1;i < min(numberOfDetectionValuesToTest, (int)recentDFsamples.size() - 1);i++){
andrew@0 395 double angle = 0;
andrew@0 396 int otherIndex = recentDFsamples.size() - i + 1;
andrew@0 397 double testValue = 0;
andrew@0 398
andrew@0 399 if (otherIndex > 0 && recentDFsamples[otherIndex] > 0
andrew@0 400 && recentDFsamples[otherIndex] < dfvalue
andrew@0 401 ){
andrew@0 402 angle = atan((float)(i * dfvalue)/ (numberOfDetectionValuesToTest*(dfvalue-recentDFsamples[otherIndex])) );
andrew@0 403 testValue = (dfvalue - recentDFsamples[otherIndex]) * cos(angle);
andrew@0 404 }
andrew@0 405
andrew@0 406 if (testValue > bestValue)
andrew@0 407 bestValue = testValue;
andrew@0 408 }
andrew@0 409
andrew@0 410 return bestValue;
andrew@0 411
andrew@0 412 }
andrew@0 413
andrew@0 414
andrew@0 415
andrew@0 416 bool testApp :: checkForSlopeOnset(const float& bestValue){
andrew@0 417 bool onsetDetected = false;
andrew@0 418 //check for onset relative to our processed slope function
andrew@0 419 //a mix between increase in value and the gradient of that increase
andrew@0 420
andrew@0 421 currentFrame++;
andrew@0 422
andrew@0 423 if (bestValue > bestSlopeMedian * thresholdRelativeToMedian && //better than recent average
andrew@0 424 (currentFrame - lastSlopeOnsetFrame) > cutoffForRepeatOnsetsFrames //after cutoff time
andrew@0 425 && slopeFallenBelowMedian // has had onset and fall away again
andrew@0 426 && bestValue > detectionTriggerThreshold * detectionTriggerRatio //longer term ratio of winning onsets
andrew@0 427 ){
andrew@0 428 // printf("frame diff between onsets %6.1f", (1000*framesToSeconds(currentFrame - lastMedianOnsetFrame)) );
andrew@0 429 onsetDetected = true;
andrew@0 430 lastSlopeOnsetFrame = currentFrame;
andrew@0 431 slopeFallenBelowMedian = false;
andrew@0 432
andrew@0 433 updateDetectionTriggerThreshold(bestValue);
andrew@0 434 }
andrew@0 435
andrew@0 436
andrew@0 437 if (bestValue > bestSlopeMedian){
andrew@0 438 bestSlopeMedian += (bestValue - bestSlopeMedian)*0.04;//was 1.1
andrew@0 439 }
andrew@0 440 else{
andrew@0 441 bestSlopeMedian *= 0.99;
andrew@0 442 slopeFallenBelowMedian = true;;
andrew@0 443 }
andrew@0 444
andrew@0 445 //bestSlopeMedian += 0.02* (bestValue - bestSlopeMedian);
andrew@0 446
andrew@0 447
andrew@0 448
andrew@0 449 return onsetDetected;
andrew@0 450 }
andrew@0 451
andrew@0 452 void testApp :: updateDetectionTriggerThreshold(const float& val){
andrew@0 453 float detectionAdaptSpeed = 0.05;//moving average, roughly last twenty onsets
andrew@0 454 detectionTriggerThreshold *= 1- detectionAdaptSpeed;
andrew@0 455 detectionTriggerThreshold += (val * detectionAdaptSpeed);
andrew@0 456 }
andrew@0 457
andrew@0 458 */
andrew@0 459 //--------------------------------------------------------------
andrew@0 460 void testApp::keyPressed (int key){
andrew@0 461 if( key == 's' ){
andrew@0 462 soundStream.start();
andrew@0 463 }
andrew@0 464
andrew@0 465 if( key == 'e' ){
andrew@0 466 soundStream.stop();
andrew@0 467 }
andrew@0 468
andrew@0 469 if (key == 'h'){
andrew@0 470 holdOn = !holdOn;
andrew@0 471 }
andrew@0 472 }
andrew@0 473
andrew@0 474 //--------------------------------------------------------------
andrew@0 475 void testApp::keyReleased(int key){
andrew@0 476
andrew@0 477 }
andrew@0 478
andrew@0 479 //--------------------------------------------------------------
andrew@0 480 void testApp::mouseMoved(int x, int y ){
andrew@0 481
andrew@0 482 }
andrew@0 483
andrew@0 484 //--------------------------------------------------------------
andrew@0 485 void testApp::mouseDragged(int x, int y, int button){
andrew@0 486
andrew@0 487 }
andrew@0 488
andrew@0 489 //--------------------------------------------------------------
andrew@0 490 void testApp::mousePressed(int x, int y, int button){
andrew@0 491
andrew@0 492 }
andrew@0 493
andrew@0 494 //--------------------------------------------------------------
andrew@0 495 void testApp::mouseReleased(int x, int y, int button){
andrew@0 496
andrew@0 497 }
andrew@0 498
andrew@0 499 //--------------------------------------------------------------
andrew@0 500 void testApp::windowResized(int w, int h){
andrew@0 501
andrew@0 502 }
andrew@0 503
andrew@0 504 //--------------------------------------------------------------
andrew@0 505 void testApp::gotMessage(ofMessage msg){
andrew@0 506
andrew@0 507 }
andrew@0 508
andrew@0 509 //--------------------------------------------------------------
andrew@0 510 void testApp::dragEvent(ofDragInfo dragInfo){
andrew@0 511
andrew@0 512 }
andrew@0 513