Puts the generation logic in a seperate file. Adds stereo
This commit is contained in:
parent
3e7d71c6d2
commit
5ee2bee289
6 changed files with 118 additions and 54 deletions
|
@ -29,6 +29,7 @@
|
|||
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 */; };
|
||||
42ABF54B187035F900B20D82 /* Spectographer.m in Sources */ = {isa = PBXBuildFile; fileRef = 42ABF54A187035F900B20D82 /* Spectographer.m */; };
|
||||
42E12A91186F122400866CB3 /* testMusic.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 42E12A90186F122400866CB3 /* testMusic.mp3 */; };
|
||||
42E12A94186F1F4C00866CB3 /* AudioFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 42E12A93186F1F4C00866CB3 /* AudioFile.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
@ -73,6 +74,8 @@
|
|||
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; };
|
||||
42ABF549187035F900B20D82 /* Spectographer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Spectographer.h; sourceTree = "<group>"; };
|
||||
42ABF54A187035F900B20D82 /* Spectographer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Spectographer.m; sourceTree = "<group>"; };
|
||||
42E12A90186F122400866CB3 /* testMusic.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = testMusic.mp3; sourceTree = "<group>"; };
|
||||
42E12A92186F1F4C00866CB3 /* AudioFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioFile.h; sourceTree = "<group>"; };
|
||||
42E12A93186F1F4C00866CB3 /* AudioFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioFile.m; sourceTree = "<group>"; };
|
||||
|
@ -150,6 +153,8 @@
|
|||
424F84BD18661F8000687D3B /* Main_iPad.storyboard */,
|
||||
424F84C018661F8000687D3B /* ViewController.h */,
|
||||
424F84C118661F8000687D3B /* ViewController.m */,
|
||||
42ABF549187035F900B20D82 /* Spectographer.h */,
|
||||
42ABF54A187035F900B20D82 /* Spectographer.m */,
|
||||
42E12A92186F1F4C00866CB3 /* AudioFile.h */,
|
||||
42E12A93186F1F4C00866CB3 /* AudioFile.m */,
|
||||
426665B31869A7CC005D62AC /* RuledScrollView.h */,
|
||||
|
@ -293,6 +298,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
42E12A94186F1F4C00866CB3 /* AudioFile.m in Sources */,
|
||||
42ABF54B187035F900B20D82 /* Spectographer.m in Sources */,
|
||||
426665B81869CEFE005D62AC /* FFTTest.m in Sources */,
|
||||
424F84C218661F8000687D3B /* ViewController.m in Sources */,
|
||||
424F84B918661F8000687D3B /* AppDelegate.m in Sources */,
|
||||
|
|
|
@ -16,6 +16,6 @@
|
|||
+ (AudioFile*) audioFileFromURL:(NSURL*) url;
|
||||
|
||||
// Reads nSamples of data (left channel), return actual number of samples read
|
||||
- (unsigned int) fillArray:(float*)array withNumberOfSamples:(unsigned int)nSamples;
|
||||
- (unsigned int) fillLeft:(float*)left andRight:(float*)right withNumberOfSamples:(unsigned int)nSamples;
|
||||
|
||||
@end
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
#pragma mark
|
||||
#pragma mark Usage
|
||||
|
||||
- (unsigned int)fillArray:(float *)array withNumberOfSamples:(unsigned int)nSamples{
|
||||
- (unsigned int)fillLeft:(float *)left andRight:(float *)right withNumberOfSamples:(unsigned int)nSamples {
|
||||
AudioBufferList bufferList;
|
||||
bufferList.mNumberBuffers = 1;
|
||||
bufferList.mBuffers[0].mNumberChannels = 2;
|
||||
|
@ -74,15 +74,16 @@
|
|||
assert(err == 0);
|
||||
|
||||
short * buffer = bufferList.mBuffers[0].mData;
|
||||
float * end = array + nSamples;
|
||||
float * leftEnd = left + nSamples;
|
||||
for(unsigned int i = 0; i < nFrames; ++i){
|
||||
*array++ = *buffer++ / 32768.0;
|
||||
// skip right channel
|
||||
buffer++;
|
||||
*left++ = *buffer++ / 32768.0;
|
||||
*right++ = *buffer++ / 32768.0;
|
||||
}
|
||||
|
||||
while(array != end){
|
||||
*array++ = 0.0;
|
||||
// assume left and right are of the same size
|
||||
while(left != leftEnd){
|
||||
*left++ = 0.0;
|
||||
*right++ = 0.0;
|
||||
}
|
||||
|
||||
free(bufferList.mBuffers[0].mData);
|
||||
|
|
16
SpectogramPrototype/Spectographer.h
Normal file
16
SpectogramPrototype/Spectographer.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// Spectographer.h
|
||||
// SpectogramPrototype
|
||||
//
|
||||
// Created by Joshua Moerman on 29/12/13.
|
||||
// Copyright (c) 2013 Joshua Moerman. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Spectographer : NSObject
|
||||
|
||||
- (void)openAudioFile:(NSURL*)url;
|
||||
- (CGImageRef)generate;
|
||||
|
||||
@end
|
78
SpectogramPrototype/Spectographer.m
Normal file
78
SpectogramPrototype/Spectographer.m
Normal file
|
@ -0,0 +1,78 @@
|
|||
//
|
||||
// Spectographer.m
|
||||
// SpectogramPrototype
|
||||
//
|
||||
// Created by Joshua Moerman on 29/12/13.
|
||||
// Copyright (c) 2013 Joshua Moerman. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Spectographer.h"
|
||||
#import "FFTTest.h"
|
||||
#import "AudioFile.h"
|
||||
|
||||
UInt8 clamp_to_uint8(float x){
|
||||
if(x >= 1.0) return 255;
|
||||
if(x <= 0.0) return 0;
|
||||
return 255.0 * x;
|
||||
}
|
||||
|
||||
@interface Spectographer (){
|
||||
FFTTest * FFTHandler;
|
||||
AudioFile * audioFile;
|
||||
float * left;
|
||||
float * right;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation Spectographer
|
||||
|
||||
- (id)init{
|
||||
if(self = [super init]){
|
||||
FFTHandler = [[FFTTest alloc] init];
|
||||
left = calloc(FFTHandler.acceptedSize, sizeof(float));
|
||||
right = calloc(FFTHandler.acceptedSize, sizeof(float));
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)openAudioFile:(NSURL *)url{
|
||||
audioFile = [AudioFile audioFileFromURL: url];
|
||||
assert(audioFile);
|
||||
}
|
||||
|
||||
- (CGImageRef)generate{
|
||||
unsigned int size = FFTHandler.acceptedSize;
|
||||
unsigned int width = size/4;
|
||||
unsigned int height = size/8;
|
||||
|
||||
char * rgba = calloc(width*height*4, sizeof(char));
|
||||
|
||||
for(unsigned int x = 0; x < width; ++x){
|
||||
[audioFile fillLeft:left andRight:right withNumberOfSamples:size];
|
||||
[FFTHandler inPlaceFFT:left forSize:size];
|
||||
[FFTHandler inPlaceFFT:right forSize:size];
|
||||
for(unsigned int y = 0; y < height; ++y){
|
||||
unsigned int yy = height - y - 1;
|
||||
rgba[4*width*yy + 4*x + 0] = clamp_to_uint8(100.0 * left[y]);
|
||||
rgba[4*width*yy + 4*x + 1] = clamp_to_uint8(100.0 * right[y]);
|
||||
rgba[4*width*yy + 4*x + 2] = clamp_to_uint8(10.0 * (left[y] + right[y]));
|
||||
rgba[4*width*yy + 4*x + 3] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
assert(colorSpace);
|
||||
CGContextRef bitmapContext = CGBitmapContextCreate(rgba, width, height, 8, 4*width, colorSpace, (CGBitmapInfo)kCGImageAlphaNoneSkipLast);
|
||||
assert(bitmapContext);
|
||||
CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext);
|
||||
assert(cgImage);
|
||||
|
||||
CGContextRelease(bitmapContext);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
free(rgba);
|
||||
|
||||
return cgImage;
|
||||
}
|
||||
|
||||
@end
|
|
@ -11,8 +11,7 @@
|
|||
|
||||
#import "ViewController.h"
|
||||
#import "RuledScrollView.h"
|
||||
#import "FFTTest.h"
|
||||
#import "AudioFile.h"
|
||||
#import "Spectographer.h"
|
||||
|
||||
typedef enum {
|
||||
iPad,
|
||||
|
@ -38,16 +37,9 @@ device get_device(){
|
|||
return device;
|
||||
}
|
||||
|
||||
UInt8 clamp_to_uint8(float x){
|
||||
if(x >= 1.0) return 255;
|
||||
if(x <= 0.0) return 0;
|
||||
return 255.0 * x;
|
||||
}
|
||||
|
||||
@interface ViewController () <MPMediaPickerControllerDelegate> {
|
||||
Spectographer * spectographer;
|
||||
UIPopoverController * pop;
|
||||
FFTTest * fft_handler;
|
||||
float * data;
|
||||
}
|
||||
- (void) openAudioFile:(NSURL*)filePath;
|
||||
@property (nonatomic, strong) UILabel* header;
|
||||
|
@ -73,51 +65,22 @@ UInt8 clamp_to_uint8(float x){
|
|||
}
|
||||
|
||||
- (void)openAudioFile:(NSURL *)filePath{
|
||||
AudioFile * audioFile = [AudioFile audioFileFromURL:filePath];
|
||||
if(!spectographer)
|
||||
spectographer = [[Spectographer alloc] init];
|
||||
|
||||
if(!fft_handler)
|
||||
fft_handler = [[FFTTest alloc] init];
|
||||
[spectographer openAudioFile:filePath];
|
||||
CGImageRef image = [spectographer generate];
|
||||
|
||||
unsigned int size = fft_handler.acceptedSize;
|
||||
unsigned int width = size/4;
|
||||
unsigned int height = size/8;
|
||||
|
||||
if(!data)
|
||||
data = calloc(size, sizeof(float));
|
||||
|
||||
char * rgba = calloc(width*height*4, sizeof(char));
|
||||
|
||||
for(unsigned int x = 0; x < width; ++x){
|
||||
[audioFile fillArray:data withNumberOfSamples:size];
|
||||
[fft_handler inPlaceFFT:data forSize:size];
|
||||
for(unsigned int y = 0; y < height; ++y){
|
||||
unsigned int yy = height - y - 1;
|
||||
rgba[4*width*yy + 4*x + 0] = clamp_to_uint8(100.0 * data[y]);
|
||||
rgba[4*width*yy + 4*x + 1] = clamp_to_uint8(50.0 * data[y]);
|
||||
rgba[4*width*yy + 4*x + 2] = clamp_to_uint8(10.0 * data[y]);
|
||||
rgba[4*width*yy + 4*x + 3] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
assert(colorSpace);
|
||||
CGContextRef bitmapContext = CGBitmapContextCreate(rgba, width, height, 8, 4*width, colorSpace, (CGBitmapInfo)kCGImageAlphaNoneSkipLast);
|
||||
assert(bitmapContext);
|
||||
CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext);
|
||||
assert(cgImage);
|
||||
UIImage * newUIImage = [UIImage imageWithCGImage:cgImage];
|
||||
UIImage * newUIImage = [UIImage imageWithCGImage:image];
|
||||
assert(newUIImage);
|
||||
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
CGContextRelease(bitmapContext);
|
||||
CGImageRelease(cgImage);
|
||||
free(rgba);
|
||||
CGImageRelease(image);
|
||||
|
||||
UIImageView * view = [[UIImageView alloc] initWithImage:newUIImage];
|
||||
view.frame = CGRectMake(0, 0, width, height);
|
||||
|
||||
[contentView removeFromSuperview];
|
||||
contentView = view;
|
||||
scrollView.zoomScale = 1.0;
|
||||
|
||||
[scrollView.content addSubview:contentView];
|
||||
contentView.autoresizingMask = UIViewAutoresizingNone;
|
||||
|
|
Reference in a new issue