Music to spectrogram on iOS with the accelerate framework
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 

175 lines
4.8 KiB

//
// ViewController.m
// SpectogramPrototype
//
// Created by Joshua Moerman on 21/12/13.
// Copyright (c) 2013 Joshua Moerman. All rights reserved.
//
#import <MediaPlayer/MPMediaPickerController.h>
#import <AudioToolbox/ExtendedAudioFile.h>
#import "ViewController.h"
#import "RuledScrollView.h"
#import "FFTTest.h"
#import "AudioFile.h"
typedef enum {
iPad,
iPod,
Simulator
} device;
// NOTE: the simulator has no media, so we cant use MPMediaPicker
// and the iPad has to use a popover, while the iPod/iPhone doesn't
// So that's why we check the device
device get_device(){
device device = iPad;
NSRange range = [[[UIDevice currentDevice] model] rangeOfString:@"Simulator"];
if(range.location != NSNotFound) {
device = Simulator;
}
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
device = iPod;
}
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> {
UIPopoverController * pop;
FFTTest * fft_handler;
float * data;
}
- (void) openAudioFile:(NSURL*)filePath;
@property (nonatomic, strong) UILabel* header;
@end
@implementation ViewController
@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)openAudioFile:(NSURL *)filePath{
AudioFile * audioFile = [AudioFile audioFileFromURL:filePath];
if(!fft_handler)
fft_handler = [[FFTTest alloc] init];
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];
assert(newUIImage);
CGColorSpaceRelease(colorSpace);
CGContextRelease(bitmapContext);
CGImageRelease(cgImage);
free(rgba);
UIImageView * view = [[UIImageView alloc] initWithImage:newUIImage];
view.frame = CGRectMake(0, 0, width, height);
[contentView removeFromSuperview];
contentView = view;
[scrollView.content addSubview:contentView];
contentView.autoresizingMask = UIViewAutoresizingNone;
scrollView.contentSize = contentView.bounds.size;
}
- (void)mediaButtonPressed:(UIButton*)sender{
MPMediaPickerController * mppc = nil;
device device = get_device();
switch (device) {
case iPad:
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];
break;
case iPod:
mppc = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeAnyAudio];
mppc.delegate = self;
mppc.allowsPickingMultipleItems = NO;
mppc.showsCloudItems = NO;
[self presentViewController:mppc animated:YES completion:nil];
break;
case Simulator:
NSLog(@"WARNING: No MPMediaPicker in Simulator, opening some file");
[self openAudioFile:[[NSBundle mainBundle] URLForResource:@"testMusic" withExtension:@".mp3"]];
break;
}
}
- (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)mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker {
[pop dismissPopoverAnimated:YES];
pop = nil;
}
@end