iphone - Tap pressure strength detection using accelerometer -


yesterday, in presentation new garageband ipad 2, apple demoed interesting feature: detection of tap pressure using accelerometer. (see drums section on garageband page.)

i'm wondering how that's supposed work if ipad lays flat on table. no movement, no measurable acceleration, no?

some answers. here's working code. implemented subclass of uigesturerecognizer can drop in , attach uiview or uibutton. once triggered, have "pressure" set float between 0.0f , 2.0f. can optionally set minimum , maximum pressures required recognize. enjoy.

// //  cpbpressuretouchgesturerecognizer.h //  pressuresensitivebutton // //  created anthony picciano on 3/21/11. //  copyright 2011 anthony picciano. rights reserved. // //  redistribution , use in source , binary forms, or without //  modification, permitted provided following conditions //  met: //  1. redistributions of source code must retain above copyright //     notice, list of conditions , following disclaimer. //  2. redistributions in binary form must reproduce above copyright //     notice, list of conditions , following disclaimer in //     documentation and/or other materials provided distribution. //   //  software provided author ``as is'' , express or //  implied warranties, including, not limited to, implied warranties //  of merchantability , fitness particular purpose disclaimed. //  in no event shall author liable direct, indirect, //  incidental, special, exemplary, or consequential damages (including, //  not limited to, procurement of substitute goods or services; loss of use, //  data, or profits; or business interruption) caused , on //  theory of liability, whether in contract, strict liability, or tort //  (including negligence or otherwise) arising in way out of use of //  software, if advised of possibility of such damage. //  #import <uikit/uikit.h>  #define cpbpressurenone         0.0f #define cpbpressurelight        0.1f #define cpbpressuremedium       0.3f #define cpbpressurehard         0.8f #define cpbpressureinfinite     2.0f  @interface cpbpressuretouchgesturerecognizer : uigesturerecognizer <uiaccelerometerdelegate> {     @public     float pressure;     float minimumpressurerequired;     float maximumpressurerequired;      @private     float pressurevalues[30];     uint currentpressurevalueindex;     uint setnextpressurevalue; }  @property (readonly, assign) float pressure; @property (readwrite, assign) float minimumpressurerequired; @property (readwrite, assign) float maximumpressurerequired;  @end   // //  cpbpressuretouchgesturerecognizer.h //  pressuresensitivebutton // //  created anthony picciano on 3/21/11. //  copyright 2011 anthony picciano. rights reserved. // //  redistribution , use in source , binary forms, or without //  modification, permitted provided following conditions //  met: //  1. redistributions of source code must retain above copyright //     notice, list of conditions , following disclaimer. //  2. redistributions in binary form must reproduce above copyright //     notice, list of conditions , following disclaimer in //     documentation and/or other materials provided distribution. //   //  software provided author ``as is'' , express or //  implied warranties, including, not limited to, implied warranties //  of merchantability , fitness particular purpose disclaimed. //  in no event shall author liable direct, indirect, //  incidental, special, exemplary, or consequential damages (including, //  not limited to, procurement of substitute goods or services; loss of use, //  data, or profits; or business interruption) caused , on //  theory of liability, whether in contract, strict liability, or tort //  (including negligence or otherwise) arising in way out of use of //  software, if advised of possibility of such damage. //  #import <uikit/uigesturerecognizersubclass.h> #import "cpbpressuretouchgesturerecognizer.h"  #define kupdatefrequency            60.0f #define knumberofpressuresamples    3  @interface cpbpressuretouchgesturerecognizer (private) - (void)setup; @end  @implementation cpbpressuretouchgesturerecognizer @synthesize pressure, minimumpressurerequired, maximumpressurerequired;  - (id)initwithtarget:(id)target action:(sel)action {     self = [super initwithtarget:target action:action];     if (self != nil) {        [self setup];      }     return self; }  - (id)init {     self = [super init];     if (self != nil) {         [self setup];     }     return self; }  - (void)setup {     minimumpressurerequired = cpbpressurenone;     maximumpressurerequired = cpbpressureinfinite;     pressure = cpbpressurenone;      [[uiaccelerometer sharedaccelerometer] setupdateinterval:1.0f / kupdatefrequency];     [[uiaccelerometer sharedaccelerometer] setdelegate:self]; }  #pragma - #pragma uiaccelerometerdelegate methods  -(void)accelerometer:(uiaccelerometer *)accelerometer didaccelerate:(uiacceleration *)acceleration {     int sz = (sizeof pressurevalues) / (sizeof pressurevalues[0]);      // set current pressure value     pressurevalues[currentpressurevalueindex%sz] = acceleration.z;      if (setnextpressurevalue > 0) {          // calculate average pressure         float total = 0.0f;         (int loop=0; loop<sz; loop++) total += pressurevalues[loop];          float average = total / sz;          // start recent past pressure sample         if (setnextpressurevalue == knumberofpressuresamples) {             float mostrecent = pressurevalues[(currentpressurevalueindex-1)%sz];             pressure = fabsf(average - mostrecent);         }          // caluculate pressure difference between average , current acceleration         float diff = fabsf(average - acceleration.z);         if (pressure < diff) pressure = diff;         setnextpressurevalue--;          if (setnextpressurevalue == 0) {             if (pressure >= minimumpressurerequired && pressure <= maximumpressurerequired)                 self.state = uigesturerecognizerstaterecognized;             else                 self.state = uigesturerecognizerstatefailed;         }     }      currentpressurevalueindex++; }  #pragma - #pragma uigesturerecognizer subclass methods  - (void)touchesbegan:(nsset *)touches withevent:(uievent *)event {     setnextpressurevalue = knumberofpressuresamples;     self.state = uigesturerecognizerstatepossible; }  - (void)touchescancelled:(nsset *)touches withevent:(uievent *)event {     self.state = uigesturerecognizerstatefailed; }  - (void)reset {     pressure = cpbpressurenone;     setnextpressurevalue = 0;     currentpressurevalueindex = 0; }  @end 

Comments

Popular posts from this blog

c# - How to set Z index when using WPF DrawingContext? -

razor - Is this a bug in WebMatrix PageData? -

visual c++ - Using relative values in array sorting ( asm ) -