2011-06-30 11 views
0

私は、サウンドのデシベル値を、coreplotを使ってグラフ(CPScatterPlot)にプロットしようとしています。しかし問題は、Y軸に対して垂直な線でグラフを取得し、デシベル値の変化に対してY軸上を上下に移動していることです。私はこのようなグラフをプロットする必要があります。ここenter image description herecoreplotを使ってグラフをリアルタイムでプロットする方法は?

が私のコードです: `

-(void) generateDataSamples 
    { 

    samples = [[NSMutableArray alloc]initWithCapacity:NUM_SAMPLES]; 

    for (int i=0; i < NUM_SAMPLES; i++) 

     { 
      // peakVal is a variable that holds the decibel value 
      NSDictionary *sample = [NSDictionary dictionaryWithObjectsAndKeys:       
      [NSNumber numberWithDouble:peakVal],Y_VAL,nil]; 
      [samples addObject:sample]; 
      } 

    } 

-(NSUInteger)numberOfRecordsForPlot:(CPPlot *)plot; 
{ 
    return [samples count]; 
} 

-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum 
       recordIndex:(NSUInteger)index{ 

NSDictionary *sample = [samples objectAtIndex:index]; 
NSDecimalNumber *num = [NSDecimalNumber zero]; 
    if (fieldEnum == CPScatterPlotFieldX) 
    { 
     num = (NSDecimalNumber *) [NSDecimalNumber numberWithInt:index + 1]; 
    } 
    else if (fieldEnum == CPScatterPlotFieldY) 
    { 
    return [sample valueForKey:Y_VAL]; 
    } 
    return num; 
} 

だから、私は、上図のようなグラフを得るために何をすべきでしょうか?私を助けてください、私はここで新しいです。

もう1つ、上記の図のように、Y軸ラベルがプロット領域内に配置されています。

はここに私のコード全体で、変更を提案してください:あなたは、すべてのデータポイントに同じpeakValを使用しているよう

#import "MicBlowViewController.h" 
#import "SecondVC.h" 
#define DBOFFSET -74.0 
#define START_POINT 0.0 
#define END_POINT 100.0 
#define NUM_SAMPLES 200.0 
#define MAX_PEAK 100.0 

#define X_VAL @"X_VAL" 
#define Y_VAL @"Y_VAL" 
#define S_VAL @"S_VAL" 


@implementation MicBlowViewController 
@synthesize avgLabel, peakLabel,absValue,pageControl; 


-(void)reloadData 
{ 
    if(!graph) 
    { 
     //setting graph 
     double xAxisStart = START_POINT; 
     double xAxisLength = END_POINT - START_POINT; 
     double maxY = 100;//[[samples valueForKeyPath:@"@max.Y_VAL"] doubleValue]; 
     double yAxisStart = START_POINT; 
     double yAxisLength = maxY+3; 
     xVal=START_POINT+0.1; 
     hostingView = [[CPGraphHostingView alloc] initWithFrame:CGRectMake(0, 79, 320, 361)]; 
     [self.view addSubview:hostingView]; 
     graph = [[CPXYGraph alloc] initWithFrame:CGRectMake(0, 79, 320, 361)]; 
     hostingView.hostedGraph = graph; 

     CPTheme *theme = [CPTheme themeNamed:kCPDarkGradientTheme]; 
     [graph applyTheme:theme]; 
     graph.paddingTop = 0.0; 
     graph.paddingBottom = 0.0; 
     graph.paddingLeft = 0.0; 
     graph.paddingRight = 0.0; 
     [[graph defaultPlotSpace] setAllowsUserInteraction:TRUE]; 
     CPXYAxisSet *axisSet = (CPXYAxisSet *)graph.axisSet; 
     axisSet.yAxis.labelOffset=0.1; 
     CPXYAxis *x = axisSet.xAxis; 
     x.majorIntervalLength = CPDecimalFromDouble(10.0); 
     x.orthogonalCoordinateDecimal = CPDecimalFromInteger(0); 
     x.minorTicksPerInterval = 1; 

     CPXYAxis *y = axisSet.yAxis; 

     y.majorIntervalLength=CPDecimalFromDouble(10.0); 
     y.orthogonalCoordinateDecimal = CPDecimalFromInteger(0); 
     y.minorTicksPerInterval = 1; 
     y.tickDirection = CPSignPositive; 
     y.labelAlignment = CPAlignmentLeft; 
     y.alternatingBandFills = [NSArray arrayWithObjects:[[CPColor whiteColor] colorWithAlphaComponent:0.1], [NSNull null], nil]; 
     CPXYPlotSpace *plotSpace = (CPXYPlotSpace *)graph.defaultPlotSpace; 
     plotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromDouble(xAxisStart) 
                 length:CPDecimalFromDouble(xAxisLength)]; 

     plotSpace.yRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromDouble(yAxisStart) 
                 length:CPDecimalFromDouble(yAxisLength)];  

     CPScatterPlot *dataSourceLinePlot = [[CPScatterPlot alloc] init]; 
     dataSourceLinePlot.dataSource = self; 
     //[dataSourceLinePlot insertDataAtIndex:[samplesY count]-1 numberOfRecords:1]; 

     CPMutableLineStyle *lineStyle = [[dataSourceLinePlot.dataLineStyle mutableCopy] autorelease]; 
     lineStyle.lineWidth = 2.f; 
     lineStyle.lineColor = [CPColor cyanColor]; 
     dataSourceLinePlot.dataLineStyle = lineStyle; 

     [graph addPlot:dataSourceLinePlot]; 

     [dataSourceLinePlot release]; 
     [graph release]; 
     [hostingView release]; 
    } 
} 

- (void)generateData 
{ 

     // if (plotData == nil) { 
     NSMutableArray *contentArray = [NSMutableArray array]; 

     for (NSUInteger i = 0; i < 200; i++) { 
      //double test = (double)[peakLabel.text doubleValue]; 
      absValue.text =[NSString stringWithFormat:@"%.2f",peakVal]; 
      id x = [NSDecimalNumber numberWithDouble:1.0 + i ]; 
      id y = [NSDecimalNumber numberWithDouble:peakVal * rand()/(double)RAND_MAX + 0.05]; 
      [contentArray addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:x, @"x", y, @"y", nil]]; 
     } 
     plotData = [contentArray retain]; 
     //} 

} 
-(NSUInteger)numberOfRecordsForPlot:(CPPlot *)plot ; 
{ 
    return [plotData count]; 
} 

-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum 
       recordIndex:(NSUInteger)index; 
{ 
    NSNumber *num = [[plotData objectAtIndex:index] valueForKey:(fieldEnum == CPScatterPlotFieldX ? @"x" : @"y")]; 

    if (fieldEnum == CPScatterPlotFieldY) { 
     num = [NSNumber numberWithDouble:[num doubleValue]]; 

    } 
    return num; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    pageControl = [[UIPageControl alloc]init]; 
    [pageControl addTarget:self action:@selector(changePage) forControlEvents:UIControlEventValueChanged]; 
    samplesY = [[NSMutableArray alloc]init]; 
    //checking for sound 
    NSURL *url = [NSURL fileURLWithPath:@"/dev/null"]; 

    NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys: 
           [NSNumber numberWithFloat: 44100.0],     AVSampleRateKey, 
           [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey, 
           [NSNumber numberWithInt: 1],       AVNumberOfChannelsKey, 
           [NSNumber numberWithInt: AVAudioQualityMax],   AVEncoderAudioQualityKey, 
           nil]; 

    NSError *error; 
    recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error]; 

    if (recorder) { 
     [recorder prepareToRecord]; 
     recorder.meteringEnabled = YES; 
     [recorder record]; 
     levelTimer = [NSTimer scheduledTimerWithTimeInterval: 0.03 target: self selector: @selector(levelTimerCallback:) userInfo: nil repeats: YES]; 
    }// else 
    //NSLog([error description]); 
} 


- (void)levelTimerCallback:(NSTimer *)timer { 
    // getting decibel values.... 
    [recorder updateMeters]; 

    const double ALPHA = 0.05; 
    double peakPowerForChannel = pow(10, (0.05 * [recorder peakPowerForChannel:0])); 

    lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults; 

    NSLog(@"Average input: %f Peak input: %f Low pass results: %f", 
      [recorder averagePowerForChannel:0], [recorder peakPowerForChannel:0], lowPassResults); 
    peakval=fabs([recorder peakPowerForChannel:0]); 
    double avgval=fabs([recorder averagePowerForChannel:0]); 
    peakVal=MAX_PEAK - peakval; 
    avgVal=MAX_PEAK - avgval; 
    NSLog(@"First: %.2f",peakVal); 

    avgLabel.text=[NSString stringWithFormat:@"%.2f",avgVal]; 
    peakLabel.text=[NSString stringWithFormat:@"%.2f",peakVal]; 
    if (lowPassResults < 0.95) 
     NSLog(@"Mic blow detected: %d",lowPassResults); 

    [self generateData]; 

    [self reloadData]; 

} 

- (IBAction) changePage:(id)sender{ 
    SecondVC *vc = [[SecondVC alloc]init]; 
    vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; 
    [self presentModalViewController:vc animated:YES]; 
    [vc release]; 
} 

- (void)dealloc { 
    [peakLabel.text release]; 
    [avgLabel.text release]; 
    [samples release]; 
    [levelTimer release]; 
    [recorder release]; 
    [super dealloc]; 
} 

@end 

答えて

2

に見えます。 -generateDataSamplesメソッドを確認し、正しい値をsamples配列に格納していることを確認してください。配列内に既にデータがある場合は、そのメソッドを完全にスキップして、-numberForPlot:field:recordIndex:のインデックスでルックアップしてください。

また、プロットスペースのxRangeyRangeをチェックして、それらが自分のデータに合っていることを確認します。プロットの範囲はNSRangeのようなもので、開始位置と終了位置ではなく、開始位置と長さを使用して作成されます。

ラベルをy軸の右側に移動するには、yAxis.tickDirection = CPTSignPositive;を使用します。コメント

に応じて

編集は、新しいデータを取得するたびに-generateDataSamplesを呼び出さないでください。代わりに、新しい値をsamples配列に追加します。アレイを初めて使用する前に、アレイを初期化することを忘れないでください。

NSDictionary *sample = [NSDictionary dictionaryWithObjectsAndKeys:       
    [NSNumber numberWithDouble:peakVal],Y_VAL,nil]; 
[samples addObject:sample]; 

データが配列に入ったら、Core Plotに新しいポイントだけをロードするように指示します。これは、更新するたびにすべてのデータをリロードするよりも速くなります。

[myScatterPlot insertDataAtIndex:(samples.count - 1) 
       numberOfRecords:1]; 

あなたがグラフに歴史のすべてを維持する必要がない場合は、古いデータポイントを削除するにはCPTPlotメソッド-deleteDataInIndexRange:を使用することができます。 samples配列からも対応するポイントを削除することを忘れないでください。

+0

yAxis.tickDirection = CPTSignPositive;私が使用しているcoreplotのバージョンでは動作しません。小さな変更が必要、yAxis.tickDirection = CPSignPositive;ありがとうございます – Mithun

+0

私はそれをまだ働かせることができませんでした。私はここに新しいです、助けてください。 – Mithun

+0

誰かが私を助けてください、私はこの3日間最後に働いています。 – Mithun

関連する問題