2013-10-29 22:51:55 +00:00
|
|
|
//
|
|
|
|
// HVLDecoder.m
|
|
|
|
// Hively
|
|
|
|
//
|
|
|
|
// Created by Christopher Snowhill on 10/29/13.
|
|
|
|
// Copyright 2013 __NoWork, Inc__. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#import "HVLDecoder.h"
|
|
|
|
|
2014-02-14 05:16:18 +00:00
|
|
|
#import "PlaylistController.h"
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
static void oneTimeInit(void) {
|
|
|
|
static BOOL initialized = NO;
|
|
|
|
if(!initialized) {
|
|
|
|
hvl_InitReplayer();
|
|
|
|
initialized = YES;
|
|
|
|
}
|
2013-10-29 22:51:55 +00:00
|
|
|
}
|
|
|
|
|
2021-04-30 01:16:24 +00:00
|
|
|
@implementation HVLDecoder
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
+ (void)initialize {
|
|
|
|
if([self class] == [HVLDecoder class])
|
|
|
|
oneTimeInit();
|
2013-10-29 22:51:55 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (BOOL)open:(id<CogSource>)s {
|
|
|
|
[s seek:0 whence:SEEK_END];
|
|
|
|
long size = [s tell];
|
|
|
|
[s seek:0 whence:SEEK_SET];
|
|
|
|
|
|
|
|
if(size > UINT_MAX)
|
|
|
|
return NO;
|
|
|
|
|
|
|
|
void *data = malloc(size);
|
|
|
|
[s read:data amount:size];
|
|
|
|
|
|
|
|
tune = hvl_LoadTune(data, (uint32_t)size, 44100, 2);
|
|
|
|
free(data);
|
|
|
|
if(!tune)
|
|
|
|
return NO;
|
|
|
|
|
|
|
|
unsigned long safety = 2 * 60 * 60 * 50 * tune->ht_SpeedMultiplier;
|
|
|
|
|
|
|
|
NSURL *url = [s url];
|
|
|
|
if([[url fragment] length] == 0)
|
2013-10-29 22:51:55 +00:00
|
|
|
trackNumber = 0;
|
|
|
|
else
|
|
|
|
trackNumber = [[url fragment] intValue];
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
hvl_InitSubsong(tune, trackNumber);
|
|
|
|
|
|
|
|
unsigned long loops = 0;
|
|
|
|
|
|
|
|
while(loops < 2 && safety) {
|
|
|
|
while(!tune->ht_SongEndReached && safety) {
|
|
|
|
hvl_play_irq(tune);
|
|
|
|
--safety;
|
|
|
|
}
|
|
|
|
tune->ht_SongEndReached = 0;
|
|
|
|
++loops;
|
|
|
|
}
|
|
|
|
|
|
|
|
framesLength = tune->ht_PlayingTime * 44100 / (tune->ht_SpeedMultiplier * 50);
|
|
|
|
framesFade = 44100 * 8;
|
|
|
|
totalFrames = framesLength + framesFade;
|
|
|
|
|
|
|
|
framesRead = 0;
|
|
|
|
framesInBuffer = 0;
|
|
|
|
|
|
|
|
buffer = malloc(sizeof(int32_t) * (44100 / 50) * 2);
|
|
|
|
|
|
|
|
hvl_InitSubsong(tune, trackNumber);
|
|
|
|
|
|
|
|
[self willChangeValueForKey:@"properties"];
|
2013-10-29 22:51:55 +00:00
|
|
|
[self didChangeValueForKey:@"properties"];
|
|
|
|
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (NSDictionary *)properties {
|
2022-06-17 13:39:02 +00:00
|
|
|
return @{ @"bitrate": @(0),
|
|
|
|
@"sampleRate": @(44100),
|
|
|
|
@"totalFrames": @(totalFrames),
|
|
|
|
@"bitsPerSample": @(32),
|
|
|
|
@"floatingPoint": @(YES),
|
|
|
|
@"channels": @(2),
|
|
|
|
@"seekable": @(YES),
|
|
|
|
@"endian": @"host",
|
|
|
|
@"encoding": @"synthesized" };
|
2013-10-29 22:51:55 +00:00
|
|
|
}
|
|
|
|
|
2022-02-09 03:56:39 +00:00
|
|
|
- (NSDictionary *)metadata {
|
|
|
|
return @{};
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
|
|
|
BOOL repeatone = IsRepeatOneSet();
|
|
|
|
|
|
|
|
if(!repeatone && framesRead >= totalFrames)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
int total = 0;
|
|
|
|
while(total < frames) {
|
|
|
|
if(framesInBuffer) {
|
|
|
|
float *outbuffer = ((float *)buf) + total * 2;
|
|
|
|
int framesToCopy = frames - total;
|
|
|
|
if(framesToCopy > framesInBuffer)
|
|
|
|
framesToCopy = (int)framesInBuffer;
|
|
|
|
for(int i = 0; i < framesToCopy; ++i) {
|
|
|
|
outbuffer[0] = buffer[i * 2 + 0] * (1.0f / 16777216.0f);
|
|
|
|
outbuffer[1] = buffer[i * 2 + 1] * (1.0f / 16777216.0f);
|
|
|
|
outbuffer += 2;
|
|
|
|
}
|
|
|
|
framesInBuffer -= framesToCopy;
|
|
|
|
total += framesToCopy;
|
|
|
|
if(framesInBuffer) {
|
|
|
|
memcpy(buffer, buffer + framesToCopy * 2, sizeof(int32_t) * framesInBuffer * 2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
hvl_DecodeFrame(tune, (int8_t *)buffer, ((int8_t *)buffer) + 4, 8);
|
|
|
|
framesInBuffer = 44100 / 50;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!repeatone && framesRead + total > framesLength) {
|
|
|
|
long fadeStart = (framesLength > framesRead) ? framesLength : framesRead;
|
|
|
|
long fadeEnd = (framesRead + total) > totalFrames ? totalFrames : (framesRead + total);
|
|
|
|
long fadePos;
|
|
|
|
|
|
|
|
float *buff = (float *)buf;
|
|
|
|
|
|
|
|
float fadeScale = (float)(totalFrames - fadeStart) / (float)framesFade;
|
|
|
|
float fadeStep = 1.0 / (float)framesFade;
|
|
|
|
for(fadePos = fadeStart; fadePos < fadeEnd; ++fadePos) {
|
|
|
|
buff[0] *= fadeScale;
|
|
|
|
buff[1] *= fadeScale;
|
|
|
|
buff += 2;
|
|
|
|
fadeScale -= fadeStep;
|
|
|
|
if(fadeScale <= 0.0) break;
|
|
|
|
}
|
|
|
|
total = (int)(fadePos - fadeStart);
|
|
|
|
}
|
|
|
|
|
2013-10-29 22:51:55 +00:00
|
|
|
framesRead += total;
|
2022-02-07 05:49:27 +00:00
|
|
|
|
|
|
|
return total;
|
2013-10-29 22:51:55 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (long)seek:(long)frame {
|
|
|
|
if(frame < framesRead) {
|
|
|
|
hvl_InitSubsong(tune, trackNumber);
|
|
|
|
framesRead = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(framesRead < frame) {
|
|
|
|
hvl_play_irq(tune);
|
|
|
|
framesRead += 44100 / 50;
|
|
|
|
}
|
|
|
|
|
|
|
|
return framesRead;
|
2013-10-29 22:51:55 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)close {
|
|
|
|
if(tune) {
|
|
|
|
hvl_FreeTune(tune);
|
|
|
|
tune = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(buffer) {
|
|
|
|
free(buffer);
|
|
|
|
buffer = NULL;
|
|
|
|
}
|
2013-10-29 22:51:55 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)dealloc {
|
|
|
|
[self close];
|
2016-06-19 19:57:18 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
+ (NSArray *)fileTypes {
|
2022-01-19 02:12:57 +00:00
|
|
|
return @[@"hvl", @"ahx"];
|
2013-10-29 22:51:55 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
+ (NSArray *)fileTypeAssociations {
|
|
|
|
return @[
|
|
|
|
@[@"Hively Tracker File", @"song.icns", @"hvl"],
|
2022-02-20 09:51:11 +00:00
|
|
|
@[@"Abyss' Highest eXperience File", @"song.icns", @"ahx"]
|
2022-02-07 05:49:27 +00:00
|
|
|
];
|
2022-01-18 11:06:03 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
+ (NSArray *)mimeTypes {
|
2013-10-29 22:51:55 +00:00
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
+ (float)priority {
|
|
|
|
return 1.0;
|
2013-10-29 22:51:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@end
|