Browse Source

First stubs:

- View with rulers
- FFT with Accelerated framework
- Opening music from iTunes (almost)
TODO: ducktape things together
master
Joshua Moerman 10 years ago
parent
commit
75f469885d
  1. 5
      .gitignore
  2. 34
      SpectogramPrototype.xcodeproj/project.pbxproj
  3. 61
      SpectogramPrototype/Base.lproj/Main_iPad.storyboard
  4. 68
      SpectogramPrototype/ContentView.xib
  5. 14
      SpectogramPrototype/FFTTest.h
  6. 77
      SpectogramPrototype/FFTTest.m
  7. 15
      SpectogramPrototype/RuledScrollView.h
  8. 109
      SpectogramPrototype/RuledScrollView.m
  9. 8
      SpectogramPrototype/ViewController.h
  10. 101
      SpectogramPrototype/ViewController.m

5
.gitignore

@ -0,0 +1,5 @@
*xcworkspace
*xcuserdata
build

34
SpectogramPrototype.xcodeproj/project.pbxproj

@ -22,6 +22,13 @@
424F84CD18661F8000687D3B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 424F84AC18661F8000687D3B /* UIKit.framework */; };
424F84D518661F8000687D3B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 424F84D318661F8000687D3B /* InfoPlist.strings */; };
424F84D718661F8000687D3B /* SpectogramPrototypeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 424F84D618661F8000687D3B /* SpectogramPrototypeTests.m */; };
4261F08818671ECD00AA0EF9 /* ContentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4261F08718671ECD00AA0EF9 /* ContentView.xib */; };
426665B51869A7CC005D62AC /* RuledScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 426665B41869A7CC005D62AC /* RuledScrollView.m */; };
426665B81869CEFE005D62AC /* FFTTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 426665B71869CEFE005D62AC /* FFTTest.m */; };
426665BA1869CF73005D62AC /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 426665B91869CF73005D62AC /* Accelerate.framework */; };
426665BC1869EF4B005D62AC /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 426665BB1869EF4B005D62AC /* CoreAudio.framework */; };
426665C11869F194005D62AC /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 426665C01869F194005D62AC /* AudioToolbox.framework */; };
426665C51869F50B005D62AC /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 426665C41869F50B005D62AC /* MediaPlayer.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -55,6 +62,15 @@
424F84D218661F8000687D3B /* SpectogramPrototypeTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SpectogramPrototypeTests-Info.plist"; sourceTree = "<group>"; };
424F84D418661F8000687D3B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
424F84D618661F8000687D3B /* SpectogramPrototypeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SpectogramPrototypeTests.m; sourceTree = "<group>"; };
4261F08718671ECD00AA0EF9 /* ContentView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ContentView.xib; sourceTree = "<group>"; };
426665B31869A7CC005D62AC /* RuledScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuledScrollView.h; sourceTree = "<group>"; };
426665B41869A7CC005D62AC /* RuledScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RuledScrollView.m; sourceTree = "<group>"; };
426665B61869CEFE005D62AC /* FFTTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FFTTest.h; sourceTree = "<group>"; };
426665B71869CEFE005D62AC /* FFTTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FFTTest.m; sourceTree = "<group>"; };
426665B91869CF73005D62AC /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
426665BB1869EF4B005D62AC /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
426665C01869F194005D62AC /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
426665C41869F50B005D62AC /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -62,6 +78,10 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
426665C51869F50B005D62AC /* MediaPlayer.framework in Frameworks */,
426665C11869F194005D62AC /* AudioToolbox.framework in Frameworks */,
426665BC1869EF4B005D62AC /* CoreAudio.framework in Frameworks */,
426665BA1869CF73005D62AC /* Accelerate.framework in Frameworks */,
424F84AB18661F8000687D3B /* CoreGraphics.framework in Frameworks */,
424F84AD18661F8000687D3B /* UIKit.framework in Frameworks */,
424F84A918661F8000687D3B /* Foundation.framework in Frameworks */,
@ -103,6 +123,10 @@
424F84A718661F8000687D3B /* Frameworks */ = {
isa = PBXGroup;
children = (
426665C41869F50B005D62AC /* MediaPlayer.framework */,
426665C01869F194005D62AC /* AudioToolbox.framework */,
426665BB1869EF4B005D62AC /* CoreAudio.framework */,
426665B91869CF73005D62AC /* Accelerate.framework */,
424F84A818661F8000687D3B /* Foundation.framework */,
424F84AA18661F8000687D3B /* CoreGraphics.framework */,
424F84AC18661F8000687D3B /* UIKit.framework */,
@ -120,6 +144,11 @@
424F84BD18661F8000687D3B /* Main_iPad.storyboard */,
424F84C018661F8000687D3B /* ViewController.h */,
424F84C118661F8000687D3B /* ViewController.m */,
426665B31869A7CC005D62AC /* RuledScrollView.h */,
426665B41869A7CC005D62AC /* RuledScrollView.m */,
426665B61869CEFE005D62AC /* FFTTest.h */,
426665B71869CEFE005D62AC /* FFTTest.m */,
4261F08718671ECD00AA0EF9 /* ContentView.xib */,
424F84C318661F8000687D3B /* Images.xcassets */,
424F84AF18661F8000687D3B /* Supporting Files */,
);
@ -234,6 +263,7 @@
424F84BF18661F8000687D3B /* Main_iPad.storyboard in Resources */,
424F84C418661F8000687D3B /* Images.xcassets in Resources */,
424F84BC18661F8000687D3B /* Main_iPhone.storyboard in Resources */,
4261F08818671ECD00AA0EF9 /* ContentView.xib in Resources */,
424F84B318661F8000687D3B /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -253,8 +283,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
426665B81869CEFE005D62AC /* FFTTest.m in Sources */,
424F84C218661F8000687D3B /* ViewController.m in Sources */,
424F84B918661F8000687D3B /* AppDelegate.m in Sources */,
426665B51869A7CC005D62AC /* RuledScrollView.m in Sources */,
424F84B518661F8000687D3B /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -474,6 +506,7 @@
424F84DC18661F8000687D3B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
424F84DD18661F8000687D3B /* Build configuration list for PBXNativeTarget "SpectogramPrototypeTests" */ = {
isa = XCConfigurationList;
@ -482,6 +515,7 @@
424F84DF18661F8000687D3B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};

61
SpectogramPrototype/Base.lproj/Main_iPad.storyboard

@ -1,21 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="4451" systemVersion="13A461" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES" initialViewController="BYZ-38-t0r">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES" initialViewController="DUW-zh-mwd">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3676"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3747"/>
</dependencies>
<scenes>
<!--class Prefix:identifier View Controller-->
<scene sceneID="tne-QT-ifu">
<!--View Controller-->
<scene sceneID="B70-p7-wwL">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="20" width="768" height="1004"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<viewController id="DUW-zh-mwd" customClass="ViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="n1Z-VL-Qbf"/>
<viewControllerLayoutGuide type="bottom" id="yY7-qN-ozv"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="hed-94-g1X">
<rect key="frame" x="0.0" y="0.0" width="768" height="1024"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" minimumZoomScale="0.5" maximumZoomScale="4" translatesAutoresizingMaskIntoConstraints="NO" id="chg-BV-Ue8" customClass="RuledScrollView">
<rect key="frame" x="0.0" y="0.0" width="768" height="1024"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.40000000600000002" green="1" blue="0.40000000600000002" alpha="1" colorSpace="calibratedRGB"/>
</scrollView>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Bzu-fO-jsM">
<rect key="frame" x="200" y="200" width="111" height="42"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="22"/>
<state key="normal" title="Calculate!">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="calculateButtonPressed:" destination="DUW-zh-mwd" eventType="touchUpInside" id="4Rp-2D-265"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kj8-JR-vKG">
<rect key="frame" x="200" y="300" width="111" height="42"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="22"/>
<state key="normal" title="Media">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="mediaButtonPressed:" destination="DUW-zh-mwd" eventType="touchUpInside" id="hZd-Q2-HcR"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="chg-BV-Ue8" secondAttribute="trailing" id="0fj-54-kGr"/>
<constraint firstItem="chg-BV-Ue8" firstAttribute="top" secondItem="hed-94-g1X" secondAttribute="top" id="OzJ-ZW-YG0"/>
<constraint firstAttribute="bottom" secondItem="chg-BV-Ue8" secondAttribute="bottom" id="Sc7-ra-bZs"/>
<constraint firstItem="chg-BV-Ue8" firstAttribute="leading" secondItem="hed-94-g1X" secondAttribute="leading" id="vH2-JI-XSk"/>
</constraints>
</view>
<connections>
<outlet property="scrollView" destination="chg-BV-Ue8" id="WUp-YA-u0t"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="Hdo-F1-anW" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-189" y="-654"/>
</scene>
</scenes>
<simulatedMetricsContainer key="defaultSimulatedMetrics">

68
SpectogramPrototype/ContentView.xib

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="4514"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ViewController">
<connections>
<outlet property="contentView" destination="1" id="waQ-1e-XtN"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="1">
<rect key="frame" x="0.0" y="0.0" width="534" height="376"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qOE-WQ-xv7">
<rect key="frame" x="414" y="256" width="100" height="100"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.40000000600000002" green="1" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="100" id="20Q-nP-HWg"/>
<constraint firstAttribute="width" constant="100" id="Isk-N0-p0Z"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="V5r-JV-Fkh">
<rect key="frame" x="414" y="20" width="100" height="100"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.80000001192092896" green="1" blue="0.40000000596046448" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="100" id="GAt-IV-PXp"/>
<constraint firstAttribute="height" constant="100" id="eYY-eK-hai"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xhz-dx-nq1">
<rect key="frame" x="20" y="20" width="100" height="100"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="0.80000001192092896" blue="0.40000000596046448" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="100" id="L4i-fJ-6Ko"/>
<constraint firstAttribute="width" constant="100" id="ym9-zy-Fdt"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="01T-Bq-eRq">
<rect key="frame" x="20" y="256" width="100" height="100"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="0.43529412150382996" blue="0.81176471710205078" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="100" id="Vc9-mU-Out"/>
<constraint firstAttribute="width" constant="100" id="zza-hp-DTx"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="1" green="0.40000000596046448" blue="0.40000000596046448" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstItem="01T-Bq-eRq" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="20" id="D6I-ib-Jul"/>
<constraint firstAttribute="trailing" secondItem="V5r-JV-Fkh" secondAttribute="trailing" constant="20" id="Jx3-5I-Mar"/>
<constraint firstItem="xhz-dx-nq1" firstAttribute="top" secondItem="1" secondAttribute="top" constant="20" id="MPA-2Y-2Ax"/>
<constraint firstItem="xhz-dx-nq1" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="20" id="TSQ-mb-8WP"/>
<constraint firstAttribute="bottom" secondItem="qOE-WQ-xv7" secondAttribute="bottom" constant="20" id="cwF-Rs-2Ma"/>
<constraint firstItem="V5r-JV-Fkh" firstAttribute="top" secondItem="1" secondAttribute="top" constant="20" id="lta-Lt-WYv"/>
<constraint firstAttribute="trailing" secondItem="qOE-WQ-xv7" secondAttribute="trailing" constant="20" id="oNF-uM-mJr"/>
<constraint firstAttribute="bottom" secondItem="01T-Bq-eRq" secondAttribute="bottom" constant="20" id="qi3-cZ-ZFw"/>
</constraints>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
</view>
</objects>
</document>

14
SpectogramPrototype/FFTTest.h

@ -0,0 +1,14 @@
//
// FFTTest.h
// SpectogramPrototype
//
// Created by Joshua Moerman on 24/12/13.
// Copyright (c) 2013 Joshua Moerman. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface FFTTest : NSObject
- (void) inPlaceFFT:(float*)data forSize:(unsigned int)n;
@property (readonly) unsigned int acceptedSize;
@end

77
SpectogramPrototype/FFTTest.m

@ -0,0 +1,77 @@
//
// FFTTest.m
// SpectogramPrototype
//
// Created by Joshua Moerman on 24/12/13.
// Copyright (c) 2013 Joshua Moerman. All rights reserved.
//
#import "FFTTest.h"
#import <Accelerate/Accelerate.h>
@interface FFTTest () {
FFTSetup setup;
float * window;
float * buffer;
}
@end
const int logN = 3;
const int N = 1 << logN;
const float scaling = 1.0 / N;
@implementation FFTTest
@synthesize acceptedSize;
- (id)init{
if(self = [super init]){
acceptedSize = N;
setup = vDSP_create_fftsetup(logN, kFFTRadix2);
window = calloc(N, sizeof(float));
buffer = calloc(N, sizeof(float));
assert(setup && window && buffer);
}
return self;
}
- (void)dealloc{
free(buffer);
free(window);
vDSP_destroy_fftsetup(setup);
}
- (void)inPlaceFFT:(float *)data forSize:(unsigned int)n{
assert(n == N);
// Output the source data
for(int i = 0; i < N; ++i){
printf("%f, ", data[i]);
}
printf("\n");
// Window our time - slice
// vDSP_blkman_window(window, N, 0);
// vmul(data, 1, window, 1, data, 1, N);
// Rearrange data
DSPSplitComplex split_buffer = { buffer, buffer + N/2 };
vDSP_ctoz((DSPComplex *)data, 2, &split_buffer, 1, N/2);
// DO IT!
vDSP_fft_zrip(setup, &split_buffer, 1, logN, FFT_FORWARD);
// Calculates magnitudes (so ignores phases)
vDSP_zvabs(&split_buffer, 1, data, 1, N/2);
vDSP_vsmul(data, 1, &scaling, data, 1, N/2);
// Output results:
for(int i = 0; i < N/2; ++i){
printf("%f, ", data[i]);
}
printf("\n");
}
@end

15
SpectogramPrototype/RuledScrollView.h

@ -0,0 +1,15 @@
//
// RuledScrollView.h
// SpectogramPrototype
//
// Created by Joshua Moerman on 24/12/13.
// Copyright (c) 2013 Joshua Moerman. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RuledScrollView : UIScrollView
@property (nonatomic, readonly) UIView * content;
@property (nonatomic, readonly) UIView * topRuler;
@property (nonatomic, readonly) UIView * leftRuler;
@end

109
SpectogramPrototype/RuledScrollView.m

@ -0,0 +1,109 @@
//
// RuledScrollView.m
// SpectogramPrototype
//
// Created by Joshua Moerman on 24/12/13.
// Copyright (c) 2013 Joshua Moerman. All rights reserved.
//
#import "RuledScrollView.h"
@interface RuledScrollView () <UIScrollViewDelegate> {
CGFloat rulerHeight;
CGFloat rulerWidth;
}
- (void) initView;
- (void) placeTicks;
@end
@implementation RuledScrollView
@synthesize content, topRuler, leftRuler;
- (id)initWithFrame:(CGRect)frame{
if(self = [super initWithFrame:frame]){
[self initView];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder{
if(self = [super initWithCoder:aDecoder]){
[self initView];
}
return self;
}
- (void)initView {
rulerHeight = 44;
rulerWidth = 120;
self.delegate = self;
self.backgroundColor = [UIColor whiteColor];
content = [[UIView alloc] initWithFrame:self.frame];
content.autoresizesSubviews = NO;
[self addSubview:content];
CGRect frame2 = self.frame;
frame2.size.height = rulerHeight;
topRuler = [[UIView alloc] initWithFrame:frame2];
topRuler.layer.opacity = 0.5;
topRuler.backgroundColor = self.backgroundColor;
[self addSubview:topRuler];
CGRect frame3 = self.frame;
frame3.size.width = rulerWidth;
leftRuler = [[UIView alloc] initWithFrame:frame3];
leftRuler.layer.opacity = 0.5;
leftRuler.backgroundColor = self.backgroundColor;
[self addSubview:leftRuler];
}
/* we should draw the ticks in drawRect:
[[UIColor blackColor] setFill];
UIRectFill((CGRect){0,200,rect.size.width,1});
and do tiling for the text
*/
- (void)placeTicks {
[topRuler.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
for (CGFloat x = rulerWidth + 50; x < topRuler.frame.size.width; x += 100){
UIView * line = [[UIView alloc] initWithFrame:CGRectMake(x, 0, 1, rulerHeight)];
line.backgroundColor = [UIColor blackColor];
[topRuler addSubview:line];
CGFloat width = 100;
UILabel * text = [[UILabel alloc] initWithFrame:CGRectMake(x - width/2, 0, width, rulerHeight)];
text.text = [NSString stringWithFormat:@"%.0f", x];
text.textAlignment = NSTextAlignmentCenter;
[topRuler addSubview:text];
}
}
- (void)layoutSubviews {
{
CGRect frame = self.topRuler.frame;
frame.origin.y = self.contentOffset.y;
self.topRuler.frame = frame;
[self placeTicks];
}
{
CGRect frame = self.leftRuler.frame;
frame.origin.x = self.contentOffset.x;
self.leftRuler.frame = frame;
}
}
- (void)setContentSize:(CGSize)contentSize{
[super setContentSize:CGSizeMake(contentSize.width + rulerWidth, contentSize.height + rulerHeight)];
content.frame = CGRectMake(rulerWidth, rulerHeight, contentSize.width, contentSize.height);
topRuler.frame = CGRectMake(0, 0, contentSize.width + rulerWidth, rulerHeight);
leftRuler.frame = CGRectMake(0, 0, rulerWidth, contentSize.height + rulerHeight);
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return content;
}
@end

8
SpectogramPrototype/ViewController.h

@ -8,6 +8,14 @@
#import <UIKit/UIKit.h>
@class RuledScrollView;
@interface ViewController : UIViewController
@property (nonatomic) IBOutlet RuledScrollView * scrollView;
@property (nonatomic) IBOutlet UIView * contentView;
- (IBAction) calculateButtonPressed:(id)sender;
- (IBAction) mediaButtonPressed:(UIButton*)sender;
@end

101
SpectogramPrototype/ViewController.m

@ -6,24 +6,105 @@
// Copyright (c) 2013 Joshua Moerman. All rights reserved.
//
#import "ViewController.h"
#import <MediaPlayer/MPMediaPickerController.h>
#import <AudioToolbox/ExtendedAudioFile.h>
@interface ViewController ()
#import "ViewController.h"
#import "RuledScrollView.h"
#import "FFTTest.h"
@interface ViewController () <MPMediaPickerControllerDelegate> {
UIPopoverController * pop;
FFTTest * fft_handler;
}
- (void) openAudioFile:(NSURL*)filePath;
@property (nonatomic, strong) UILabel* header;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
@synthesize scrollView, contentView, header;
- (void)viewDidLoad{
[super viewDidLoad];
if(!contentView){
[[NSBundle mainBundle] loadNibNamed:@"ContentView" owner:self options:nil];
[scrollView.content addSubview:contentView];
contentView.autoresizingMask = UIViewAutoresizingNone;
scrollView.contentSize = contentView.bounds.size;
}
}
- (void)didReceiveMemoryWarning{
[super didReceiveMemoryWarning];
}
- (void)calculateButtonPressed:(id)sender{
if(!fft_handler)
fft_handler = [[FFTTest alloc] init];
unsigned int size = fft_handler.acceptedSize;
float * data = calloc(size, sizeof(float));
[fft_handler inPlaceFFT:data forSize:size];
free(data);
}
- (void)openAudioFile:(NSURL *)filePath{
OSStatus err;
ExtAudioFileRef audioFile = NULL;
err = ExtAudioFileOpenURL((__bridge CFURLRef) filePath, &audioFile);
assert(err == 0);
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mNumberChannels = 2;
bufferList.mBuffers[0].mDataByteSize = 32768;
bufferList.mBuffers[0].mData = calloc(32768, 1);
while(true){
bufferList.mBuffers[0].mDataByteSize = 32768;
UInt32 nFrames = 32768 / 6;
err = ExtAudioFileRead(audioFile, &nFrames, &bufferList);
assert(err == 0);
if(!nFrames) break;
}
NSLog(@"Read some bits");
err = ExtAudioFileDispose(audioFile);
assert(err == 0);
}
- (void)mediaButtonPressed:(UIButton*)sender{
MPMediaPickerController * mppc = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeAnyAudio];
mppc.delegate = self;
mppc.allowsPickingMultipleItems = NO;
mppc.showsCloudItems = NO;
if(pop){
[pop dismissPopoverAnimated:YES];
pop = nil;
}
pop = [[UIPopoverController alloc] initWithContentViewController:mppc];
[pop presentPopoverFromRect:sender.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection {
for(MPMediaItem * mediaItem in mediaItemCollection.items){
NSURL * url = [mediaItem valueForProperty:MPMediaItemPropertyAssetURL];
[self openAudioFile:url];
}
[pop dismissPopoverAnimated:YES];
pop = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
- (void)mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker {
[pop dismissPopoverAnimated:YES];
pop = nil;
}
@end